diff --git a/DEPS b/DEPS index 2c37ba3c..fd8737d 100644 --- a/DEPS +++ b/DEPS
@@ -268,7 +268,7 @@ 'screen_ai_windows_386': 'version:138.06', # siso CIPD package version. - 'siso_version': 'git_revision:7e7d85fc69f9084d2168385fb504b31e830dbfff', + 'siso_version': 'git_revision:c23de742b8483ddc09d8b68ef845efc7f5c6192f', # download libaom test data 'download_libaom_testdata': False, @@ -294,11 +294,11 @@ # 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': '35d5edfa0d50984c22ff94f5438c31e0db12c6f8', + 'skia_revision': '47766ee60ccc6e9e0a024348192ba72391e5785e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '9541b18ce700cdef8cce07fef49f1ac9d74a1dd2', + 'v8_revision': '4d7c9f183f3c41ac42eb0d622a4d8e58a0982693', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -310,7 +310,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'b6457bcccc5c86ac7159f957fa8dbea3d5e13f49', + 'pdfium_revision': '1dbcd29c45a96d9717e040662bba05395d790145', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -362,7 +362,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. - 'crossbench_revision': '6acc0ec6a547f0d9cfc307fedd515459d239fa24', + 'crossbench_revision': '749d1a4f48bb0ae63aa8559ef96180a677b65307', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -378,7 +378,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': 'ea58b6707370f3b440b362fe178e7f6cd4a9170b', + 'devtools_frontend_revision': 'fee355f9b7f54daccee81b9ef82034656243e834', # 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. @@ -402,7 +402,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'd03fe7eda12dfce1578bf69da2814f89fd78c1e9', + 'dawn_revision': '830dc86845102bb7c45f45ca14251b92add5dbb9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -510,7 +510,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling llvm-libc # and whatever else without interference from each other. - 'compiler_rt_revision': 'd3919a20084ce47e31983ffa3724f6318f34390c', + 'compiler_rt_revision': '2a4f69a118bdc5d03c415de1b9b166b2f1d4084f', # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. @@ -1563,7 +1563,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '9e7cc1ffbb07d1afe8f3528f10d621b54993c515', + '37813b0fe2b96138bf8f715b42ac30fba422b9d2', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1717,7 +1717,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': '-KXWut6mOUpWy_b-s5qaRRUSsLCznTQ6aiZoYO3b4zsC', + 'version': 'RMTIxBSE0B55RT6WlvZAfFwWK9rBMMW14yPXf2AzfysC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2053,7 +2053,7 @@ 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ae917185501cda874f12f3e1d870de8505b0807c', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8f878438075a8d5d76f57bd10ab866d58d706319', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -2593,7 +2593,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'cca1748cb16b9dc0cac21515813c3855a983917d', + Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'faeba3e4b27b5adb924ece5548a61bef8013faed', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -3143,7 +3143,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'pNSGXXsmfoCc9iNOIrFiMFPhvTk348XeiQ7uuRP3KIYC', + 'version': 'AbrE_oILb_zjITzM-b71AVUd4sYJZCam8HpaxgVNMj8C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/prefetch/aw_prefetch_manager.cc b/android_webview/browser/prefetch/aw_prefetch_manager.cc index b52a6be..2ff4508d 100644 --- a/android_webview/browser/prefetch/aw_prefetch_manager.cc +++ b/android_webview/browser/prefetch/aw_prefetch_manager.cc
@@ -144,8 +144,9 @@ browser_context_->StartBrowserPrefetchRequest( pf_url, AW_PREFETCH_METRICS_SUFFIX, GetIsJavaScriptEnabledFromPrefetchParameters(env, prefetch_params), - expected_no_vary_search, additional_headers, - std::move(request_status_listener), base::Seconds(ttl_in_sec_), + expected_no_vary_search, /*priority=*/std::nullopt, + additional_headers, std::move(request_status_listener), + base::Seconds(ttl_in_sec_), /*should_append_variations_header=*/false, /*should_disable_block_until_head_timeout=*/true);
diff --git a/ash/birch/birch_model_unittest.cc b/ash/birch/birch_model_unittest.cc index 61aec25..97ca989c 100644 --- a/ash/birch/birch_model_unittest.cc +++ b/ash/birch/birch_model_unittest.cc
@@ -722,17 +722,9 @@ EXPECT_TRUE(model->IsDataFresh()); } -// TODO(https://crbug.com/324963992): Fix `BirchModel*Test.DataFetchTimeout` -// for debug builds. -#if defined(NDEBUG) -#define MAYBE_DataFetchTimeout DataFetchTimeout -#else -#define MAYBE_DataFetchTimeout DISABLED_DataFetchTimeout -#endif - // Test that consumer is notified when waiting a set amount of time after // requesting birch data. -TEST_F(BirchModelTest, MAYBE_DataFetchTimeout) { +TEST_F(BirchModelTest, DataFetchTimeout) { BirchModel* model = Shell::Get()->birch_model(); TestModelConsumer consumer; EXPECT_TRUE(model);
diff --git a/ash/shelf/scrollable_shelf_view_unittest.cc b/ash/shelf/scrollable_shelf_view_unittest.cc index aaf4a8c..1d93406 100644 --- a/ash/shelf/scrollable_shelf_view_unittest.cc +++ b/ash/shelf/scrollable_shelf_view_unittest.cc
@@ -346,12 +346,10 @@ // No crash. } -// TODO(crbug.com/40867071): Enable when the bug is fixed. // Verifies that the display rotation from the long side to the short side // should not break the scrollable shelf's UI behavior // (https://crbug.com/1000764). -TEST_P(ScrollableShelfViewRTLTest, - DISABLED_CorrectUIAfterDisplayRotationLongToShort) { +TEST_P(ScrollableShelfViewRTLTest, CorrectUIAfterDisplayRotationLongToShort) { // Changes the display setting in order that the display's width is greater // than the height. UpdateDisplay("600x300");
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc index 7da2f69..716d86a9 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc +++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc
@@ -71,7 +71,8 @@ enum class AllocatorType { kSystem, kPartitionAlloc, - kPartitionAllocWithThreadCache, + kPartitionAllocWithThreadCache, /* NormalBucketDist */ + kPartitionAllocWithThreadCacheAndDenserBucketDist, #if BUILDFLAG(ENABLE_ALLOCATION_STACK_TRACE_RECORDER) kPartitionAllocWithAllocationStackTraceRecorder, #endif @@ -362,8 +363,7 @@ return timer.LapsPerSecond(); } -std::unique_ptr<Allocator> CreateAllocator(AllocatorType type, - bool use_denser_bucket_dist) { +std::unique_ptr<Allocator> CreateAllocator(AllocatorType type) { switch (type) { case AllocatorType::kSystem: return std::make_unique<SystemAllocator>(); @@ -371,7 +371,10 @@ return std::make_unique<PartitionAllocator>(); case AllocatorType::kPartitionAllocWithThreadCache: return std::make_unique<PartitionAllocatorWithThreadCache>( - use_denser_bucket_dist); + /*use_denser_bucket_dist=*/false); + case AllocatorType::kPartitionAllocWithThreadCacheAndDenserBucketDist: + return std::make_unique<PartitionAllocatorWithThreadCache>( + /*use_denser_bucket_dist=*/true); #if BUILDFLAG(ENABLE_ALLOCATION_STACK_TRACE_RECORDER) case AllocatorType::kPartitionAllocWithAllocationStackTraceRecorder: return std::make_unique< @@ -389,13 +392,37 @@ << "," << min_laps_per_second; } +std::string MakeTestName(int thread_count, AllocatorType alloc_type) { + char const* alloc_type_str; + switch (alloc_type) { + case AllocatorType::kSystem: + alloc_type_str = "System"; + break; + case AllocatorType::kPartitionAlloc: + alloc_type_str = "PartitionAlloc"; + break; + case AllocatorType::kPartitionAllocWithThreadCache: + alloc_type_str = "PartitionAllocWithThreadCache"; + break; + case AllocatorType::kPartitionAllocWithThreadCacheAndDenserBucketDist: + alloc_type_str = "PartitionAllocWithThreadCacheAndDenserBucketDist"; + break; +#if BUILDFLAG(ENABLE_ALLOCATION_STACK_TRACE_RECORDER) + case AllocatorType::kPartitionAllocWithAllocationStackTraceRecorder: + alloc_type_str = "PartitionAllocWithAllocationStackTraceRecorder"; + break; +#endif + } + + return base::TruncatingStringPrintf("%s_%d", alloc_type_str, thread_count); +} + void RunTest(int thread_count, - bool use_denser_bucket_dist, AllocatorType alloc_type, float (*test_fn)(Allocator*), float (*noisy_neighbor_fn)(Allocator*), const char* story_base_name) { - auto alloc = CreateAllocator(alloc_type, use_denser_bucket_dist); + auto alloc = CreateAllocator(alloc_type); std::unique_ptr<TestLoopThread> noisy_neighbor_thread = nullptr; if (noisy_neighbor_fn) { @@ -420,27 +447,10 @@ noisy_neighbor_thread->Run(); } - char const* alloc_type_str; - switch (alloc_type) { - case AllocatorType::kSystem: - alloc_type_str = "System"; - break; - case AllocatorType::kPartitionAlloc: - alloc_type_str = "PartitionAlloc"; - break; - case AllocatorType::kPartitionAllocWithThreadCache: - alloc_type_str = "PartitionAllocWithThreadCache"; - break; -#if BUILDFLAG(ENABLE_ALLOCATION_STACK_TRACE_RECORDER) - case AllocatorType::kPartitionAllocWithAllocationStackTraceRecorder: - alloc_type_str = "PartitionAllocWithAllocationStackTraceRecorder"; - break; -#endif - } - - std::string name = base::TruncatingStringPrintf( - "%s%s_%s_%d", kMetricPrefixMemoryAllocation, story_base_name, - alloc_type_str, thread_count); + std::string test_name = MakeTestName(thread_count, alloc_type); + std::string name = + base::TruncatingStringPrintf("%s%s_%s", kMetricPrefixMemoryAllocation, + story_base_name, test_name.c_str()); DisplayResults(name + "_total", total_laps_per_second); DisplayResults(name + "_worst", min_laps_per_second); @@ -449,7 +459,7 @@ } class PartitionAllocMemoryAllocationPerfTest - : public testing::TestWithParam<std::tuple<int, bool, AllocatorType>> { + : public testing::TestWithParam<std::tuple<int, AllocatorType>> { #if PA_CONFIG(ENABLE_SHADOW_METADATA) void SetUp() override { PartitionRoot::EnableShadowMetadata( @@ -466,64 +476,63 @@ PartitionAllocMemoryAllocationPerfTest, ::testing::Combine( ::testing::Values(1, 2, 3, 4), - ::testing::Values(false, true), ::testing::Values( AllocatorType::kSystem, AllocatorType::kPartitionAlloc, - AllocatorType::kPartitionAllocWithThreadCache + AllocatorType::kPartitionAllocWithThreadCache, + AllocatorType::kPartitionAllocWithThreadCacheAndDenserBucketDist #if BUILDFLAG(ENABLE_ALLOCATION_STACK_TRACE_RECORDER) , AllocatorType::kPartitionAllocWithAllocationStackTraceRecorder #endif - ))); + )), + [](const testing::TestParamInfo< + PartitionAllocMemoryAllocationPerfTest::ParamType>& info) { + return MakeTestName(std::get<0>(info.param), std::get<1>(info.param)); + }); // This test (and the other one below) allocates a large amount of memory, which // can cause issues on Android. #if !defined(MEMORY_CONSTRAINED) TEST_P(PartitionAllocMemoryAllocationPerfTest, SingleBucket) { auto params = GetParam(); - RunTest(std::get<int>(params), std::get<bool>(params), - std::get<AllocatorType>(params), SingleBucket, nullptr, - "SingleBucket"); + RunTest(std::get<int>(params), std::get<AllocatorType>(params), SingleBucket, + nullptr, "SingleBucket"); } #endif // defined(MEMORY_CONSTRAINED) TEST_P(PartitionAllocMemoryAllocationPerfTest, SingleBucketWithFree) { auto params = GetParam(); - RunTest(std::get<int>(params), std::get<bool>(params), - std::get<AllocatorType>(params), SingleBucketWithFree, nullptr, - "SingleBucketWithFree"); + RunTest(std::get<int>(params), std::get<AllocatorType>(params), + SingleBucketWithFree, nullptr, "SingleBucketWithFree"); } #if !defined(MEMORY_CONSTRAINED) TEST_P(PartitionAllocMemoryAllocationPerfTest, MultiBucket) { auto params = GetParam(); - RunTest(std::get<int>(params), std::get<bool>(params), - std::get<AllocatorType>(params), MultiBucket, nullptr, "MultiBucket"); + RunTest(std::get<int>(params), std::get<AllocatorType>(params), MultiBucket, + nullptr, "MultiBucket"); } #endif // defined(MEMORY_CONSTRAINED) TEST_P(PartitionAllocMemoryAllocationPerfTest, MultiBucketWithFree) { auto params = GetParam(); - RunTest(std::get<int>(params), std::get<bool>(params), - std::get<AllocatorType>(params), MultiBucketWithFree, nullptr, - "MultiBucketWithFree"); + RunTest(std::get<int>(params), std::get<AllocatorType>(params), + MultiBucketWithFree, nullptr, "MultiBucketWithFree"); } TEST_P(PartitionAllocMemoryAllocationPerfTest, DirectMapped) { auto params = GetParam(); - RunTest(std::get<int>(params), std::get<bool>(params), - std::get<AllocatorType>(params), DirectMapped, nullptr, - "DirectMapped"); + RunTest(std::get<int>(params), std::get<AllocatorType>(params), DirectMapped, + nullptr, "DirectMapped"); } #if !defined(MEMORY_CONSTRAINED) TEST_P(PartitionAllocMemoryAllocationPerfTest, DISABLED_MultiBucketWithNoisyNeighbor) { auto params = GetParam(); - RunTest(std::get<int>(params), std::get<bool>(params), - std::get<AllocatorType>(params), MultiBucket, DirectMapped, - "MultiBucketWithNoisyNeighbor"); + RunTest(std::get<int>(params), std::get<AllocatorType>(params), MultiBucket, + DirectMapped, "MultiBucketWithNoisyNeighbor"); } #endif // !defined(MEMORY_CONSTRAINED)
diff --git a/base/android/base_feature_map.cc b/base/android/base_feature_map.cc index c1cfeb15..f6c4c746 100644 --- a/base/android/base_feature_map.cc +++ b/base/android/base_feature_map.cc
@@ -19,6 +19,7 @@ &features::kBackgroundNotPerceptibleBinding, &features::kPostPowerMonitorBroadcastReceiverInitToBackground, &features::kPostGetMyMemoryStateToBackground, + &features::kUpdateStateBeforeUnbinding, &features::kUseSharedRebindServiceConnection, };
diff --git a/base/android/java/src/org/chromium/base/BaseFeatureList.java b/base/android/java/src/org/chromium/base/BaseFeatureList.java index e1750dbbb..b5e58d5 100644 --- a/base/android/java/src/org/chromium/base/BaseFeatureList.java +++ b/base/android/java/src/org/chromium/base/BaseFeatureList.java
@@ -11,6 +11,12 @@ public class BaseFeatureList { private BaseFeatureList() {} + public static final MutableFlagWithSafeDefault sUpdateStateBeforeUnbinding = + new MutableFlagWithSafeDefault( + BaseFeatureMap.getInstance(), + BaseFeatures.UPDATE_STATE_BEFORE_UNBINDING, + false); + public static final MutableFlagWithSafeDefault sUseSharedRebindServiceConnection = new MutableFlagWithSafeDefault( BaseFeatureMap.getInstance(),
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java index 3fca572..08883be 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
@@ -1094,15 +1094,22 @@ mService = null; mConnectionParams = null; mUnbound = true; - mStrongBinding.unbindServiceConnection(); + if (BaseFeatureList.sUpdateStateBeforeUnbinding.isEnabled()) { + // Update binding state to ChildBindingState.UNBOUND before unbinding + // actual bindings below. + updateBindingState(); + } + mStrongBinding.unbindServiceConnection(null); // We must clear shared waived binding when we unbind a waived binding. clearSharedWaivedBinding(); - mWaivedBinding.unbindServiceConnection(); + mWaivedBinding.unbindServiceConnection(null); if (mNotPerceptibleBinding != null) { - mNotPerceptibleBinding.unbindServiceConnection(); + mNotPerceptibleBinding.unbindServiceConnection(null); } - mVisibleBinding.unbindServiceConnection(); - updateBindingState(); + mVisibleBinding.unbindServiceConnection(null); + if (!BaseFeatureList.sUpdateStateBeforeUnbinding.isEnabled()) { + updateBindingState(); + } if (mMemoryPressureCallback != null) { final MemoryPressureCallback callback = mMemoryPressureCallback; @@ -1171,8 +1178,12 @@ assert mStrongBindingCount > 0; mStrongBindingCount--; if (mStrongBindingCount == 0) { - mStrongBinding.unbindServiceConnection(); - updateBindingState(); + if (BaseFeatureList.sUpdateStateBeforeUnbinding.isEnabled()) { + mStrongBinding.unbindServiceConnection(() -> updateBindingState()); + } else { + mStrongBinding.unbindServiceConnection(null); + updateBindingState(); + } } } @@ -1207,8 +1218,12 @@ assert mVisibleBindingCount > 0; mVisibleBindingCount--; if (mVisibleBindingCount == 0) { - mVisibleBinding.unbindServiceConnection(); - updateBindingState(); + if (BaseFeatureList.sUpdateStateBeforeUnbinding.isEnabled()) { + mVisibleBinding.unbindServiceConnection(() -> updateBindingState()); + } else { + mVisibleBinding.unbindServiceConnection(null); + updateBindingState(); + } } } @@ -1245,8 +1260,13 @@ assert mNotPerceptibleBindingCount > 0; mNotPerceptibleBindingCount--; if (mNotPerceptibleBindingCount == 0) { - assumeNonNull(mNotPerceptibleBinding).unbindServiceConnection(); - updateBindingState(); + if (BaseFeatureList.sUpdateStateBeforeUnbinding.isEnabled()) { + assumeNonNull(mNotPerceptibleBinding) + .unbindServiceConnection(() -> updateBindingState()); + } else { + assumeNonNull(mNotPerceptibleBinding).unbindServiceConnection(null); + updateBindingState(); + } } }
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java index aca11232..c6701a7 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java
@@ -5,13 +5,20 @@ package org.chromium.base.process_launcher; import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; /** Interface representing a connection to the Android service. Can be mocked in unit-tests. */ @NullMarked /* package */ interface ChildServiceConnection { boolean bindServiceConnection(); - void unbindServiceConnection(); + /** + * Unbinds the underlying service connection. + * + * @param onUnbindCallback A callback to be run after isBound() become false and before the + * service is unbound. + */ + void unbindServiceConnection(@Nullable Runnable onStateChangeCallback); boolean isBound();
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java index 73375d08..564e3b9 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java
@@ -70,10 +70,13 @@ } @Override - public void unbindServiceConnection() { + public void unbindServiceConnection(@Nullable Runnable onStateChangeCallback) { if (mBound) { - mContext.unbindService(this); mBound = false; + if (onStateChangeCallback != null) { + onStateChangeCallback.run(); + } + mContext.unbindService(this); } } @@ -109,7 +112,7 @@ @Override public void retire() { mDelegate = null; - unbindServiceConnection(); + unbindServiceConnection(null); } @Override
diff --git a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java index d16d4c5..3d1c53c 100644 --- a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java +++ b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
@@ -44,6 +44,7 @@ import org.chromium.base.ChildBindingState; import org.chromium.base.library_loader.IRelroLibInfo; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.build.annotations.Nullable; import java.util.ArrayList; @@ -73,8 +74,11 @@ } @Override - public void unbindServiceConnection() { + public void unbindServiceConnection(@Nullable Runnable onStateChangeCallback) { mBound = false; + if (onStateChangeCallback != null) { + onStateChangeCallback.run(); + } } @Override @@ -604,11 +608,96 @@ // Kill and verify state. connection.kill(); verify(mIChildProcessService).forceKill(); + assertEquals(ChildBindingState.UNBOUND, connection.bindingStateCurrent()); assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrentOrWhenDied()); Assert.assertTrue(connection.isKilledByUs()); } @Test + public void testBindingDowngrade() throws RemoteException { + ChildProcessConnection connection = createDefaultTestConnection(); + assertNotNull(mFirstServiceConnection); + connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); + mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder); + connection.setupConnection( + /* childProcessArgs= */ null, + /* clientInterfaces= */ null, + /* binderBox= */ null, + mConnectionCallback, + /* zygoteInfoCallback= */ null); + verify(mConnectionCallback, never()).onConnected(any()); + ShadowLooper.runUiThreadTasks(); + assertNotNull(mConnectionParentProcess); + sendPid(34); + verify(mConnectionCallback, times(1)).onConnected(connection); + connection.removeVisibleBinding(); + + // Add all bindings + connection.addStrongBinding(); + connection.addVisibleBinding(); + if (ChildProcessConnection.supportNotPerceptibleBinding()) { + connection.addNotPerceptibleBinding(); + } + assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrentOrWhenDied()); + + // Remove binding from the highest. + connection.removeStrongBinding(); + assertEquals(ChildBindingState.VISIBLE, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.VISIBLE, connection.bindingStateCurrentOrWhenDied()); + connection.removeVisibleBinding(); + if (ChildProcessConnection.supportNotPerceptibleBinding()) { + assertEquals(ChildBindingState.NOT_PERCEPTIBLE, connection.bindingStateCurrent()); + assertEquals( + ChildBindingState.NOT_PERCEPTIBLE, connection.bindingStateCurrentOrWhenDied()); + + connection.removeNotPerceptibleBinding(); + } + assertEquals(ChildBindingState.WAIVED, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.WAIVED, connection.bindingStateCurrentOrWhenDied()); + + // Add all bindings + connection.addStrongBinding(); + connection.addVisibleBinding(); + if (ChildProcessConnection.supportNotPerceptibleBinding()) { + connection.addNotPerceptibleBinding(); + } + assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrentOrWhenDied()); + + // Remove the binding in the middle priority. + connection.removeVisibleBinding(); + assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrentOrWhenDied()); + connection.removeStrongBinding(); + if (ChildProcessConnection.supportNotPerceptibleBinding()) { + assertEquals(ChildBindingState.NOT_PERCEPTIBLE, connection.bindingStateCurrent()); + assertEquals( + ChildBindingState.NOT_PERCEPTIBLE, connection.bindingStateCurrentOrWhenDied()); + + connection.removeNotPerceptibleBinding(); + } + assertEquals(ChildBindingState.WAIVED, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.WAIVED, connection.bindingStateCurrentOrWhenDied()); + + // Add strong binding only + connection.addStrongBinding(); + assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.STRONG, connection.bindingStateCurrentOrWhenDied()); + // Remove the strong binding + connection.removeStrongBinding(); + assertEquals(ChildBindingState.WAIVED, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.WAIVED, connection.bindingStateCurrentOrWhenDied()); + + // Kill and verify state from waived binding only. + connection.kill(); + verify(mIChildProcessService).forceKill(); + assertEquals(ChildBindingState.UNBOUND, connection.bindingStateCurrent()); + assertEquals(ChildBindingState.WAIVED, connection.bindingStateCurrentOrWhenDied()); + Assert.assertTrue(connection.isKilledByUs()); + } + + @Test public void testUpdateGroupImportanceSmoke() throws RemoteException { ChildProcessConnection connection = createDefaultTestConnection(); connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null);
diff --git a/base/containers/auto_spanification_helper.h b/base/containers/auto_spanification_helper.h index 155d50d..7a8d677 100644 --- a/base/containers/auto_spanification_helper.h +++ b/base/containers/auto_spanification_helper.h
@@ -24,6 +24,19 @@ return sizeof(Element) * N; } +// This helper is used to rewrite code that passes the address of a single +// variable or object member (e.g. `&my_var` or `&obj.member`) to a function +// that expects a `span` representing a single element. +// +// WARNING: This function should only be used by the auto-spanification tool. +// Do not use this helper outside of the tool. +template <typename T> +span<T, 1> SpanFromSingleElement(T& ref) { + // This is a single element and the address is always valid as long as the + // reference is valid. + return UNSAFE_TODO(span<T, 1u>(&ref, 1u)); +} + // Modifies the input span by removing its first element (if not empty) // and returns the modified span. // Used to rewrite pre-increment (++ptr).
diff --git a/base/features.cc b/base/features.cc index a5c96cba..f75a71a 100644 --- a/base/features.cc +++ b/base/features.cc
@@ -133,6 +133,11 @@ "PostGetMyMemoryStateToBackground", FEATURE_ENABLED_BY_DEFAULT); +// Update child process binding state before unbinding. +BASE_FEATURE(kUpdateStateBeforeUnbinding, + "UpdateStateBeforeUnbinding", + FEATURE_DISABLED_BY_DEFAULT); + // Use shared service connection to rebind a service binding to update the LRU // in the ProcessList of OomAdjuster. BASE_FEATURE(kUseSharedRebindServiceConnection,
diff --git a/base/features.h b/base/features.h index 6d13f4a..b745510 100644 --- a/base/features.h +++ b/base/features.h
@@ -43,6 +43,7 @@ BASE_EXPORT BASE_DECLARE_FEATURE( kPostPowerMonitorBroadcastReceiverInitToBackground); BASE_EXPORT BASE_DECLARE_FEATURE(kPostGetMyMemoryStateToBackground); +BASE_EXPORT BASE_DECLARE_FEATURE(kUpdateStateBeforeUnbinding); BASE_EXPORT BASE_DECLARE_FEATURE(kUseSharedRebindServiceConnection); BASE_EXPORT BASE_DECLARE_FEATURE(kBackgroundThreadPoolFieldTrial);
diff --git a/base/memory/raw_ptr.md b/base/memory/raw_ptr.md index 9ab540d..62870e2 100644 --- a/base/memory/raw_ptr.md +++ b/base/memory/raw_ptr.md
@@ -94,7 +94,7 @@ Make sure to look at [the "Extra pointer rules" section](#Extra-pointer-rules) before resorting to this exclusion. -- [RawPtrManualPathsToIgnore.h](../../tools/clang/plugins/RawPtrManualPathsToIgnore.h) +- [RawPtrManualPathsToIgnore.h](../../tools/clang/raw_ptr_plugin/RawPtrManualPathsToIgnore.h) to exclude at a directory level (NOTE, use it as last resort, and be aware it'll require a Clang plugin roll). Examples: - Renderer-only code (i.e. code in paths that contain `/renderer/` or
diff --git a/base/test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java b/base/test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java index 9fe0b962..fa76734 100644 --- a/base/test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java +++ b/base/test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java
@@ -8,6 +8,8 @@ import android.content.Intent; import android.os.Bundle; +import org.chromium.build.annotations.Nullable; + /** An implementation of ChildProcessConnection that does not connect to a real service. */ public class TestChildProcessConnection extends ChildProcessConnection { private static class MockChildServiceConnection implements ChildServiceConnection { @@ -20,8 +22,11 @@ } @Override - public void unbindServiceConnection() { + public void unbindServiceConnection(@Nullable Runnable onStateChangeCallback) { mBound = false; + if (onStateChangeCallback != null) { + onStateChangeCallback.run(); + } } @Override
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 031b87d..ada28949 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -540,36 +540,15 @@ } DEFAULT_MODULE_DEPS = [ - "//buildtools/third_party/libc++:_Builtin_float", "//buildtools/third_party/libc++:_Builtin_intrinsics", - "//buildtools/third_party/libc++:_Builtin_inttypes", "//buildtools/third_party/libc++:_Builtin_limits", - "//buildtools/third_party/libc++:_Builtin_stdalign", "//buildtools/third_party/libc++:_Builtin_stdarg", - "//buildtools/third_party/libc++:_Builtin_stdatomic", "//buildtools/third_party/libc++:_Builtin_stdbool", - "//buildtools/third_party/libc++:_Builtin_stddef", "//buildtools/third_party/libc++:_Builtin_stdint", "//buildtools/third_party/libc++:_Builtin_unwind", "//buildtools/third_party/libc++:std", - "//buildtools/third_party/libc++:std_config", - "//buildtools/third_party/libc++:std_core", - "//buildtools/third_party/libc++:std_ctype_h", - "//buildtools/third_party/libc++:std_errno_h", - "//buildtools/third_party/libc++:std_fenv_h", - "//buildtools/third_party/libc++:std_float_h", - "//buildtools/third_party/libc++:std_inttypes_h", - "//buildtools/third_party/libc++:std_math_h", - "//buildtools/third_party/libc++:std_private_mbstate_t", "//buildtools/third_party/libc++:std_stdatomic_h", - "//buildtools/third_party/libc++:std_stdbool_h", - "//buildtools/third_party/libc++:std_string_h", - "//buildtools/third_party/libc++:std_uchar_h", - "//buildtools/third_party/libc++:std_wchar_h", - "//buildtools/third_party/libc++:std_wctype_h", - "//buildtools/third_party/libc++:sysroot_bits", "//buildtools/third_party/libc++:sysroot_features", - "//buildtools/third_party/libc++:sysroot_time", "//buildtools/third_party/libc++:sysroot_types", ]
diff --git a/buildtools/third_party/libc++/BUILD.gn b/buildtools/third_party/libc++/BUILD.gn index 1e2cb5c..88aefac1 100644 --- a/buildtools/third_party/libc++/BUILD.gn +++ b/buildtools/third_party/libc++/BUILD.gn
@@ -89,8 +89,6 @@ sysroot_modules("sysroot_types") { public_deps = [ - ":_Builtin_stddef", - ":std_config", ":sysroot_bits", ":sysroot_features", ":sysroot_time", @@ -120,7 +118,6 @@ } builtin_modules("_Builtin_inttypes") { - public_deps = [ ":_Builtin_stdint" ] } builtin_modules("_Builtin_limits") { @@ -134,10 +131,6 @@ } builtin_modules("_Builtin_stdatomic") { - public_deps = [ - ":_Builtin_stddef", - ":_Builtin_stdint", - ] } builtin_modules("_Builtin_stdbool") { @@ -198,9 +191,6 @@ libcxx_modules("std") { public_deps = [ - ":_Builtin_stdarg", - ":_Builtin_stddef", - ":std_config", ":std_core", ":std_ctype_h", ":std_errno_h", @@ -211,12 +201,7 @@ ":std_private_mbstate_t", ":std_string_h", ":std_uchar_h", - ":std_wchar_h", ":std_wctype_h", - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ":sysroot_types", ] } @@ -224,11 +209,6 @@ } libcxx_modules("std_core") { - public_deps = [ - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ] } libcxx_modules("std_ctype_h") { @@ -244,40 +224,16 @@ } libcxx_modules("std_inttypes_h") { - public_deps = [ - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ] } libcxx_modules("std_math_h") { - public_deps = [ - ":std_core", - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ] + public_deps = [ ":std_core" ] } libcxx_modules("std_private_mbstate_t") { - public_deps = [ - ":_Builtin_stdarg", - ":_Builtin_stddef", - ":std_config", - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ":sysroot_types", - ] } libcxx_modules("std_stdatomic_h") { - public_deps = [ - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ] } libcxx_modules("std_stdbool_h") { @@ -290,30 +246,10 @@ } libcxx_modules("std_uchar_h") { - public_deps = [ - ":_Builtin_stddef", - ":std_config", - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ":sysroot_types", - ] - if (is_mac) { - public_deps += [ ":std_private_mbstate_t" ] - } + public_deps = [ ":std_private_mbstate_t" ] } libcxx_modules("std_wchar_h") { - public_deps = [ - ":_Builtin_stdarg", - ":_Builtin_stddef", - ":std_config", - ":std_private_mbstate_t", - ":sysroot_bits", - ":sysroot_features", - ":sysroot_time", - ":sysroot_types", - ] } libcxx_modules("std_wctype_h") {
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index 45835b8..2c684f7 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -1314,9 +1314,6 @@ !layer_tree_impl()->IsReadyToActivate()); return true; } - // We can recreate the tiling if we would invalidate all of its tiles. - if (high_res.may_contain_low_resolution_tiles()) - return true; // Keep the non-ideal raster translation unchanged for transform animations // to avoid re-rasterization during animation. if (draw_properties().screen_space_transform_is_animating || @@ -1397,13 +1394,6 @@ // We always need a high res tiling, so create one if it doesn't exist. high_res = AddTiling(gfx::AxisTransform2d::FromScaleAndTranslation( raster_contents_scale_, raster_translation)); - } else if (high_res->may_contain_low_resolution_tiles()) { - // If the tiling we find here was LOW_RESOLUTION previously, it may not be - // fully rastered, so destroy the old tiles. - high_res->Reset(); - // Reset the flag now that we'll make it high res, it will have fully - // rastered content. - high_res->reset_may_contain_low_resolution_tiles(); } high_res->set_resolution(HIGH_RESOLUTION);
diff --git a/cc/tiles/picture_layer_tiling.h b/cc/tiles/picture_layer_tiling.h index 7f1e62e..92395953 100644 --- a/cc/tiles/picture_layer_tiling.h +++ b/cc/tiles/picture_layer_tiling.h
@@ -123,12 +123,6 @@ resolution_ = resolution; } TileResolution resolution() const { return resolution_; } - bool may_contain_low_resolution_tiles() const { - return may_contain_low_resolution_tiles_; - } - void reset_may_contain_low_resolution_tiles() { - may_contain_low_resolution_tiles_ = false; - } void set_can_require_tiles_for_activation(bool can_require_tiles) { can_require_tiles_for_activation_ = can_require_tiles; } @@ -455,7 +449,6 @@ const float min_preraster_distance_; const float max_preraster_distance_; TileResolution resolution_ = NON_IDEAL_RESOLUTION; - bool may_contain_low_resolution_tiles_ = false; // Internal data. TilingData tiling_data_{gfx::Size(), gfx::Rect(), kBorderTexels};
diff --git a/cc/tiles/picture_layer_tiling_set.cc b/cc/tiles/picture_layer_tiling_set.cc index 34386f9a..d5c8601 100644 --- a/cc/tiles/picture_layer_tiling_set.cc +++ b/cc/tiles/picture_layer_tiling_set.cc
@@ -611,7 +611,6 @@ // compute them only when the tiling set has changed instead. size_t tilings_size = tilings_.size(); TilingRange high_res_range(0, 0); - TilingRange low_res_range(tilings_size, tilings_size); for (size_t i = 0; i < tilings_size; ++i) { const PictureLayerTiling* tiling = tilings_[i].get(); if (tiling->resolution() == HIGH_RESOLUTION) @@ -627,22 +626,7 @@ range = high_res_range; break; case BETWEEN_HIGH_AND_LOW_RES: - // TODO(vmpstr): This code assumes that high res tiling will come before - // low res tiling, however there are cases where this assumption is - // violated. As a result, it's better to be safe in these situations, - // since otherwise we can end up accessing a tiling that doesn't exist. - // See crbug.com/429397 for high res tiling appearing after low res - // tiling discussion/fixes. - if (high_res_range.start <= low_res_range.start) - range = TilingRange(high_res_range.end, low_res_range.start); - else - range = TilingRange(low_res_range.end, high_res_range.start); - break; - case LOW_RES: - range = low_res_range; - break; - case LOWER_THAN_LOW_RES: - range = TilingRange(low_res_range.end, tilings_size); + range = TilingRange(high_res_range.end, tilings_size); break; }
diff --git a/cc/tiles/picture_layer_tiling_set.h b/cc/tiles/picture_layer_tiling_set.h index d817df2..f3e2a67 100644 --- a/cc/tiles/picture_layer_tiling_set.h +++ b/cc/tiles/picture_layer_tiling_set.h
@@ -32,8 +32,6 @@ HIGHER_THAN_HIGH_RES, HIGH_RES, BETWEEN_HIGH_AND_LOW_RES, - LOW_RES, - LOWER_THAN_LOW_RES }; struct TilingRange { TilingRange(size_t start, size_t end) : start(start), end(end) {}
diff --git a/cc/tiles/picture_layer_tiling_set_unittest.cc b/cc/tiles/picture_layer_tiling_set_unittest.cc index af0e5adc..dea3c88 100644 --- a/cc/tiles/picture_layer_tiling_set_unittest.cc +++ b/cc/tiles/picture_layer_tiling_set_unittest.cc
@@ -97,14 +97,6 @@ EXPECT_EQ(2u, between_high_and_low_res_range.start); EXPECT_EQ(4u, between_high_and_low_res_range.end); - low_res_range = - set_without_low_res->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(0u, low_res_range.end - low_res_range.start); - - lower_than_low_res_range = set_without_low_res->GetTilingRange( - PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); - std::unique_ptr<TestablePictureLayerTilingSet> set_with_only_high_res = CreateTilingSet(&client); high_res_tiling = @@ -125,14 +117,6 @@ PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); EXPECT_EQ(0u, between_high_and_low_res_range.end - between_high_and_low_res_range.start); - - low_res_range = - set_with_only_high_res->GetTilingRange(PictureLayerTilingSet::LOW_RES); - EXPECT_EQ(0u, low_res_range.end - low_res_range.start); - - lower_than_low_res_range = set_with_only_high_res->GetTilingRange( - PictureLayerTilingSet::LOWER_THAN_LOW_RES); - EXPECT_EQ(0u, lower_than_low_res_range.end - lower_than_low_res_range.start); } class PictureLayerTilingSetTestWithResources : public testing::Test {
diff --git a/cc/tiles/tiling_set_eviction_queue.cc b/cc/tiles/tiling_set_eviction_queue.cc index e3c80a9..dd0decc1 100644 --- a/cc/tiles/tiling_set_eviction_queue.cc +++ b/cc/tiles/tiling_set_eviction_queue.cc
@@ -44,14 +44,6 @@ tilings_.push_back(tiling); } - range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOWER_THAN_LOW_RES); - for (size_t i = range.start; i < range.end; ++i) { - size_t index = range.start + (range.end - 1 - i); - PictureLayerTiling* tiling = tiling_set->tiling_at(index); - if (tiling->has_tiles()) - tilings_.push_back(tiling); - } - range = tiling_set->GetTilingRange( PictureLayerTilingSet::BETWEEN_HIGH_AND_LOW_RES); for (size_t i = range.start; i < range.end; ++i) { @@ -61,13 +53,6 @@ tilings_.push_back(tiling); } - range = tiling_set->GetTilingRange(PictureLayerTilingSet::LOW_RES); - for (size_t index = range.start; index < range.end; ++index) { - PictureLayerTiling* tiling = tiling_set->tiling_at(index); - if (tiling->has_tiles()) - tilings_.push_back(tiling); - } - range = tiling_set->GetTilingRange(PictureLayerTilingSet::HIGH_RES); for (size_t index = range.start; index < range.end; ++index) { PictureLayerTiling* tiling = tiling_set->tiling_at(index);
diff --git a/chrome/VERSION b/chrome/VERSION index cc4fd5a3..21c4eb4 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=139 MINOR=0 -BUILD=7256 +BUILD=7257 PATCH=0
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java index 622498e..607c9a6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java
@@ -15,6 +15,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewStub; +import android.view.Window; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -26,6 +27,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.ui.edge_to_edge.EdgeToEdgeUtils; +import org.chromium.components.browser_ui.edge_to_edge.EdgeToEdgeStateProvider; import org.chromium.components.browser_ui.widget.ContextMenuDialog; import org.chromium.components.embedder_support.contextmenu.ChipDelegate; import org.chromium.components.embedder_support.contextmenu.ChipRenderParams; @@ -106,6 +108,35 @@ dismissDialog(); } + // Calculate true top content offset to be used to compute the AnchorRect used by + // AnchoredPopupWindow, with origin below the system decoration which may or may not be merged + // with the tabstrip. + private static float topContentOffset(float offset, WindowAndroid windowAndroid) { + // If edge-to-edge mode is disabled, the input offset i.e. height of tabstrip plus toolbar + // is correct. + if (!EdgeToEdgeStateProvider.isEdgeToEdgeEnabledForWindow(windowAndroid)) return offset; + + // Otherwise, the system decoration is tabstrip, so the input offset should only be height + // of toolbar. + // Compute the height of system decoration to get height of tabstrip, and subtract it from + // the input offset. + Window window = windowAndroid.getWindow(); + if (window == null) return offset; + View view = window.getDecorView(); + // The rect of the window without system decoration, see + // https://developer.android.com/reference/android/view/View#getWindowVisibleDisplayFrame(android.graphics.Rect) + Rect windowVisibleRect = new Rect(); + view.getWindowVisibleDisplayFrame(windowVisibleRect); + // The coordinates of the window root (with system decoration), see + // https://developer.android.com/reference/android/view/View#getLocationOnScreen(int[]) + int[] windowRootCoordinates = new int[2]; + view.getLocationOnScreen(windowRootCoordinates); + // Difference of the two top-left y-coordinates is the height of the system decoration. + float systemDecorHeight = windowVisibleRect.top - windowRootCoordinates[1]; + + return offset - systemDecorHeight; + } + // Shows the menu with chip. void displayMenuWithChip( final WindowAndroid window, @@ -147,7 +178,7 @@ window.getWindow(), webContents, params, - mTopContentOffsetPx, + topContentOffset(mTopContentOffsetPx, window), usePopupWindow, layout); boolean shouldRemoveScrim = ContextMenuUtils.isPopupSupported(activity);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java index 65b9922..a7c642d5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webauth/Fido2CredentialRequestTest.java
@@ -108,7 +108,6 @@ import org.chromium.content_public.browser.test.mock.MockRenderFrameHost; import org.chromium.content_public.browser.test.mock.MockWebContents; import org.chromium.content_public.common.ContentSwitches; -import org.chromium.device.DeviceFeatureList; import org.chromium.net.test.EmbeddedTestServer; import org.chromium.ui.test.util.GmsCoreVersionRestriction; import org.chromium.url.GURL; @@ -2705,7 +2704,6 @@ @Test @SmallTest @UseMethodParameter(SameOriginTestParams.class) - @EnableFeatures(DeviceFeatureList.WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS) public void testMakeCredential_remoteDesktopClientOverride_generatesCorrectClientDataJson( boolean sameOriginWithAncestors) { mIntentSender.setNextResultIntent( @@ -2769,7 +2767,6 @@ @Test @SmallTest @UseMethodParameter(SameOriginTestParams.class) - @EnableFeatures(DeviceFeatureList.WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS) public void testGetAssertion_remoteDesktopClientOverride_generatesCorrectClientDataJson( boolean sameOriginWithAncestors) { mIntentSender.setNextResultIntent(Fido2ApiTestHelper.createSuccessfulGetAssertionIntent());
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index d7c51be..4b850185 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -7813,14 +7813,19 @@ "//services/accessibility/public/mojom", "//ui/events/ozone/layout:layout", - # TODO(crbug.com/40227502): Currently EnterpriseDeviceAttributes - # internally uses profile manager. We should get rid of it. + # For allow_circular_includes_from below. + "//chrome/browser/chromeos/extensions/login_screen/login", "//chrome/browser/extensions/api/enterprise_device_attributes", + "//chrome/browser/extensions/api/enterprise_login", ] allow_circular_includes_from += [ # TODO(crbug.com/40227502): Currently EnterpriseDeviceAttributes # internally uses profile manager. We should get rid of it. "//chrome/browser/extensions/api/enterprise_device_attributes", + + # For chrome::AttemptUserExit(). + "//chrome/browser/chromeos/extensions/login_screen/login", + "//chrome/browser/extensions/api/enterprise_login", ] } }
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 48cbba3..f032d34d 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4856,6 +4856,9 @@ {"webrtc-hw-encoding", flag_descriptions::kWebrtcHwEncodingName, flag_descriptions::kWebrtcHwEncodingDescription, kOsAndroid | kOsCrOS, FEATURE_VALUE_TYPE(features::kWebRtcHWEncoding)}, + {"webrtc-pqc-for-dtls", flag_descriptions::kWebRtcPqcForDtlsName, + flag_descriptions::kWebRtcPqcForDtlsDescription, kOsAll, + FEATURE_VALUE_TYPE(blink::features::kWebRtcPqcForDtls)}, {"enable-webrtc-allow-input-volume-adjustment", flag_descriptions::kWebRtcAllowInputVolumeAdjustmentName, flag_descriptions::kWebRtcAllowInputVolumeAdjustmentDescription,
diff --git a/chrome/browser/ash/account_manager/BUILD.gn b/chrome/browser/ash/account_manager/BUILD.gn index 37d4f9d..219347b 100644 --- a/chrome/browser/ash/account_manager/BUILD.gn +++ b/chrome/browser/ash/account_manager/BUILD.gn
@@ -14,7 +14,6 @@ "account_apps_availability_factory.h", "account_manager_edu_coexistence_controller.cc", "account_manager_edu_coexistence_controller.h", - "account_manager_facade_factory_ash.cc", "account_manager_policy_controller.cc", "account_manager_policy_controller.h", "account_manager_policy_controller_factory.cc",
diff --git a/chrome/browser/ash/account_manager/account_apps_availability_factory.cc b/chrome/browser/ash/account_manager/account_apps_availability_factory.cc index fb3689ce..17c360c 100644 --- a/chrome/browser/ash/account_manager/account_apps_availability_factory.cc +++ b/chrome/browser/ash/account_manager/account_apps_availability_factory.cc
@@ -10,7 +10,7 @@ #include "chrome/browser/ash/account_manager/account_manager_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "components/keyed_service/core/keyed_service.h" #include "content/public/browser/browser_context.h" @@ -55,7 +55,7 @@ return nullptr; return std::make_unique<AccountAppsAvailability>( - ::GetAccountManagerFacade(profile->GetPath().value()), + GetAccountManagerFacade(profile->GetPath().value()), IdentityManagerFactory::GetForProfile(profile), profile->GetPrefs()); }
diff --git a/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc b/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc index c4774c3..f9d9847c 100644 --- a/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc +++ b/chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller_unittest.cc
@@ -18,12 +18,12 @@ #include "chrome/browser/ui/webui/ash/edu_coexistence/edu_coexistence_login_handler.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" #include "components/account_id/account_id.h" #include "components/account_manager_core/account.h" #include "components/account_manager_core/account_manager_facade.h" #include "components/account_manager_core/chromeos/account_manager.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_task_environment.h" #include "google_apis/gaia/gaia_id.h" @@ -117,7 +117,7 @@ ->GetAccountManagerFactory() ->GetAccountManager(profile()->GetPath().value()); account_manager_facade_ = - ::GetAccountManagerFacade(profile()->GetPath().value()); + GetAccountManagerFacade(profile()->GetPath().value()); AddAccount(account_manager(), kPrimaryAccount, kPrimaryAccountGaiaId); }
diff --git a/chrome/browser/ash/account_manager/account_manager_policy_controller.cc b/chrome/browser/ash/account_manager/account_manager_policy_controller.cc index 15694252..21e0344 100644 --- a/chrome/browser/ash/account_manager/account_manager_policy_controller.cc +++ b/chrome/browser/ash/account_manager/account_manager_policy_controller.cc
@@ -12,9 +12,9 @@ #include "chrome/browser/ash/account_manager/account_manager_edu_coexistence_controller.h" #include "chrome/browser/ash/account_manager/account_manager_util.h" #include "chrome/browser/profiles/profile.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "components/account_manager_core/account_manager_facade.h" #include "components/account_manager_core/chromeos/account_manager.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/account_manager_core/pref_names.h" #include "components/prefs/pref_service.h" #include "google_apis/gaia/gaia_id.h"
diff --git a/chrome/browser/ash/account_manager/account_manager_policy_controller_browsertest.cc b/chrome/browser/ash/account_manager/account_manager_policy_controller_browsertest.cc index b3219d4..c4dfe37 100644 --- a/chrome/browser/ash/account_manager/account_manager_policy_controller_browsertest.cc +++ b/chrome/browser/ash/account_manager/account_manager_policy_controller_browsertest.cc
@@ -23,13 +23,13 @@ #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" #include "components/account_id/account_id.h" #include "components/account_manager_core/account.h" #include "components/account_manager_core/account_manager_facade.h" #include "components/account_manager_core/chromeos/account_manager.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/account_manager_core/pref_names.h" #include "components/session_manager/core/session_manager.h" #include "components/signin/public/base/consent_level.h" @@ -91,7 +91,7 @@ g_browser_process->platform_part()->GetAccountManagerFactory(); account_manager_ = factory->GetAccountManager(profile()->GetPath().value()); account_manager_facade_ = - ::GetAccountManagerFacade(profile()->GetPath().value()); + GetAccountManagerFacade(profile()->GetPath().value()); identity_test_environment_adaptor_ = std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get());
diff --git a/chrome/browser/ash/account_manager/account_manager_policy_controller_factory.cc b/chrome/browser/ash/account_manager/account_manager_policy_controller_factory.cc index 386aa5c..800a641 100644 --- a/chrome/browser/ash/account_manager/account_manager_policy_controller_factory.cc +++ b/chrome/browser/ash/account_manager/account_manager_policy_controller_factory.cc
@@ -7,10 +7,10 @@ #include "base/no_destructor.h" #include "chrome/browser/ash/account_manager/account_manager_policy_controller.h" #include "chrome/browser/profiles/profile.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/user_manager/user.h" namespace ash { @@ -55,7 +55,7 @@ return nullptr; auto* account_manager_facade = - ::GetAccountManagerFacade(profile->GetPath().value()); + GetAccountManagerFacade(profile->GetPath().value()); if (!account_manager_facade) return nullptr;
diff --git a/chrome/browser/ash/ambient/ambient_client_impl_unittest.cc b/chrome/browser/ash/ambient/ambient_client_impl_unittest.cc index 05683a8..19a047f 100644 --- a/chrome/browser/ash/ambient/ambient_client_impl_unittest.cc +++ b/chrome/browser/ash/ambient/ambient_client_impl_unittest.cc
@@ -40,7 +40,7 @@ void SetUp() override { profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &testing_local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); profile_user_manager_controller_ =
diff --git a/chrome/browser/ash/arc/arc_util_unittest.cc b/chrome/browser/ash/arc/arc_util_unittest.cc index 88f68432..d874857 100644 --- a/chrome/browser/ash/arc/arc_util_unittest.cc +++ b/chrome/browser/ash/arc/arc_util_unittest.cc
@@ -154,7 +154,7 @@ ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); profile_ = profile_manager_->CreateTestingProfile(kTestProfileName);
diff --git a/chrome/browser/ash/arc/auth/BUILD.gn b/chrome/browser/ash/arc/auth/BUILD.gn index b93977d..5f5eef9d 100644 --- a/chrome/browser/ash/arc/auth/BUILD.gn +++ b/chrome/browser/ash/arc/auth/BUILD.gn
@@ -34,6 +34,7 @@ "//chrome/browser/ash/profiles", "//chrome/browser/profiles:profile", "//chrome/common", + "//chromeos/ash/components/account_manager", "//chromeos/ash/experiences/arc", "//components/account_manager_core", "//components/prefs",
diff --git a/chrome/browser/ash/arc/auth/arc_auth_service.cc b/chrome/browser/ash/arc/auth/arc_auth_service.cc index dc0b354c..3d5ec1a9 100644 --- a/chrome/browser/ash/arc/auth/arc_auth_service.cc +++ b/chrome/browser/ash/arc/auth/arc_auth_service.cc
@@ -36,6 +36,7 @@ #include "chrome/browser/ui/settings_window_manager_chromeos.h" #include "chrome/browser/ui/webui/signin/ash/inline_login_dialog.h" #include "chrome/common/webui_url_constants.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/experiences/arc/arc_browser_context_keyed_service_factory_base.h" #include "chromeos/ash/experiences/arc/arc_features.h" #include "chromeos/ash/experiences/arc/arc_prefs.h" @@ -45,7 +46,6 @@ #include "chromeos/ash/experiences/arc/session/arc_management_transition.h" #include "chromeos/ash/experiences/arc/session/arc_service_manager.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/prefs/pref_service.h" #include "components/signin/public/base/consent_level.h" #include "components/user_manager/user_manager.h" @@ -507,7 +507,7 @@ void ArcAuthService::HandleAddAccountRequest() { DCHECK(ash::IsAccountManagerAvailable(profile_)); - ::GetAccountManagerFacade(profile_->GetPath().value()) + ash::GetAccountManagerFacade(profile_->GetPath().value()) ->ShowAddAccountDialog( account_manager::AccountManagerFacade::AccountAdditionSource::kArc); } @@ -522,7 +522,7 @@ void ArcAuthService::HandleUpdateCredentialsRequest(const std::string& email) { DCHECK(ash::IsAccountManagerAvailable(profile_)); - ::GetAccountManagerFacade(profile_->GetPath().value()) + ash::GetAccountManagerFacade(profile_->GetPath().value()) ->ShowReauthAccountDialog( account_manager::AccountManagerFacade::AccountAdditionSource::kArc, email, base::DoNothing());
diff --git a/chrome/browser/ash/arc/auth/arc_auth_service_browsertest.cc b/chrome/browser/ash/arc/auth/arc_auth_service_browsertest.cc index 4e9d302..12808f0 100644 --- a/chrome/browser/ash/arc/auth/arc_auth_service_browsertest.cc +++ b/chrome/browser/ash/arc/auth/arc_auth_service_browsertest.cc
@@ -55,6 +55,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" #include "chromeos/ash/components/cryptohome/cryptohome_parameters.h" @@ -68,7 +69,6 @@ #include "chromeos/ash/experiences/arc/test/connection_holder_util.h" #include "chromeos/ash/experiences/arc/test/fake_arc_session.h" #include "components/account_id/account_id.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/policy/core/common/cloud/device_management_service.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "components/policy/core/common/policy_switches.h" @@ -439,7 +439,7 @@ auth_service_->SetURLLoaderFactoryForTesting(test_shared_loader_factory_); arc_availability_setter_ = std::make_unique<AccountAppsAvailabilitySetter>( ash::AccountAppsAvailabilityFactory::GetForProfile(profile()), - ::GetAccountManagerFacade(profile()->GetPath().value())); + ash::GetAccountManagerFacade(profile()->GetPath().value())); arc_bridge_service_ = ArcServiceManager::Get()->arc_bridge_service(); DCHECK(arc_bridge_service_); arc_bridge_service_->auth()->SetInstance(&auth_instance_);
diff --git a/chrome/browser/ash/arc/locked_fullscreen/arc_locked_fullscreen_manager_unittest.cc b/chrome/browser/ash/arc/locked_fullscreen/arc_locked_fullscreen_manager_unittest.cc index 0d91e35..d455f48 100644 --- a/chrome/browser/ash/arc/locked_fullscreen/arc_locked_fullscreen_manager_unittest.cc +++ b/chrome/browser/ash/arc/locked_fullscreen/arc_locked_fullscreen_manager_unittest.cc
@@ -127,8 +127,7 @@ ash::ScopedCrosSettingsTestHelper cros_settings_helper_; ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; std::unique_ptr<user_manager::UserManagerImpl> user_manager_; - TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal(), - &local_state_}; + TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()}; session_manager::SessionManager session_manager_; raw_ptr<TestingProfile> profile_; std::unique_ptr<ArcSessionManager> arc_session_manager_;
diff --git a/chrome/browser/ash/assistant/assistant_util_unittest.cc b/chrome/browser/ash/assistant/assistant_util_unittest.cc index ecf24f86..f65c399 100644 --- a/chrome/browser/ash/assistant/assistant_util_unittest.cc +++ b/chrome/browser/ash/assistant/assistant_util_unittest.cc
@@ -175,7 +175,7 @@ ASSERT_TRUE(data_dir_.CreateUniqueTempDir()); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); profile_ = profile_manager_->CreateTestingProfile(
diff --git a/chrome/browser/ash/crosapi/crosapi_util_unittest.cc b/chrome/browser/ash/crosapi/crosapi_util_unittest.cc index ea5a65f..d40f7bd 100644 --- a/chrome/browser/ash/crosapi/crosapi_util_unittest.cc +++ b/chrome/browser/ash/crosapi/crosapi_util_unittest.cc
@@ -71,7 +71,7 @@ ash::system::StatisticsProvider::SetTestProvider(&statistics_provider_); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); testing_profile_ = profile_manager_->CreateTestingProfile( TestingProfile::kDefaultProfileUserName);
diff --git a/chrome/browser/ash/crosapi/login_ash.cc b/chrome/browser/ash/crosapi/login_ash.cc index ec23138a..9a546e7 100644 --- a/chrome/browser/ash/crosapi/login_ash.cc +++ b/chrome/browser/ash/crosapi/login_ash.cc
@@ -74,34 +74,6 @@ extensions::login_api_errors::kNoManagedGuestSessionAccounts); } -void LoginAsh::ExitCurrentSession( - const std::optional<std::string>& data_for_next_login_attempt, - ExitCurrentSessionCallback callback) { - PrefService* local_state = g_browser_process->local_state(); - DCHECK(local_state); - - if (data_for_next_login_attempt) { - local_state->SetString(prefs::kLoginExtensionApiDataForNextLoginAttempt, - *data_for_next_login_attempt); - } else { - local_state->ClearPref(prefs::kLoginExtensionApiDataForNextLoginAttempt); - } - - chrome::AttemptUserExit(); - std::move(callback).Run(std::nullopt); -} - -void LoginAsh::FetchDataForNextLoginAttempt( - FetchDataForNextLoginAttemptCallback callback) { - PrefService* local_state = g_browser_process->local_state(); - DCHECK(local_state); - std::string data_for_next_login_attempt = - local_state->GetString(prefs::kLoginExtensionApiDataForNextLoginAttempt); - local_state->ClearPref(prefs::kLoginExtensionApiDataForNextLoginAttempt); - - std::move(callback).Run(data_for_next_login_attempt); -} - void LoginAsh::LockManagedGuestSession( LockManagedGuestSessionCallback callback) { ui::UserActivityDetector::Get()->HandleExternalUserActivity(); @@ -225,17 +197,6 @@ weak_factory_.GetWeakPtr(), std::move(callback))); } -void LoginAsh::SetDataForNextLoginAttempt( - const std::string& data_for_next_login_attempt, - SetDataForNextLoginAttemptCallback callback) { - PrefService* local_state = g_browser_process->local_state(); - DCHECK(local_state); - local_state->SetString(prefs::kLoginExtensionApiDataForNextLoginAttempt, - data_for_next_login_attempt); - - std::move(callback).Run(); -} - void LoginAsh::AddExternalLogoutRequestObserver( mojo::PendingRemote<mojom::ExternalLogoutRequestObserver> observer) { mojo::Remote<mojom::ExternalLogoutRequestObserver> remote(
diff --git a/chrome/browser/ash/crosapi/login_ash.h b/chrome/browser/ash/crosapi/login_ash.h index ee2d085..6909129 100644 --- a/chrome/browser/ash/crosapi/login_ash.h +++ b/chrome/browser/ash/crosapi/login_ash.h
@@ -42,18 +42,10 @@ void BindReceiver(mojo::PendingReceiver<mojom::Login> receiver); // crosapi::mojom::Login: - void ExitCurrentSession( - const std::optional<std::string>& data_for_next_login_attempt, - ExitCurrentSessionCallback callback) override; - void FetchDataForNextLoginAttempt( - FetchDataForNextLoginAttemptCallback callback) override; void LockManagedGuestSession( LockManagedGuestSessionCallback callback) override; void LockCurrentSession(LockCurrentSessionCallback callback) override; void EndSharedSession(EndSharedSessionCallback callback) override; - void SetDataForNextLoginAttempt( - const std::string& data_for_next_login_attempt, - SetDataForNextLoginAttemptCallback callback) override; void AddExternalLogoutRequestObserver( mojo::PendingRemote<mojom::ExternalLogoutRequestObserver> observer) override;
diff --git a/chrome/browser/ash/file_manager/path_util_unittest.cc b/chrome/browser/ash/file_manager/path_util_unittest.cc index a6542a82..e1c130c7 100644 --- a/chrome/browser/ash/file_manager/path_util_unittest.cc +++ b/chrome/browser/ash/file_manager/path_util_unittest.cc
@@ -716,7 +716,7 @@ void SetUp() override { fake_user_manager_.Reset(std::make_unique<ash::FakeChromeUserManager>()); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); // Set up fake user manager.
diff --git a/chrome/browser/ash/input_method/japanese/japanese_settings.cc b/chrome/browser/ash/input_method/japanese/japanese_settings.cc index 62d6a98d..4771fd5 100644 --- a/chrome/browser/ash/input_method/japanese/japanese_settings.cc +++ b/chrome/browser/ash/input_method/japanese/japanese_settings.cc
@@ -272,6 +272,7 @@ response->automatically_switch_to_halfwidth = prefs.FindBool(kJpPrefAutomaticallySwitchToHalfwidth) .value_or(response->automatically_switch_to_halfwidth); + RecordJapaneseSettingsMetrics(*response); return response; }
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_impl_unittest.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_impl_unittest.cc index 1296824..2b5f51f 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_impl_unittest.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_impl_unittest.cc
@@ -102,8 +102,7 @@ private: ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; content::BrowserTaskEnvironment task_environment_; - TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal(), - &local_state_}; + TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()}; user_manager::TypedScopedUserManager<FakeChromeUserManager> fake_chrome_user_manager_{std::make_unique<FakeChromeUserManager>()}; raw_ptr<testing::StrictMock<test::MockUserImageLoaderDelegate>>
diff --git a/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc b/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc index 02ffe31..ceb1b3f7 100644 --- a/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc +++ b/chrome/browser/ash/login/users/multi_user_sign_in_policy_controller_unittest.cc
@@ -137,7 +137,7 @@ void SetUp() override { profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); for (const auto& account_id : test_users_) {
diff --git a/chrome/browser/ash/login/users/profile_user_manager_controller_unittest.cc b/chrome/browser/ash/login/users/profile_user_manager_controller_unittest.cc index 8f2ae57..c53b5d20 100644 --- a/chrome/browser/ash/login/users/profile_user_manager_controller_unittest.cc +++ b/chrome/browser/ash/login/users/profile_user_manager_controller_unittest.cc
@@ -51,7 +51,7 @@ // pointer first. std::unique_ptr<ProfileUserManagerController> controller_; TestingProfileManager testing_profile_manager_{ - TestingBrowserProcess::GetGlobal(), &local_state_}; + TestingBrowserProcess::GetGlobal()}; }; TEST_F(ProfileUserManagerControllerTest, GetProfilePrefs) {
diff --git a/chrome/browser/ash/power/extension_event_observer_unittest.cc b/chrome/browser/ash/power/extension_event_observer_unittest.cc index a27dc766..82264c3 100644 --- a/chrome/browser/ash/power/extension_event_observer_unittest.cc +++ b/chrome/browser/ash/power/extension_event_observer_unittest.cc
@@ -57,7 +57,7 @@ testing_local_state_ = std::make_unique<ScopedTestingLocalState>( TestingBrowserProcess::GetGlobal()); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), testing_local_state_.get()); + TestingBrowserProcess::GetGlobal()); // Must be called from ::testing::Test::SetUp. ASSERT_TRUE(profile_manager_->SetUp());
diff --git a/chrome/browser/ash/shimless_rma/chrome_shimless_rma_delegate_unittest.cc b/chrome/browser/ash/shimless_rma/chrome_shimless_rma_delegate_unittest.cc index e6cf1c9..27beb8a 100644 --- a/chrome/browser/ash/shimless_rma/chrome_shimless_rma_delegate_unittest.cc +++ b/chrome/browser/ash/shimless_rma/chrome_shimless_rma_delegate_unittest.cc
@@ -267,7 +267,7 @@ protected: base::test::ScopedFeatureList feature_list_; TestingProfileManager testing_profile_manager_{ - TestingBrowserProcess::GetGlobal(), &testing_local_state_}; + TestingBrowserProcess::GetGlobal()}; variations::ScopedVariationsIdsProvider scoped_variations_ids_provider_{ variations::VariationsIdsProvider::Mode::kUseSignedInState}; std::unique_ptr<FakeDiagnosticsAppProfileHelperDelegate>
diff --git a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc index c3923df..d4438e4 100644 --- a/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc +++ b/chrome/browser/ash/system_web_apps/apps/personalization_app/personalization_app_user_provider_impl_unittest.cc
@@ -318,8 +318,7 @@ user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> user_manager_{std::make_unique<ash::FakeChromeUserManager>()}; UserImageManagerRegistry user_image_manager_registry_{user_manager_.Get()}; - TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal(), - &local_state_}; + TestingProfileManager profile_manager_{TestingBrowserProcess::GetGlobal()}; data_decoder::test::InProcessDataDecoder data_decoder_; content::TestWebUI web_ui_; std::unique_ptr<content::WebContents> web_contents_;
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc index a9043a7b..76b8b385 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -1161,7 +1161,7 @@ // check if a feature is enabled, to avoid tsan data races. CHECK(temp_dir_.CreateUniqueTempDir()); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); CHECK(profile_manager_->SetUp(temp_dir_.GetPath())); profile_ = profile_manager_->CreateTestingProfile("test_profile", GetTestingFactories());
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 1a845e2a..2ab396ee 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -346,7 +346,6 @@ #include "content/public/common/origin_util.h" #include "content/public/common/url_utils.h" #include "content/public/common/window_container_type.mojom-shared.h" -#include "device/fido/features.h" #include "device/vr/buildflags/buildflags.h" #include "extensions/browser/browser_frame_context_data.h" #include "extensions/buildflags/buildflags.h" @@ -2900,9 +2899,7 @@ // Make the WebAuthenticationRemoteDesktopAllowedOrigins policy enable the // experimental WebAuthenticationRemoteDesktopSupport Blink runtime // feature. - if (base::FeatureList::IsEnabled( - device::kWebAuthnRemoteDesktopAllowedOriginsPolicy) && - !prefs->GetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins) + if (!prefs->GetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins) .empty()) { command_line->AppendSwitch(switches::kWebAuthRemoteDesktopSupport); }
diff --git a/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc b/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc index 5061cbef..6334a9f 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc
@@ -280,8 +280,7 @@ KioskBrowserSessionBaseTest() : local_state_(std::make_unique<ScopedTestingLocalState>( TestingBrowserProcess::GetGlobal())), - testing_profile_manager_(TestingBrowserProcess::GetGlobal(), - local_state_.get()) {} + testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {} KioskBrowserSessionBaseTest(const KioskBrowserSessionBaseTest&) = delete; KioskBrowserSessionBaseTest& operator=(const KioskBrowserSessionBaseTest&) =
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/BUILD.gn b/chrome/browser/chromeos/extensions/login_screen/login/BUILD.gn index d18f85c78..65d249a 100644 --- a/chrome/browser/chromeos/extensions/login_screen/login/BUILD.gn +++ b/chrome/browser/chromeos/extensions/login_screen/login/BUILD.gn
@@ -29,6 +29,7 @@ deps = [ "//ash/constants", + "//chrome/browser:browser_process", "//chrome/browser/ash/login", "//chrome/browser/ash/login/lock", "//chrome/browser/chromeos/extensions/login_screen/login/cleanup",
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/DEPS b/chrome/browser/chromeos/extensions/login_screen/login/DEPS index d179ff0a..5fd419f 100644 --- a/chrome/browser/chromeos/extensions/login_screen/login/DEPS +++ b/chrome/browser/chromeos/extensions/login_screen/login/DEPS
@@ -22,6 +22,7 @@ "+chrome/browser/browser_process.h", "+chrome/browser/chromeos/extensions/login_screen", "+chrome/browser/extensions/extension_api_unittest.h", + "+chrome/browser/lifetime/application_lifetime.h", "+chrome/browser/lifetime/termination_notification.h", "+chrome/browser/policy/extension_force_install_mixin.h", "+chrome/browser/ui/ash/login",
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_api.cc b/chrome/browser/chromeos/extensions/login_screen/login/login_api.cc index e214168..192d20ca 100644 --- a/chrome/browser/chromeos/extensions/login_screen/login/login_api.cc +++ b/chrome/browser/chromeos/extensions/login_screen/login/login_api.cc
@@ -14,7 +14,11 @@ #include "chrome/browser/ash/crosapi/crosapi_ash.h" #include "chrome/browser/ash/crosapi/crosapi_manager.h" #include "chrome/browser/ash/crosapi/login_ash.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/common/extensions/api/login.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_service.h" #include "google_apis/gaia/gaia_id.h" namespace extensions { @@ -38,19 +42,6 @@ return Respond(NoArguments()); } -ExtensionFunctionWithStringResult::~ExtensionFunctionWithStringResult() = - default; - -void ExtensionFunctionWithStringResult::OnResult(const std::string& result) { - Respond(WithArguments(result)); -} - -ExtensionFunctionWithVoidResult::~ExtensionFunctionWithVoidResult() = default; - -void ExtensionFunctionWithVoidResult::OnResult() { - Respond(NoArguments()); -} - LoginLaunchManagedGuestSessionFunction:: LoginLaunchManagedGuestSessionFunction() = default; LoginLaunchManagedGuestSessionFunction:: @@ -80,17 +71,17 @@ auto parameters = api::login::ExitCurrentSession::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(parameters); - auto callback = - base::BindOnce(&LoginExitCurrentSessionFunction::OnResult, this); + PrefService* local_state = g_browser_process->local_state(); + CHECK(local_state); - std::optional<std::string> data_for_next_login_attempt; if (parameters->data_for_next_login_attempt) { - data_for_next_login_attempt = - std::move(*parameters->data_for_next_login_attempt); + local_state->SetString(prefs::kLoginExtensionApiDataForNextLoginAttempt, + std::move(*parameters->data_for_next_login_attempt)); + } else { + local_state->ClearPref(prefs::kLoginExtensionApiDataForNextLoginAttempt); } - GetLoginApi()->ExitCurrentSession(data_for_next_login_attempt, - std::move(callback)); - return did_respond() ? AlreadyResponded() : RespondLater(); + chrome::AttemptUserExit(); + return RespondNow(NoArguments()); } LoginFetchDataForNextLoginAttemptFunction:: @@ -100,11 +91,13 @@ ExtensionFunction::ResponseAction LoginFetchDataForNextLoginAttemptFunction::Run() { - auto callback = base::BindOnce( - &LoginFetchDataForNextLoginAttemptFunction::OnResult, this); + PrefService* local_state = g_browser_process->local_state(); + CHECK(local_state); - GetLoginApi()->FetchDataForNextLoginAttempt(std::move(callback)); - return did_respond() ? AlreadyResponded() : RespondLater(); + std::string data_for_next_login_attempt = + local_state->GetString(prefs::kLoginExtensionApiDataForNextLoginAttempt); + local_state->ClearPref(prefs::kLoginExtensionApiDataForNextLoginAttempt); + return RespondNow(WithArguments(std::move(data_for_next_login_attempt))); } LoginLockManagedGuestSessionFunction::LoginLockManagedGuestSessionFunction() = @@ -255,12 +248,11 @@ api::login::SetDataForNextLoginAttempt::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(parameters); - auto callback = - base::BindOnce(&LoginSetDataForNextLoginAttemptFunction::OnResult, this); - - GetLoginApi()->SetDataForNextLoginAttempt( - parameters->data_for_next_login_attempt, std::move(callback)); - return did_respond() ? AlreadyResponded() : RespondLater(); + PrefService* local_state = g_browser_process->local_state(); + CHECK(local_state); + local_state->SetString(prefs::kLoginExtensionApiDataForNextLoginAttempt, + parameters->data_for_next_login_attempt); + return RespondNow(NoArguments()); } LoginRequestExternalLogoutFunction::LoginRequestExternalLogoutFunction() =
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/login_api.h b/chrome/browser/chromeos/extensions/login_screen/login/login_api.h index 4bbfb6c..f482bd4 100644 --- a/chrome/browser/chromeos/extensions/login_screen/login/login_api.h +++ b/chrome/browser/chromeos/extensions/login_screen/login/login_api.h
@@ -19,20 +19,6 @@ void OnResult(const std::optional<std::string>& error); }; -class ExtensionFunctionWithStringResult : public ExtensionFunction { - protected: - ~ExtensionFunctionWithStringResult() override; - - void OnResult(const std::string& result); -}; - -class ExtensionFunctionWithVoidResult : public ExtensionFunction { - protected: - ~ExtensionFunctionWithVoidResult() override; - - void OnResult(); -}; - class LoginLaunchManagedGuestSessionFunction : public ExtensionFunctionWithOptionalErrorResult { public: @@ -75,8 +61,7 @@ ResponseAction Run() override; }; -class LoginFetchDataForNextLoginAttemptFunction - : public ExtensionFunctionWithStringResult { +class LoginFetchDataForNextLoginAttemptFunction : public ExtensionFunction { public: LoginFetchDataForNextLoginAttemptFunction(); @@ -283,8 +268,7 @@ ResponseAction Run() override; }; -class LoginSetDataForNextLoginAttemptFunction - : public ExtensionFunctionWithVoidResult { +class LoginSetDataForNextLoginAttemptFunction : public ExtensionFunction { public: LoginSetDataForNextLoginAttemptFunction();
diff --git a/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc b/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc index 16780de..f93dfb8e 100644 --- a/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc +++ b/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc
@@ -151,7 +151,7 @@ ReportSchedulerTest() : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), local_state_(TestingBrowserProcess::GetGlobal()), - profile_manager_(TestingBrowserProcess::GetGlobal(), &local_state_) {} + profile_manager_(TestingBrowserProcess::GetGlobal()) {} ReportSchedulerTest(const ReportSchedulerTest&) = delete; ReportSchedulerTest& operator=(const ReportSchedulerTest&) = delete;
diff --git a/chrome/browser/extensions/api/enterprise_login/BUILD.gn b/chrome/browser/extensions/api/enterprise_login/BUILD.gn index ae83943..d43834a6 100644 --- a/chrome/browser/extensions/api/enterprise_login/BUILD.gn +++ b/chrome/browser/extensions/api/enterprise_login/BUILD.gn
@@ -13,14 +13,13 @@ "enterprise_login_api.h", ] - public_deps = [ - "//chromeos/crosapi/mojom", - "//extensions/browser", - ] + public_deps = [ "//extensions/browser" ] deps = [ "//base", - "//chrome/browser/ash/crosapi", + "//chrome/browser:browser_process", + "//chrome/browser:browser_public_dependencies", "//chrome/common/extensions/api", + "//components/prefs", ] }
diff --git a/chrome/browser/extensions/api/enterprise_login/enterprise_login_api.cc b/chrome/browser/extensions/api/enterprise_login/enterprise_login_api.cc index 1643afb1..8f5ce1a99 100644 --- a/chrome/browser/extensions/api/enterprise_login/enterprise_login_api.cc +++ b/chrome/browser/extensions/api/enterprise_login/enterprise_login_api.cc
@@ -4,13 +4,11 @@ #include "chrome/browser/extensions/api/enterprise_login/enterprise_login_api.h" -#include <optional> -#include <string> - -#include "chrome/browser/ash/crosapi/crosapi_ash.h" -#include "chrome/browser/ash/crosapi/crosapi_manager.h" -#include "chrome/browser/ash/crosapi/login_ash.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/common/extensions/api/enterprise_login.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_service.h" #include "components/user_manager/user_manager.h" namespace extensions { @@ -20,31 +18,18 @@ EnterpriseLoginExitCurrentManagedGuestSessionFunction:: ~EnterpriseLoginExitCurrentManagedGuestSessionFunction() = default; -void EnterpriseLoginExitCurrentManagedGuestSessionFunction::OnResult( - const std::optional<std::string>& error) { - if (error) { - Respond(Error(*error)); - return; - } - - return Respond(NoArguments()); -} - ExtensionFunction::ResponseAction EnterpriseLoginExitCurrentManagedGuestSessionFunction::Run() { if (!user_manager::UserManager::Get() || !user_manager::UserManager::Get()->IsLoggedInAsManagedGuestSession()) { return RespondNow(Error("Not a managed guest session.")); } - auto callback = base::BindOnce( - &EnterpriseLoginExitCurrentManagedGuestSessionFunction::OnResult, this); - crosapi::CrosapiManager::Get() - ->crosapi_ash() - ->login_ash() - ->ExitCurrentSession(/*data_for_next_login_attempt=*/std::nullopt, - std::move(callback)); - return did_respond() ? AlreadyResponded() : RespondLater(); + g_browser_process->local_state()->ClearPref( + prefs::kLoginExtensionApiDataForNextLoginAttempt); + + chrome::AttemptUserExit(); + return RespondNow(NoArguments()); } } // namespace extensions
diff --git a/chrome/browser/extensions/api/enterprise_login/enterprise_login_api.h b/chrome/browser/extensions/api/enterprise_login/enterprise_login_api.h index c4d8ddd..b7521d3 100644 --- a/chrome/browser/extensions/api/enterprise_login/enterprise_login_api.h +++ b/chrome/browser/extensions/api/enterprise_login/enterprise_login_api.h
@@ -5,9 +5,6 @@ #ifndef CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_LOGIN_ENTERPRISE_LOGIN_API_H_ #define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_LOGIN_ENTERPRISE_LOGIN_API_H_ -#include <optional> -#include <string> - #include "extensions/browser/extension_function.h" namespace extensions { @@ -29,8 +26,6 @@ protected: ~EnterpriseLoginExitCurrentManagedGuestSessionFunction() override; - void OnResult(const std::optional<std::string>& error); - // ExtensionFunction: ResponseAction Run() override; };
diff --git a/chrome/browser/extensions/extension_util_unittest.cc b/chrome/browser/extensions/extension_util_unittest.cc index b0de5b3a..ea530473 100644 --- a/chrome/browser/extensions/extension_util_unittest.cc +++ b/chrome/browser/extensions/extension_util_unittest.cc
@@ -210,7 +210,7 @@ ExtensionUtilUnittest::SetUp(); testing_profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &testing_local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(testing_profile_manager_->SetUp()); auto policy_service = std::make_unique<policy::PolicyServiceImpl>( std::vector<
diff --git a/chrome/browser/feature_engagement/tracker_factory.cc b/chrome/browser/feature_engagement/tracker_factory.cc index ae7e861f..72828b5 100644 --- a/chrome/browser/feature_engagement/tracker_factory.cc +++ b/chrome/browser/feature_engagement/tracker_factory.cc
@@ -6,11 +6,13 @@ #include "base/files/file_path.h" #include "base/no_destructor.h" +#include "base/path_service.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_paths.h" #include "components/feature_engagement/public/configuration_provider.h" #include "components/feature_engagement/public/field_trial_configuration_provider.h" #include "components/feature_engagement/public/local_configuration_provider.h" @@ -72,6 +74,11 @@ base::FilePath storage_dir = profile->GetPath().Append( chrome::kFeatureEngagementTrackerStorageDirname); + base::FilePath device_storage_dir; + base::PathService::Get(chrome::DIR_USER_DATA, &device_storage_dir); + device_storage_dir = device_storage_dir.Append( + chrome::kFeatureEngagementTrackerStorageDirname); + leveldb_proto::ProtoDatabaseProvider* db_provider = profile->GetDefaultStoragePartition()->GetProtoDatabaseProvider(); auto providers = @@ -86,8 +93,8 @@ #endif return feature_engagement::Tracker::Create( - storage_dir, background_task_runner, db_provider, nullptr, - std::move(providers)); + storage_dir, device_storage_dir, background_task_runner, db_provider, + nullptr, std::move(providers)); } } // namespace feature_engagement
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index c474b56..995498c 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -10493,6 +10493,11 @@ "expiry_milestone": -1 }, { + "name": "webrtc-pqc-for-dtls", + "owners": [ "agpalak@chromium.org", "guidou@chromium.org"], + "expiry_milestone": 170 + }, + { "name": "webrtc-wgc-require-border", "owners": [ "eladalon@chromium.org", "kron@chromium.org" ], "expiry_milestone": 180
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index a7d53f10..eeff7940f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -4561,6 +4561,10 @@ const char kWebrtcHwEncodingDescription[] = "Support in WebRTC for encoding video streams using platform hardware."; +const char kWebRtcPqcForDtlsName[] = "WebRTC PQC for DTLS"; +const char kWebRtcPqcForDtlsDescription[] = + "Support in WebRTC to enable PQC for DTLS"; + const char kWebrtcUseMinMaxVEADimensionsName[] = "WebRTC Min/Max Video Encode Accelerator dimensions"; const char kWebrtcUseMinMaxVEADimensionsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 717e0f8..504496b 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2639,6 +2639,9 @@ extern const char kWebrtcHwEncodingName[]; extern const char kWebrtcHwEncodingDescription[]; +extern const char kWebRtcPqcForDtlsName[]; +extern const char kWebRtcPqcForDtlsDescription[]; + extern const char kWebrtcUseMinMaxVEADimensionsName[]; extern const char kWebrtcUseMinMaxVEADimensionsDescription[];
diff --git a/chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc b/chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc index b2288df..5502f4e 100644 --- a/chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc +++ b/chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc
@@ -23,6 +23,7 @@ #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/identity_manager.h" +#include "components/sync/base/features.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/browser_task_traits.h" @@ -250,13 +251,17 @@ // TODO(crbug.com/40067771): ConsentLevel::kSync is deprecated and should be // removed. See ConsentLevel::kSync documentation for details. + const signin::ConsentLevel consent_level = + base::FeatureList::IsEnabled(syncer::kReplaceSyncPromosWithSignInPromos) + ? signin::ConsentLevel::kSignin + : signin::ConsentLevel::kSync; return std::make_unique<EndpointFetcher>( profile_->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(), kDiscoveryOAuthConsumerName, GURL(base::StrCat({GetDiscoveryUrl(), "/", access_code})), kGetMethod, kContentType, discovery_scopes, kTimeout, kEmptyPostData, - kTrafficAnnotation, identity_manager_, signin::ConsentLevel::kSync); + kTrafficAnnotation, identity_manager_, consent_level); } void AccessCodeCastDiscoveryInterface::ValidateDiscoveryAccessCode(
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc index d59b5e1..276b645a 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -520,7 +520,7 @@ fake_user_manager_.Reset( std::make_unique<user_manager::FakeUserManager>(local_state_.Get())); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); network_notifier_ = net::test::MockNetworkChangeNotifier::Create();
diff --git a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc index 63f7d566..38178c7 100644 --- a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
@@ -838,25 +838,16 @@ // When the 1st soft navigation comes in, we record the // soft_navigation_interval_responsiveness_metrics_normalization_ as INP // before soft nav. - if (current_soft_navigation_metrics->count == 0 && - new_soft_navigation_metrics.count == 1) { + if (current_soft_navigation_metrics->count == 0) { RecordResponsivenessMetricsBeforeSoftNavigationForMainFrame(); RecordLayoutShiftBeforeSoftNavigationForMainFrame(); + } else { + // Even though a soft-nav arrived, we don't flush until the current one + // unloads (i.e. next soft nav arrives). So the very first skips reporting. + RecordSoftNavigationMetrics( + GetDelegate().GetPreviousUkmSourceIdForSoftNavigation(), + *current_soft_navigation_metrics); } - - // Record current soft navigation metrics into Ukm when a new soft navigation - // comes in. For example, when 2nd soft navigation with a larger count comes - // in, the 1st(current) soft metrics are recorded. The initial soft - // navigation metrics that have default values should not reported. - if (current_soft_navigation_metrics->count == 0 || - current_soft_navigation_metrics->count >= - new_soft_navigation_metrics.count) { - return; - } - - RecordSoftNavigationMetrics( - GetDelegate().GetPreviousUkmSourceIdForSoftNavigation(), - *current_soft_navigation_metrics); } const page_load_metrics::ContentfulPaintTimingInfo&
diff --git a/chrome/browser/permissions/permission_manager_browsertest.cc b/chrome/browser/permissions/permission_manager_browsertest.cc index 7100fec..1f7a0e1 100644 --- a/chrome/browser/permissions/permission_manager_browsertest.cc +++ b/chrome/browser/permissions/permission_manager_browsertest.cc
@@ -57,6 +57,9 @@ content::PermissionController::SubscriptionId subscription_id) override { permissions::PermissionManager::OnPermissionStatusChangeSubscriptionAdded( subscription_id); + if (callback_.is_null()) { + return; + } std::move(callback_).Run(); }
diff --git a/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc b/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc index 25aa90a..f4acd6c 100644 --- a/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc +++ b/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc
@@ -6,6 +6,7 @@ #include "base/metrics/histogram_functions.h" #include "chrome/browser/preloading/chrome_preloading.h" +#include "chrome/browser/preloading/preloading_features.h" #include "chrome/browser/preloading/prerender/prerender_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" @@ -93,10 +94,9 @@ /*additional_headers=*/net::HttpRequestHeaders(), /*no_vary_search_hint=*/std::nullopt, ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_BOOKMARK), - // Considering the characteristics of triggers (e.g., the duration - // from trigger to activation), warm-up is not enabled for now on - // this trigger. Please see crbug and its doc for more details. - /*should_warm_up_compositor=*/false, + /*should_warm_up_compositor=*/ + base::FeatureList::IsEnabled( + features::kPrerender2WarmUpCompositorForBookmarkBar), /*should_prepare_paint_tree=*/false, content::PreloadingHoldbackStatus::kUnspecified, pipeline_info_, preloading_attempt,
diff --git a/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline_manager.cc b/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline_manager.cc index 60783954..19beee86 100644 --- a/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline_manager.cc +++ b/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline_manager.cc
@@ -39,10 +39,12 @@ void BookmarkBarPreloadPipelineManager::StartPrerender(const GURL& url) { if (pipeline_) { - // Prerender is expected to be reset when mouseExit happens or every primary - // page changed, so if a pipeline is present, the url is expected to be the - // same. - CHECK_EQ(url, pipeline_->url()); + // TODO(https://crbug.com/413259638) Adds back the CHECK which checks `url + // == pipeline_->url()` when the investigation is done. Prerender is + // expected to be reset when mouseExit happens or every primary page + // changed, so if a pipeline is present, the url is expected to be the same. + // But the CHECK is causing https://crbug.com/425612820 unexpectedly, the + // CHECK is removed at the moment. return; }
diff --git a/chrome/browser/preloading/prefetch/chrome_prefetch_manager.cc b/chrome/browser/preloading/prefetch/chrome_prefetch_manager.cc index feda4e3..ad4cdb2 100644 --- a/chrome/browser/preloading/prefetch/chrome_prefetch_manager.cc +++ b/chrome/browser/preloading/prefetch/chrome_prefetch_manager.cc
@@ -57,6 +57,7 @@ prefetch_url, use_prefetch_proxy, kCCTMetricsSuffix, blink::mojom::Referrer(), referring_origin, /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, content::PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/content::PreloadingType:: kPrefetch),
diff --git a/chrome/browser/preloading/preloading_features.cc b/chrome/browser/preloading/preloading_features.cc index 12272b9..39f69eb 100644 --- a/chrome/browser/preloading/preloading_features.cc +++ b/chrome/browser/preloading/preloading_features.cc
@@ -14,4 +14,11 @@ "zero_suggest_trigger", false); +BASE_FEATURE(kPrerender2WarmUpCompositorForBookmarkBar, + "Prerender2WarmUpCompositorForBookmarkBar", + base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kPrerender2WarmUpCompositorForNewTabPage, + "Prerender2WarmUpCompositorForNewTabPage", + base::FEATURE_DISABLED_BY_DEFAULT); + } // namespace features
diff --git a/chrome/browser/preloading/preloading_features.h b/chrome/browser/preloading/preloading_features.h index 27bbec53..936e59b 100644 --- a/chrome/browser/preloading/preloading_features.h +++ b/chrome/browser/preloading/preloading_features.h
@@ -15,6 +15,11 @@ BASE_DECLARE_FEATURE_PARAM(std::string, kPrewarmUrl); BASE_DECLARE_FEATURE_PARAM(bool, kPrewarmZeroSuggestTrigger); +// If enabled, requests the compositor warm-up (crbug.com/41496019) for +// each prerender trigger. +BASE_DECLARE_FEATURE(kPrerender2WarmUpCompositorForBookmarkBar); +BASE_DECLARE_FEATURE(kPrerender2WarmUpCompositorForNewTabPage); + } // namespace features #endif // CHROME_BROWSER_PRELOADING_PRELOADING_FEATURES_H_
diff --git a/chrome/browser/preloading/prerender/prerender_manager.cc b/chrome/browser/preloading/prerender/prerender_manager.cc index 4e54db33..eb8e7eb 100644 --- a/chrome/browser/preloading/prerender/prerender_manager.cc +++ b/chrome/browser/preloading/prerender/prerender_manager.cc
@@ -237,10 +237,9 @@ /*additional_headers=*/net::HttpRequestHeaders(), /*no_vary_search_hint=*/std::nullopt, ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_BOOKMARK), - // Considering the characteristics of triggers (e.g., the duration from - // trigger to activation), warm-up is not enabled for now on this trigger. - // Please see crbug and its doc for more details. - /*should_warm_up_compositor=*/false, + /*should_warm_up_compositor=*/ + base::FeatureList::IsEnabled( + features::kPrerender2WarmUpCompositorForNewTabPage), /*should_prepare_paint_tree=*/false, content::PreloadingHoldbackStatus::kUnspecified, content::PreloadPipelineInfo::Create(
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline.cc b/chrome/browser/preloading/search_preload/search_preload_pipeline.cc index 7e27979..9f24d1b 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline.cc +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline.cc
@@ -87,8 +87,8 @@ /*use_prefetch_proxy=*/false, prerender_utils::kDefaultSearchEngineMetricSuffix, blink::mojom::Referrer(), - /*referring_origin=*/std::nullopt, no_vary_search_hint, pipeline_info_, - attempt->GetWeakPtr(), + /*referring_origin=*/std::nullopt, no_vary_search_hint, + /*priority=*/std::nullopt, pipeline_info_, attempt->GetWeakPtr(), /*holdback_status_override=*/std::nullopt, /*ttl=*/features::kDsePreload2PrefetchTtl.Get()); CHECK(prefetch_handle_);
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cc index 6de7b63..7067e364 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cc +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_impl_unittest.cc
@@ -354,7 +354,7 @@ void CreateDefaultProfile() { default_profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(default_profile_manager_->SetUp()); default_profile_ = default_profile_manager_->CreateTestingProfile(
diff --git a/chrome/browser/profiles/profiles_state_unittest.cc b/chrome/browser/profiles/profiles_state_unittest.cc index 05afa3e..b229bc74 100644 --- a/chrome/browser/profiles/profiles_state_unittest.cc +++ b/chrome/browser/profiles/profiles_state_unittest.cc
@@ -81,8 +81,7 @@ class IsGuestModeEnabledTest : public testing::TestWithParam<bool> { public: IsGuestModeEnabledTest() - : profile_manager_(TestingBrowserProcess::GetGlobal(), - &testing_local_state_), + : profile_manager_(TestingBrowserProcess::GetGlobal()), testing_local_state_(TestingBrowserProcess::GetGlobal()) { testing_local_state_.Get()->SetBoolean(prefs::kBrowserGuestModeEnabled, BrowserGuestModePrefValue());
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc index 735be55..d99592d 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -286,7 +286,7 @@ : public ChromeRenderViewHostTestHarness { public: ChromePasswordProtectionServiceTest() - : profile_manager_(TestingBrowserProcess::GetGlobal(), &local_state_), + : profile_manager_(TestingBrowserProcess::GetGlobal()), local_state_(TestingBrowserProcess::GetGlobal()) { EXPECT_TRUE(profile_manager_.SetUp()); }
diff --git a/chrome/browser/signin/account_reconcilor_factory.cc b/chrome/browser/signin/account_reconcilor_factory.cc index 51d6e4b..fd1ecb2 100644 --- a/chrome/browser/signin/account_reconcilor_factory.cc +++ b/chrome/browser/signin/account_reconcilor_factory.cc
@@ -27,8 +27,8 @@ #include "base/time/time.h" #include "chrome/browser/ash/account_manager/account_manager_util.h" #include "chrome/browser/lifetime/application_lifetime.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/install_attributes/install_attributes.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/prefs/pref_service.h" #include "components/signin/public/base/signin_pref_names.h" #include "components/user_manager/user_manager.h" @@ -144,7 +144,7 @@ std::unique_ptr<AccountReconcilor> reconcilor = std::make_unique<AccountReconcilor>( identity_manager, signin_client, - ::GetAccountManagerFacade(profile->GetPath().value()), + ash::GetAccountManagerFacade(profile->GetPath().value()), CreateAccountReconcilorDelegate(profile)); #else std::unique_ptr<AccountReconcilor> reconcilor =
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc index 1a6c95c5..ae43534 100644 --- a/chrome/browser/signin/chrome_signin_helper.cc +++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -52,7 +52,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/ui/browser_window.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "components/supervised_user/core/browser/supervised_user_service.h" #if BUILDFLAG(ENABLE_EXTENSIONS) @@ -321,14 +321,14 @@ // 3. Displaying an account addition window. if (service_type == GAIA_SERVICE_TYPE_ADDSESSION) { - ::GetAccountManagerFacade(profile->GetPath().value()) + ash::GetAccountManagerFacade(profile->GetPath().value()) ->ShowAddAccountDialog(account_manager::AccountManagerFacade:: AccountAdditionSource::kOgbAddAccount); return; } // 4. Displaying the Account Manager for managing accounts. - ::GetAccountManagerFacade(profile->GetPath().value()) + ash::GetAccountManagerFacade(profile->GetPath().value()) ->ShowManageAccountsSettings(); return;
diff --git a/chrome/browser/signin/identity_manager_factory.cc b/chrome/browser/signin/identity_manager_factory.cc index b66a7695..5606e56e 100644 --- a/chrome/browser/signin/identity_manager_factory.cc +++ b/chrome/browser/signin/identity_manager_factory.cc
@@ -40,7 +40,7 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/browser_process_platform_part.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #endif #if BUILDFLAG(IS_WIN) @@ -154,7 +154,7 @@ #if BUILDFLAG(IS_CHROMEOS) if (ash::ProfileHelper::IsUserProfile(profile)) { params.account_manager_facade = - GetAccountManagerFacade(profile->GetPath().value()); + ash::GetAccountManagerFacade(profile->GetPath().value()); params.is_regular_profile = true; } #endif
diff --git a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc index 9b2b639..77d9caab 100644 --- a/chrome/browser/signin/identity_test_environment_profile_adaptor.cc +++ b/chrome/browser/signin/identity_test_environment_profile_adaptor.cc
@@ -14,8 +14,8 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #endif // static @@ -83,7 +83,7 @@ ChromeSigninClientFactory::GetForProfile(profile), profile->GetPrefs(), profile->GetPath(), g_browser_process->platform_part()->GetAccountManagerFactory(), - GetAccountManagerFacade(profile->GetPath().value())); + ash::GetAccountManagerFacade(profile->GetPath().value())); #else return signin::IdentityTestEnvironment::BuildIdentityManagerForTests( ChromeSigninClientFactory::GetForProfile(profile), profile->GetPrefs(),
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc index 42057a2..1bfa37f 100644 --- a/chrome/browser/signin/signin_ui_util.cc +++ b/chrome/browser/signin/signin_ui_util.cc
@@ -55,8 +55,8 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/signin/signin_ui_chromeos_util.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/user_manager/user.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -187,7 +187,7 @@ const std::string& email, signin_metrics::AccessPoint access_point) { #if BUILDFLAG(IS_CHROMEOS) - ::GetAccountManagerFacade(profile->GetPath().value()) + ash::GetAccountManagerFacade(profile->GetPath().value()) ->ShowReauthAccountDialog( GetAccountReauthSourceFromAccessPoint(access_point), email, base::DoNothing());
diff --git a/chrome/browser/signin/signin_ui_util_unittest.cc b/chrome/browser/signin/signin_ui_util_unittest.cc index 39043997..7d979694 100644 --- a/chrome/browser/signin/signin_ui_util_unittest.cc +++ b/chrome/browser/signin/signin_ui_util_unittest.cc
@@ -869,8 +869,7 @@ content::BrowserTaskEnvironment task_environment( base::test::TaskEnvironment::TimeSource::MOCK_TIME); ScopedTestingLocalState local_state(TestingBrowserProcess::GetGlobal()); - TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal(), - &local_state); + TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager.SetUp()); std::string name("testing_profile"); TestingProfile* profile = profile_manager.CreateTestingProfile(
diff --git a/chrome/browser/ui/ash/clipboard/clipboard_image_model_factory_impl.cc b/chrome/browser/ui/ash/clipboard/clipboard_image_model_factory_impl.cc index 7dc852d..700a11db 100644 --- a/chrome/browser/ui/ash/clipboard/clipboard_image_model_factory_impl.cc +++ b/chrome/browser/ui/ash/clipboard/clipboard_image_model_factory_impl.cc
@@ -6,41 +6,10 @@ #include <algorithm> -#include "chrome/browser/profiles/profile.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" +#include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" -namespace { - -// Helpers --------------------------------------------------------------------- - -// Analogous to `ProfileManager::GetPrimaryUserProfile()` except this method -// returns `nullptr` in the case where the primary user profile is not ready. -Profile* GetPrimaryUserProfile() { - const auto* const user_manager = user_manager::UserManager::Get(); - if (!user_manager) { - return nullptr; - } - - const auto* const user = user_manager->GetPrimaryUser(); - if (!user) { - return nullptr; - } - - auto* const helper = ash::BrowserContextHelper::Get(); - if (!helper) { - return nullptr; - } - - auto* const browser_context = helper->GetBrowserContextByUser(user); - return browser_context ? Profile::FromBrowserContext(browser_context) - : nullptr; -} - -} // namespace - -// ClipboardImageModelFactoryImpl ---------------------------------------------- - ClipboardImageModelFactoryImpl::ClipboardImageModelFactoryImpl() : idle_timer_(FROM_HERE, base::Minutes(2), @@ -107,7 +76,7 @@ } void ClipboardImageModelFactoryImpl::OnShutdown() { - // Reset |request_| to drop its reference to Profile, specifically the + // Reset |request_| to drop its reference to BrowserContext, specifically the // RenderProcessHost of its WebContents. request_.reset(); } @@ -123,10 +92,10 @@ } if (!request_) { - // Use the primary profile instead of the active profile to create the + // Use the primary user instead of the active user to create the // `content::WebContents` that renders html. request_ = std::make_unique<ClipboardImageModelRequest>( - GetPrimaryUserProfile(), + user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId(), base::BindRepeating(&ClipboardImageModelFactoryImpl::StartNextRequest, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/chrome/browser/ui/ash/clipboard/clipboard_image_model_request.cc b/chrome/browser/ui/ash/clipboard/clipboard_image_model_request.cc index 168144f..c3ea320 100644 --- a/chrome/browser/ui/ash/clipboard/clipboard_image_model_request.cc +++ b/chrome/browser/ui/ash/clipboard/clipboard_image_model_request.cc
@@ -12,7 +12,8 @@ #include "base/metrics/histogram.h" #include "base/metrics/histogram_macros.h" #include "base/task/sequenced_task_runner.h" -#include "chrome/browser/profiles/profile.h" +#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" +#include "components/account_id/account_id.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" @@ -41,6 +42,15 @@ ClipboardImageModelRequest::TestParams* g_test_params = nullptr; +content::BrowserContext* GetBrowserContextByAccountId( + const AccountId& account_id) { + auto* browser_context = + ash::BrowserContextHelper::Get()->GetBrowserContextByAccountId( + account_id); + CHECK(browser_context); + return browser_context; +} + } // namespace // ClipboardImageModelFactory::Params: ----------------------------------------- @@ -108,14 +118,12 @@ } ClipboardImageModelRequest::ClipboardImageModelRequest( - Profile* profile, + const AccountId& account_id, base::RepeatingClosure on_request_finished_callback) : widget_(std::make_unique<views::Widget>()), - web_view_(new views::WebView(profile)), + web_view_(new views::WebView(GetBrowserContextByAccountId(account_id))), on_request_finished_callback_(std::move(on_request_finished_callback)), request_creation_time_(base::TimeTicks::Now()) { - CHECK(profile); - views::Widget::InitParams widget_params( views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
diff --git a/chrome/browser/ui/ash/clipboard/clipboard_image_model_request.h b/chrome/browser/ui/ash/clipboard/clipboard_image_model_request.h index e74228f1..c0afd29 100644 --- a/chrome/browser/ui/ash/clipboard/clipboard_image_model_request.h +++ b/chrome/browser/ui/ash/clipboard/clipboard_image_model_request.h
@@ -17,6 +17,8 @@ #include "content/public/browser/web_contents_observer.h" #include "ui/base/models/image_model.h" +class AccountId; + namespace ash { class ScopedClipboardHistoryPause; } // namespace ash @@ -30,8 +32,6 @@ class Widget; } // namespace views -class Profile; - // Renders html in an off-screen WebView, copies the rendered surface, and // passes the copy through |deliver_image_model_callback_|. If the request takes // takes more than 5s to load, timeout is declared and the callback is not @@ -105,7 +105,7 @@ }; ClipboardImageModelRequest( - Profile* profile, + const AccountId& account_id, base::RepeatingClosure on_request_finished_callback); ClipboardImageModelRequest(const ClipboardImageModelRequest&) = delete; ClipboardImageModelRequest operator=(const ClipboardImageModelRequest&) =
diff --git a/chrome/browser/ui/ash/projector/BUILD.gn b/chrome/browser/ui/ash/projector/BUILD.gn index 6dbc0221..f63bac8 100644 --- a/chrome/browser/ui/ash/projector/BUILD.gn +++ b/chrome/browser/ui/ash/projector/BUILD.gn
@@ -45,6 +45,7 @@ "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/web_applications", "//chrome/services/media_gallery_util/public/cpp", + "//chromeos/ash/components/account_manager", "//chromeos/ash/components/drivefs", "//chromeos/ash/components/drivefs/mojom", "//chromeos/ash/components/login/login_state",
diff --git a/chrome/browser/ui/ash/projector/projector_app_client_impl.cc b/chrome/browser/ui/ash/projector/projector_app_client_impl.cc index a7ad7be..c625ef1 100644 --- a/chrome/browser/ui/ash/projector/projector_app_client_impl.cc +++ b/chrome/browser/ui/ash/projector/projector_app_client_impl.cc
@@ -20,8 +20,8 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/ash/projector/projector_soda_installation_controller.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/application_locale_storage/application_locale_storage.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/signin/public/identity_manager/identity_manager.h" @@ -179,7 +179,7 @@ } void ProjectorAppClientImpl::HandleAccountReauth(const std::string& email) { - ::GetAccountManagerFacade( + ash::GetAccountManagerFacade( ProfileManager::GetActiveUserProfile()->GetPath().value()) ->ShowReauthAccountDialog( account_manager::AccountManagerFacade::AccountAdditionSource::
diff --git a/chrome/browser/ui/ash/session/session_controller_client_impl_unittest.cc b/chrome/browser/ui/ash/session/session_controller_client_impl_unittest.cc index a0ca43d..f554574 100644 --- a/chrome/browser/ui/ash/session/session_controller_client_impl_unittest.cc +++ b/chrome/browser/ui/ash/session/session_controller_client_impl_unittest.cc
@@ -80,7 +80,7 @@ assistant_delegate_ = std::make_unique<AssistantBrowserDelegateImpl>(); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); cros_settings_test_helper_ =
diff --git a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc index 28b87e1d59..f5c2ea3e 100644 --- a/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc +++ b/chrome/browser/ui/views/location_bar/content_setting_bubble_dialog_browsertest.cc
@@ -228,6 +228,16 @@ /*constraints=*/{}, content_settings::PartitionKey::GetDefaultForTesting()); } + + // WINDOW_MANAGEMENT is observed fairly early on, so we need to make sure it's + // set to a reasonable value regardless of the |types| passed in. + provider->SetWebsiteSetting( + ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), + ContentSettingsType::WINDOW_MANAGEMENT, + base::Value(ContentSetting::CONTENT_SETTING_BLOCK), + /*constraints=*/{}, + content_settings::PartitionKey::GetDefaultForTesting()); + content_settings::TestUtils::OverrideProvider(map, std::move(provider), GetParam()); }
diff --git a/chrome/browser/ui/webui/ash/account_manager/BUILD.gn b/chrome/browser/ui/webui/ash/account_manager/BUILD.gn index e270d0d..a0869bb 100644 --- a/chrome/browser/ui/webui/ash/account_manager/BUILD.gn +++ b/chrome/browser/ui/webui/ash/account_manager/BUILD.gn
@@ -34,6 +34,7 @@ "//chrome/browser/profiles:profile", "//chrome/browser/ui/webui/signin/ash", "//chrome/common:constants", + "//chromeos/ash/components/account_manager", "//components/account_manager_core", "//components/prefs", "//net",
diff --git a/chrome/browser/ui/webui/ash/account_manager/account_migration_welcome_ui.cc b/chrome/browser/ui/webui/ash/account_manager/account_migration_welcome_ui.cc index cd8e0435..5cc380a 100644 --- a/chrome/browser/ui/webui/ash/account_manager/account_migration_welcome_ui.cc +++ b/chrome/browser/ui/webui/ash/account_manager/account_migration_welcome_ui.cc
@@ -17,8 +17,8 @@ #include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_data_source.h" #include "net/base/url_util.h" @@ -62,7 +62,7 @@ const std::string& account_email = args[0].GetString(); Profile* profile = Profile::FromWebUI(web_ui()); - ::GetAccountManagerFacade(profile->GetPath().value()) + GetAccountManagerFacade(profile->GetPath().value()) ->ShowReauthAccountDialog( account_manager::AccountManagerFacade::AccountAdditionSource:: kAccountManagerMigrationWelcomeScreen,
diff --git a/chrome/browser/ui/webui/ash/login/signin_userlist_unittest.cc b/chrome/browser/ui/webui/ash/login/signin_userlist_unittest.cc index 21705d9..b6203e4 100644 --- a/chrome/browser/ui/webui/ash/login/signin_userlist_unittest.cc +++ b/chrome/browser/ui/webui/ash/login/signin_userlist_unittest.cc
@@ -52,7 +52,7 @@ void SetUp() override { testing::Test::SetUp(); profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); for (size_t i = 0; i < std::size(kUsersPublic); ++i) {
diff --git a/chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler.cc b/chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler.cc index 8af73553..480dba96 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler.cc
@@ -26,9 +26,9 @@ #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chrome/browser/ui/webui/signin/ash/inline_login_dialog.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/signin/public/base/consent_level.h" #include "components/signin/public/identity_manager/tribool.h" #include "components/user_manager/user.h" @@ -362,7 +362,7 @@ void AccountManagerUIHandler::HandleAddAccount(const base::Value::List& args) { AllowJavascript(); - ::GetAccountManagerFacade(profile_->GetPath().value()) + GetAccountManagerFacade(profile_->GetPath().value()) ->ShowAddAccountDialog( account_manager::AccountManagerFacade::AccountAdditionSource:: kSettingsAddAccountButton); @@ -375,7 +375,7 @@ CHECK(!args.empty()); const std::string& account_email = args[0].GetString(); - ::GetAccountManagerFacade(profile_->GetPath().value()) + GetAccountManagerFacade(profile_->GetPath().value()) ->ShowReauthAccountDialog( account_manager::AccountManagerFacade::AccountAdditionSource:: kSettingsReauthAccountButton,
diff --git a/chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler_browsertest.cc b/chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler_browsertest.cc index a6f7c73..15a8a89 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler_browsertest.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler_browsertest.cc
@@ -21,11 +21,11 @@ #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" #include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "components/account_manager_core/account_manager_facade.h" #include "components/account_manager_core/chromeos/account_manager.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/session_manager/core/session_manager.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" @@ -151,7 +151,7 @@ SetUpEnvironment(); auto* account_manager_facade = - ::GetAccountManagerFacade(profile_->GetPath().value()); + GetAccountManagerFacade(profile_->GetPath().value()); account_apps_availability_ = AccountAppsAvailabilityFactory::GetForProfile(profile()); @@ -401,7 +401,7 @@ SetUpEnvironment(); auto* account_manager_facade = - ::GetAccountManagerFacade(profile()->GetPath().value()); + GetAccountManagerFacade(profile()->GetPath().value()); account_apps_availability_ = AccountAppsAvailabilityFactory::GetForProfile(profile());
diff --git a/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc b/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc index 3c1cd45..2d240b7 100644 --- a/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc +++ b/chrome/browser/ui/webui/ash/settings/pages/people/people_section.cc
@@ -46,11 +46,11 @@ #include "chrome/grit/branded_strings.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/account_manager_core/pref_names.h" #include "components/omnibox/common/omnibox_features.h" #include "components/prefs/pref_service.h" @@ -497,7 +497,7 @@ account_manager_ = factory->GetAccountManager(profile->GetPath().value()); DCHECK(account_manager_); account_manager_facade_ = - ::GetAccountManagerFacade(profile->GetPath().value()); + GetAccountManagerFacade(profile->GetPath().value()); DCHECK(account_manager_facade_); account_manager_facade_observation_.Observe(account_manager_facade_.get()); account_apps_availability_ =
diff --git a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc index 05ee096..8367fbb7 100644 --- a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc +++ b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
@@ -489,7 +489,7 @@ #if BUILDFLAG(IS_CHROMEOS) void SetUp() override { profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); fake_user_manager_.Reset( std::make_unique<user_manager::FakeUserManager>(local_state_.Get())); @@ -630,7 +630,7 @@ #else void SetUp() override { profile_manager_ = std::make_unique<TestingProfileManager>( - TestingBrowserProcess::GetGlobal(), &local_state_); + TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); } void TearDown() override {
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc index 198bd8eb..13146851 100644 --- a/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -158,13 +158,13 @@ #include "chrome/browser/ui/webui/ash/settings/pages/people/account_manager_ui_handler.h" #include "chrome/common/chrome_switches.h" #include "chrome/grit/browser_resources.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" #include "chromeos/ash/components/login/auth/password_visibility_utils.h" #include "chromeos/ash/components/phonehub/phone_hub_manager.h" #include "chromeos/ash/experiences/arc/arc_util.h" #include "chromeos/constants/chromeos_features.h" #include "components/account_manager_core/chromeos/account_manager.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/user_manager/user.h" #include "ui/base/ui_base_features.h" #else // !BUILDFLAG(IS_CHROMEOS) @@ -656,7 +656,7 @@ factory->GetAccountManager(profile->GetPath().value()); DCHECK(account_manager); auto* account_manager_facade = - ::GetAccountManagerFacade(profile->GetPath().value()); + ash::GetAccountManagerFacade(profile->GetPath().value()); DCHECK(account_manager_facade); web_ui()->AddMessageHandler(
diff --git a/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl.cc index a2ea154..e459194 100644 --- a/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl.cc +++ b/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl.cc
@@ -32,11 +32,11 @@ #include "chrome/browser/ui/webui/signin/ash/signin_helper.h" #include "chrome/browser/ui/webui/signin/inline_login_handler.h" #include "chrome/common/pref_names.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "chromeos/ash/components/account_manager/account_manager_factory.h" #include "chromeos/version/version_loader.h" #include "components/account_manager_core/account.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/account_manager_core/chromeos/account_manager_mojo_service.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -337,7 +337,7 @@ return; } - ::GetAccountManagerFacade(Profile::FromWebUI(web_ui())->GetPath().value()) + GetAccountManagerFacade(Profile::FromWebUI(web_ui())->GetPath().value()) ->GetAccounts( base::BindOnce(&InlineLoginHandlerImpl::OnGetAccountsToCompleteLogin, weak_factory_.GetWeakPtr(), params)); @@ -428,7 +428,7 @@ const base::Value::List& args) { const std::string& callback_id = args[0].GetString(); const Profile* profile = Profile::FromWebUI(web_ui()); - ::GetAccountManagerFacade(profile->GetPath().value()) + GetAccountManagerFacade(profile->GetPath().value()) ->GetAccounts(base::BindOnce(&InlineLoginHandlerImpl::OnGetAccounts, weak_factory_.GetWeakPtr(), callback_id)); } @@ -454,7 +454,7 @@ AllowJavascript(); CHECK_EQ(1u, args.size()); const std::string& callback_id = args[0].GetString(); - ::GetAccountManagerFacade(Profile::FromWebUI(web_ui())->GetPath().value()) + GetAccountManagerFacade(Profile::FromWebUI(web_ui())->GetPath().value()) ->GetAccounts(base::BindOnce( &InlineLoginHandlerImpl::ContinueGetAccountsNotAvailableInArc, weak_factory_.GetWeakPtr(), callback_id));
diff --git a/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl_browsertest.cc b/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl_browsertest.cc index 2101f84..6b2d9cf 100644 --- a/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl_browsertest.cc +++ b/chrome/browser/ui/webui/signin/ash/inline_login_handler_impl_browsertest.cc
@@ -31,8 +31,8 @@ #include "chrome/browser/ui/webui/ash/edu_coexistence/edu_coexistence_login_handler.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include "components/account_manager_core/account_manager_facade.h" -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" #include "components/account_manager_core/mock_account_manager_facade.h" #include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/signin/public/identity_manager/primary_account_mutator.h" @@ -366,7 +366,7 @@ base::ScopedObservation<account_manager::AccountManagerFacade, account_manager::AccountManagerFacade::Observer> observation{&observer}; - observation.Observe(::GetAccountManagerFacade(profile()->GetPath().value())); + observation.Observe(GetAccountManagerFacade(profile()->GetPath().value())); // Call "completeLogin". base::Value::List args; @@ -391,7 +391,7 @@ base::ScopedObservation<account_manager::AccountManagerFacade, account_manager::AccountManagerFacade::Observer> observation{&observer}; - observation.Observe(::GetAccountManagerFacade(profile()->GetPath().value())); + observation.Observe(GetAccountManagerFacade(profile()->GetPath().value())); // Call "completeLogin". base::Value::List args;
diff --git a/chrome/browser/webauthn/chrome_web_authentication_delegate_base.cc b/chrome/browser/webauthn/chrome_web_authentication_delegate_base.cc index 1e82a8d..f74405af 100644 --- a/chrome/browser/webauthn/chrome_web_authentication_delegate_base.cc +++ b/chrome/browser/webauthn/chrome_web_authentication_delegate_base.cc
@@ -62,10 +62,6 @@ bool IsAllowedByPlatformEnterprisePolicy( content::BrowserContext* browser_context, const url::Origin& caller_origin) { - if (!base::FeatureList::IsEnabled( - device::kWebAuthnRemoteDesktopAllowedOriginsPolicy)) { - return false; - } const Profile* profile = Profile::FromBrowserContext(browser_context); const PrefService* prefs = profile->GetPrefs(); const base::Value::List& allowed_origins =
diff --git a/chrome/browser/webauthn/chrome_web_authentication_delegate_base_unittest.cc b/chrome/browser/webauthn/chrome_web_authentication_delegate_base_unittest.cc index 5504d0a..bf84f505 100644 --- a/chrome/browser/webauthn/chrome_web_authentication_delegate_base_unittest.cc +++ b/chrome/browser/webauthn/chrome_web_authentication_delegate_base_unittest.cc
@@ -5,14 +5,12 @@ #include "chrome/browser/webauthn/chrome_web_authentication_delegate_base.h" #include "base/test/scoped_command_line.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/webauthn/webauthn_pref_names.h" #include "chrome/browser/webauthn/webauthn_switches.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_context.h" -#include "device/fido/features.h" namespace { @@ -31,8 +29,6 @@ static constexpr char kExampleOrigin[] = "https://example.com"; static constexpr char kAnotherExampleOrigin[] = "https://another.example.com"; - - base::test::ScopedFeatureList scoped_feature_list_; }; #if !BUILDFLAG(IS_ANDROID) @@ -116,7 +112,7 @@ AdditionalOriginSwitch_WithAllowedOriginsPolicy) { // The --webauthn-remote-proxied-requests-allowed-additional-origin switch // allows passing an additional origin for testing. This origin will be - // allowed if the kWebAuthnRemoteDesktopAllowedOriginsPolicy preference is set + // allowed if the WebAuthenticationRemoteDesktopAllowedOrigins policy is set // to a non-empty list of origins. If the policy is set, the command-line // origin is treated as another allowed origin in addition to those specified // by the policy. @@ -125,8 +121,6 @@ scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( webauthn::switches::kRemoteProxiedRequestsAllowedAdditionalOrigin, kExampleOrigin); - scoped_feature_list_.InitAndEnableFeature( - device::kWebAuthnRemoteDesktopAllowedOriginsPolicy); // Initially, no origins should be allowed because the allowed origins pref // hasn't been set yet. @@ -170,8 +164,6 @@ scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( webauthn::switches::kRemoteProxiedRequestsAllowedAdditionalOrigin, kExampleOrigin); - scoped_feature_list_.InitAndEnableFeature( - device::kWebAuthnRemoteDesktopAllowedOriginsPolicy); PrefService* prefs = Profile::FromBrowserContext(GetBrowserContext())->GetPrefs(); @@ -191,8 +183,6 @@ TEST_F(OriginMayUseRemoteDesktopClientOverrideTest, AllowedOriginsPolicy_InvalidURLs) { ChromeWebAuthenticationDelegateBase delegate; - scoped_feature_list_.InitAndEnableFeature( - device::kWebAuthnRemoteDesktopAllowedOriginsPolicy); PrefService* prefs = Profile::FromBrowserContext(GetBrowserContext())->GetPrefs(); @@ -225,26 +215,8 @@ } TEST_F(OriginMayUseRemoteDesktopClientOverrideTest, - AllowedOriginsPolicy_FeatureDisabled) { - ChromeWebAuthenticationDelegateBase delegate; - // Feature explicitly disabled. - scoped_feature_list_.InitAndDisableFeature( - device::kWebAuthnRemoteDesktopAllowedOriginsPolicy); - - PrefService* prefs = - Profile::FromBrowserContext(GetBrowserContext())->GetPrefs(); - prefs->SetList(webauthn::pref_names::kRemoteDesktopAllowedOrigins, - base::Value::List().Append(kExampleOrigin)); - - EXPECT_FALSE(delegate.OriginMayUseRemoteDesktopClientOverride( - browser_context(), url::Origin::Create(GURL(kExampleOrigin)))); -} - -TEST_F(OriginMayUseRemoteDesktopClientOverrideTest, AllowedOriginsPolicy_MultipleValidURLs) { ChromeWebAuthenticationDelegateBase delegate; - scoped_feature_list_.InitAndEnableFeature( - device::kWebAuthnRemoteDesktopAllowedOriginsPolicy); PrefService* prefs = Profile::FromBrowserContext(GetBrowserContext())->GetPrefs(); @@ -269,8 +241,6 @@ TEST_F(OriginMayUseRemoteDesktopClientOverrideTest, AllowedOriginsPolicy_SchemePortPathMismatch) { ChromeWebAuthenticationDelegateBase delegate; - scoped_feature_list_.InitAndEnableFeature( - device::kWebAuthnRemoteDesktopAllowedOriginsPolicy); PrefService* prefs = Profile::FromBrowserContext(GetBrowserContext())->GetPrefs();
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index 491e859..45e10c0e 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1750615142-d9184a80be8928f7544a47d00dddd6651104ae64-2fb5013d8b56b7ce1abf4de9f1eb7fd7c30be5cc.profdata +chrome-android32-main-1750658045-50e3c8677b6f20e00f8866d1d5b29fe70ecf9ba0-7018a9aa0e473ed9715ddf370076c0c7b5139b5c.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 175edf4..0bb0e0bb0e 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1750626127-aaf5d63b9ec02a7dcd95b03caa61597f8b0b83d5-66f202f434b2ca5e0d202fde9fe7a068bec361fe.profdata +chrome-android64-main-1750659584-7ba5ed25f0bcfd87fe883085f93dc73702922c8b-c8111d5d605d669b1a6616df216dc310d88d1024.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt index 47255ec..9d4a396 100644 --- a/chrome/build/android-desktop-x64.pgo.txt +++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@ -chrome-android-desktop-x64-main-1750399281-0d6a4fab094e091b031248ed5e363c178368e522-8d1dfcf686439ae4b28eaf59cfed8925b167369d.profdata +chrome-android-desktop-x64-main-1750643961-35e68d17396f6db2bcbc23dd27892cb6240ae0eb-6f8723a37996015adf9f0973cdaed7a179682c44.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 56f24f9..0134b11 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1750615142-3c539fd21f329e5f44652e1d1ef7982b10a308fd-2fb5013d8b56b7ce1abf4de9f1eb7fd7c30be5cc.profdata +chrome-linux-main-1750658045-4ca2511459b7acd028d0ee68bf1451c8837d91f7-7018a9aa0e473ed9715ddf370076c0c7b5139b5c.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 90fe416..1575933 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1750629070-d4c7f48610c9c00fd6cc18bf1cd42ae5cb299944-21ed3aa07ddaa556707b6d6d2c9dda5cd4b0daff.profdata +chrome-mac-arm-main-1750665581-b6aba323566cf03ed56fa8929fc1798d64cbc613-8a68f2ecaf5aae6ccbadd7abf27f71817977390d.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 14a90af..0d70abd 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1750615142-4116698ee1e56c1b794ba1fe54cdd1c033dcf87d-2fb5013d8b56b7ce1abf4de9f1eb7fd7c30be5cc.profdata +chrome-mac-main-1750658045-403688b17121d56327474cfea91854fa5376e640-7018a9aa0e473ed9715ddf370076c0c7b5139b5c.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index 94910ffc..fcaa5e2 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1750615142-ab6989a2826f4da9428e21f685c9f9e4cf7e287d-2fb5013d8b56b7ce1abf4de9f1eb7fd7c30be5cc.profdata +chrome-win-arm64-main-1750635802-275ece283fdf3cb06c9b8885c21d3eb616392b4a-a4d9d8a51958ced830089b4a6ba1b4a8b236c7a1.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index e6d7439..24e746f2 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1750582428-b6a70ce89be11feb19742cc53f99c30197d8642a-f2ba84e7a48046c9491af6a9a064864e6ff1ffe3.profdata +chrome-win32-main-1750625805-eb3eeeb59d884f884116ed13d3ba586ae61010f0-51afbe5ef4c84fa220551fa554021b3c5c6bbfe9.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 96c2312..535ceea 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1750604285-22d0de20cb03f4822cc9db460fe7c02c0eb4ccad-8375b4e94505c046627f98db15a231be538c4de5.profdata +chrome-win64-main-1750635802-21c841cc9744448c18d7f13635e413c8d76d30a8-a4d9d8a51958ced830089b4a6ba1b4a8b236c7a1.profdata
diff --git a/chrome/test/base/testing_profile_manager.cc b/chrome/test/base/testing_profile_manager.cc index 6eecb40b..d565c34 100644 --- a/chrome/test/base/testing_profile_manager.cc +++ b/chrome/test/base/testing_profile_manager.cc
@@ -62,14 +62,6 @@ local_state_ = owned_local_state_.get(); } -TestingProfileManager::TestingProfileManager( - TestingBrowserProcess* process, - ScopedTestingLocalState* local_state) - : called_set_up_(false), - browser_process_(process), - local_state_(local_state), - profile_manager_(nullptr) {} - TestingProfileManager::~TestingProfileManager() { ProfileDestroyer::DestroyPendingProfilesForShutdown();
diff --git a/chrome/test/base/testing_profile_manager.h b/chrome/test/base/testing_profile_manager.h index 860e4412..ac00541f 100644 --- a/chrome/test/base/testing_profile_manager.h +++ b/chrome/test/base/testing_profile_manager.h
@@ -40,8 +40,6 @@ class TestingProfileManager : public ProfileObserver { public: explicit TestingProfileManager(TestingBrowserProcess* browser_process); - TestingProfileManager(TestingBrowserProcess* browser_process, - ScopedTestingLocalState* local_state); TestingProfileManager(const TestingProfileManager&) = delete; TestingProfileManager& operator=(const TestingProfileManager&) = delete; ~TestingProfileManager() override;
diff --git a/chrome/test/v8/OWNERS b/chrome/test/v8/OWNERS index 67907d6..088ab44 100644 --- a/chrome/test/v8/OWNERS +++ b/chrome/test/v8/OWNERS
@@ -1 +1,3 @@ +jkummerow@chromium.org +clemensb@chromium.org ahaas@chromium.org
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 6de97e5..73ff525 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -16327.0.0-1069769 \ No newline at end of file +16327.0.0-1069780 \ No newline at end of file
diff --git a/chromeos/ash/components/account_manager/BUILD.gn b/chromeos/ash/components/account_manager/BUILD.gn index b636dc82..0ceaf5d5 100644 --- a/chromeos/ash/components/account_manager/BUILD.gn +++ b/chromeos/ash/components/account_manager/BUILD.gn
@@ -6,13 +6,18 @@ component("account_manager") { sources = [ + "account_manager_facade_factory.cc", + "account_manager_facade_factory.h", "account_manager_factory.cc", "account_manager_factory.h", ] public_deps = [ "//components/account_manager_core:account_manager_core" ] - deps = [ "//base" ] + deps = [ + "//base", + "//chromeos/crosapi/mojom", + ] defines = [ "IS_CHROMEOS_ASH_COMPONENTS_ACCOUNT_MANAGER_IMPL" ] }
diff --git a/chrome/browser/ash/account_manager/account_manager_facade_factory_ash.cc b/chromeos/ash/components/account_manager/account_manager_facade_factory.cc similarity index 94% rename from chrome/browser/ash/account_manager/account_manager_facade_factory_ash.cc rename to chromeos/ash/components/account_manager/account_manager_facade_factory.cc index a23e367..f55739e 100644 --- a/chrome/browser/ash/account_manager/account_manager_facade_factory_ash.cc +++ b/chromeos/ash/components/account_manager/account_manager_facade_factory.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/account_manager_core/chromeos/account_manager_facade_factory.h" +#include "chromeos/ash/components/account_manager/account_manager_facade_factory.h" #include <limits> #include <map> @@ -15,6 +15,7 @@ #include "components/account_manager_core/chromeos/account_manager.h" #include "components/account_manager_core/chromeos/account_manager_mojo_service.h" +namespace ash { namespace { crosapi::AccountManagerMojoService* GetAccountManagerMojoService( @@ -62,3 +63,5 @@ return it->second.get(); } + +} // namespace ash
diff --git a/chromeos/ash/components/account_manager/account_manager_facade_factory.h b/chromeos/ash/components/account_manager/account_manager_facade_factory.h new file mode 100644 index 0000000..0d9196d3 --- /dev/null +++ b/chromeos/ash/components/account_manager/account_manager_facade_factory.h
@@ -0,0 +1,31 @@ +// Copyright 2020 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_ASH_COMPONENTS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_FACADE_FACTORY_H_ +#define CHROMEOS_ASH_COMPONENTS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_FACADE_FACTORY_H_ + +#include <memory> +#include <string> + +#include "base/compiler_specific.h" +#include "base/component_export.h" + +namespace account_manager { +class AccountManagerFacade; +} // namespace account_manager + +namespace ash { + +// A factory function for getting platform specific implementations of +// |AccountManagerFacade|. +// Returns the |AccountManagerFacade| for the given |profile_path|. +// Note that |AccountManagerFacade| is independent of a |Profile|, and this is +// needed only because of Multi-Login on Chrome OS, and will be removed soon. +COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_ACCOUNT_MANAGER) +account_manager::AccountManagerFacade* GetAccountManagerFacade( + const std::string& profile_path); + +} // namespace ash + +#endif // CHROMEOS_ASH_COMPONENTS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_FACADE_FACTORY_H_
diff --git a/chromeos/crosapi/mojom/login.mojom b/chromeos/crosapi/mojom/login.mojom index e1d9cb1a..a8bf204 100644 --- a/chromeos/crosapi/mojom/login.mojom +++ b/chromeos/crosapi/mojom/login.mojom
@@ -29,14 +29,9 @@ // Next MinVersion: 5 [Uuid="639e9f04-981f-46d1-91da-583c2958265b"] interface Login { - // Exits the current session. If |data_for_next_login_attempt| is provided, - // stores data which can be read by |FetchDataForNextLoginAttempt()|. - ExitCurrentSession@1(string? data_for_next_login_attempt) => (string? error); - - // Reads the |data_for_next_login_attempt| set by |ExitCurrentSession()|. - // Clears the previously stored data after reading so it can only be read - // once. - FetchDataForNextLoginAttempt@2() => (string data); + // ExitCurrentSession@1 was removed. + // FetchDataForNextLoginAttempt@2 was removed. + // SetDataForNextLoginAttempt@9 was removed. // Deprecated. Use |LockCurrentSession()| below. LockManagedGuestSession@3() => (string? error); @@ -47,10 +42,6 @@ // Fails if there is no existing shared session. EndSharedSession@8() => (string? error); - // Sets data for the next login attempt. The data can be retrieved by - // calling |FetchDataForNextLoginAttempt()|. - SetDataForNextLoginAttempt@9(string data_for_next_login_attempt) => (); - // Locks the current session. The session has to be either a user session or a // Managed Guest Session launched by |LaunchManagedGuestSession()| with a // password.
diff --git a/clank b/clank index 9e7cc1f..37813b0f 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 9e7cc1ffbb07d1afe8f3528f10d621b54993c515 +Subproject commit 37813b0fe2b96138bf8f715b42ac30fba422b9d2
diff --git a/components/account_manager_core/BUILD.gn b/components/account_manager_core/BUILD.gn index 56105f5..dd3a468 100644 --- a/components/account_manager_core/BUILD.gn +++ b/components/account_manager_core/BUILD.gn
@@ -24,7 +24,6 @@ "chromeos/access_token_fetcher.h", "chromeos/account_manager.cc", "chromeos/account_manager.h", - "chromeos/account_manager_facade_factory.h", "chromeos/account_manager_mojo_service.cc", "chromeos/account_manager_mojo_service.h", "chromeos/account_manager_ui.cc",
diff --git a/components/account_manager_core/chromeos/account_manager_facade_factory.h b/components/account_manager_core/chromeos/account_manager_facade_factory.h deleted file mode 100644 index 05d8dfb..0000000 --- a/components/account_manager_core/chromeos/account_manager_facade_factory.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright 2020 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_ACCOUNT_MANAGER_CORE_CHROMEOS_ACCOUNT_MANAGER_FACADE_FACTORY_H_ -#define COMPONENTS_ACCOUNT_MANAGER_CORE_CHROMEOS_ACCOUNT_MANAGER_FACADE_FACTORY_H_ - -#include <memory> -#include <string> - -#include "base/compiler_specific.h" -#include "base/component_export.h" - -namespace account_manager { -class AccountManagerFacade; -} // namespace account_manager - -// A factory function for getting platform specific implementations of -// |AccountManagerFacade|. -// Returns the |AccountManagerFacade| for the given |profile_path|. -// Note that |AccountManagerFacade| is independent of a |Profile|, and this is -// needed only because of Multi-Login on Chrome OS, and will be removed soon. -account_manager::AccountManagerFacade* COMPONENT_EXPORT(ACCOUNT_MANAGER_CORE) - GetAccountManagerFacade(const std::string& profile_path); - -#endif // COMPONENTS_ACCOUNT_MANAGER_CORE_CHROMEOS_ACCOUNT_MANAGER_FACADE_FACTORY_H_
diff --git a/components/autofill/core/browser/data_model/autofill_ai/entity_type.cc b/components/autofill/core/browser/data_model/autofill_ai/entity_type.cc index 5dbeb82..65fe1dc0 100644 --- a/components/autofill/core/browser/data_model/autofill_ai/entity_type.cc +++ b/components/autofill/core/browser/data_model/autofill_ai/entity_type.cc
@@ -6,14 +6,22 @@ #include <optional> +#include "base/feature_list.h" #include "base/types/cxx23_to_underlying.h" #include "components/autofill/core/browser/data_model/addresses/contact_info.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/common/autofill_features.h" #include "components/strings/grit/components_strings.h" #include "ui/base/l10n/l10n_util.h" namespace autofill { +FieldType AttributeType::field_type() const { + return base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes) + ? field_type_without_tag_types() + : field_type_with_tag_types(); +} + FieldTypeSet AttributeType::storable_field_types( base::PassKey<EntityTable> pass_key) const { if (data_type() == DataType::kName) {
diff --git a/components/autofill/core/browser/data_model/autofill_ai/entity_type.h b/components/autofill/core/browser/data_model/autofill_ai/entity_type.h index 1b5f8643..6691c5f 100644 --- a/components/autofill/core/browser/data_model/autofill_ai/entity_type.h +++ b/components/autofill/core/browser/data_model/autofill_ai/entity_type.h
@@ -86,7 +86,9 @@ // For name types, `field_subtypes()` includes `NAME_FIRST` etc. // - `storable_field_types()` are the ones that may be physically stored in // the database. - constexpr FieldType field_type() const; + FieldType field_type() const; + constexpr FieldType field_type_with_tag_types() const; + constexpr FieldType field_type_without_tag_types() const; constexpr FieldTypeSet field_subtypes() const; FieldTypeSet storable_field_types(base::PassKey<EntityTable> pass_key) const; @@ -147,7 +149,7 @@ NOTREACHED(); } -constexpr FieldType AttributeType::field_type() const { +constexpr FieldType AttributeType::field_type_with_tag_types() const { switch (name_) { case AttributeTypeName::kPassportName: return PASSPORT_NAME_TAG; @@ -189,11 +191,18 @@ NOTREACHED(); } +constexpr FieldType AttributeType::field_type_without_tag_types() const { + if (data_type() == DataType::kName) { + return NAME_FULL; + } + return field_type_with_tag_types(); +} + constexpr FieldTypeSet AttributeType::field_subtypes() const { if (data_type() == DataType::kName) { return FieldTypesOfGroup(FieldTypeGroup::kName); } - return {field_type()}; + return {field_type_without_tag_types()}; } template <>
diff --git a/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.cc b/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.cc index c8ef750..29d3e6b 100644 --- a/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.cc +++ b/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.cc
@@ -24,9 +24,13 @@ namespace { -using EntityMap = - base::flat_map<EntityType, std::vector<AutofillFieldWithAttributeType>>; -using SectionMap = base::flat_map<Section, EntityMap>; +// The furthest distance between two fields so that one field's AttributeType +// may lead to a dynamic AttributeType assignment of the other. +constexpr int kMaxPropagationDistance = 5; + +bool IsRelevant(const AutofillField& field) { + return field.is_focusable() || field.IsSelectElement(); +} // The set of all FieldTypes that have **more** than one associated // AttributeType. @@ -56,18 +60,37 @@ static_assert(!kNonInjectiveFieldTypes.contains_any( {DRIVERS_LICENSE_EXPIRATION_DATE, PASSPORT_NUMBER, VEHICLE_MODEL})); +// If kAutofillAiNoTagTypes is disabled: +// AttributeType::field_type() must be injective: distinct AttributeTypes must +// be mapped to distinct FieldTypes. +static_assert( + std::ranges::all_of(DenseSet<AttributeType>::all(), [](AttributeType a) { + return std::ranges::all_of( + DenseSet<AttributeType>::all(), [&a](AttributeType b) { + return a == b || a.field_type_with_tag_types() != + b.field_type_with_tag_types(); + }); + })); + +// If kAutofillAiNoTagTypes is enabled: // AttributeType::field_type() must be mostly injective: distinct AttributeTypes // other than `kNonInjectiveFieldTypes` must be mapped to distinct FieldTypes. static_assert( std::ranges::all_of(DenseSet<AttributeType>::all(), [](AttributeType a) { return std::ranges::all_of( DenseSet<AttributeType>::all(), [&a](AttributeType b) { - return a == b || a.field_type() != b.field_type() || - kNonInjectiveFieldTypes.contains(a.field_type()) || - kNonInjectiveFieldTypes.contains(b.field_type()); + return a == b || + a.field_type_without_tag_types() != + b.field_type_without_tag_types() || + kNonInjectiveFieldTypes.contains( + a.field_type_without_tag_types()) || + kNonInjectiveFieldTypes.contains( + b.field_type_without_tag_types()); }); })); +// A field's static AttributeType is the unique AttributeType whose +// AttributeType::field_type() is the field's FieldType. std::optional<AttributeType> GetStaticAttributeType( const AutofillField& field) { std::optional<FieldType> ft = field.GetAutofillAiServerTypePredictions(); @@ -79,7 +102,7 @@ static constexpr auto kTable = []() { std::array<std::optional<AttributeType>, MAX_VALID_FIELD_TYPE> arr{}; for (AttributeType at : DenseSet<AttributeType>::all()) { - arr[at.field_type()] = at; + arr[at.field_type_with_tag_types()] = at; } return arr; }(); @@ -91,8 +114,9 @@ static constexpr auto kTable = []() { std::array<std::optional<AttributeType>, MAX_VALID_FIELD_TYPE> arr{}; for (AttributeType at : DenseSet<AttributeType>::all()) { - if (!kNonInjectiveFieldTypes.contains(at.field_type())) { - arr[at.field_type()] = at; + if (!kNonInjectiveFieldTypes.contains( + at.field_type_without_tag_types())) { + arr[at.field_type_without_tag_types()] = at; } } return arr; @@ -100,69 +124,110 @@ return 0 <= *ft && *ft < kTable.size() ? kTable[*ft] : std::nullopt; } -// The `i`th element of the returned vector contains the type of `fields[i]`. -std::vector<std::optional<AttributeType>> GetStaticAttributeTypes( +// A field is assignable a dynamic AttributeType if there are more than one +// AttributeTypes whose AttributeType::field_type() is the field's FieldType. +bool IsAssignableDynamicAttributeType(FieldType ft) { + return kNonInjectiveFieldTypes.contains(ft); +} + +std::optional<AttributeType> GetAttributeType(EntityType entity, + FieldType field_type) { + for (AttributeType at : entity.attributes()) { + if (at.field_subtypes().contains(field_type)) { + return at; + } + } + return std::nullopt; +} + +// Adds to `attributes_by_field[i]` the static types of `fields[i]`. +void AddStaticAttributeTypes( base::span<const std::unique_ptr<AutofillField>> fields, - base::optional_ref<const Section> section_of_interest, - base::optional_ref<const EntityType> entity_of_interest) { - std::vector<std::optional<AttributeType>> field_to_type; - field_to_type.resize(fields.size()); - for (size_t i = 0; i < fields.size(); ++i) { - if (section_of_interest && *section_of_interest != fields[i]->section()) { + base::span<DenseSet<AttributeType>> attributes_by_field) { + DCHECK_EQ(fields.size(), attributes_by_field.size()); + for (auto [field, attributes] : base::zip(fields, attributes_by_field)) { + if (!IsRelevant(*field)) { continue; } - std::optional<AttributeType> at = GetStaticAttributeType(*fields[i]); + std::optional<AttributeType> at = GetStaticAttributeType(*field); if (!at) { continue; } - if (entity_of_interest && *entity_of_interest != at->entity_type()) { - continue; - } - field_to_type[i] = at; + attributes.insert(*at); } - return field_to_type; } -// The `i`th element of the returned vector contains the type of `fields[i]`. -std::vector<std::vector<AttributeType>> GetDynamicAttributeTypes( +// Adds to `attributes_by_field[i]` the dynamic types of `fields[i]`. +void AddDynamicAttributeTypes( base::span<const std::unique_ptr<AutofillField>> fields, - base::span<const std::optional<AttributeType>> stc_types, - base::optional_ref<const Section> section_of_interest, - base::optional_ref<const EntityType> entity_of_interest) { - std::vector<std::vector<AttributeType>> dyn_types; - dyn_types.resize(fields.size()); - - if (!base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes)) { - return dyn_types; + base::span<DenseSet<AttributeType>> attributes_by_field) { + DCHECK_EQ(fields.size(), attributes_by_field.size()); + if (!base::FeatureList::IsEnabled(features::kAutofillAiNoTagTypes) || + std::ranges::all_of(attributes_by_field, + &DenseSet<AttributeType>::empty)) { + return; } - // TODO(crbug.com/422563282): Implement. - return dyn_types; + // Propagates the applicable EntityTypes in `last_seen` to the `attributes` of + // `field`. + // + // This function is to be called in sequence for a range of AutofillFields. + // `offset` counts how many relevant AutofillFields were encountered so far. + // `last_seen` maps the EntityTypes and Sections to the maximum offset where + // they were seen so far. + auto loop_body = [](std::map<std::pair<Section, EntityType>, int>& last_seen, + int& offset, const AutofillField& field, + DenseSet<AttributeType>& attributes) { + if (!IsRelevant(field)) { + return; + } + ++offset; + const FieldType field_type = field.Type().GetStorableType(); + if (IsAssignableDynamicAttributeType(field_type)) { + for (const auto& [p, entity_offset] : last_seen) { + const auto& [entity_section, entity] = p; + if (std::abs(entity_offset - offset) > kMaxPropagationDistance || + entity_section != field.section()) { + continue; + } + if (const std::optional<AttributeType> attribute = + GetAttributeType(entity, field_type)) { + attributes.insert(*attribute); + } + } + } + for (AttributeType attribute : attributes) { + last_seen[{field.section(), attribute.entity_type()}] = offset; + } + }; + + // Propagate types forward and backward. + const int num_fields = static_cast<int>(fields.size()); + { + std::map<std::pair<Section, EntityType>, int> last_seen; + int offset = 0; + for (int i = 0; i < num_fields; ++i) { + loop_body(last_seen, offset, *fields[i], attributes_by_field[i]); + } + } + { + std::map<std::pair<Section, EntityType>, int> last_seen; + int offset = 0; + for (int i = num_fields - 1; i >= 0; --i) { + loop_body(last_seen, offset, *fields[i], attributes_by_field[i]); + } + } } -// Merges the static and dynamic AttributeTypes and calls `cb(field, type)` for -// every possible `type` of `field`. -template <typename Callback> -void GetAttributeTypes(base::span<const std::unique_ptr<AutofillField>> fields, - base::optional_ref<const Section> section_of_interest, - base::optional_ref<const EntityType> entity_of_interest, - Callback cb) { - std::vector<std::optional<AttributeType>> stc_types_by_field = - GetStaticAttributeTypes(fields, section_of_interest, entity_of_interest); - std::vector<std::vector<AttributeType>> dyn_types_by_field = - GetDynamicAttributeTypes(fields, stc_types_by_field, section_of_interest, - entity_of_interest); - for (auto [field, stc_type, dyn_types] : - base::zip(fields, stc_types_by_field, dyn_types_by_field)) { - if (stc_type) { - DCHECK(dyn_types.empty()); - std::invoke(cb, *field, *stc_type); - } - for (AttributeType dyn_type : dyn_types) { - DCHECK(!stc_type); - std::invoke(cb, *field, dyn_type); - } - } +// Returns the static and dynamic AttributeTypes. +// The `i`th value in the returned vector is the dynamic type of `fields[i]`. +std::vector<DenseSet<AttributeType>> GetAttributeTypes( + base::span<const std::unique_ptr<AutofillField>> fields) { + std::vector<DenseSet<AttributeType>> attributes_by_field; + attributes_by_field.resize(fields.size()); + AddStaticAttributeTypes(fields, attributes_by_field); + AddDynamicAttributeTypes(fields, attributes_by_field); + return attributes_by_field; } } // namespace @@ -171,36 +236,54 @@ base::span<const std::unique_ptr<AutofillField>> fields LIFETIME_BOUND, const Section& section_of_interest, EntityType entity_of_interest) { - std::vector<AutofillFieldWithAttributeType> c; - GetAttributeTypes(fields, section_of_interest, entity_of_interest, - [&](const AutofillField& field, AttributeType type) { - c.emplace_back(field, type); - }); - return c; + const std::vector<DenseSet<AttributeType>> attributes_by_field = + GetAttributeTypes(fields); + std::vector<AutofillFieldWithAttributeType> r; + for (auto [field, attributes] : base::zip(fields, attributes_by_field)) { + if (!section_of_interest || field->section() == section_of_interest) { + for (AttributeType attribute : attributes) { + if (entity_of_interest == attribute.entity_type()) { + r.emplace_back(*field, attribute); + } + } + } + } + return r; } +using EntityMap = + base::flat_map<EntityType, std::vector<AutofillFieldWithAttributeType>>; + EntityMap DetermineAttributeTypes( base::span<const std::unique_ptr<AutofillField>> fields LIFETIME_BOUND, const Section& section_of_interest) { - EntityMap c; - GetAttributeTypes(fields, section_of_interest, - /*entity_of_interest=*/std::nullopt, - [&](const AutofillField& field, AttributeType type) { - c[type.entity_type()].emplace_back(field, type); - }); - return c; + const std::vector<DenseSet<AttributeType>> attributes_by_field = + GetAttributeTypes(fields); + EntityMap r; + for (auto [field, attributes] : base::zip(fields, attributes_by_field)) { + if (!section_of_interest || field->section() == section_of_interest) { + for (AttributeType attribute : attributes) { + r[attribute.entity_type()].emplace_back(*field, attribute); + } + } + } + return r; } +using SectionMap = base::flat_map<Section, EntityMap>; + SectionMap DetermineAttributeTypes( base::span<const std::unique_ptr<AutofillField>> fields LIFETIME_BOUND) { - SectionMap c; - GetAttributeTypes(fields, /*section_of_interest=*/std::nullopt, - /*entity_of_interest=*/std::nullopt, - [&](const AutofillField& field, AttributeType type) { - c[field.section()][type.entity_type()].emplace_back(field, - type); - }); - return c; + const std::vector<DenseSet<AttributeType>> attributes_by_field = + GetAttributeTypes(fields); + SectionMap r; + for (auto [field, attributes] : base::zip(fields, attributes_by_field)) { + for (AttributeType attribute : attributes) { + r[field->section()][attribute.entity_type()].emplace_back(*field, + attribute); + } + } + return r; } } // namespace autofill
diff --git a/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.h b/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.h index e918af07..a157809d 100644 --- a/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.h +++ b/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types.h
@@ -34,13 +34,20 @@ // (AutofillField::GetAutofillAiServerTypePredictions()). // Every field has at most one static AttributeType. // -// Dynamic types are determined by looking at the surrounding fields. -// (AutofillField::GetAutofillAiServerTypePredictions()). -// Every field has at most one static AttributeType. +// Dynamic types are determined by propagating types to neighboring fields as +// follows: a target field is assigned an AttributeType if +// - the source field has been assigned an AttributeType that belongs to the +// same EntityType, and +// - the target field's FieldType is one of the target field's AttributeType's +// subtypes (AttributeType::field_subtype()). +// We only propagate between pairs of fields that are in the same section and +// whose distance is at most 5. // // Dynamic types are only determined if `features::kAutofillAiNoTagTypes` is // enabled. // +// Invisible non-<select> fields are ignored; they're not assigned any type. +// // The overloads are just specializations of one another for performance // reasons. The following expressions are equivalent: // - `DetermineAttributeTypes(fields, section, entity)`
diff --git a/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types_unittest.cc b/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types_unittest.cc index 4b78bec..7f55f26 100644 --- a/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types_unittest.cc +++ b/components/autofill/core/browser/form_processing/autofill_ai/determine_attribute_types_unittest.cc
@@ -21,6 +21,10 @@ namespace autofill { +void PrintTo(const AutofillFieldWithAttributeType& f, ::std::ostream* os) { + *os << f.field->global_id() << " -> " << f.type.name_as_string(); +} + namespace { using ::testing::_; @@ -42,14 +46,20 @@ std::vector<std::unique_ptr<AutofillField>> fields = base::ToVector(field_types, [](const std::vector<FieldType>& fts) { auto field = std::make_unique<AutofillField>( - test::CreateFieldByRole(!fts.empty() ? fts.front() : EMPTY_TYPE)); + test::GetFormFieldData(test::FieldDescription( + {.role = !fts.empty() ? fts.front() : EMPTY_TYPE}))); field->set_server_predictions( base::ToVector(fts, [](const FieldType ft) { return test::CreateFieldPrediction(ft); })); return field; }); - AssignSections(fields); + + base::flat_map<LocalFrameToken, size_t> frame_tokens; + for (auto& field : fields) { + field->set_section( + Section::FromFieldIdentifier(*fields.front(), frame_tokens)); + } return fields; } @@ -64,15 +74,20 @@ Field(&AutofillFieldWithAttributeType::type, type)); } +class DetermineAttributeTypesTest : public testing::Test { + private: + autofill::test::AutofillUnitTestEnvironment autofill_environment_; +}; + // Tests that DetermineAttributeTypes() doesn't crash on empty lists. -TEST(DetermineAttributeTypesTest, ToleratesEmptyList) { +TEST_F(DetermineAttributeTypesTest, ToleratesEmptyList) { EXPECT_THAT(DetermineAttributeTypes({}), IsEmpty()); EXPECT_THAT(DetermineAttributeTypes({}, Section()), IsEmpty()); EXPECT_THAT(DetermineAttributeTypes({}, Section(), kPassport), IsEmpty()); } // Tests that DetermineAttributeTypes() is empty on forms that have no entities. -TEST(DetermineAttributeTypesTest, IsEmptyInUnrelatedForm) { +TEST_F(DetermineAttributeTypesTest, IsEmptyInUnrelatedForm) { std::vector<std::unique_ptr<AutofillField>> fields = CreateFields({ {NAME_FULL}, {ADDRESS_HOME_LINE1}, @@ -90,8 +105,7 @@ } // Tests that DetermineAttributeTypes() processes `*_TAG` correctly if -TEST(DetermineAttributeTypesTest, LegacyBehavior) { - base::test::ScopedFeatureList features_{features::kAutofillAiNoTagTypes}; +TEST_F(DetermineAttributeTypesTest, LegacyBehavior) { base::test::ScopedFeatureList feature_list; feature_list.InitAndDisableFeature(features::kAutofillAiNoTagTypes); @@ -114,34 +128,373 @@ FieldAndType(fields[4], AttributeType(kDriversLicenseName)), FieldAndType(fields[5], AttributeType(kDriversLicenseNumber)), FieldAndType(fields[6], AttributeType(kDriversLicenseExpirationDate))); + const Section section = fields.front()->section(); // DetermineAttributeTypes() overload with Section and AttributeType. - EXPECT_THAT( - DetermineAttributeTypes(fields, fields.front()->section(), kVehicle), - vehicle_matcher); - EXPECT_THAT(DetermineAttributeTypes(fields, fields.front()->section(), - kDriversLicense), + EXPECT_THAT(DetermineAttributeTypes(fields, section, kVehicle), + vehicle_matcher); + EXPECT_THAT(DetermineAttributeTypes(fields, section, kDriversLicense), drivers_license_matcher); - EXPECT_THAT( - DetermineAttributeTypes(fields, fields.front()->section(), kPassport), - IsEmpty()); - // DetermineAttributeTypes() overload with Section, without AttributeType. + // DetermineAttributeTypes() overload with Section, without EntityType. EXPECT_THAT( - DetermineAttributeTypes(fields, fields.front()->section()), + DetermineAttributeTypes(fields, section), UnorderedElementsAre(Pair(kVehicle, vehicle_matcher), Pair(kDriversLicense, drivers_license_matcher))); // DetermineAttributeTypes() overload without Section and AttributeType. + EXPECT_THAT( + DetermineAttributeTypes(fields), + UnorderedElementsAre( + Pair(section, UnorderedElementsAre( + Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))))); +} + +// Tests that DetermineAttributeTypes() assigns static types correctly. +TEST_F(DetermineAttributeTypesTest, AssignsStaticTypes) { + base::test::ScopedFeatureList feature_list{features::kAutofillAiNoTagTypes}; + + std::vector<std::unique_ptr<AutofillField>> fields = CreateFields({ + {DRIVERS_LICENSE_NUMBER}, + {VEHICLE_MAKE}, + {VEHICLE_MODEL}, + {DRIVERS_LICENSE_EXPIRATION_DATE}, + {ADDRESS_HOME_ZIP}, + }); + + using enum AttributeTypeName; + auto vehicle_matcher = + ElementsAre(FieldAndType(fields[1], AttributeType(kVehicleMake)), + FieldAndType(fields[2], AttributeType(kVehicleModel))); + auto drivers_license_matcher = ElementsAre( + FieldAndType(fields[0], AttributeType(kDriversLicenseNumber)), + FieldAndType(fields[3], AttributeType(kDriversLicenseExpirationDate))); + const Section section = fields.front()->section(); + + // DetermineAttributeTypes() overload with Section and AttributeType. + EXPECT_THAT(DetermineAttributeTypes(fields, section, kVehicle), + vehicle_matcher); + EXPECT_THAT(DetermineAttributeTypes(fields, section, kDriversLicense), + drivers_license_matcher); + + // DetermineAttributeTypes() overload with Section, without EntityType. + EXPECT_THAT( + DetermineAttributeTypes(fields, section), + UnorderedElementsAre(Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))); + + // DetermineAttributeTypes() overload without Section and AttributeType. + EXPECT_THAT( + DetermineAttributeTypes(fields), + UnorderedElementsAre( + Pair(section, UnorderedElementsAre( + Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))))); +} + +// Tests that DetermineAttributeTypes() assigns dynamic types correctly: +// - It must look at both the forward and backward vicinity. +// - Fields can have multiple types simultaneously. +TEST_F(DetermineAttributeTypesTest, AssignsDynamicTypesToTheVicinity) { + base::test::ScopedFeatureList features_list{features::kAutofillAiNoTagTypes}; + + // The NAME_{FIRST,MIDDLE,LAST} fields are expected to be assigned to both the + // vehicle and the driver's license entities. + std::vector<std::unique_ptr<AutofillField>> fields = CreateFields({ + {VEHICLE_MAKE}, + {VEHICLE_MODEL}, + {NAME_FIRST}, + {NAME_MIDDLE}, + {NAME_LAST}, + {DRIVERS_LICENSE_NUMBER}, + {DRIVERS_LICENSE_EXPIRATION_DATE}, + }); + + using enum AttributeTypeName; + auto vehicle_matcher = + ElementsAre(FieldAndType(fields[0], AttributeType(kVehicleMake)), + FieldAndType(fields[1], AttributeType(kVehicleModel)), + FieldAndType(fields[2], AttributeType(kVehicleOwner)), + FieldAndType(fields[3], AttributeType(kVehicleOwner)), + FieldAndType(fields[4], AttributeType(kVehicleOwner))); + auto drivers_license_matcher = ElementsAre( + FieldAndType(fields[2], AttributeType(kDriversLicenseName)), + FieldAndType(fields[3], AttributeType(kDriversLicenseName)), + FieldAndType(fields[4], AttributeType(kDriversLicenseName)), + FieldAndType(fields[5], AttributeType(kDriversLicenseNumber)), + FieldAndType(fields[6], AttributeType(kDriversLicenseExpirationDate))); + const Section section = fields.front()->section(); + + // DetermineAttributeTypes() overload with Section and AttributeType. + EXPECT_THAT(DetermineAttributeTypes(fields, section, kVehicle), + vehicle_matcher); + EXPECT_THAT(DetermineAttributeTypes(fields, section, kDriversLicense), + drivers_license_matcher); + + // DetermineAttributeTypes() overload with Section, without EntityType. + EXPECT_THAT( + DetermineAttributeTypes(fields, section), + UnorderedElementsAre(Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))); + + // DetermineAttributeTypes() overload without Section and AttributeType. + EXPECT_THAT( + DetermineAttributeTypes(fields), + UnorderedElementsAre( + Pair(section, UnorderedElementsAre( + Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))))); +} + +// Tests that DetermineAttributeTypes() propagates dynamic types forward. +TEST_F(DetermineAttributeTypesTest, PropagatesDynamicTypesForward) { + base::test::ScopedFeatureList features_list{features::kAutofillAiNoTagTypes}; + using enum AttributeTypeName; + + // The last NAME_FULL field is too far away to be reached by the propagation. + std::vector<std::unique_ptr<AutofillField>> fields = CreateFields({ + {VEHICLE_MAKE}, {UNKNOWN_TYPE}, {NAME_FULL}, {UNKNOWN_TYPE}, + {UNKNOWN_TYPE}, {NAME_FULL}, {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, + {UNKNOWN_TYPE}, {NAME_FULL}, {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, + {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {NAME_FULL}, {UNKNOWN_TYPE}, + {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, + {NAME_FULL}, + }); + + auto vehicle_matcher = + ElementsAre(FieldAndType(fields[0], AttributeType(kVehicleMake)), + FieldAndType(fields[2], AttributeType(kVehicleOwner)), + FieldAndType(fields[5], AttributeType(kVehicleOwner)), + FieldAndType(fields[9], AttributeType(kVehicleOwner)), + FieldAndType(fields[14], AttributeType(kVehicleOwner))); + const Section section = fields.front()->section(); + EXPECT_THAT(DetermineAttributeTypes(fields, section, kVehicle), + vehicle_matcher); +} + +// Tests that DetermineAttributeTypes() propagates dynamic types backward. +TEST_F(DetermineAttributeTypesTest, PropagatesDynamicTypesBackward) { + base::test::ScopedFeatureList features_list{features::kAutofillAiNoTagTypes}; + using enum AttributeTypeName; + + // The last NAME_FULL field is too far away to be reached by the propagation. + std::vector<std::unique_ptr<AutofillField>> fields = CreateFields({ + {NAME_FULL}, {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, + {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {NAME_FULL}, {UNKNOWN_TYPE}, + {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {NAME_FULL}, + {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {NAME_FULL}, + {UNKNOWN_TYPE}, {UNKNOWN_TYPE}, {NAME_FULL}, {UNKNOWN_TYPE}, + {VEHICLE_MAKE}, + }); + + auto vehicle_matcher = + ElementsAre(FieldAndType(fields[6], AttributeType(kVehicleOwner)), + FieldAndType(fields[11], AttributeType(kVehicleOwner)), + FieldAndType(fields[15], AttributeType(kVehicleOwner)), + FieldAndType(fields[18], AttributeType(kVehicleOwner)), + FieldAndType(fields[20], AttributeType(kVehicleMake))); + const Section section = fields.front()->section(); + EXPECT_THAT(DetermineAttributeTypes(fields, section, kVehicle), + vehicle_matcher); +} + +// Tests that DetermineAttributeTypes() propagates dynamic types even if there +// are other entities between the source and target. +TEST_F(DetermineAttributeTypesTest, + PropagatesDynamicTypesForwardAcrossEntities) { + base::test::ScopedFeatureList features_list{features::kAutofillAiNoTagTypes}; + using enum AttributeTypeName; + + std::vector<std::unique_ptr<AutofillField>> fields = + CreateFields({{DRIVERS_LICENSE_NUMBER}, {VEHICLE_VIN}, {NAME_FULL}}); + + auto drivers_license_matcher = + ElementsAre(FieldAndType(fields[0], AttributeType(kDriversLicenseNumber)), + FieldAndType(fields[2], AttributeType(kDriversLicenseName))); + auto vehicle_matcher = + ElementsAre(FieldAndType(fields[1], AttributeType(kVehicleVin)), + FieldAndType(fields[2], AttributeType(kVehicleOwner))); + const Section section = fields.front()->section(); + + // DetermineAttributeTypes() overload with Section and AttributeType. + EXPECT_THAT(DetermineAttributeTypes(fields, section, kVehicle), + vehicle_matcher); + EXPECT_THAT(DetermineAttributeTypes(fields, section, kDriversLicense), + drivers_license_matcher); + + // DetermineAttributeTypes() overload with Section, without EntityType. + EXPECT_THAT( + DetermineAttributeTypes(fields, section), + UnorderedElementsAre(Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))); + + // DetermineAttributeTypes() overload without Section and AttributeType. + EXPECT_THAT( + DetermineAttributeTypes(fields), + UnorderedElementsAre( + Pair(section, UnorderedElementsAre( + Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))))); +} + +// Tests that DetermineAttributeTypes() propagates dynamic types even if there +// are other entities between the source and target. +TEST_F(DetermineAttributeTypesTest, + PropagatesDynamicTypesBackwardAcrossEntities) { + base::test::ScopedFeatureList features_list{features::kAutofillAiNoTagTypes}; + using enum AttributeTypeName; + + std::vector<std::unique_ptr<AutofillField>> fields = + CreateFields({{NAME_FULL}, {DRIVERS_LICENSE_NUMBER}, {VEHICLE_VIN}}); + + auto drivers_license_matcher = ElementsAre( + FieldAndType(fields[0], AttributeType(kDriversLicenseName)), + FieldAndType(fields[1], AttributeType(kDriversLicenseNumber))); + auto vehicle_matcher = + ElementsAre(FieldAndType(fields[0], AttributeType(kVehicleOwner)), + FieldAndType(fields[2], AttributeType(kVehicleVin))); + const Section section = fields.front()->section(); + + // DetermineAttributeTypes() overload with Section and AttributeType. + EXPECT_THAT(DetermineAttributeTypes(fields, section, kVehicle), + vehicle_matcher); + EXPECT_THAT(DetermineAttributeTypes(fields, section, kDriversLicense), + drivers_license_matcher); + + // DetermineAttributeTypes() overload with Section, without EntityType. + EXPECT_THAT( + DetermineAttributeTypes(fields, section), + UnorderedElementsAre(Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))); + + // DetermineAttributeTypes() overload without Section and AttributeType. + EXPECT_THAT( + DetermineAttributeTypes(fields), + UnorderedElementsAre( + Pair(section, UnorderedElementsAre( + Pair(kVehicle, vehicle_matcher), + Pair(kDriversLicense, drivers_license_matcher))))); +} + +// Tests that DetermineAttributeTypes() isolates fields from different sections +// from another. +TEST_F(DetermineAttributeTypesTest, DistinguishesBetweenSections) { + base::test::ScopedFeatureList features_list{features::kAutofillAiNoTagTypes}; + + std::vector<std::unique_ptr<AutofillField>> fields = CreateFields({ + {NAME_FIRST}, + {NAME_MIDDLE}, + {NAME_LAST}, + {VEHICLE_MAKE}, + {VEHICLE_MODEL}, + {NAME_FIRST}, + {NAME_MIDDLE}, + {NAME_LAST}, + {DRIVERS_LICENSE_NUMBER}, + {DRIVERS_LICENSE_EXPIRATION_DATE}, + }); + AssignSections(fields); + + using enum AttributeTypeName; + auto vehicle_matcher = + ElementsAre(FieldAndType(fields[0], AttributeType(kVehicleOwner)), + FieldAndType(fields[1], AttributeType(kVehicleOwner)), + FieldAndType(fields[2], AttributeType(kVehicleOwner)), + FieldAndType(fields[3], AttributeType(kVehicleMake)), + FieldAndType(fields[4], AttributeType(kVehicleModel))); + auto drivers_license_matcher = ElementsAre( + FieldAndType(fields[5], AttributeType(kDriversLicenseName)), + FieldAndType(fields[6], AttributeType(kDriversLicenseName)), + FieldAndType(fields[7], AttributeType(kDriversLicenseName)), + FieldAndType(fields[8], AttributeType(kDriversLicenseNumber)), + FieldAndType(fields[9], AttributeType(kDriversLicenseExpirationDate))); + const Section vehicle_section = fields[0]->section(); + const Section drivers_license_section = fields[5]->section(); + ASSERT_NE(vehicle_section, drivers_license_section); + + // DetermineAttributeTypes() overload with Section and AttributeType. + EXPECT_THAT(DetermineAttributeTypes(fields, vehicle_section, kVehicle), + vehicle_matcher); + EXPECT_THAT(DetermineAttributeTypes(fields, vehicle_section, kDriversLicense), + IsEmpty()); + EXPECT_THAT( + DetermineAttributeTypes(fields, drivers_license_section, kDriversLicense), + drivers_license_matcher); + EXPECT_THAT( + DetermineAttributeTypes(fields, drivers_license_section, kVehicle), + IsEmpty()); + + // DetermineAttributeTypes() overload with Section, without EntityType. + EXPECT_THAT(DetermineAttributeTypes(fields, vehicle_section), + UnorderedElementsAre(Pair(kVehicle, vehicle_matcher))); + EXPECT_THAT( + DetermineAttributeTypes(fields, drivers_license_section), + UnorderedElementsAre(Pair(kDriversLicense, drivers_license_matcher))); + + // DetermineAttributeTypes() overload without Section and AttributeType. + EXPECT_THAT( + DetermineAttributeTypes(fields), + UnorderedElementsAre( + Pair(vehicle_section, ElementsAre(Pair(kVehicle, vehicle_matcher))), + Pair(drivers_license_section, + ElementsAre(Pair(kDriversLicense, drivers_license_matcher))))); +} + +// Tests for that the overloads behave equivalently: +// - `DetermineAttributeTypes(fields, section, entity)` +// - `DetermineAttributeTypes(fields, section)[entity]` +// - `DetermineAttributeTypes(fields)[section][entity]` +TEST_F(DetermineAttributeTypesTest, OverloadEquivalence) { + base::test::ScopedFeatureList features_list{features::kAutofillAiNoTagTypes}; + + // We create four fields such that + // - `field[0]` propagates to `field[2]` and + // - `field[3]` propagates to `field[1]`. + // In particular, one propagation should not block the other. + std::vector<std::unique_ptr<AutofillField>> fields = CreateFields({ + {VEHICLE_MAKE}, + {NAME_FULL}, + {NAME_FULL}, + {DRIVERS_LICENSE_NUMBER}, + }); + base::flat_map<LocalFrameToken, size_t> frame_tokens; + Section section1 = Section::FromFieldIdentifier(*fields[0], frame_tokens); + Section section2 = Section::FromFieldIdentifier(*fields[2], frame_tokens); + ASSERT_NE(section1, section2); + fields[0]->set_section(section1); + fields[1]->set_section(section2); + fields[2]->set_section(section1); + fields[3]->set_section(section2); + + using enum AttributeTypeName; + auto vehicle_matcher = + ElementsAre(FieldAndType(fields[0], AttributeType(kVehicleMake)), + FieldAndType(fields[2], AttributeType(kVehicleOwner))); + auto drivers_license_matcher = ElementsAre( + FieldAndType(fields[1], AttributeType(kDriversLicenseName)), + FieldAndType(fields[3], AttributeType(kDriversLicenseNumber))); + + EXPECT_THAT(DetermineAttributeTypes(fields, section1, kVehicle), + vehicle_matcher); + EXPECT_THAT(DetermineAttributeTypes(fields, section2, kVehicle), IsEmpty()); + EXPECT_THAT(DetermineAttributeTypes(fields, section1, kDriversLicense), + IsEmpty()); + EXPECT_THAT(DetermineAttributeTypes(fields, section2, kDriversLicense), + drivers_license_matcher); + + // DetermineAttributeTypes() overload with Section, without EntityType. + EXPECT_THAT(DetermineAttributeTypes(fields, section1), + ElementsAre(Pair(kVehicle, vehicle_matcher))); + EXPECT_THAT(DetermineAttributeTypes(fields, section2), + ElementsAre(Pair(kDriversLicense, drivers_license_matcher))); + + // DetermineAttributeTypes() overload without Section and AttributeType. EXPECT_THAT(DetermineAttributeTypes(fields), UnorderedElementsAre( - Pair(fields.front()->section(), - UnorderedElementsAre( - Pair(kVehicle, vehicle_matcher), - Pair(kDriversLicense, drivers_license_matcher))))); - EXPECT_THAT(DetermineAttributeTypes({}, Section(), - EntityType(EntityTypeName::kPassport)), - IsEmpty()); + Pair(section1, ElementsAre(Pair(kVehicle, vehicle_matcher))), + Pair(section2, ElementsAre(Pair(kDriversLicense, + drivers_license_matcher))))); } } // namespace
diff --git a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager.cc b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager.cc index e8b4308..e74deef 100644 --- a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager.cc +++ b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_manager.cc
@@ -372,8 +372,7 @@ const AutofillField* autofill_field = form.GetFieldById(trigger_field.global_id()); - if (!autofill_field || - !autofill_field->GetAutofillAiServerTypePredictions()) { + if (!autofill_field) { return {}; }
diff --git a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions_unittest.cc b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions_unittest.cc index c93bb92d..b5311c7b 100644 --- a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions_unittest.cc +++ b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions_unittest.cc
@@ -4,25 +4,24 @@ #include "components/autofill/core/browser/integrators/autofill_ai/autofill_ai_suggestions.h" +#include <optional> #include <ranges> #include <string> -#include <variant> #include "base/check.h" -#include "base/containers/contains.h" #include "base/containers/span.h" #include "base/containers/to_vector.h" -#include "base/strings/utf_string_conversions.h" +#include "base/types/optional_ref.h" #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/data_model/autofill_ai/entity_instance.h" #include "components/autofill/core/browser/data_model/autofill_ai/entity_type.h" #include "components/autofill/core/browser/data_model/autofill_ai/entity_type_names.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/suggestions/suggestion_test_helpers.h" #include "components/autofill/core/browser/suggestions/suggestion_type.h" #include "components/autofill/core/browser/test_utils/autofill_form_test_utils.h" #include "components/autofill/core/browser/test_utils/autofill_test_utils.h" -#include "components/autofill/core/common/unique_ids.h" #include "testing/gtest/include/gtest/gtest.h" namespace autofill { @@ -31,10 +30,13 @@ using FieldPrediction = AutofillQueryResponse::FormSuggestion::FieldSuggestion::FieldPrediction; -using ::testing::Ge; +using ::testing::Contains; +using ::testing::ElementsAre; +using ::testing::Field; using ::testing::IsEmpty; +using ::testing::Matcher; using ::testing::Not; -using ::testing::SizeIs; +using ::testing::ResultOf; constexpr char kAppLocaleUS[] = "en-US"; @@ -51,352 +53,286 @@ return test::GetVehicleEntityInstance(options); } +Matcher<const Suggestion&> HasMainText(const std::u16string& text) { + return ResultOf( + "Suggestion::main_text.value", + [](const Suggestion& s) { return s.main_text.value; }, text); +} + +Matcher<const Suggestion&> HasLabel(const std::u16string& label) { + return Field( + &Suggestion::labels, + ElementsAre(ElementsAre(Field(&Suggestion::Text::value, label)))); +} + +Matcher<const Suggestion&> HasType(SuggestionType type) { + return Field("Suggestion::type", &Suggestion::type, type); +} + +auto SuggestionsAre(auto&&... matchers) { + return ElementsAre(std::forward<decltype(matchers)>(matchers)..., + HasType(SuggestionType::kSeparator), + HasType(SuggestionType::kManageAutofillAi)); +} + class AutofillAiSuggestionsTest : public testing::Test { + public: + void SetEntities(std::vector<EntityInstance> entities) { + entities_ = std::move(entities); + } + + // Sets the form to one whose `i`th field has types `multiple_field_types[i]`. + void SetForm( + const std::vector<std::vector<FieldType>>& multiple_field_types) { + test::FormDescription form_description; + for (std::vector<FieldType> field_types : multiple_field_types) { + FieldType type = field_types.empty() ? UNKNOWN_TYPE : field_types[0]; + form_description.fields.emplace_back( + test::FieldDescription({.role = type})); + } + form_structure_.emplace(test::GetFormData(form_description)); + CHECK_EQ(multiple_field_types.size(), form_structure_->field_count()); + for (size_t i = 0; i < form_structure_->field_count(); i++) { + form_structure_->field(i)->set_server_predictions( + base::ToVector(multiple_field_types[i], [](FieldType type) { + FieldPrediction prediction; + prediction.set_type(type); + return prediction; + })); + } + } + + // Sets the form to one whose `i`th field has type `field_types[i]`. + void SetForm(const std::vector<FieldType>& field_types) { + SetForm(base::ToVector(field_types, [](FieldType type) { + return std::vector<FieldType>({type}); + })); + } + + AutofillField& field(size_t i) { return *form_structure_->fields()[i]; } + + std::optional<std::u16string> GetFillValueForField( + const Suggestion::AutofillAiPayload& payload, + const AutofillField& field) { + auto entity_it = + std::ranges::find(entities_, payload.guid, &EntityInstance::guid); + if (entity_it == entities_.end()) { + return std::nullopt; + } + auto attribute_it = std::ranges::find_if( + entity_it->attributes(), [&field](const AttributeInstance& attribute) { + return attribute.type().field_type() == + field.GetAutofillAiServerTypePredictions(); + }); + if (attribute_it == entity_it->attributes().end()) { + return std::nullopt; + } + return attribute_it->GetInfo(field.Type().GetStorableType(), kAppLocaleUS, + field.format_string()); + } + + std::vector<Suggestion> CreateFillingSuggestions(const AutofillField& field) { + return autofill::CreateFillingSuggestions(*form_structure_, field, + entities_, kAppLocaleUS); + } + private: test::AutofillUnitTestEnvironment autofill_test_environment_; + std::vector<EntityInstance> entities_; + std::optional<FormStructure> form_structure_; }; -size_t CountFillingSuggestions(base::span<const Suggestion> suggestions) { - return std::ranges::count_if(suggestions, [](const Suggestion& suggestion) { - return suggestion.type == SuggestionType::kFillAutofillAi; - }); +std::u16string GetPassportName(const EntityInstance& entity) { + return entity.attribute(AttributeType(AttributeTypeName::kPassportName)) + ->GetCompleteInfo(kAppLocaleUS); } -std::u16string GetEntityInstanceValue( - const EntityInstance entity, - AttributeType attribute, - const std::string& app_locale = kAppLocaleUS) { - return entity.attribute(attribute)->GetCompleteInfo(app_locale); +std::u16string GetPassportNumber(const EntityInstance& entity) { + return entity.attribute(AttributeType(AttributeTypeName::kPassportNumber)) + ->GetCompleteInfo(kAppLocaleUS); } -std::optional<std::u16string> GetFillValueForField( - base::span<const EntityInstance> entities, - const Suggestion::AutofillAiPayload& payload, - const AutofillField& field, - const std::string& app_locale = kAppLocaleUS) { - auto entity_it = - std::ranges::find(entities, payload.guid, &EntityInstance::guid); - if (entity_it == entities.end()) { - return std::nullopt; - } - auto attribute_it = std::ranges::find_if( - entity_it->attributes(), [&field](const AttributeInstance& attribute) { - return attribute.type().field_type() == - field.GetAutofillAiServerTypePredictions(); - }); - if (attribute_it == entity_it->attributes().end()) { - return std::nullopt; - } - return attribute_it->GetInfo(field.Type().GetStorableType(), app_locale, - field.format_string()); -} - -std::unique_ptr<FormStructure> CreateFormStructureWithMultiplePredictions( - const std::vector<std::vector<FieldType>>& multiple_field_types) { - test::FormDescription form_description; - for (std::vector<FieldType> field_types : multiple_field_types) { - FieldType type = field_types.empty() ? UNKNOWN_TYPE : field_types[0]; - form_description.fields.emplace_back( - test::FieldDescription({.role = type})); - } - auto form_structure = - std::make_unique<FormStructure>(test::GetFormData(form_description)); - CHECK_EQ(multiple_field_types.size(), form_structure->field_count()); - for (size_t i = 0; i < form_structure->field_count(); i++) { - form_structure->field(i)->set_server_predictions( - base::ToVector(multiple_field_types[i], [](FieldType type) { - FieldPrediction prediction; - prediction.set_type(type); - return prediction; - })); - } - return form_structure; -} - -std::unique_ptr<FormStructure> CreateFormStructure( - const std::vector<FieldType>& field_types) { - return CreateFormStructureWithMultiplePredictions(base::ToVector( - field_types, - [](FieldType type) { return std::vector<FieldType>({type}); })); +// Tests that no suggestions are generated when the field has a non-Autofill AI +// type. +TEST_F(AutofillAiSuggestionsTest, NoSuggestionsOnNonAiField) { + SetEntities({MakePassportWithRandomGuid()}); + SetForm({ADDRESS_HOME_ZIP, PASSPORT_NUMBER, PHONE_HOME_WHOLE_NUMBER}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), IsEmpty()); } TEST_F(AutofillAiSuggestionsTest, GetFillingSuggestion_PassportEntity) { EntityInstance passport_entity = MakePassportWithRandomGuid(); - std::vector<EntityInstance> entities = {passport_entity}; + SetEntities({passport_entity}); + SetForm({PASSPORT_NAME_TAG, PASSPORT_NUMBER, PHONE_HOME_WHOLE_NUMBER}); - FieldType triggering_field_type = PASSPORT_NAME_TAG; - AttributeType triggering_attribute_type = - AttributeType(AttributeTypeName::kPassportName); - std::unique_ptr<FormStructure> form = CreateFormStructure( - {triggering_field_type, PASSPORT_NUMBER, PHONE_HOME_WHOLE_NUMBER}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], entities, kAppLocaleUS); + std::vector<Suggestion> suggestions = CreateFillingSuggestions(field(0)); // There should be only one suggestion whose main text matches the entity - // value for the `triggering_field_type`. - EXPECT_EQ(suggestions.size(), 3u); - EXPECT_EQ(suggestions[0].main_text.value, - GetEntityInstanceValue(passport_entity, triggering_attribute_type)); - EXPECT_EQ(suggestions[1].type, SuggestionType::kSeparator); - EXPECT_EQ(suggestions[2].type, SuggestionType::kManageAutofillAi); + // value for the PASSPORT_NAME_TAG. + EXPECT_THAT(suggestions, + SuggestionsAre(HasMainText(GetPassportName(passport_entity)))); const Suggestion::AutofillAiPayload* payload = std::get_if<Suggestion::AutofillAiPayload>(&suggestions[0].payload); ASSERT_TRUE(payload); - EXPECT_EQ(suggestions[0].icon, Suggestion::Icon::kIdCard); + EXPECT_THAT(suggestions[0], HasIcon(Suggestion::Icon::kIdCard)); - // The triggering/first field is of AutofillAi Type. - EXPECT_EQ(GetFillValueForField(entities, *payload, *form->fields()[0]), - GetEntityInstanceValue(passport_entity, triggering_attribute_type)); - // The second field in the form is also of AutofillAi. - EXPECT_EQ( - GetFillValueForField(entities, *payload, *form->fields()[1]), - GetEntityInstanceValue( - passport_entity, AttributeType(AttributeTypeName::kPassportNumber))); - // The third field is not of AutofillAi type. - EXPECT_EQ(GetFillValueForField(entities, *payload, *form->fields()[2]), - std::nullopt); + // The triggering/first field is of Autofill AI type. + EXPECT_EQ(GetFillValueForField(*payload, field(0)), + GetPassportName(passport_entity)); + // The second field in the form is also of Autofill AI type. + EXPECT_EQ(GetFillValueForField(*payload, field(1)), + GetPassportNumber(passport_entity)); + // The third field is not of Autofill AI type. + EXPECT_EQ(GetFillValueForField(*payload, field(2)), std::nullopt); } TEST_F(AutofillAiSuggestionsTest, GetFillingSuggestion_PrefixMatching) { EntityInstance passport_prefix_matches = MakePassportWithRandomGuid({.name = u"Jon Doe"}); - EntityInstance passport_prefix_does_not_match = MakePassportWithRandomGuid({.name = u"Harry Potter"}); - FieldType triggering_field_type = PASSPORT_NAME_TAG; - AttributeType triggering_attribute_type = - AttributeType(AttributeTypeName::kPassportName); - std::unique_ptr<FormStructure> form = CreateFormStructure( - {triggering_field_type, PASSPORT_NUMBER, PHONE_HOME_WHOLE_NUMBER}); - - form->field(0)->set_value(u"J"); - - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], - {passport_prefix_matches, passport_prefix_does_not_match}, kAppLocaleUS); + SetEntities({passport_prefix_matches, passport_prefix_does_not_match}); + SetForm({PASSPORT_NAME_TAG, PASSPORT_NUMBER, PHONE_HOME_WHOLE_NUMBER}); + field(0).set_value(u"J"); // There should be only one suggestion whose main text matches is a prefix of // the value already existing in the triggering field. // Note that there is one separator and one footer suggestion as well. - EXPECT_EQ(suggestions.size(), 3u); - EXPECT_EQ(suggestions[0].main_text.value, - GetEntityInstanceValue(passport_prefix_matches, - triggering_attribute_type)); + EXPECT_THAT( + CreateFillingSuggestions(field(0)), + SuggestionsAre(HasMainText(GetPassportName(passport_prefix_matches)))); } // Tests that no prefix matching is performed if the attribute that would be // filled into the triggering field is obfuscated. TEST_F(AutofillAiSuggestionsTest, GetFillingSuggestionNoPrefixMatchingForObfuscatedAttributes) { - EntityInstance passport = MakePassportWithRandomGuid({.number = u"12345"}); - - FieldType triggering_field_type = PASSPORT_NUMBER; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_ISSUING_COUNTRY}); - - form->field(0)->set_value(u"12"); - - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], {passport}, kAppLocaleUS); - EXPECT_FALSE(suggestions.empty()); + SetEntities({MakePassportWithRandomGuid({.number = u"12345"})}); + SetForm({PASSPORT_NUMBER, PASSPORT_ISSUING_COUNTRY}); + field(0).set_value(u"12"); + EXPECT_THAT(CreateFillingSuggestions(field(0)), Not(IsEmpty())); } TEST_F(AutofillAiSuggestionsTest, GetFillingSuggestion_SkipFieldsThatDoNotMatchTheTriggeringFieldSection) { EntityInstance passport_entity = MakePassportWithRandomGuid(); - std::vector<EntityInstance> entities = {passport_entity}; + SetEntities({passport_entity}); + SetForm({PASSPORT_NAME_TAG, PASSPORT_NUMBER}); - FieldType triggering_field_type = PASSPORT_NAME_TAG; - AttributeType triggering_attribute_type = - AttributeType(AttributeTypeName::kPassportName); - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_NUMBER}); - // Assign different sections to the fields. - base::flat_map<LocalFrameToken, size_t> frame_token_ids; - for (const std::unique_ptr<AutofillField>& field : form->fields()) { - field->set_section(Section::FromFieldIdentifier(*field, frame_token_ids)); - } + field(0).set_section(Section::FromAutocomplete(Section::Autocomplete("foo"))); + field(1).set_section(Section::FromAutocomplete(Section::Autocomplete("bar"))); + ASSERT_NE(field(0).section(), field(1).section()); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], entities, kAppLocaleUS); - - // There should be only one suggestion whose main text matches the entity - // value for the `triggering_field_type`. - EXPECT_THAT(suggestions, SizeIs(Ge(1))); - EXPECT_EQ(suggestions[0].main_text.value, - GetEntityInstanceValue(passport_entity, triggering_attribute_type)); + std::vector<Suggestion> suggestions = CreateFillingSuggestions(field(0)); + EXPECT_THAT(suggestions, + SuggestionsAre(HasMainText(GetPassportName(passport_entity)))); const Suggestion::AutofillAiPayload* payload = std::get_if<Suggestion::AutofillAiPayload>(&suggestions[0].payload); ASSERT_TRUE(payload); - // The triggering/first field is of AutofillAi Type. - EXPECT_EQ(GetFillValueForField(entities, *payload, *form->fields()[0]), - GetEntityInstanceValue(passport_entity, triggering_attribute_type)); + // The triggering/first field is of Autofill AI type. + EXPECT_EQ(GetFillValueForField(*payload, field(0)), + GetPassportName(passport_entity)); } +// Tests that there are no suggestions if the existing entities don't match the +// triggering field. TEST_F(AutofillAiSuggestionsTest, NonMatchingEntity_DoNoReturnSuggestions) { EntityInstance drivers_license_entity = test::GetDriversLicenseEntityInstance(); - std::vector<EntityInstance> entities = {drivers_license_entity}; - - FieldType triggering_field_type = PASSPORT_NAME_TAG; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], entities, kAppLocaleUS); - - // There should be no suggestion since the triggering is a passport field and - // the only available entity is for loyalty cards. - EXPECT_EQ(suggestions.size(), 0u); + SetEntities({drivers_license_entity}); + SetForm({PASSPORT_NAME_TAG}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), IsEmpty()); } // Tests that suggestions whose structured attribute would have empty text for // the value to fill into the triggering field are not shown. TEST_F(AutofillAiSuggestionsTest, EmptyMainTextForStructuredAttribute) { EntityInstance passport = MakePassportWithRandomGuid({.name = u"Miller"}); + SetEntities({passport}); - std::unique_ptr<FormStructure> form = - CreateFormStructureWithMultiplePredictions( - {{NAME_FIRST, PASSPORT_NAME_TAG}, + base::optional_ref<const AttributeInstance> name = + passport.attribute(AttributeType(AttributeTypeName::kPassportName)); + ASSERT_TRUE(name); + ASSERT_EQ(name->GetInfo(NAME_FIRST, kAppLocaleUS, std::nullopt), u""); + ASSERT_EQ(name->GetInfo(NAME_LAST, kAppLocaleUS, std::nullopt), u"Miller"); + + SetForm({{NAME_FIRST, PASSPORT_NAME_TAG}, {NAME_LAST, PASSPORT_NAME_TAG}, {PASSPORT_NUMBER}}); - base::optional_ref<const AttributeInstance> name_attribute = - passport.attribute(AttributeType(AttributeTypeName::kPassportName)); - ASSERT_TRUE(name_attribute); - ASSERT_THAT(name_attribute->GetInfo(NAME_FIRST, kAppLocaleUS, std::nullopt), - u""); - ASSERT_THAT(name_attribute->GetInfo(NAME_LAST, kAppLocaleUS, std::nullopt), - u"Miller"); - - EXPECT_THAT(CreateFillingSuggestions(*form, *form->fields()[0], {passport}, - kAppLocaleUS), - IsEmpty()); - EXPECT_THAT(CreateFillingSuggestions(*form, *form->fields()[1], {passport}, - kAppLocaleUS), - Not(IsEmpty())); + EXPECT_THAT(CreateFillingSuggestions(field(0)), IsEmpty()); + EXPECT_THAT(CreateFillingSuggestions(field(1)), Not(IsEmpty())); } TEST_F(AutofillAiSuggestionsTest, GetFillingSuggestion_DedupeSuggestions) { - EntityInstance passport = MakePassportWithRandomGuid(); - - EntityInstance passport_a_with_different_expiry_date = + EntityInstance passport1 = MakePassportWithRandomGuid(); + EntityInstance passport2 = MakePassportWithRandomGuid( + {.name = u"Jon Doe", .number = u"927908CYGAS1"}); + EntityInstance passport3 = MakePassportWithRandomGuid({.expiry_date = u"2001-12-01"}); - - EntityInstance passport_a_without_an_expiry_date = + EntityInstance passport4 = MakePassportWithRandomGuid({.expiry_date = nullptr}); + SetEntities({passport1, passport2, passport3, passport4}); + SetForm({PASSPORT_NAME_TAG, PASSPORT_NUMBER, PASSPORT_ISSUING_COUNTRY}); - EntityInstance another_persons_passport = MakePassportWithRandomGuid( - {.name = u"Jon doe", .number = u"927908CYGAS1"}); - - std::vector<EntityInstance> entities = {passport, another_persons_passport, - passport_a_with_different_expiry_date, - passport_a_without_an_expiry_date}; - - FieldType triggering_field_type = PASSPORT_NAME_TAG; - AttributeType triggering_attribute_type = - AttributeType(AttributeTypeName::kPassportName); - std::unique_ptr<FormStructure> form = CreateFormStructure( - {triggering_field_type, PASSPORT_NUMBER, PASSPORT_ISSUING_COUNTRY}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], entities, kAppLocaleUS); - - // The passport with passport_a_with_different_expiry_date should be - // deduped because while it has an unique attribute (expiry date), the form - // does not contain a field with PASSPORT_ISSUE_DATE, which - // makes it identical to `passport`. The passport with - // passport_a_without_an_expiry_date should be deduped because it is a - // proper subset of `passport`. - ASSERT_THAT(suggestions, SizeIs(Ge(2))); - EXPECT_EQ(suggestions[0].main_text.value, - GetEntityInstanceValue(another_persons_passport, - triggering_attribute_type)); - EXPECT_EQ(suggestions[1].main_text.value, - GetEntityInstanceValue(passport, triggering_attribute_type)); + // `passport3` is deduped because there is no expiry date in the form and its + // remaining attributes are a subset of `passport1`. + // `passport4` is deduped because it is a proper subset of `passport1`. + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasMainText(GetPassportName(passport2)), + HasMainText(GetPassportName(passport1)))); } // Tests that an "Undo Autofill" suggestion is appended if the trigger field // is autofilled. TEST_F(AutofillAiSuggestionsTest, GetFillingSuggestions_Undo) { - EntityInstance passport_entity = MakePassportWithRandomGuid(); + SetEntities({MakePassportWithRandomGuid()}); + SetForm({PASSPORT_NUMBER}); - std::unique_ptr<FormStructure> form = CreateFormStructure({PASSPORT_NUMBER}); - - EXPECT_FALSE( - base::Contains(CreateFillingSuggestions(*form, *form->fields()[0], - {passport_entity}, kAppLocaleUS), - SuggestionType::kUndoOrClear, &Suggestion::type)); - - form->field(0)->set_is_autofilled(true); - EXPECT_TRUE( - base::Contains(CreateFillingSuggestions(*form, *form->fields()[0], - {passport_entity}, kAppLocaleUS), - SuggestionType::kUndoOrClear, &Suggestion::type)); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + Not(Contains(HasType(SuggestionType::kUndoOrClear)))); + field(0).set_is_autofilled(true); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + Contains(HasType(SuggestionType::kUndoOrClear))); } TEST_F(AutofillAiSuggestionsTest, LabelGeneration_SingleEntity_NoLabelAdded) { - EntityInstance passport_entity = MakePassportWithRandomGuid(); - - FieldType triggering_field_type = PASSPORT_NUMBER; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_NAME_TAG}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], {passport_entity}, kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 1u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, u"Passport"); + SetEntities({MakePassportWithRandomGuid()}); + SetForm({PASSPORT_NUMBER, PASSPORT_NAME_TAG}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Passport"))); } -// Check that the existence of an entity (in this case `vehicle_entity`) that -// does not fill the triggering field, still affects label generation. +// Tests that the existence of an entity that does not fill the triggering field +// still affects label generation. TEST_F( AutofillAiSuggestionsTest, LabelGeneration_SingleSuggestion_OtherEntitiesFillOtherFieldsInForm_LabelAdded) { - EntityInstance vehicle_entity = MakeVehicleWithRandomGuid( - {.plate = nullptr, .make = nullptr, .model = nullptr, .year = nullptr}); - EntityInstance vehicle_entity_b = - MakeVehicleWithRandomGuid({.name = nullptr, .number = nullptr}); - - FieldType triggering_field_type = VEHICLE_LICENSE_PLATE; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, VEHICLE_VIN}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], {vehicle_entity, vehicle_entity_b}, - kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 1u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, u"Vehicle · BMW · Series 2"); + SetEntities( + {MakeVehicleWithRandomGuid({.plate = nullptr, + .make = nullptr, + .model = nullptr, + .year = nullptr}), + MakeVehicleWithRandomGuid({.name = nullptr, .number = nullptr})}); + SetForm({VEHICLE_LICENSE_PLATE, VEHICLE_VIN}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Vehicle · BMW · Series 2"))); } -// In this test, the main test is the passport number, which is not the top -// differentiating attribute (passport name), therefore, we add a label. +// Test that if focused field (here: passport number) is not the highest-ranking +// disambiguating label (passport name), we the latter as a label. TEST_F(AutofillAiSuggestionsTest, LabelGeneration_TwoSuggestions_SameMainText_AddTopDifferentiatingLabel) { - EntityInstance passport_entity = MakePassportWithRandomGuid(); - EntityInstance passport_entity_b = MakePassportWithRandomGuid( - {.name = u"Machado de Assis", .number = u"123"}); - - FieldType triggering_field_type = PASSPORT_NUMBER; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_NAME_TAG}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], {passport_entity, passport_entity_b}, - kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 2u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, u"Passport · Pippi Långstrump"); - - EXPECT_EQ(suggestions[1].labels.size(), 1u); - EXPECT_EQ(suggestions[1].labels[0].size(), 1u); - EXPECT_EQ(suggestions[1].labels[0][0].value, u"Passport · Machado de Assis"); + SetEntities({MakePassportWithRandomGuid(), + MakePassportWithRandomGuid( + {.name = u"Machado de Assis", .number = u"123"})}); + SetForm({PASSPORT_NUMBER, PASSPORT_NAME_TAG}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Passport · Pippi Långstrump"), + HasLabel(u"Passport · Machado de Assis"))); } // Note that because the main text is the top disambiguating field (and is @@ -404,26 +340,14 @@ TEST_F( AutofillAiSuggestionsTest, LabelGeneration_TwoSuggestions_MainTextIsDisambiguating_DifferentMainText_DoNotAddDifferentiatingLabel) { - EntityInstance passport_entity = MakePassportWithRandomGuid(); - EntityInstance passport_entity_b = MakePassportWithRandomGuid( - {.name = u"Machado de Assis", .country = u"Brazil"}); + SetEntities({MakePassportWithRandomGuid(), + MakePassportWithRandomGuid( + {.name = u"Machado de Assis", .country = u"Brazil"})}); // Note that passport name is the first at the rank of disambiguating texts. - FieldType triggering_field_type = PASSPORT_NAME_TAG; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_ISSUING_COUNTRY}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], {passport_entity, passport_entity_b}, - kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 2u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, u"Passport"); - - EXPECT_EQ(suggestions[1].labels.size(), 1u); - EXPECT_EQ(suggestions[1].labels[0].size(), 1u); - EXPECT_EQ(suggestions[1].labels[0][0].value, u"Passport"); + SetForm({PASSPORT_NAME_TAG, PASSPORT_ISSUING_COUNTRY}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Passport"), HasLabel(u"Passport"))); } // Note that while the main text is the top disambiguating field, we need @@ -431,26 +355,14 @@ TEST_F( AutofillAiSuggestionsTest, LabelGeneration_TwoSuggestions_MainTextIsDisambiguating_SameMainText_AddDifferentiatingLabel) { - EntityInstance passport_entity = MakePassportWithRandomGuid(); - EntityInstance passport_entity_b = - MakePassportWithRandomGuid({.country = u"Brazil"}); + SetEntities({MakePassportWithRandomGuid(), + MakePassportWithRandomGuid({.country = u"Brazil"})}); // Note that passport name is the first at the rank of disambiguating texts. - FieldType triggering_field_type = PASSPORT_NAME_TAG; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_ISSUING_COUNTRY}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], {passport_entity, passport_entity_b}, - kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 2u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, u"Passport · Sweden"); - - EXPECT_EQ(suggestions[1].labels.size(), 1u); - EXPECT_EQ(suggestions[1].labels[0].size(), 1u); - EXPECT_EQ(suggestions[1].labels[0][0].value, u"Passport · Brazil"); + SetForm({PASSPORT_NAME_TAG, PASSPORT_ISSUING_COUNTRY}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Passport · Sweden"), + HasLabel(u"Passport · Brazil"))); } // Note that because the main text is not the top disambiguating field, we do @@ -459,124 +371,61 @@ TEST_F( AutofillAiSuggestionsTest, LabelGeneration_TwoSuggestions_MainTextIsNotTopDisambiguatingType_addDifferentiatingLabel) { - EntityInstance passport_entity = MakePassportWithRandomGuid(); - EntityInstance passport_entity_b = MakePassportWithRandomGuid( - {.name = u"Machado de Assis", .country = u"Brazil"}); + SetEntities({MakePassportWithRandomGuid(), + MakePassportWithRandomGuid( + {.name = u"Machado de Assis", .country = u"Brazil"})}); // Passport country is a disambiguating text, meaning it can be used to // further differentiate passport labels when the top type (passport name) is // the same. However, we still add the top differentiating label as a label, // as we always prioritize having it. - FieldType triggering_field_type = PASSPORT_ISSUING_COUNTRY; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_NUMBER}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], {passport_entity, passport_entity_b}, - kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 2u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, u"Passport · Pippi Långstrump"); - - EXPECT_EQ(suggestions[1].labels.size(), 1u); - EXPECT_EQ(suggestions[1].labels[0].size(), 1u); - EXPECT_EQ(suggestions[1].labels[0][0].value, u"Passport · Machado de Assis"); + SetForm({PASSPORT_ISSUING_COUNTRY, PASSPORT_NUMBER}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Passport · Pippi Långstrump"), + HasLabel(u"Passport · Machado de Assis"))); } // Note that in this case all entities have the same maker, so it is removed // from the possible list of labels. TEST_F(AutofillAiSuggestionsTest, LabelGeneration_ThreeSuggestions_AddDifferentiatingLabel) { - EntityInstance vehicle_entity = MakeVehicleWithRandomGuid(); - EntityInstance vehicle_entity_b = - MakeVehicleWithRandomGuid({.model = u"Series 3"}); - EntityInstance vehicle_entity_c = - MakeVehicleWithRandomGuid({.name = u"Diego Maradona"}); - - std::unique_ptr<FormStructure> form = CreateFormStructure( - {VEHICLE_LICENSE_PLATE, VEHICLE_MODEL, VEHICLE_OWNER_TAG}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], - {vehicle_entity, vehicle_entity_b, vehicle_entity_c}, kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 3u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, - u"Vehicle · Series 2 · Knecht Ruprecht"); - - EXPECT_EQ(suggestions[1].labels.size(), 1u); - EXPECT_EQ(suggestions[1].labels[0].size(), 1u); - EXPECT_EQ(suggestions[1].labels[0][0].value, - u"Vehicle · Series 3 · Knecht Ruprecht"); - - EXPECT_EQ(suggestions[2].labels.size(), 1u); - EXPECT_EQ(suggestions[2].labels[0].size(), 1u); - EXPECT_EQ(suggestions[2].labels[0][0].value, - u"Vehicle · Series 2 · Diego Maradona"); + SetEntities({MakeVehicleWithRandomGuid(), + MakeVehicleWithRandomGuid({.model = u"Series 3"}), + MakeVehicleWithRandomGuid({.name = u"Diego Maradona"})}); + SetForm({VEHICLE_LICENSE_PLATE, VEHICLE_MODEL, VEHICLE_OWNER_TAG}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Vehicle · Series 2 · Knecht Ruprecht"), + HasLabel(u"Vehicle · Series 3 · Knecht Ruprecht"), + HasLabel(u"Vehicle · Series 2 · Diego Maradona"))); } TEST_F( AutofillAiSuggestionsTest, LabelGeneration_ThreeSuggestions_WithMissingValues_AddDifferentiatingLabel) { - EntityInstance passport_entity_a = - MakePassportWithRandomGuid({.country = u"Brazil"}); - - // Note that passport b can only fill the triggering name field and has no - // country data label to add. - EntityInstance passport_entity_b = - MakePassportWithRandomGuid({.number = u"9876", .country = nullptr}); - - EntityInstance passport_entity_c = MakePassportWithRandomGuid(); - - FieldType triggering_field_type = PASSPORT_NUMBER; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_ISSUING_COUNTRY}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], - {passport_entity_a, passport_entity_b, passport_entity_c}, kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 3u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, u"Passport · Brazil"); - - EXPECT_EQ(suggestions[1].labels.size(), 1u); - EXPECT_EQ(suggestions[1].labels[0].size(), 1u); - EXPECT_EQ(suggestions[1].labels[0][0].value, u"Passport"); - - EXPECT_EQ(suggestions[2].labels.size(), 1u); - EXPECT_EQ(suggestions[2].labels[0].size(), 1u); - EXPECT_EQ(suggestions[2].labels[0][0].value, u"Passport · Sweden"); + SetEntities( + {MakePassportWithRandomGuid({.country = u"Brazil"}), + // This passport can only fill the triggering name field and has no + // country data label to add. + MakePassportWithRandomGuid({.number = u"9876", .country = nullptr}), + MakePassportWithRandomGuid()}); + SetForm({PASSPORT_NUMBER, PASSPORT_ISSUING_COUNTRY}); + EXPECT_THAT( + CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Passport · Brazil"), HasLabel(u"Passport"), + HasLabel(u"Passport · Sweden"))); } -// In this test we see that while the passports have different expiry dates, -// they are not added as labels since they are not part of the entity -// disambiguating attributes. +// Test that the non-disambiguating attributes (here: the expiry dates) do not +// occur in the labels. TEST_F( AutofillAiSuggestionsTest, LabelGeneration_TwoSuggestions_PassportsWithDifferentExpiryDates_DoNotAddDifferentiatingLabel) { - EntityInstance passport_entity = MakePassportWithRandomGuid(); - EntityInstance passport_entity_b = - MakePassportWithRandomGuid({.expiry_date = u"2018-12-29"}); - - FieldType triggering_field_type = PASSPORT_NUMBER; - std::unique_ptr<FormStructure> form = - CreateFormStructure({triggering_field_type, PASSPORT_ISSUING_COUNTRY, - PASSPORT_NAME_TAG, PASSPORT_EXPIRATION_DATE}); - std::vector<Suggestion> suggestions = CreateFillingSuggestions( - *form, *form->fields()[0], {passport_entity, passport_entity_b}, - kAppLocaleUS); - - ASSERT_EQ(CountFillingSuggestions(suggestions), 2u); - EXPECT_EQ(suggestions[0].labels.size(), 1u); - EXPECT_EQ(suggestions[0].labels[0].size(), 1u); - EXPECT_EQ(suggestions[0].labels[0][0].value, u"Passport"); - - EXPECT_EQ(suggestions[1].labels.size(), 1u); - EXPECT_EQ(suggestions[1].labels[0].size(), 1u); - EXPECT_EQ(suggestions[1].labels[0][0].value, u"Passport"); + SetEntities({MakePassportWithRandomGuid(), + MakePassportWithRandomGuid({.expiry_date = u"2018-12-29"})}); + SetForm({PASSPORT_NUMBER, PASSPORT_ISSUING_COUNTRY, PASSPORT_NAME_TAG, + PASSPORT_EXPIRATION_DATE}); + EXPECT_THAT(CreateFillingSuggestions(field(0)), + SuggestionsAre(HasLabel(u"Passport"), HasLabel(u"Passport"))); } } // namespace
diff --git a/components/autofill/core/browser/payments/payments_service_url.cc b/components/autofill/core/browser/payments/payments_service_url.cc index 4419938..935f0e99 100644 --- a/components/autofill/core/browser/payments/payments_service_url.cc +++ b/components/autofill/core/browser/payments/payments_service_url.cc
@@ -36,19 +36,18 @@ // URLs used when opening the Payment methods management page from // chrome://settings/payments. const char kProdPaymentsManageCardsUrl[] = - "https://pay.google.com/" - "pay?p=paymentmethods&utm_source=chrome&utm_medium=settings&utm_campaign=" - "payment_methods"; + "https://wallet.google.com/wallet?" + "p=paymentmethods&utm_source=chrome&utm_medium=settings&utm_campaign=" + "paymentmethods"; const char kSandboxPaymentsManageCardsUrl[] = "https://pay.sandbox.google.com/" "pay?p=paymentmethods&utm_source=chrome&utm_medium=settings&utm_campaign=" "payment_methods"; // URL used when opening the Loyalty cards page from chrome://settings/payments. -// TODO(crbug.com/416662510): Update the UTM params to be the correct one. const char kManageLoyaltyCardsUrl[] = - "https://pay.google.com/" - "pay?p=passes&utm_source=chrome&utm_medium=settings"; + "https://wallet.google.com/wallet?" + "p=passes&utm_source=chrome&utm_medium=settings&utm_campaign=loyalty"; // LINT.IfChange const char kVirtualCardEnrollmentSupportUrl[] =
diff --git a/components/autofill/core/browser/payments/payments_service_url_unittest.cc b/components/autofill/core/browser/payments/payments_service_url_unittest.cc index 4f0e5961..18ff048 100644 --- a/components/autofill/core/browser/payments/payments_service_url_unittest.cc +++ b/components/autofill/core/browser/payments/payments_service_url_unittest.cc
@@ -35,9 +35,9 @@ switches::kWalletServiceUseSandbox, "0"); const char kExpectedURL[] = - "https://pay.google.com/" - "pay?p=paymentmethods&utm_source=chrome&utm_medium=settings&utm_campaign=" - "payment_methods"; + "https://wallet.google.com/wallet?" + "p=paymentmethods&utm_source=chrome&utm_medium=settings&utm_campaign=" + "paymentmethods"; EXPECT_EQ(kExpectedURL, GetManageInstrumentsUrl().spec()); EXPECT_EQ(kExpectedURL, GetManageAddressesUrl().spec()); @@ -45,9 +45,9 @@ TEST(PaymentsServiceUrl, UrlWithInstrumentId) { const char kExpectedURL[] = - "https://pay.google.com/" - "pay?p=paymentmethods&utm_source=chrome&utm_medium=settings&utm_campaign=" - "payment_methods&id=123"; + "https://wallet.google.com/wallet?" + "p=paymentmethods&utm_source=chrome&utm_medium=settings&utm_campaign=" + "paymentmethods&id=123"; EXPECT_EQ(kExpectedURL, GetManageInstrumentUrl(/*instrument_id=*/123).spec()); }
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 a5da5cb..50ead8d0 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
@@ -22,6 +22,7 @@ return result; } +// Returns the form field relevant to the `role`. FormFieldData CreateFieldByRole(FieldType role) { FormFieldData field; // TODO(crbug.com/406073718): Add the missing roles and/or fail loudly.
diff --git a/components/autofill/core/browser/test_utils/autofill_form_test_utils.h b/components/autofill/core/browser/test_utils/autofill_form_test_utils.h index 6e170ca..94204f9 100644 --- a/components/autofill/core/browser/test_utils/autofill_form_test_utils.h +++ b/components/autofill/core/browser/test_utils/autofill_form_test_utils.h
@@ -121,9 +121,6 @@ // messages might refer to the form. testing::Message DescribeFormData(const FormData& form_data); -// Returns the form field relevant to the |role|. -FormFieldData CreateFieldByRole(FieldType role); - // Creates a FormFieldData to be fed to the parser. FormFieldData GetFormFieldData(const FieldDescription& fd);
diff --git a/components/autofill/core/browser/webdata/autofill_ai/entity_table.cc b/components/autofill/core/browser/webdata/autofill_ai/entity_table.cc index c6edc81..a9b55960 100644 --- a/components/autofill/core/browser/webdata/autofill_ai/entity_table.cc +++ b/components/autofill/core/browser/webdata/autofill_ai/entity_table.cc
@@ -372,10 +372,10 @@ } std::underlying_type_t<VerificationStatus> underlying_verification_status = s.ColumnInt(4); - attribute_records[entity_guid][attribute_type_name].push_back( - {.field_type = underlying_field_type, - .value = decrypted_value, - .verification_status = underlying_verification_status}); + attribute_records[std::move(entity_guid)][std::move(attribute_type_name)] + .push_back({.field_type = underlying_field_type, + .value = std::move(decrypted_value), + .verification_status = underlying_verification_status}); } if (!s.Succeeded()) { return {};
diff --git a/components/collaboration_strings.grdp b/components/collaboration_strings.grdp index 3030c42..20f0f45 100644 --- a/components/collaboration_strings.grdp +++ b/components/collaboration_strings.grdp
@@ -56,6 +56,12 @@ <message name="IDS_COLLABORATION_SHARE_BUTTON_CHROME_OUT_OF_DATE_ERROR_DIALOG_BODY" desc="The body for the chrome out of date dialog, shown when user tries to share a tab group."> To share tab groups, update Chrome </message> + <message name="IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_UPDATE_BUTTON" desc="The text of the button to update the app from the chrome out of date dialog, shown when user tries to share or join a tab group."> + Update Chrome + </message> + <message name="IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_NOT_NOW_BUTTON" desc="The text of the button to skip updating the app from the chrome out of date dialog, shown when user tries to share or join a tab group."> + Not now + </message> <message name="IDS_COLLABORATION_SIGNED_OUT_HEADER" desc="The title for the signed out dialog." formatter_data="android_java"> You're signed out </message>
diff --git a/components/collaboration_strings_grdp/IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_NOT_NOW_BUTTON.png.sha1 b/components/collaboration_strings_grdp/IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_NOT_NOW_BUTTON.png.sha1 new file mode 100644 index 0000000..d720ca41 --- /dev/null +++ b/components/collaboration_strings_grdp/IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_NOT_NOW_BUTTON.png.sha1
@@ -0,0 +1 @@ +a9440a89daeb5a5953bc8f1db0e90820ff392a5b \ No newline at end of file
diff --git a/components/collaboration_strings_grdp/IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_UPDATE_BUTTON.png.sha1 b/components/collaboration_strings_grdp/IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_UPDATE_BUTTON.png.sha1 new file mode 100644 index 0000000..d720ca41 --- /dev/null +++ b/components/collaboration_strings_grdp/IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_UPDATE_BUTTON.png.sha1
@@ -0,0 +1 @@ +a9440a89daeb5a5953bc8f1db0e90820ff392a5b \ No newline at end of file
diff --git a/components/feature_engagement/internal/tracker_impl.cc b/components/feature_engagement/internal/tracker_impl.cc index ecd38562..5889ed8 100644 --- a/components/feature_engagement/internal/tracker_impl.cc +++ b/components/feature_engagement/internal/tracker_impl.cc
@@ -34,6 +34,8 @@ #include "components/feature_engagement/internal/feature_config_event_storage_validator.h" #include "components/feature_engagement/internal/in_memory_event_store.h" #include "components/feature_engagement/internal/init_aware_event_model.h" +#include "components/feature_engagement/internal/multiple_event_model_provider.h" +#include "components/feature_engagement/internal/multiple_event_model_writer.h" #include "components/feature_engagement/internal/never_availability_model.h" #include "components/feature_engagement/internal/never_event_storage_validator.h" #include "components/feature_engagement/internal/noop_display_lock_controller.h" @@ -143,6 +145,7 @@ // static std::unique_ptr<Tracker> Tracker::Create( const base::FilePath& storage_dir, + const base::FilePath& device_storage_dir, const scoped_refptr<base::SequencedTaskRunner>& background_task_runner, leveldb_proto::ProtoDatabaseProvider* db_provider, std::unique_ptr<TrackerEventExporter> event_exporter, @@ -184,8 +187,7 @@ auto event_model = std::make_unique<InitAwareEventModel>(std::move(raw_event_model)); - auto event_model_provider = - std::make_unique<SingleEventModelProvider>(std::move(event_model)); + auto condition_validator = std::make_unique<FeatureConfigConditionValidator>(); auto time_provider = std::make_unique<SystemTimeProvider>(); @@ -202,6 +204,35 @@ auto availability_model = std::make_unique<AvailabilityModelImpl>( std::move(availability_store_loader)); + std::unique_ptr<EventModelProvider> event_model_provider; + if (IsOnDeviceStorageEnabled()) { + base::FilePath device_event_storage_dir = + device_storage_dir.AppendASCII(std::string(kEventDBName)); + auto device_event_db = db_provider->GetUniqueDB<Event>( + leveldb_proto::ProtoDbType::FEATURE_ENGAGEMENT_EVENT, + device_event_storage_dir, background_task_runner); + + auto device_event_store = + std::make_unique<PersistentEventStore>(std::move(device_event_db)); + + auto device_event_storage_validator = + std::make_unique<FeatureConfigEventStorageValidator>(); + device_event_storage_validator->InitializeFeatures( + GetAllFeatures(), GetAllGroups(), *configuration); + + auto device_raw_event_model = std::make_unique<EventModelImpl>( + std::move(device_event_store), + std::move(device_event_storage_validator)); + + auto device_event_model = std::make_unique<InitAwareEventModel>( + std::move(device_raw_event_model)); + event_model_provider = std::make_unique<MultipleEventModelProvider>( + std::move(event_model), std::move(device_event_model)); + } else { + event_model_provider = + std::make_unique<SingleEventModelProvider>(std::move(event_model)); + } + return std::make_unique<TrackerImpl>( std::move(event_model_provider), std::move(availability_model), std::move(configuration), std::make_unique<DisplayLockControllerImpl>(),
diff --git a/components/feature_engagement/internal/tracker_impl_unittest.cc b/components/feature_engagement/internal/tracker_impl_unittest.cc index ed564a4..6c4e9ac 100644 --- a/components/feature_engagement/internal/tracker_impl_unittest.cc +++ b/components/feature_engagement/internal/tracker_impl_unittest.cc
@@ -28,6 +28,7 @@ #include "components/feature_engagement/internal/event_model_impl.h" #include "components/feature_engagement/internal/feature_config_condition_validator.h" #include "components/feature_engagement/internal/in_memory_event_store.h" +#include "components/feature_engagement/internal/multiple_event_model_provider.h" #include "components/feature_engagement/internal/never_availability_model.h" #include "components/feature_engagement/internal/never_event_storage_validator.h" #include "components/feature_engagement/internal/once_condition_validator.h" @@ -64,6 +65,9 @@ BASE_FEATURE(kTrackerTestFeatureSnooze, "test_snooze", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kTrackerTestFeatureDeviceStorage, + "test_device_storage", + base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kTrackerTestGroupOne, "test_group_one", base::FEATURE_DISABLED_BY_DEFAULT); @@ -73,7 +77,8 @@ bool valid, bool tracking_only, bool snooze_params, - const char* additional_event_name = nullptr) { + const char* additional_event_name = nullptr, + StorageType storage_type = StorageType::PROFILE) { FeatureConfig config; config.valid = valid; config.used.name = feature.name + std::string("_used"); @@ -94,6 +99,7 @@ event_config.storage = 7U; config.event_configs.emplace(std::move(event_config)); } + config.storage_type = storage_type; configuration->SetConfiguration(&feature, config); } @@ -1503,6 +1509,295 @@ 1); } +class MultipleEventModelTrackerImplTest : public TrackerImplTest { + public: + MultipleEventModelTrackerImplTest() = default; + + MultipleEventModelTrackerImplTest(const MultipleEventModelTrackerImplTest&) = + delete; + MultipleEventModelTrackerImplTest& operator=( + const MultipleEventModelTrackerImplTest&) = delete; + + void SetUp() override { + std::unique_ptr<EditableConfiguration> configuration = + std::make_unique<EditableConfiguration>(); + configuration_ = configuration.get(); + + RegisterFeatureConfig(configuration.get(), kTrackerTestFeatureFoo, + true /* is_valid */, false /* tracking_only */, + false /* snooze_params */); + RegisterFeatureConfig(configuration.get(), kTrackerTestFeatureBar, + true /* is_valid */, false /* tracking_only */, + false /* snooze_params */); + RegisterFeatureConfig(configuration.get(), kTrackerTestFeatureBaz, + true /* is_valid */, true /* tracking_only */, + false /* snooze_params */); + RegisterFeatureConfig(configuration.get(), kTrackerTestFeatureQux, + false /* is_valid */, false /* tracking_only */, + false /* snooze_params */); + RegisterFeatureConfig(configuration.get(), kTrackerTestFeatureEvent, + /*valid=*/true, /*tracking_only=*/false, + /*snooze_params=*/false, "test_event_event"); + RegisterFeatureConfig(configuration.get(), kTrackerTestFeatureSnooze, + true /* is_valid */, false /* tracking_only */, + true /* snooze_params */); + RegisterFeatureConfig(configuration.get(), kTrackerTestFeatureDeviceStorage, + true /* is_valid */, false /* tracking_only */, + true /* snooze_params */, + nullptr /* additional_event_name */, + StorageType::DEVICE); + RegisterGroupConfig(configuration.get(), kTrackerTestGroupOne, + true /* is_valid */); + + std::unique_ptr<TestTrackerInMemoryEventStore> profile_event_store = + CreateEventStore(); + profile_event_store_ = profile_event_store.get(); + + std::unique_ptr<TestTrackerInMemoryEventStore> device_event_store = + CreateEventStore(); + device_event_store_ = device_event_store.get(); + + auto profile_event_model = std::make_unique<EventModelImpl>( + std::move(profile_event_store), + std::make_unique<StoreEverythingEventStorageValidator>()); + profile_event_model_ = profile_event_model.get(); + + auto device_event_model = std::make_unique<EventModelImpl>( + std::move(device_event_store), + std::make_unique<StoreEverythingEventStorageValidator>()); + device_event_model_ = device_event_model.get(); + + auto multiple_event_model_provider = + std::make_unique<MultipleEventModelProvider>( + std::move(profile_event_model), std::move(device_event_model)); + + auto availability_model = std::make_unique<TestTrackerAvailabilityModel>(); + availability_model_ = availability_model.get(); + availability_model_->SetIsReady(ShouldAvailabilityStoreBeReady()); + + auto display_lock_controller = + std::make_unique<TestTrackerDisplayLockController>(); + display_lock_controller_ = display_lock_controller.get(); + + auto condition_validator = CreateConditionValidator(); + condition_validator_ = condition_validator.get(); + + auto time_provider = std::make_unique<TestTimeProvider>(); + time_provider_ = time_provider.get(); + time_provider->SetCurrentDay(1u); + + auto event_exporter = std::make_unique<TestTrackerEventExporter>(); + event_exporter_ = event_exporter.get(); + + auto session_controller = std::make_unique<TestSessionController>(); + session_controller_ = session_controller.get(); + + tracker_ = std::make_unique<TrackerImpl>( + std::move(multiple_event_model_provider), std::move(availability_model), + std::move(configuration), std::move(display_lock_controller), + std::move(condition_validator), std::move(time_provider), + std::move(event_exporter), std::move(session_controller)); + } + + protected: + void VerifyEventTriggerForStore(TestTrackerInMemoryEventStore* store, + const std::string& event_name, + uint32_t count) { + Event trigger_event = store->GetEvent(event_name); + if (count == 0) { + EXPECT_EQ(0, trigger_event.events_size()); + return; + } + + EXPECT_EQ(1, trigger_event.events_size()); + EXPECT_EQ(1u, trigger_event.events(0).day()); + EXPECT_EQ(count, trigger_event.events(0).count()); + } + + void VerifyEventTrigger(TestTrackerInMemoryEventStore* store, + std::string event_name, + uint32_t count) { + VerifyEventTriggerForStore(store, event_name, count); + } + + void VerifyEventTriggerEvents(TestTrackerInMemoryEventStore* store, + const base::Feature& feature, + uint32_t count) { + VerifyEventTrigger( + store, configuration_->GetFeatureConfig(feature).trigger.name, count); + } + + void VerifyGroupEventTriggerEvents(TestTrackerInMemoryEventStore* store, + const base::Feature& group, + uint32_t count) { + VerifyEventTrigger( + store, configuration_->GetGroupConfig(group).trigger.name, count); + } + + raw_ptr<EventModel> profile_event_model_; + raw_ptr<EventModel> device_event_model_; + raw_ptr<TestTrackerInMemoryEventStore> device_event_store_; + raw_ptr<TestTrackerInMemoryEventStore> profile_event_store_; +}; + +TEST_F(MultipleEventModelTrackerImplTest, + TestInitializationWithMultipleStorage) { + EXPECT_FALSE(tracker_->IsInitialized()); + + StoringInitializedCallback callback; + tracker_->AddOnInitializedCallback(base::BindOnce( + &StoringInitializedCallback::OnInitialized, base::Unretained(&callback))); + EXPECT_FALSE(callback.invoked()); + + // Ensure all initialization is finished. + base::RunLoop().RunUntilIdle(); + + EXPECT_TRUE(tracker_->IsInitialized()); + EXPECT_TRUE(callback.invoked()); + EXPECT_TRUE(callback.success()); +} + +TEST_F(MultipleEventModelTrackerImplTest, TestWriteEventToMultipleStores) { + // Ensure all initialization is finished. + StoringInitializedCallback callback; + tracker_->AddOnInitializedCallback(base::BindOnce( + &StoringInitializedCallback::OnInitialized, base::Unretained(&callback))); + base::RunLoop().RunUntilIdle(); + base::UserActionTester user_action_tester; + + // The first time a feature triggers it should be shown. + EXPECT_TRUE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureFoo)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureFoo, 1u); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureFoo, 1u); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 1u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 1u); + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureFoo)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureFoo, 1u); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureFoo, 1u); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 1u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 1u); + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureQux)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureQux, 0); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureQux, 0); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 1u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 1u); + VerifyUserActionsTriggerChecks(user_action_tester, 2, 0, 0, 1); + VerifyUserActionsTriggered(user_action_tester, 1, 0, 0, 0); + VerifyUserActionsNotTriggered(user_action_tester, 1, 0, 0, 1); + VerifyUserActionsWouldHaveTriggered(user_action_tester, 0, 0, 0, 0); + VerifyUserActionsDismissed(user_action_tester, 0); + VerifyHistograms(true, 1, 1, 0, false, 0, 0, 0, false, 0, 0, 0, true, 0, 1, + 0); + + // While in-product help is currently showing, no other features should be + // shown. + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureBar)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureBar, 0); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureBar, 0); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 1u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 1u); + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureQux)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureQux, 0); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureQux, 0); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 1u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 1u); + VerifyUserActionsTriggerChecks(user_action_tester, 2, 1, 0, 2); + VerifyUserActionsTriggered(user_action_tester, 1, 0, 0, 0); + VerifyUserActionsNotTriggered(user_action_tester, 1, 1, 0, 2); + VerifyUserActionsWouldHaveTriggered(user_action_tester, 0, 0, 0, 0); + VerifyUserActionsDismissed(user_action_tester, 0); + VerifyHistograms(true, 1, 1, 0, true, 0, 1, 0, false, 0, 0, 0, true, 0, 2, 0); + + // After dismissing the current in-product help, that feature can not be shown + // again, but a different feature should. + tracker_->Dismissed(kTrackerTestFeatureFoo); + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureFoo)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureFoo, 1u); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureFoo, 1u); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 1u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 1u); + EXPECT_TRUE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureBar)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureBar, 1u); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureBar, 1u); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 2u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 2u); + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureQux)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureQux, 0); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureQux, 0); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 2u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 2u); + VerifyUserActionsTriggerChecks(user_action_tester, 3, 2, 0, 3); + VerifyUserActionsTriggered(user_action_tester, 1, 1, 0, 0); + VerifyUserActionsNotTriggered(user_action_tester, 2, 1, 0, 3); + VerifyUserActionsWouldHaveTriggered(user_action_tester, 0, 0, 0, 0); + VerifyUserActionsDismissed(user_action_tester, 1); + VerifyHistograms(true, 1, 2, 0, true, 1, 1, 0, false, 0, 0, 0, true, 0, 3, 0); + + // After dismissing the second registered feature, no more in-product help + // should be shown, since kTrackerTestFeatureQux is invalid. + tracker_->Dismissed(kTrackerTestFeatureBar); + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureFoo)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureFoo, 1u); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureFoo, 1u); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 2u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 2u); + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureBar)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureBar, 1u); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureBar, 1u); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 2u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 2u); + EXPECT_FALSE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureQux)); + VerifyEventTriggerEvents(profile_event_store_, kTrackerTestFeatureQux, 0); + VerifyEventTriggerEvents(device_event_store_, kTrackerTestFeatureQux, 0); + VerifyGroupEventTriggerEvents(profile_event_store_, kTrackerTestGroupOne, 2u); + VerifyGroupEventTriggerEvents(device_event_store_, kTrackerTestGroupOne, 2u); + VerifyUserActionsTriggerChecks(user_action_tester, 4, 3, 0, 4); + VerifyUserActionsTriggered(user_action_tester, 1, 1, 0, 0); + VerifyUserActionsNotTriggered(user_action_tester, 3, 2, 0, 4); + VerifyUserActionsWouldHaveTriggered(user_action_tester, 0, 0, 0, 0); + VerifyUserActionsDismissed(user_action_tester, 2); + VerifyHistograms(true, 1, 3, 0, true, 1, 2, 0, false, 0, 0, 0, true, 0, 4, 0); +} + +TEST_F(MultipleEventModelTrackerImplTest, TestReadEventFromSingleStorage) { + // Ensure all initialization is finished. + StoringInitializedCallback callback; + tracker_->AddOnInitializedCallback(base::BindOnce( + &StoringInitializedCallback::OnInitialized, base::Unretained(&callback))); + base::RunLoop().RunUntilIdle(); + base::UserActionTester user_action_tester; + + // All the features should not be triggered yet. + EXPECT_FALSE( + tracker_->HasEverTriggered(kTrackerTestFeatureDeviceStorage, false)); + + // For triggered features, has ever triggered from storage should returns + // true, as the storage is set to 1. + EXPECT_TRUE(tracker_->ShouldTriggerHelpUI(kTrackerTestFeatureDeviceStorage)); + tracker_->Dismissed(kTrackerTestFeatureDeviceStorage); + VerifyEventTriggerEvents(profile_event_store_, + kTrackerTestFeatureDeviceStorage, 1u); + VerifyEventTriggerEvents(device_event_store_, + kTrackerTestFeatureDeviceStorage, 1u); + + const std::string& event_trigger_name = + kTrackerTestFeatureDeviceStorage.name + std::string("_trigger"); + + // Clear the trigger event from the profile model. `HasEverTriggered` should + // still return true because the event persists in the device model, which is + // the designated storage for this feature. + profile_event_model_->ClearEvent(event_trigger_name); + EXPECT_TRUE( + tracker_->HasEverTriggered(kTrackerTestFeatureDeviceStorage, false)); + + // Clear the trigger event from the device model. Now that the event is + // cleared from its designated storage, `HasEverTriggered` should return + // false. + device_event_model_->ClearEvent(event_trigger_name); + EXPECT_FALSE( + tracker_->HasEverTriggered(kTrackerTestFeatureDeviceStorage, false)); +} + namespace test { class ScopedIphFeatureListTest : public TrackerImplTest {
diff --git a/components/feature_engagement/public/feature_constants.h b/components/feature_engagement/public/feature_constants.h index 1e3f0a3..1830578b 100644 --- a/components/feature_engagement/public/feature_constants.h +++ b/components/feature_engagement/public/feature_constants.h
@@ -17,6 +17,7 @@ namespace feature_engagement { // Returns true if adding on-device storage is enabled. +COMPONENT_EXPORT(FEATURE_ENGAGEMENT_FEATURE_CONSTANTS) bool IsOnDeviceStorageEnabled(); #define FEATURE_CONSTANTS_DECLARE_FEATURE(feature_name) \
diff --git a/components/feature_engagement/public/tracker.h b/components/feature_engagement/public/tracker.h index a6e04e8..48fe65ea 100644 --- a/components/feature_engagement/public/tracker.h +++ b/components/feature_engagement/public/tracker.h
@@ -160,6 +160,7 @@ // will be provided. static std::unique_ptr<Tracker> Create( const base::FilePath& storage_dir, + const base::FilePath& device_storage_dir, const scoped_refptr<base::SequencedTaskRunner>& background_task_runner, leveldb_proto::ProtoDatabaseProvider* db_provider, std::unique_ptr<TrackerEventExporter> event_exporter,
diff --git a/components/page_load_metrics/renderer/page_timing_metrics_sender.cc b/components/page_load_metrics/renderer/page_timing_metrics_sender.cc index 8b081d0..e727b60 100644 --- a/components/page_load_metrics/renderer/page_timing_metrics_sender.cc +++ b/components/page_load_metrics/renderer/page_timing_metrics_sender.cc
@@ -132,7 +132,7 @@ // increase by one, and the navigation_id to update, however, we have no // expectations about start_time values. This is because soft-navs start_time // might not be monotonically increasing. See: crbug.com/418449366#comment3 - CHECK(new_metrics.count > soft_navigation_metrics_->count); + CHECK(new_metrics.count >= soft_navigation_metrics_->count); CHECK(!new_metrics.start_time.is_zero()); CHECK(new_metrics.navigation_id != soft_navigation_metrics_->navigation_id);
diff --git a/components/signin/public/base/signin_switches.cc b/components/signin/public/base/signin_switches.cc index 323144d..ea66837a 100644 --- a/components/signin/public/base/signin_switches.cc +++ b/components/signin/public/base/signin_switches.cc
@@ -226,7 +226,12 @@ BASE_FEATURE(kEnableExtensionsExplicitBrowserSignin, "EnableExtensionsExplicitBrowserSignin", - base::FEATURE_DISABLED_BY_DEFAULT); +#if BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +); bool IsExtensionsExplicitBrowserSigninEnabled() { return base::FeatureList::IsEnabled(kEnableExtensionsExplicitBrowserSignin);
diff --git a/components/viz/service/layers/layer_context_impl_base_unittest.cc b/components/viz/service/layers/layer_context_impl_base_unittest.cc index b16a626..056144f 100644 --- a/components/viz/service/layers/layer_context_impl_base_unittest.cc +++ b/components/viz/service/layers/layer_context_impl_base_unittest.cc
@@ -99,6 +99,12 @@ compositor_frame_sink_support_.get(), /*draw_mode_is_gpu=*/true); } +void LayerContextImplTest::RecreateLayerContextImplWithParams( + bool draw_mode_is_gpu) { + layer_context_impl_ = LayerContextImpl::CreateForTesting( + compositor_frame_sink_support_.get(), draw_mode_is_gpu); +} + void LayerContextImplTest::ResetTestState() { // Property tree node IDs and layers are reinitialized in // CreateDefaultUpdate if first_update_ is true.
diff --git a/components/viz/service/layers/layer_context_impl_base_unittest.h b/components/viz/service/layers/layer_context_impl_base_unittest.h index 701be2f..a694981 100644 --- a/components/viz/service/layers/layer_context_impl_base_unittest.h +++ b/components/viz/service/layers/layer_context_impl_base_unittest.h
@@ -189,6 +189,7 @@ protected: cc::LayerImpl* GetLayerFromActiveTree(int layer_id); + void RecreateLayerContextImplWithParams(bool draw_mode_is_gpu); FakeCompositorFrameSinkClient dummy_client_; FrameSinkManagerImpl frame_sink_manager_;
diff --git a/components/viz/service/layers/layer_context_impl_unittest.cc b/components/viz/service/layers/layer_context_impl_unittest.cc index 79dde09f2..d5cbc738 100644 --- a/components/viz/service/layers/layer_context_impl_unittest.cc +++ b/components/viz/service/layers/layer_context_impl_unittest.cc
@@ -180,6 +180,16 @@ return name.str(); }); +TEST_F(LayerContextImplTest, DrawModeIsGpuForwardedViaSettings) { + RecreateLayerContextImplWithParams(/*draw_mode_is_gpu=*/true); + cc::LayerTreeHostImpl* host_impl = layer_context_impl_->host_impl(); + EXPECT_TRUE(host_impl->settings().display_tree_draw_mode_is_gpu); + + RecreateLayerContextImplWithParams(/*draw_mode_is_gpu=*/false); + host_impl = layer_context_impl_->host_impl(); + EXPECT_FALSE(host_impl->settings().display_tree_draw_mode_is_gpu); +} + TEST_F(LayerContextImplTest, TransferableUIResourceLifecycleAndEdgeCases) { cc::LayerTreeHostImpl* host_impl = layer_context_impl_->host_impl();
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java index 0dba893..92fc16e 100644 --- a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java +++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java
@@ -229,8 +229,7 @@ mErrorCallback = errorCallback; mRecordingCallback = recordingCallback; @Nullable Origin remoteDesktopOrigin = null; - if (DeviceFeatureMap.isEnabled(DeviceFeatureList.WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS) - && options.remoteDesktopClientOverride != null + if (options.remoteDesktopClientOverride != null && isChrome(mAuthenticationContextProvider.getWebContents())) { // SECURITY: remoteDesktopClientOverride comes from the renderer process and is // untrusted. We only use the override origin if the "caller origin" is explicitly @@ -281,10 +280,8 @@ String effectiveOriginString = convertOriginToString(origin); // Handle remote desktop client override for ClientDataJSON. // The origin from remoteDesktopClientOverride is only used after validation in - // ValidateDomainAndRelyingPartyID() confirmed that "caller origin" is allowlisted. - if (DeviceFeatureMap.isEnabled( - DeviceFeatureList.WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS) - && options.remoteDesktopClientOverride != null) { + // ValidateDomainAndRelyingPartyID() confirmed that the "caller origin" is allowlisted. + if (options.remoteDesktopClientOverride != null) { effectiveOriginString = convertOriginToString( new Origin(options.remoteDesktopClientOverride.origin)); @@ -462,8 +459,7 @@ } @Nullable Origin remoteDesktopOrigin = null; - if (DeviceFeatureMap.isEnabled(DeviceFeatureList.WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS) - && options.extensions.remoteDesktopClientOverride != null + if (options.extensions.remoteDesktopClientOverride != null && isChrome(mAuthenticationContextProvider.getWebContents())) { // SECURITY: remoteDesktopClientOverride comes from the renderer process and is // untrusted. We only use the override origin if the "caller origin" is explicitly @@ -525,10 +521,8 @@ String effectiveOriginString = callerOriginString; // Handle remote desktop client override for ClientDataJSON. // The origin from remoteDesktopClientOverride is only used after validation in - // ValidateDomainAndRelyingPartyID() confirmed that "caller origin" is allowlisted. - if (DeviceFeatureMap.isEnabled( - DeviceFeatureList.WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS) - && options.extensions.remoteDesktopClientOverride != null) { + // ValidateDomainAndRelyingPartyID() confirmed that the "caller origin" is allowlisted. + if (options.extensions.remoteDesktopClientOverride != null) { effectiveOriginString = convertOriginToString( new Origin(options.extensions.remoteDesktopClientOverride.origin));
diff --git a/components/webauthn/android/junit/src/org/chromium/components/webauthn/Fido2CredentialRequestRobolectricTest.java b/components/webauthn/android/junit/src/org/chromium/components/webauthn/Fido2CredentialRequestRobolectricTest.java index 4c50629..5ae7b9e 100644 --- a/components/webauthn/android/junit/src/org/chromium/components/webauthn/Fido2CredentialRequestRobolectricTest.java +++ b/components/webauthn/android/junit/src/org/chromium/components/webauthn/Fido2CredentialRequestRobolectricTest.java
@@ -104,7 +104,6 @@ public void setUp() throws Exception { FeatureOverrides.newBuilder() .enable(DeviceFeatureList.WEBAUTHN_ANDROID_USE_PASSKEY_CACHE) - .enable(DeviceFeatureList.WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS) .disable(BlinkFeatures.SECURE_PAYMENT_CONFIRMATION_BROWSER_BOUND_KEYS) .apply();
diff --git a/content/browser/browser_context.cc b/content/browser/browser_context.cc index 80919b9..60f267e 100644 --- a/content/browser/browser_context.cc +++ b/content/browser/browser_context.cc
@@ -198,6 +198,7 @@ const std::string& embedder_histogram_suffix, bool javascript_enabled, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, const net::HttpRequestHeaders& additional_headers, std::unique_ptr<PrefetchRequestStatusListener> request_status_listener, base::TimeDelta ttl, @@ -221,6 +222,7 @@ this, url, prefetch_type, embedder_histogram_suffix, blink::mojom::Referrer(), javascript_enabled, /*referring_origin=*/std::nullopt, std::move(no_vary_search_hint), + std::move(priority), /*attempt=*/nullptr, additional_headers, std::move(request_status_listener), ttl, should_append_variations_header, should_disable_block_until_head_timeout);
diff --git a/content/browser/permissions/permission_controller_impl.cc b/content/browser/permissions/permission_controller_impl.cc index bc4dd4c..8fed0c9 100644 --- a/content/browser/permissions/permission_controller_impl.cc +++ b/content/browser/permissions/permission_controller_impl.cc
@@ -701,12 +701,7 @@ PermissionStatus PermissionControllerImpl::GetCombinedPermissionAndDeviceStatus( const blink::mojom::PermissionDescriptorPtr& permission, RenderFrameHost* render_frame_host) { - auto permission_type = - blink::PermissionDescriptorToPermissionType(permission); - - CHECK(permission_type == blink::PermissionType::VIDEO_CAPTURE || - permission_type == blink::PermissionType::AUDIO_CAPTURE || - permission_type == blink::PermissionType::GEOLOCATION); + CHECK(PermissionUtil::IsDevicePermission(permission)); return GetPermissionStatusForCurrentDocumentInternal( permission, render_frame_host, /*should_include_device_status=*/true); }
diff --git a/content/browser/permissions/permission_service_impl.cc b/content/browser/permissions/permission_service_impl.cc index 096c7dc7..88789e5 100644 --- a/content/browser/permissions/permission_service_impl.cc +++ b/content/browser/permissions/permission_service_impl.cc
@@ -376,21 +376,20 @@ PermissionDescriptorPtr permission, PermissionStatus last_known_status, mojo::PendingRemote<blink::mojom::PermissionObserver> observer) { - if (!base::FeatureList::IsEnabled(blink::features::kPermissionElement)) { - bad_message::ReceivedBadMessage( - context_->render_frame_host()->GetProcess(), - bad_message::PSI_ADD_PAGE_EMBEDDED_PERMISSION_OBSERVER_WITHOUT_FEATURE); - return; - } auto type = blink::MaybePermissionDescriptorToPermissionType(permission); if (!type) { ReceivedBadMessage(); return; } - context_->CreateSubscription( - permission, origin_, GetCombinedPermissionAndDeviceStatus(permission), - last_known_status, /*should_include_device_status*/ true, - std::move(observer)); + bool should_include_device_status = + PermissionUtil::IsDevicePermission(permission); + PermissionStatus current_status = + should_include_device_status + ? GetCombinedPermissionAndDeviceStatus(permission) + : GetPermissionStatusForCurrentContext(permission); + context_->CreateSubscription(permission, origin_, current_status, + last_known_status, should_include_device_status, + std::move(observer)); } void PermissionServiceImpl::NotifyEventListener(
diff --git a/content/browser/permissions/permission_util.cc b/content/browser/permissions/permission_util.cc index 2ff4b3b..4530dcf4 100644 --- a/content/browser/permissions/permission_util.cc +++ b/content/browser/permissions/permission_util.cc
@@ -97,4 +97,11 @@ return true; } +bool PermissionUtil::IsDevicePermission( + const blink::mojom::PermissionDescriptorPtr& descriptor) { + return descriptor->name == blink::mojom::PermissionName::VIDEO_CAPTURE || + descriptor->name == blink::mojom::PermissionName::AUDIO_CAPTURE || + descriptor->name == blink::mojom::PermissionName::GEOLOCATION; +} + } // namespace content
diff --git a/content/browser/permissions/permission_util.h b/content/browser/permissions/permission_util.h index b0cafa85..56576c3 100644 --- a/content/browser/permissions/permission_util.h +++ b/content/browser/permissions/permission_util.h
@@ -47,6 +47,12 @@ const std::vector<blink::mojom::PermissionDescriptorPtr>& types, RenderFrameHost* rfh, const blink::mojom::PermissionDescriptorPtr& descriptor); + + // Returns true if the given descriptor is a capability that combines the + // browser's permission status with a device-level status (and, therefore, + // can be retrieved through `GetCombinedPermissionAndDeviceStatus(...)`). + CONTENT_EXPORT static bool IsDevicePermission( + const blink::mojom::PermissionDescriptorPtr&); }; } // namespace content
diff --git a/content/browser/preloading/prefetch/contamination_delay_browsertest.cc b/content/browser/preloading/prefetch/contamination_delay_browsertest.cc index 0cfa515..c25afe3 100644 --- a/content/browser/preloading/prefetch/contamination_delay_browsertest.cc +++ b/content/browser/preloading/prefetch/contamination_delay_browsertest.cc
@@ -256,6 +256,7 @@ test::kPreloadingEmbedderHistgramSuffixForTesting, blink::mojom::Referrer(), referring_origin, /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/PreloadingType::kPrefetch), /*attempt=*/nullptr, /*holdback_status_override=*/std::nullopt,
diff --git a/content/browser/preloading/prefetch/no_vary_search_helper_unittest.cc b/content/browser/preloading/prefetch/no_vary_search_helper_unittest.cc index 967bea6..ceff8f1 100644 --- a/content/browser/preloading/prefetch/no_vary_search_helper_unittest.cc +++ b/content/browser/preloading/prefetch/no_vary_search_helper_unittest.cc
@@ -109,6 +109,7 @@ blink::mojom::Referrer(), std::make_optional(SpeculationRulesTags()), /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, /*prefetch_document_manager=*/nullptr, PreloadPipelineInfo::Create(/*planned_max_preloading_type=*/ PreloadingType::kPrefetch));
diff --git a/content/browser/preloading/prefetch/prefetch_container.cc b/content/browser/preloading/prefetch/prefetch_container.cc index 020fb66d..9defc88 100644 --- a/content/browser/preloading/prefetch/prefetch_container.cc +++ b/content/browser/preloading/prefetch/prefetch_container.cc
@@ -329,6 +329,7 @@ const blink::mojom::Referrer& referrer, std::optional<SpeculationRulesTags> speculation_rules_tags, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, base::WeakPtr<PrefetchDocumentManager> prefetch_document_manager, scoped_refptr<PreloadPipelineInfo> preload_pipeline_info, base::WeakPtr<PreloadingAttempt> attempt) @@ -357,7 +358,8 @@ .javascript_enabled, PrefetchContainerDefaultTtlInPrefetchService(), /*should_append_variations_header=*/true, - /*should_disable_block_until_head_timeout=*/false) { + /*should_disable_block_until_head_timeout=*/false, + priority) { CHECK(prefetch_type_.IsRendererInitiated()); } @@ -369,6 +371,7 @@ const blink::mojom::Referrer& referrer, const std::optional<url::Origin>& referring_origin, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, scoped_refptr<PreloadPipelineInfo> preload_pipeline_info, base::WeakPtr<PreloadingAttempt> attempt, std::optional<PreloadingHoldbackStatus> holdback_status_override, @@ -398,7 +401,8 @@ ttl.has_value() ? ttl.value() : PrefetchContainerDefaultTtlInPrefetchService(), /*should_append_variations_header=*/true, - /*should_disable_block_until_head_timeout=*/false) { + /*should_disable_block_until_head_timeout=*/false, + priority) { CHECK(!prefetch_type_.IsRendererInitiated()); CHECK(PrefetchBrowserInitiatedTriggersEnabled()); CHECK(!embedder_histogram_suffix_.value().empty()); @@ -413,6 +417,7 @@ bool javascript_enabled, const std::optional<url::Origin>& referring_origin, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, base::WeakPtr<PreloadingAttempt> attempt, const net::HttpRequestHeaders& additional_headers, std::unique_ptr<PrefetchRequestStatusListener> request_status_listener, @@ -444,7 +449,8 @@ javascript_enabled, ttl, should_append_variations_header, - should_disable_block_until_head_timeout) { + should_disable_block_until_head_timeout, + priority) { CHECK(!prefetch_type_.IsRendererInitiated()); CHECK(PrefetchBrowserInitiatedTriggersEnabled()); CHECK(!embedder_histogram_suffix_.value().empty()); @@ -472,7 +478,8 @@ bool is_javascript_enabled, base::TimeDelta ttl, bool should_append_variations_header, - bool should_disable_block_until_head_timeout) + bool should_disable_block_until_head_timeout, + std::optional<PrefetchPriority> priority) : referring_render_frame_host_id_(referring_render_frame_host_id), referring_origin_(referring_origin), referring_url_hash_(referring_url_hash), @@ -498,7 +505,8 @@ ttl_(ttl), should_append_variations_header_(should_append_variations_header), should_disable_block_until_head_timeout_( - should_disable_block_until_head_timeout) { + should_disable_block_until_head_timeout), + priority_(priority) { is_likely_ahead_of_prerender_ = CalculateIsLikelyAheadOfPrerender(*preload_pipeline_info_); @@ -1739,6 +1747,20 @@ net::SiteForCookies::FromOrigin(origin)); auto priority = [&] { + if (GetPrefetchPriority().has_value()) { + switch (GetPrefetchPriority().value()) { + case PrefetchPriority::kLow: + return net::RequestPriority::IDLE; + case PrefetchPriority::kMedium: + return net::RequestPriority::LOW; + case PrefetchPriority::kHigh: + return net::RequestPriority::MEDIUM; + case PrefetchPriority::kHighest: + return net::RequestPriority::HIGHEST; + } + } + + // TODO(crbug.com/426404355): Migrate to use `PrefetchPriority`. if (IsSpeculationRuleType(prefetch_type_.trigger_type())) { // This may seem inverted (surely immediate prefetches would be higher // priority), but the fact that we're doing this at all for more
diff --git a/content/browser/preloading/prefetch/prefetch_container.h b/content/browser/preloading/prefetch/prefetch_container.h index 3b97186..37227a8 100644 --- a/content/browser/preloading/prefetch/prefetch_container.h +++ b/content/browser/preloading/prefetch/prefetch_container.h
@@ -24,6 +24,7 @@ #include "content/browser/preloading/speculation_rules/speculation_rules_tags.h" #include "content/common/content_export.h" #include "content/public/browser/global_routing_id.h" +#include "content/public/browser/prefetch_priority.h" #include "content/public/browser/prefetch_request_status_listener.h" #include "content/public/browser/preload_pipeline_info.h" #include "content/public/browser/preloading.h" @@ -112,6 +113,7 @@ const blink::mojom::Referrer& referrer, std::optional<SpeculationRulesTags> speculation_rules_tags, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, base::WeakPtr<PrefetchDocumentManager> prefetch_document_manager, scoped_refptr<PreloadPipelineInfo> preload_pipeline_info, base::WeakPtr<PreloadingAttempt> attempt = nullptr); @@ -127,6 +129,7 @@ const blink::mojom::Referrer& referrer, const std::optional<url::Origin>& referring_origin, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, scoped_refptr<PreloadPipelineInfo> preload_pipeline_info, base::WeakPtr<PreloadingAttempt> attempt = nullptr, std::optional<PreloadingHoldbackStatus> holdback_status_override = @@ -145,6 +148,7 @@ bool javascript_enabled, const std::optional<url::Origin>& referring_origin, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, base::WeakPtr<PreloadingAttempt> attempt = nullptr, const net::HttpRequestHeaders& additional_headers = {}, std::unique_ptr<PrefetchRequestStatusListener> request_status_listener = @@ -806,6 +810,10 @@ return should_disable_block_until_head_timeout_; } + std::optional<PrefetchPriority> GetPrefetchPriority() const { + return priority_; + } + protected: friend class PrefetchContainerTestBase; @@ -838,7 +846,8 @@ bool is_javascript_enabled, base::TimeDelta ttl, bool should_append_variations_header, - bool should_disable_block_until_head_timeout); + bool should_disable_block_until_head_timeout, + std::optional<PrefetchPriority> priority); // Update |prefetch_status_| and report prefetch status to // DevTools without updating TriggeringOutcome. @@ -1118,6 +1127,10 @@ // `PrefetchBlockUntilHeadTimeout()` as a `prefetch_params`. const bool should_disable_block_until_head_timeout_ = false; + // An optimization hint indicating how quickly this prefetch should be + // available. + const std::optional<PrefetchPriority> priority_ = std::nullopt; + // Timing information for metrics // // Constraint: That earlier one is null implies that later one is null.
diff --git a/content/browser/preloading/prefetch/prefetch_container_unittest.cc b/content/browser/preloading/prefetch/prefetch_container_unittest.cc index f4020c6d..1406290 100644 --- a/content/browser/preloading/prefetch/prefetch_container_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_container_unittest.cc
@@ -83,7 +83,8 @@ /*use_prefetch_proxy=*/true, options.eagerness), blink::mojom::Referrer(), std::make_optional(std::move(options.speculation_rules_tags)), - /*no_vary_search_hint=*/std::nullopt, options.prefetch_document_manager, + /*no_vary_search_hint=*/std::nullopt, /*priority=*/std::nullopt, + options.prefetch_document_manager, PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/PreloadingType::kPrefetch)); } @@ -97,7 +98,7 @@ /*use_prefetch_proxy=*/true), test::kPreloadingEmbedderHistgramSuffixForTesting, blink::mojom::Referrer(), std::move(referring_origin), - /*no_vary_search_hint=*/std::nullopt, + /*no_vary_search_hint=*/std::nullopt, /*priority=*/std::nullopt, PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/PreloadingType::kPrefetch), /*attempt=*/nullptr); @@ -116,6 +117,7 @@ /*javascript_enabled=*/true, /*referring_origin=*/std::nullopt, /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, /*attempt=*/nullptr, additional_headers, /*request_status_listener=*/nullptr, base::Minutes(10), should_append_additional_headers); @@ -335,6 +337,7 @@ blink::mojom::Referrer(), std::make_optional(SpeculationRulesTags({"example"})), /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, /*prefetch_document_manager=*/nullptr, PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/PreloadingType::kPrefetch)); @@ -365,6 +368,7 @@ blink::mojom::Referrer(), /*referring_origin=*/std::nullopt, /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/PreloadingType::kPrefetch), /*attempt=*/nullptr);
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager.cc b/content/browser/preloading/prefetch/prefetch_document_manager.cc index 59c40d6..96e4490 100644 --- a/content/browser/preloading/prefetch/prefetch_document_manager.cc +++ b/content/browser/preloading/prefetch/prefetch_document_manager.cc
@@ -271,8 +271,9 @@ auto container = std::make_unique<PrefetchContainer>( static_cast<RenderFrameHostImpl&>(render_frame_host()), document_token_, url, prefetch_type, referrer, std::move(speculation_rules_tags), - std::move(no_vary_search_hint), weak_method_factory_.GetWeakPtr(), - std::move(preload_pipeline_info), attempt->GetWeakPtr()); + std::move(no_vary_search_hint), /*priority=*/std::nullopt, + weak_method_factory_.GetWeakPtr(), std::move(preload_pipeline_info), + attempt->GetWeakPtr()); DVLOG(1) << *container << ": created"; referring_page_metrics_.prefetch_attempted_count++;
diff --git a/content/browser/preloading/prefetch/prefetch_scheduler.cc b/content/browser/preloading/prefetch/prefetch_scheduler.cc index 03f44ee..7dbbbc6 100644 --- a/content/browser/preloading/prefetch/prefetch_scheduler.cc +++ b/content/browser/preloading/prefetch/prefetch_scheduler.cc
@@ -49,21 +49,33 @@ return GetActiveSetSizeLimitForBase(); } -PrefetchPriority CalculatePriorityImpl( +PrefetchSchedulerPriority CalculatePriorityImpl( const PrefetchContainer& prefetch_container) { + if (prefetch_container.GetPrefetchPriority().has_value()) { + switch (prefetch_container.GetPrefetchPriority().value()) { + case PrefetchPriority::kLow: + case PrefetchPriority::kMedium: + case PrefetchPriority::kHigh: + return PrefetchSchedulerPriority::kBase; + case PrefetchPriority::kHighest: + return PrefetchSchedulerPriority::kBurstForPrefetchPriority; + } + } + // Burst/prioritize if ahead of prerender. + // TODO(crbug.com/426404355): Migrate to use `PrefetchPriority`. if (prefetch_container.IsLikelyAheadOfPrerender()) { switch (features::kPrerender2FallbackPrefetchSchedulerPolicy.Get()) { case features::Prerender2FallbackPrefetchSchedulerPolicy::kNotUse: break; case features::Prerender2FallbackPrefetchSchedulerPolicy::kPrioritize: - return PrefetchPriority::kHighAheadOfPrerender; + return PrefetchSchedulerPriority::kHighAheadOfPrerender; case features::Prerender2FallbackPrefetchSchedulerPolicy::kBurst: - return PrefetchPriority::kBurstAheadOfPrerender; + return PrefetchSchedulerPriority::kBurstAheadOfPrerender; } } - return PrefetchPriority::kBase; + return PrefetchSchedulerPriority::kBase; } bool IsReadyToStartPrefetch(const PrefetchQueue::Item& item) { @@ -105,7 +117,7 @@ } // namespace PrefetchQueue::Item::Item(base::WeakPtr<PrefetchContainer> prefetch_container, - PrefetchPriority priority) + PrefetchSchedulerPriority priority) : prefetch_container(std::move(prefetch_container)), priority(priority) {} PrefetchQueue::Item::Item(const PrefetchQueue::Item&& other) @@ -127,7 +139,7 @@ PrefetchQueue::~PrefetchQueue() = default; void PrefetchQueue::Push(base::WeakPtr<PrefetchContainer> prefetch_container, - PrefetchPriority priority) { + PrefetchSchedulerPriority priority) { CHECK(prefetch_container); // Postcondition: Pushing registered one is not allowed. CHECK(!Remove(prefetch_container)); @@ -153,7 +165,7 @@ } bool PrefetchQueue::MaybeUpdatePriority(PrefetchContainer& prefetch_container, - PrefetchPriority priority) { + PrefetchSchedulerPriority priority) { for (auto it = queue_.cbegin(); it != queue_.cend(); ++it) { if (it->prefetch_container.get() == &prefetch_container) { if (it->priority != priority) { @@ -185,7 +197,7 @@ return false; } -PrefetchPriority PrefetchScheduler::CalculatePriority( +PrefetchSchedulerPriority PrefetchScheduler::CalculatePriority( const PrefetchContainer& prefetch_container) { if (calculate_priority_for_test_) { return calculate_priority_for_test_.Run(prefetch_container); @@ -202,7 +214,7 @@ } } - PrefetchPriority priority = CalculatePriority(prefetch_container); + PrefetchSchedulerPriority priority = CalculatePriority(prefetch_container); queue_.Push(prefetch_container.GetWeakPtr(), priority); Progress(); @@ -217,7 +229,7 @@ } } - PrefetchPriority priority = CalculatePriority(prefetch_container); + PrefetchSchedulerPriority priority = CalculatePriority(prefetch_container); queue_.Push(prefetch_container.GetWeakPtr(), priority); ProgressAsync(); @@ -306,7 +318,7 @@ // priority. See // https://chromium-review.googlesource.com/c/chromium/src/+/6402914/comment/8b5c845f_0b7f6f7e/ - auto internal = [&](PrefetchPriority threshold_priority, + auto internal = [&](PrefetchSchedulerPriority threshold_priority, size_t active_limit) { // Invariant: `active_set_.size() == 0 && there is a ready prefetch` is // false. I.e. doesn't stuck. @@ -334,8 +346,9 @@ } }; - internal(PrefetchPriority::kBurstThreshold, GetActiveSetSizeLimitForBurst()); - internal(PrefetchPriority::kBase, GetActiveSetSizeLimitForBase()); + internal(PrefetchSchedulerPriority::kBurstThreshold, + GetActiveSetSizeLimitForBurst()); + internal(PrefetchSchedulerPriority::kBase, GetActiveSetSizeLimitForBase()); } void PrefetchScheduler::ProgressOne( @@ -371,7 +384,7 @@ } void PrefetchScheduler::SetCalculatePriorityForTesting( - base::RepeatingCallback<PrefetchPriority(const PrefetchContainer&)> + base::RepeatingCallback<PrefetchSchedulerPriority(const PrefetchContainer&)> callback) { calculate_priority_for_test_ = std::move(callback); }
diff --git a/content/browser/preloading/prefetch/prefetch_scheduler.h b/content/browser/preloading/prefetch/prefetch_scheduler.h index 93ea5f7..b8d06bf 100644 --- a/content/browser/preloading/prefetch/prefetch_scheduler.h +++ b/content/browser/preloading/prefetch/prefetch_scheduler.h
@@ -33,10 +33,11 @@ // // TODO(crbug.com/406403063): Rethink about granularity. We don't stick on the // above policy. More rough priorities e.g. kBase/kHigh/kBurst might work well. +// This will eventually be done by `PrefetchPriority`(crbug.com/426404355). // // See also `PrefetchScheduler::NotifyAttributeMightChangedAndProgressAsync()` // when you add a new one. -enum class PrefetchPriority { +enum class PrefetchSchedulerPriority { // Default. kBase = 0, // For tests. Do not use outside tests. @@ -49,8 +50,10 @@ kBurstThreshold = 10, // For tests. Do not use outside tests. kBurstTest = 11, + // Priority derived from `PrefetchPriority`. + kBurstForPrefetchPriority = 12, // Burst priority for prefetch ahead of prerender. - kBurstAheadOfPrerender = 12, + kBurstAheadOfPrerender = 13, }; // Priority queue for prefetches @@ -61,7 +64,7 @@ public: struct Item { Item(base::WeakPtr<PrefetchContainer> prefetch_container, - PrefetchPriority priority); + PrefetchSchedulerPriority priority); ~Item(); // Movable but not copyable. @@ -71,7 +74,7 @@ Item& operator=(const Item&) = delete; base::WeakPtr<PrefetchContainer> prefetch_container; - PrefetchPriority priority; + PrefetchSchedulerPriority priority; }; PrefetchQueue(); @@ -86,7 +89,7 @@ size_t size() const { return queue_.size(); } void Push(base::WeakPtr<PrefetchContainer> prefetch_container, - PrefetchPriority priority); + PrefetchSchedulerPriority priority); // Pops `PrefetchContainer` // @@ -95,8 +98,9 @@ // - `pred` // - Priority is larger or equal to `threshold_priority`. template <class Predicate> - std::optional<PrefetchQueue::Item> Pop(Predicate pred, - PrefetchPriority threshold_priority) { + std::optional<PrefetchQueue::Item> Pop( + Predicate pred, + PrefetchSchedulerPriority threshold_priority) { for (auto it = queue_.cbegin(); it != queue_.cend(); ++it) { if (it->priority < threshold_priority) { break; @@ -120,7 +124,7 @@ // // Returns true iff priority is updated. bool MaybeUpdatePriority(PrefetchContainer& prefetch_container, - PrefetchPriority priority); + PrefetchSchedulerPriority priority); private: std::vector<PrefetchQueue::Item> queue_; @@ -189,11 +193,11 @@ void Progress(); void SetCalculatePriorityForTesting( - base::RepeatingCallback<PrefetchPriority(const PrefetchContainer&)> - callback); + base::RepeatingCallback< + PrefetchSchedulerPriority(const PrefetchContainer&)> callback); private: - PrefetchPriority CalculatePriority( + PrefetchSchedulerPriority CalculatePriority( const PrefetchContainer& prefetch_container); void ProgressAsync(); @@ -218,7 +222,7 @@ // `PrefetchScheduler::ProgressAsync()`. bool in_eviction_ = false; - base::RepeatingCallback<PrefetchPriority(const PrefetchContainer&)> + base::RepeatingCallback<PrefetchSchedulerPriority(const PrefetchContainer&)> calculate_priority_for_test_; #if DCHECK_IS_ON()
diff --git a/content/browser/preloading/prefetch/prefetch_service.cc b/content/browser/preloading/prefetch/prefetch_service.cc index 094f6543..1959097 100644 --- a/content/browser/preloading/prefetch/prefetch_service.cc +++ b/content/browser/preloading/prefetch/prefetch_service.cc
@@ -2103,17 +2103,20 @@ void PrefetchService::EvictPrefetchesForBrowsingDataRemoval( const StoragePartition::StorageKeyMatcherFunction& storage_key_filter, PrefetchStatus status) { - // TODO(crbug.com/40262310): Handle for prefetches from non-SpeculationRules std::vector<base::WeakPtr<PrefetchContainer>> prefetches_to_reset; for (const auto& prefetch_iter : owned_prefetches_) { base::WeakPtr<PrefetchContainer> prefetch_container = prefetch_iter.second->GetWeakPtr(); CHECK(prefetch_container); - std::optional<url::Origin> referring_origin = - prefetch_container->GetReferringOrigin(); - if (referring_origin.has_value() && - storage_key_filter.Run( - blink::StorageKey::CreateFirstParty(referring_origin.value()))) { + + // If `referring_origin` is std::nullopt (e.g some browser-initiated + // prefetch), use the origin of the prefetch URL itself, since we generally + // handle no referring origin prefetches as a same-origin prefetch fashion. + const url::Origin target_origin = + prefetch_container->GetReferringOrigin().value_or( + url::Origin::Create(prefetch_container->GetURL())); + if (storage_key_filter.Run( + blink::StorageKey::CreateFirstParty(target_origin))) { prefetch_container->SetPrefetchStatus(status); prefetches_to_reset.push_back(prefetch_container); }
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc index 6688eb0..d6d6dfc9 100644 --- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -537,6 +537,7 @@ test::kPreloadingEmbedderHistgramSuffixForTesting, referrer, std::move(referring_origin), /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/PreloadingType::kPrefetch), /*attempt=*/nullptr); @@ -555,7 +556,7 @@ bool should_disable_block_until_head_timeout = false) { return browser_context()->StartBrowserPrefetchRequest( url, test::kPreloadingEmbedderHistgramSuffixForTesting, true, - no_vary_search_data, additional_headers, + no_vary_search_data, /*priority=*/std::nullopt, additional_headers, std::move(request_status_listener), ttl, /*should_append_variations_header=*/true, should_disable_block_until_head_timeout); @@ -5589,6 +5590,74 @@ 0); } +// Tests that browsing data removal for prefetch is performed per 1) its +// `referring_origin` 2) if that is std::nullopt, then prefetch url. +TEST_P(PrefetchServiceTest, PrefetchEviction) { + base::HistogramTester histogram_tester; + + struct TestCase { + const std::optional<url::Origin> referring_origin; + const GURL prefetch_url; + }; + const std::vector<TestCase> test_cases = { + {url::Origin::Create(GURL("https://a.test")), GURL("https://a.test/0")}, + {url::Origin::Create(GURL("https://a.test")), GURL("https://b.test/1")}, + {url::Origin::Create(GURL("https://b.test")), GURL("https://a.test/2")}, + {url::Origin::Create(GURL("https://b.test")), GURL("https://b.test/3")}, + {std::nullopt, GURL("https://a.test/4")}, + {std::nullopt, GURL("https://b.test/5")}, + }; + + MakePrefetchService( + std::make_unique<testing::NiceMock<MockPrefetchServiceDelegate>>( + /*num_on_prefetch_likely_calls=*/std::nullopt)); + PrefetchService* prefetch_service = + BrowserContextImpl::From(browser_context())->GetPrefetchService(); + + std::vector<std::unique_ptr<PrefetchHandle>> handles; + for (const auto& test_case : test_cases) { + handles.push_back( + MakePrefetchFromEmbedder(test_case.prefetch_url, + PrefetchType(PreloadingTriggerType::kEmbedder, + /*use_prefetch_proxy=*/false), + /*referrer=*/{}, test_case.referring_origin)); + } + task_environment()->RunUntilIdle(); + + // Evict prefetches from "a.test". The prefetch for "a.test" with no + // `referring_origin` should also be removed. + auto filter_builder = BrowsingDataFilterBuilder::Create( + BrowsingDataFilterBuilder::Mode::kDelete); + filter_builder->AddOrigin(url::Origin::Create(GURL("https://a.test"))); + auto filter = filter_builder->BuildStorageKeyFilter(); + prefetch_service->EvictPrefetchesForBrowsingDataRemoval( + filter, PrefetchStatus::kPrefetchEvictedAfterBrowsingDataRemoved); + task_environment()->RunUntilIdle(); + EXPECT_FALSE(handles[0]->IsAlive()); + EXPECT_FALSE(handles[1]->IsAlive()); + EXPECT_FALSE(handles[4]->IsAlive()); + EXPECT_TRUE(handles[2]->IsAlive()); + EXPECT_TRUE(handles[3]->IsAlive()); + EXPECT_TRUE(handles[5]->IsAlive()); + histogram_tester.ExpectUniqueSample( + "Preloading.Prefetch.PrefetchStatus", + PrefetchStatus::kPrefetchEvictedAfterBrowsingDataRemoved, 3); + + // Attempt to clear all the cache. The remaining prefetches are also removed. + prefetch_service->EvictPrefetchesForBrowsingDataRemoval( + BrowsingDataFilterBuilder::Create( + BrowsingDataFilterBuilder::Mode::kPreserve) + ->BuildStorageKeyFilter(), + PrefetchStatus::kPrefetchEvictedAfterBrowsingDataRemoved); + task_environment()->RunUntilIdle(); + EXPECT_FALSE(handles[2]->IsAlive()); + EXPECT_FALSE(handles[3]->IsAlive()); + EXPECT_FALSE(handles[5]->IsAlive()); + histogram_tester.ExpectUniqueSample( + "Preloading.Prefetch.PrefetchStatus", + PrefetchStatus::kPrefetchEvictedAfterBrowsingDataRemoved, 6); +} + // Tests that the prefetch eviction for eligible but not started triggers (i.e. // `PreloadingAttempt`'s `PreloadingHoldbackStatus` is `kUnspecified`) causes no // crash. This is a regression test of crbug.com/404703517. @@ -7646,6 +7715,7 @@ prefetch_url, std::move(prefetch_type), blink::mojom::Referrer(), std::make_optional(SpeculationRulesTags()), /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, /*prefetch_document_manager=*/nullptr, PreloadPipelineInfo::Create(planned_max_preloading_type), attempt->GetWeakPtr()); @@ -7920,10 +7990,10 @@ base::BindRepeating([](const PrefetchContainer& prefetch_container) { if (prefetch_container.GetURL().possibly_invalid_spec().ends_with( "?prioritize=1")) { - return PrefetchPriority::kHighTest; + return PrefetchSchedulerPriority::kHighTest; } - return PrefetchPriority::kBase; + return PrefetchSchedulerPriority::kBase; })); const auto url_1 = GURL("https://example.com/one"); @@ -8000,10 +8070,10 @@ base::BindRepeating([](const PrefetchContainer& prefetch_container) { if (prefetch_container.GetURL().possibly_invalid_spec().ends_with( "?prioritize=1")) { - return PrefetchPriority::kHighTest; + return PrefetchSchedulerPriority::kHighTest; } - return PrefetchPriority::kBase; + return PrefetchSchedulerPriority::kBase; })); const auto url_1 = GURL("https://example.com/one"); @@ -8064,10 +8134,10 @@ base::BindRepeating([](const PrefetchContainer& prefetch_container) { if (prefetch_container.GetURL().possibly_invalid_spec().ends_with( "?burst=1")) { - return PrefetchPriority::kBurstTest; + return PrefetchSchedulerPriority::kBurstTest; } - return PrefetchPriority::kBase; + return PrefetchSchedulerPriority::kBase; })); const auto url_1 = GURL("https://example.com/one"); @@ -8169,10 +8239,10 @@ base::BindRepeating([](const PrefetchContainer& prefetch_container) { if (prefetch_container.GetURL().possibly_invalid_spec().ends_with( "?burst=1")) { - return PrefetchPriority::kBurstTest; + return PrefetchSchedulerPriority::kBurstTest; } - return PrefetchPriority::kBase; + return PrefetchSchedulerPriority::kBase; })); const auto url_1 = GURL("https://example.com/one"); @@ -8274,10 +8344,10 @@ base::BindRepeating([](const PrefetchContainer& prefetch_container) { if (prefetch_container.GetURL().possibly_invalid_spec().ends_with( "?burst=1")) { - return PrefetchPriority::kBurstTest; + return PrefetchSchedulerPriority::kBurstTest; } - return PrefetchPriority::kBase; + return PrefetchSchedulerPriority::kBase; })); const auto url_1 = GURL("https://example.com/one");
diff --git a/content/browser/preloading/prefetch/prefetch_url_loader_interceptor_unittest.cc b/content/browser/preloading/prefetch/prefetch_url_loader_interceptor_unittest.cc index e6ee973..0b076d0f9 100644 --- a/content/browser/preloading/prefetch/prefetch_url_loader_interceptor_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_url_loader_interceptor_unittest.cc
@@ -389,6 +389,7 @@ std::move(prefetch_type), blink::mojom::Referrer(), std::make_optional(SpeculationRulesTags()), /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, /*prefetch_document_manager=*/nullptr, PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/PreloadingType::kPrefetch), @@ -411,6 +412,7 @@ test::kPreloadingEmbedderHistgramSuffixForTesting, blink::mojom::Referrer(), std::move(referring_origin), /*no_vary_search_hint=*/std::nullopt, + /*priority=*/std::nullopt, PreloadPipelineInfo::Create( /*planned_max_preloading_type=*/PreloadingType::kPrefetch),
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc index 146afc55..f51ebe9 100644 --- a/content/browser/preloading/prerender/prerender_browsertest.cc +++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -2825,6 +2825,61 @@ void TestActivateOnWindowOpen(std::string_view window_features); + std::string SpeculationRulesInsertionScriptWithBothTargetHint(GURL url) { + constexpr char add_speculationrules_with_both_target_hints[] = R"({ + var script = document.createElement('script'); + script.type = 'speculationrules'; + script.text = `{"prerender": [ + {"target_hint": "_self", "urls": ["$1"]}, + {"target_hint": "_blank", "urls": ["$1"]} + ] + }`; + document.head.appendChild(script); + })"; + + return base::ReplaceStringPlaceholders( + add_speculationrules_with_both_target_hints, {url.spec()}, nullptr); + } + + std::string SpeculationRulesInsertionScriptWithOneSelfAndTwoBlankTargetHint( + GURL url) { + constexpr char add_speculationrules_with_both_target_hints[] = R"({ + var script = document.createElement('script'); + script.type = 'speculationrules'; + script.text = `{"prerender": [ + {"target_hint": "_self", "urls": ["$1"]}, + {"target_hint": "_blank", "urls": ["$1"]}, + {"target_hint": "_blank", "urls": ["$1"]} + ] + }`; + document.head.appendChild(script); + })"; + + return base::ReplaceStringPlaceholders( + add_speculationrules_with_both_target_hints, {url.spec()}, nullptr); + } + + std::string SpeculationRulesWithIdAndTargetHint(GURL url, + std::string id, + std::string target_hint) { + constexpr char add_speculationrules_with_id_and_target_hint[] = R"({ + var script = document.createElement('script'); + script.type = 'speculationrules'; + script.id = '$1'; + script.text = `{"prerender": + [{ + "target_hint": "$2", + "urls": ["$3"] + }] + }`; + document.head.appendChild(script); + })"; + + return base::ReplaceStringPlaceholders( + add_speculationrules_with_id_and_target_hint, + {id, target_hint, url.spec()}, nullptr); + } + private: base::test::ScopedFeatureList feature_list_; }; @@ -3413,6 +3468,275 @@ EXPECT_EQ(web_contents()->GetLastCommittedURL(), initial_url); } +// Tests that adding speculation rules with both target_hint and removes +// target_hint=_self won't affect prerender activation on target_hint=_blank. +IN_PROC_BROWSER_TEST_F(PrerenderTargetHintEnabledBrowserTest, + PrerenderBothTargetHintButRemovesTargetHintSelf) { + const GURL initial_url = GetUrl("/simple_links.html"); + const GURL prerendering_url = GetUrl("/title2.html"); + + const std::string add_speculation_rules_target_hint_self_script = + SpeculationRulesWithIdAndTargetHint(prerendering_url, "self_specrules", + "_self"); + const std::string add_speculation_rules_target_hint_blank_script = + SpeculationRulesWithIdAndTargetHint(prerendering_url, "blank_specrules", + "_blank"); + + // Navigate to an initial page which has a link to `prerendering_url`. + ASSERT_TRUE(NavigateToURL(shell(), initial_url)); + + // Adding speculation rules with target_hint=_self. + EXPECT_TRUE( + ExecJs(web_contents(), add_speculation_rules_target_hint_self_script)); + prerender_helper()->WaitForPrerenderLoadCompletion(*web_contents(), + prerendering_url); + + // Adding speculation rules with target_hint=_blank. + WebContents* new_tab_prerender_web_contents = nullptr; + base::RunLoop run_loop; + + auto creation_subscription = RegisterWebContentsCreationCallback( + base::BindLambdaForTesting([&](content::WebContents* web_contents) { + new_tab_prerender_web_contents = web_contents; + run_loop.QuitClosure().Run(); + })); + + EXPECT_TRUE( + ExecJs(web_contents(), add_speculation_rules_target_hint_blank_script)); + // Wait for the new tab prerender. + run_loop.Run(); + + prerender_helper()->WaitForPrerenderLoadCompletion( + *new_tab_prerender_web_contents, prerendering_url); + + ASSERT_NE(new_tab_prerender_web_contents, web_contents_impl()); + ExpectWebContentsIsForNewTabPrerendering(*new_tab_prerender_web_contents); + + ASSERT_TRUE( + ExecJs(web_contents_impl()->GetPrimaryMainFrame(), + "document.querySelector('script[id=self_specrules]').remove()")); + + // Speculationrules removal for the initiator tab shouldn't cancel the + // prerender in the new WebContents. + EXPECT_FALSE(HasHostForUrl(*web_contents(), prerendering_url)); + EXPECT_TRUE(HasHostForUrl(*new_tab_prerender_web_contents, prerendering_url)); + + // Open a new window with "_blank" and `noopener`. This should activate + // the prerendered page. + test::PrerenderHostObserver new_tab_prerender_observer( + *new_tab_prerender_web_contents, prerendering_url); + + { + const std::string new_tab_opener_script = + "window.open(\"title2.html\", \"_blank\", \"noopener\")"; + EXPECT_TRUE(ExecJs(web_contents(), new_tab_opener_script)); + new_tab_prerender_observer.WaitForActivation(); + EXPECT_EQ(new_tab_prerender_web_contents->GetLastCommittedURL(), + prerendering_url); + EXPECT_FALSE( + HasHostForUrl(*new_tab_prerender_web_contents, prerendering_url)); + } +} + +// Tests that adding speculation rules with both target_hint and removes +// target_hint=_blank won't affect prerender activation on target_hint=_self. +IN_PROC_BROWSER_TEST_F(PrerenderTargetHintEnabledBrowserTest, + PrerenderBothTargetHintButRemovesTargetHintBlank) { + const GURL initial_url = GetUrl("/simple_links.html"); + const GURL prerendering_url = GetUrl("/title2.html"); + + const std::string add_speculation_rules_target_hint_self_script = + SpeculationRulesWithIdAndTargetHint(prerendering_url, "self_specrules", + "_self"); + const std::string add_speculation_rules_target_hint_blank_script = + SpeculationRulesWithIdAndTargetHint(prerendering_url, "blank_specrules", + "_blank"); + + // Navigate to an initial page which has a link to `prerendering_url`. + ASSERT_TRUE(NavigateToURL(shell(), initial_url)); + + // Adding speculation rules with target_hint=_self. + EXPECT_TRUE( + ExecJs(web_contents(), add_speculation_rules_target_hint_self_script)); + prerender_helper()->WaitForPrerenderLoadCompletion(*web_contents(), + prerendering_url); + // Adding speculation rules with target_hint=_blank. + WebContents* new_tab_prerender_web_contents = nullptr; + base::RunLoop run_loop; + + auto creation_subscription = RegisterWebContentsCreationCallback( + base::BindLambdaForTesting([&](content::WebContents* web_contents) { + new_tab_prerender_web_contents = web_contents; + run_loop.QuitClosure().Run(); + })); + + EXPECT_TRUE( + ExecJs(web_contents(), add_speculation_rules_target_hint_blank_script)); + // Wait for the new tab prerender. + run_loop.Run(); + + prerender_helper()->WaitForPrerenderLoadCompletion( + *new_tab_prerender_web_contents, prerendering_url); + + ASSERT_NE(new_tab_prerender_web_contents, web_contents_impl()); + ExpectWebContentsIsForNewTabPrerendering(*new_tab_prerender_web_contents); + FrameTreeNodeId new_tab_host_id = test::PrerenderTestHelper::GetHostForUrl( + *new_tab_prerender_web_contents, prerendering_url); + + test::PrerenderHostObserver new_tab_prerender_observer( + *new_tab_prerender_web_contents, new_tab_host_id); + + ASSERT_TRUE( + ExecJs(web_contents_impl()->GetPrimaryMainFrame(), + "document.querySelector('script[id=blank_specrules]').remove()")); + + // Speculationrules removal for the new tab shouldn't cancel the prerender in + // the initial WebContents. + EXPECT_TRUE(HasHostForUrl(*web_contents(), prerendering_url)); + new_tab_prerender_observer.WaitForDestroyed(); + + test::PrerenderHostObserver prerender_observer(*web_contents(), + prerendering_url); + + // The prerender in the initial WebContents should be able to be activated. + { + ASSERT_TRUE(ExecJs(web_contents()->GetPrimaryMainFrame(), + JsReplace("location = $1", prerendering_url))); + prerender_observer.WaitForActivation(); + } +} + +// Tests that speculation rules with both target_hint in one script section can +// be prerendered and activated correctly. +IN_PROC_BROWSER_TEST_F(PrerenderTargetHintEnabledBrowserTest, + ActivateOnBothTargetHint) { + const GURL initial_url = GetUrl("/simple_links.html"); + const GURL prerendering_url = GetUrl("/title2.html"); + + const std::string add_speculation_rules_script = + SpeculationRulesInsertionScriptWithBothTargetHint(prerendering_url); + + // Navigate to an initial page which has a link to `prerendering_url`. + ASSERT_TRUE(NavigateToURL(shell(), initial_url)); + + // Start prerendering `prerendering_url`. + WebContents* new_tab_prerender_web_contents = nullptr; + base::RunLoop run_loop; + + auto creation_subscription = RegisterWebContentsCreationCallback( + base::BindLambdaForTesting([&](content::WebContents* web_contents) { + new_tab_prerender_web_contents = web_contents; + run_loop.QuitClosure().Run(); + })); + + EXPECT_TRUE(ExecJs(web_contents(), add_speculation_rules_script)); + // Wait for the new tab prerender. + run_loop.Run(); + + prerender_helper()->WaitForPrerenderLoadCompletion(*web_contents(), + prerendering_url); + prerender_helper()->WaitForPrerenderLoadCompletion( + *new_tab_prerender_web_contents, prerendering_url); + + ASSERT_NE(new_tab_prerender_web_contents, web_contents_impl()); + ExpectWebContentsIsForNewTabPrerendering(*new_tab_prerender_web_contents); + + // Open a new window with "_blank" and `noopener`. This should activate + // the prerendered page. + test::PrerenderHostObserver new_tab_prerender_observer( + *new_tab_prerender_web_contents, prerendering_url); + test::PrerenderHostObserver prerender_observer(*web_contents(), + prerendering_url); + + { + const std::string new_tab_opener_script = + "window.open(\"title2.html\", \"_blank\", \"noopener\")"; + EXPECT_TRUE(ExecJs(web_contents(), new_tab_opener_script)); + new_tab_prerender_observer.WaitForActivation(); + EXPECT_EQ(new_tab_prerender_web_contents->GetLastCommittedURL(), + prerendering_url); + + // Prerender activation in the new tab shouldn't cancel the prerender in + // the initial WebContents. + EXPECT_TRUE(HasHostForUrl(*web_contents(), prerendering_url)); + EXPECT_FALSE( + HasHostForUrl(*new_tab_prerender_web_contents, prerendering_url)); + } + + // The prerender in the initial WebContents should be able to be activated. + { + ASSERT_TRUE(ExecJs(web_contents()->GetPrimaryMainFrame(), + JsReplace("location = $1", prerendering_url))); + prerender_observer.WaitForActivation(); + } +} + +// Tests that speculation rules with 1 _self and 2 _blank target_hints in one +// script section can be prerendered and activated correctly. +IN_PROC_BROWSER_TEST_F(PrerenderTargetHintEnabledBrowserTest, + ActivateOnOneSelfAndTwoBlankTargetHint) { + const GURL initial_url = GetUrl("/simple_links.html"); + const GURL prerendering_url = GetUrl("/title2.html"); + + const std::string add_speculation_rules_script = + SpeculationRulesInsertionScriptWithOneSelfAndTwoBlankTargetHint( + prerendering_url); + + // Navigate to an initial page which has a link to `prerendering_url`. + ASSERT_TRUE(NavigateToURL(shell(), initial_url)); + + // Start prerendering `prerendering_url`. + WebContents* new_tab_prerender_web_contents = nullptr; + base::RunLoop run_loop; + + auto creation_subscription = RegisterWebContentsCreationCallback( + base::BindLambdaForTesting([&](content::WebContents* web_contents) { + new_tab_prerender_web_contents = web_contents; + run_loop.QuitClosure().Run(); + })); + + EXPECT_TRUE(ExecJs(web_contents(), add_speculation_rules_script)); + // Wait for the new tab prerender. + run_loop.Run(); + + prerender_helper()->WaitForPrerenderLoadCompletion(*web_contents(), + prerendering_url); + prerender_helper()->WaitForPrerenderLoadCompletion( + *new_tab_prerender_web_contents, prerendering_url); + + ASSERT_NE(new_tab_prerender_web_contents, web_contents_impl()); + ExpectWebContentsIsForNewTabPrerendering(*new_tab_prerender_web_contents); + + // Open a new window with "_blank" and `noopener`. This should activate + // the prerendered page. + test::PrerenderHostObserver new_tab_prerender_observer( + *new_tab_prerender_web_contents, prerendering_url); + test::PrerenderHostObserver prerender_observer(*web_contents(), + prerendering_url); + + { + const std::string new_tab_opener_script = + "window.open(\"title2.html\", \"_blank\", \"noopener\")"; + EXPECT_TRUE(ExecJs(web_contents(), new_tab_opener_script)); + new_tab_prerender_observer.WaitForActivation(); + EXPECT_EQ(new_tab_prerender_web_contents->GetLastCommittedURL(), + prerendering_url); + + // Prerender activation in the new tab shouldn't cancel the prerender in + // the initial WebContents. + EXPECT_TRUE(HasHostForUrl(*web_contents(), prerendering_url)); + EXPECT_FALSE( + HasHostForUrl(*new_tab_prerender_web_contents, prerendering_url)); + } + + // The prerender in the initial WebContents should be able to be activated. + { + ASSERT_TRUE(ExecJs(web_contents()->GetPrimaryMainFrame(), + JsReplace("location = $1", prerendering_url))); + prerender_observer.WaitForActivation(); + } +} + // Tests that window.open() annotated with "_blank" and "noopener" can activate // a prerender whose target_hint is "_blank". IN_PROC_BROWSER_TEST_F(PrerenderTargetHintEnabledBrowserTest,
diff --git a/content/browser/preloading/prerender/prerender_features.cc b/content/browser/preloading/prerender/prerender_features.cc index 624bd79..51d4e4c 100644 --- a/content/browser/preloading/prerender/prerender_features.cc +++ b/content/browser/preloading/prerender/prerender_features.cc
@@ -108,6 +108,13 @@ "Prerender2DisallowNonTrustworthyHttp", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kPrerender2WarmUpCompositorForImmediate, + "Prerender2WarmUpCompositorForImmediate", + base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kPrerender2WarmUpCompositorForNonImmediate, + "Prerender2WarmUpCompositorForNonImmediate", + base::FEATURE_DISABLED_BY_DEFAULT); + bool UsePrefetchPrerenderIntegration() { return base::FeatureList::IsEnabled( features::kPrerender2FallbackPrefetchSpecRules) ||
diff --git a/content/browser/preloading/prerender/prerender_features.h b/content/browser/preloading/prerender/prerender_features.h index ac07742b..8b32549 100644 --- a/content/browser/preloading/prerender/prerender_features.h +++ b/content/browser/preloading/prerender/prerender_features.h
@@ -84,6 +84,11 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kPrerender2DisallowNonTrustworthyHttp); +// If enabled, requests the compositor warm-up (crbug.com/41496019) for +// Immediate/non-Immediate Speculation Rules prerenders. +CONTENT_EXPORT BASE_DECLARE_FEATURE(kPrerender2WarmUpCompositorForImmediate); +CONTENT_EXPORT BASE_DECLARE_FEATURE(kPrerender2WarmUpCompositorForNonImmediate); + CONTENT_EXPORT bool UsePrefetchPrerenderIntegration(); } // namespace features
diff --git a/content/browser/preloading/prerenderer_impl.cc b/content/browser/preloading/prerenderer_impl.cc index 0a2bc98a..c578e9b 100644 --- a/content/browser/preloading/prerenderer_impl.cc +++ b/content/browser/preloading/prerenderer_impl.cc
@@ -9,6 +9,7 @@ #include "content/browser/preloading/prerenderer_impl.h" +#include <algorithm> #include <vector> #include "base/feature_list.h" @@ -36,10 +37,48 @@ struct PrerendererImpl::PrerenderInfo { blink::mojom::SpeculationInjectionType injection_type; blink::mojom::SpeculationEagerness eagerness; + bool is_target_blank; FrameTreeNodeId prerender_host_id; GURL url; + + PrerenderInfo() = default; + explicit PrerenderInfo( + const blink::mojom::SpeculationCandidatePtr& candidate); + + static bool PrerenderInfoComparator(const PrerenderInfo& p1, + const PrerenderInfo& p2); + + bool operator<(const PrerenderInfo& p) const { + return PrerenderInfoComparator(*this, p); + } + + bool operator==(const PrerenderInfo& p) const { + return !PrerenderInfoComparator(*this, p) && + !PrerenderInfoComparator(p, *this); + } }; +bool PrerendererImpl::PrerenderInfo::PrerenderInfoComparator( + const PrerenderInfo& p1, + const PrerenderInfo& p2) { + if (p1.url != p2.url) { + return p1.url < p2.url; + } + + return p1.is_target_blank < p2.is_target_blank; +} + +// `prerender_host_id` is not provided by `SpeculationCandidatePtr`, so +// FrameTreeNodeId() is assigned instead. The value should be updated once it is +// available. +PrerendererImpl::PrerenderInfo::PrerenderInfo( + const blink::mojom::SpeculationCandidatePtr& candidate) + : injection_type(candidate->injection_type), + eagerness(candidate->eagerness), + is_target_blank(candidate->target_browsing_context_name_hint == + blink::mojom::SpeculationTargetHint::kBlank), + url(candidate->url) {} + PrerendererImpl::PrerendererImpl(RenderFrameHost& render_frame_host) : WebContentsObserver(WebContents::FromRenderFrameHost(&render_frame_host)), render_frame_host_(render_frame_host) { @@ -97,8 +136,9 @@ } } - std::ranges::stable_sort(prerender_candidates, std::less<>(), - [](const auto& p) { return p.second->url; }); + std::ranges::stable_sort( + prerender_candidates, std::less<>(), + [](const auto& p) { return PrerenderInfo(p.second); }); std::vector<std::pair<size_t, blink::mojom::SpeculationCandidatePtr>> candidates_to_start; @@ -108,36 +148,39 @@ // Compare the sorted candidate and started prerender lists to one another. // Since they are sorted, we process the lexicographically earlier of the two - // URLs pointed at by the iterators, and compare the range of entries in each - // that match that URL. + // PrerenderInfos pointed at by the iterators, and compare the range of + // entries in each that match that PrerenderInfo. // - // URLs which are present in the prerender list but not the candidate list can - // no longer proceed and are cancelled. + // PrerenderInfos which are present in the prerender list but not the + // candidate list can no longer proceed and are cancelled. // - // URLs which are present in the candidate list but not the prerender list - // could be started and are gathered in `candidates_to_start`. + // PrerenderInfos which are present in the candidate list but not the + // prerender list could be started and are gathered in `candidates_to_start`. auto candidate_it = prerender_candidates.begin(); auto started_it = started_prerenders_.begin(); while (candidate_it != prerender_candidates.end() || started_it != started_prerenders_.end()) { - // Select the lesser of the two URLs to diff. - GURL url; - if (started_it == started_prerenders_.end()) - url = candidate_it->second->url; - else if (candidate_it == prerender_candidates.end()) - url = started_it->url; - else - url = std::min(candidate_it->second->url, started_it->url); + // Select the lesser of the two PrerenderInfos to diff. + PrerenderInfo prerender_info; + if (started_it == started_prerenders_.end()) { + prerender_info = PrerenderInfo(candidate_it->second); + } else if (candidate_it == prerender_candidates.end()) { + prerender_info = *started_it; + } else { + prerender_info = + std::min(PrerenderInfo(candidate_it->second), *started_it); + } - // Select the ranges from both that match the URL in question. + // Select the ranges from both that match the PrerenderInfo in question. auto equal_prerender_end = std::ranges::find_if( started_it, started_prerenders_.end(), - [&](const auto& started) { return started.url != url; }); + [&](const auto& started) { return started != prerender_info; }); base::span<PrerenderInfo> matching_prerenders(started_it, equal_prerender_end); auto equal_candidate_end = std::ranges::find_if( - candidate_it, prerender_candidates.end(), - [&](const auto& candidate) { return candidate.second->url != url; }); + candidate_it, prerender_candidates.end(), [&](const auto& candidate) { + return PrerenderInfo(candidate.second) != prerender_info; + }); base::span<std::pair<size_t, blink::mojom::SpeculationCandidatePtr>> matching_candidates(candidate_it, equal_candidate_end); @@ -148,19 +191,30 @@ } // TODO(jbroman): This doesn't currently care about other aspects, like // the referrer. This doesn't presently matter, but in the future we might - // want to cancel if there are candidates which match by URL but none of - // which permit this prerender. + // want to cancel if there are candidates which match by PrerenderInfo but + // none of which permit this prerender. if (matching_candidates.empty()) { removed_prerender_rules.push_back(prerender.prerender_host_id); } } // Decide what new candidates to start. - // For now, start the first candidate for a URL only if there are no - // matching prerenders. We could be cleverer in the future. + // For now, start one candidate per target hint for a URL only if there are + // no matching prerenders. We could be cleverer in the future. if (matching_prerenders.empty()) { CHECK(!matching_candidates.empty()); - candidates_to_start.push_back(std::move(matching_candidates[0])); + + std::set<PrerenderInfo> processed_prerender_info; + + for (auto& matching_candidate : matching_candidates) { + PrerenderInfo matching_candidate_prerender_info = + PrerenderInfo(matching_candidate.second); + if (processed_prerender_info + .insert(std::move(matching_candidate_prerender_info)) + .second) { + candidates_to_start.push_back(std::move(matching_candidate)); + } + } } // Advance the iterators past all matching entries. @@ -258,10 +312,13 @@ auto& rfhi = static_cast<RenderFrameHostImpl&>(render_frame_host_.get()); + // `prerender_host_id` is not available yet. + PrerenderInfo prerender_info(candidate); + auto [begin, end] = std::ranges::equal_range( - started_prerenders_.begin(), started_prerenders_.end(), candidate->url, - std::less<>(), &PrerenderInfo::url); - // cannot currently start a second prerender with the same URL + started_prerenders_.begin(), started_prerenders_.end(), prerender_info, + PrerenderInfo::PrerenderInfoComparator); + // cannot currently start a second prerender with the same URL and target_hint if (begin != end) { return false; } @@ -294,6 +351,18 @@ candidate->no_vary_search_hint); } + const bool should_warm_up_compositor = [&] { + switch (candidate->eagerness) { + case blink::mojom::SpeculationEagerness::kImmediate: + return base::FeatureList::IsEnabled( + features::kPrerender2WarmUpCompositorForImmediate); + case blink::mojom::SpeculationEagerness::kModerate: + case blink::mojom::SpeculationEagerness::kConservative: + return base::FeatureList::IsEnabled( + features::kPrerender2WarmUpCompositorForNonImmediate); + } + }(); + PrerenderAttributes attributes( candidate->url, PreloadingTriggerTypeFromSpeculationInjectionType( @@ -304,7 +373,7 @@ SpeculationRulesTags(candidate->tags)), Referrer{*candidate->referrer}, no_vary_search_hint, &rfhi, web_contents->GetWeakPtr(), ui::PAGE_TRANSITION_LINK, - /*should_warm_up_compositor=*/false, + should_warm_up_compositor, /*should_prepare_paint_tree=*/false, /*url_match_predicate=*/{}, /*prerender_navigation_handle_callback=*/{}, @@ -316,7 +385,7 @@ candidate->injection_type); PreloadingPredictor creating_predictor = GetPredictorForPreloadingTriggerType(trigger_type); - FrameTreeNodeId prerender_host_id = [&] { + prerender_info.prerender_host_id = [&] { // TODO(crbug.com/40235424): Handle the case where multiple speculation // rules have the same URL but its `target_browsing_context_name_hint` is // different. In the current implementation, only the first rule is @@ -372,18 +441,20 @@ // it is needed to re-calculate the right place here on `started_prerenders_` // for new candidates. end = std::ranges::upper_bound(started_prerenders_.begin(), - started_prerenders_.end(), candidate->url, - std::less<>(), &PrerenderInfo::url); + started_prerenders_.end(), prerender_info, + PrerenderInfo::PrerenderInfoComparator); - started_prerenders_.insert(end, {.injection_type = candidate->injection_type, - .eagerness = candidate->eagerness, - .prerender_host_id = prerender_host_id, - .url = candidate->url}); + started_prerenders_.insert(end, std::move(prerender_info)); return true; } bool PrerendererImpl::ShouldWaitForPrerenderResult(const GURL& url) { + // This function is used to check whetehr a prerender is started to avoid + // starting prefetch in OnPointerDown, OnPointerHover or other heuristic + // methods which don't take target_hint into consideration. So unlike other + // functions in this file, this part uses `url` only instead of + // `PrerenderInfo` which consists of target_hint information. auto [begin, end] = std::ranges::equal_range( started_prerenders_.begin(), started_prerenders_.end(), url, std::less<>(), &PrerenderInfo::url);
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index a424de715..2474afa 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -113,6 +113,7 @@ #include "content/browser/network/cross_origin_embedder_policy_reporter.h" #include "content/browser/permissions/permission_controller_impl.h" #include "content/browser/permissions/permission_service_context.h" +#include "content/browser/permissions/permission_util.h" #include "content/browser/preloading/preloading_decider.h" #include "content/browser/preloading/prerender/prerender_final_status.h" #include "content/browser/preloading/prerender/prerender_host_registry.h" @@ -18650,7 +18651,9 @@ std::to_array<std::pair<PermissionName, PermissionType>>( {{PermissionName::VIDEO_CAPTURE, PermissionType::VIDEO_CAPTURE}, {PermissionName::AUDIO_CAPTURE, PermissionType::AUDIO_CAPTURE}, - {PermissionName::GEOLOCATION, PermissionType::GEOLOCATION}}); + {PermissionName::GEOLOCATION, PermissionType::GEOLOCATION}, + {PermissionName::WINDOW_MANAGEMENT, + PermissionType::WINDOW_MANAGEMENT}}); base::flat_map<PermissionName, PermissionStatus> permission_map; for (const auto& permission : kPermissions) { @@ -18667,12 +18670,17 @@ blink::mojom::PermissionStatus RenderFrameHostImpl::GetCombinedPermissionStatus( blink::PermissionType permission_type) { + auto descriptor = content::PermissionDescriptorUtil:: + CreatePermissionDescriptorForPermissionType(permission_type); + if (PermissionUtil::IsDevicePermission(descriptor)) { + return GetBrowserContext() + ->GetPermissionController() + ->GetCombinedPermissionAndDeviceStatus(descriptor, this); + } return GetBrowserContext() ->GetPermissionController() - ->GetCombinedPermissionAndDeviceStatus( - content::PermissionDescriptorUtil:: - CreatePermissionDescriptorForPermissionType(permission_type), - this); + ->GetPermissionResultForCurrentDocument(descriptor, this) + .status; } media::PictureInPictureEventsInfo::AutoPipReasonCallback
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index b4ecd1aa..53e8cbf 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -566,9 +566,10 @@ kRefusedForPdfContent = 6, kRefusedForJitMismatch = 7, kRefusedForV8OptimizationMismatch = 8, - kMaxValue = kRefusedForV8OptimizationMismatch + kRefusedNonNavigation = 9, + kMaxValue = kRefusedNonNavigation }; - // LINT.ThenChange(tools/metrics/histograms/metadata/browser/histograms.xml:SpareProcessMaybeTakeAction) + // LINT.ThenChange(//tools/metrics/histograms/metadata/browser/histograms.xml:SpareProcessMaybeTakeAction) // Please keep in sync with "RenderProcessHostDelayShutdownReason" in // tools/metrics/histograms/metadata/browser/enums.xml. These values should
diff --git a/content/browser/renderer_host/spare_render_process_host_manager_browsertest.cc b/content/browser/renderer_host/spare_render_process_host_manager_browsertest.cc index 67a1250..eafc051 100644 --- a/content/browser/renderer_host/spare_render_process_host_manager_browsertest.cc +++ b/content/browser/renderer_host/spare_render_process_host_manager_browsertest.cc
@@ -929,6 +929,7 @@ features::kAndroidWarmUpSpareRendererWithTimeout, { {features::kAndroidSpareRendererKillWhenBackgrounded.name, "true"}, + {features::kAndroidSpareRendererOnlyForNavigation.name, "true"}, }); } @@ -958,6 +959,46 @@ process_watcher.Wait(); EXPECT_TRUE(spare_manager.GetSpares().empty()); } + +IN_PROC_BROWSER_TEST_F(AndroidSpareRendererProcessHostManagerTest, + OnlyForNavigation) { + ASSERT_TRUE(embedded_test_server()->Start()); + + auto& spare_manager = SpareRenderProcessHostManagerImpl::Get(); + BrowserContext* browser_context = + ShellContentBrowserClient::Get()->browser_context(); + spare_manager.WarmupSpare(browser_context); + EXPECT_EQ(spare_manager.GetSpares().size(), 1u); + + GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); + scoped_refptr<SiteInstance> test_site_instance = + SiteInstance::CreateForURL(browser_context, test_url); + base::HistogramTester histogram_tester; + + // Emulate a non-navigation process allocation. The + // kServiceWorkerProcessManager source is only used for testing. + // Since the feature AndroidSpareRendererOnlyForNavigation is enabled, + // the allocation will not get a spare renderer. + EXPECT_FALSE(spare_manager.MaybeTakeSpare( + browser_context, static_cast<SiteInstanceImpl*>(test_site_instance.get()), + ProcessAllocationContext{ + ProcessAllocationSource::kServiceWorkerProcessManager})); + // Also verify that the SpareProcessMaybeTakeAction UMA correctly records the + // reason. + histogram_tester.ExpectUniqueSample( + "BrowserRenderProcessHost.SpareProcessMaybeTakeAction", + content::RenderProcessHostImpl::SpareProcessMaybeTakeAction:: + kRefusedNonNavigation, + 1); + // Navigation request can still allocate a spare renderer. + EXPECT_TRUE(spare_manager.MaybeTakeSpare( + browser_context, static_cast<SiteInstanceImpl*>(test_site_instance.get()), + ProcessAllocationContext{ + ProcessAllocationSource::kNavigationRequest, + NavigationProcessAllocationContext{ + ProcessAllocationNavigationStage::kBeforeNetworkRequest, 0, + false}})); +} #endif class ExtraSpareRenderProcessHostManagerTest
diff --git a/content/browser/renderer_host/spare_render_process_host_manager_impl.cc b/content/browser/renderer_host/spare_render_process_host_manager_impl.cc index 69682bb..81ee93a 100644 --- a/content/browser/renderer_host/spare_render_process_host_manager_impl.cc +++ b/content/browser/renderer_host/spare_render_process_host_manager_impl.cc
@@ -134,6 +134,9 @@ case SpareProcessMaybeTakeAction::kRefusedForV8OptimizationMismatch: action_name = "RefusedForV8OptimizationMismatch"; break; + case SpareProcessMaybeTakeAction::kRefusedNonNavigation: + action_name = "RefusedNonNavigation"; + break; } return base::StrCat( {"BrowserRenderProcessHost.SpareProcessMaybeTakeTime.", action_name}); @@ -600,7 +603,17 @@ } else if (next_spare_rph->AreV8OptimizationsDisabled() != site_instance->GetSiteInfo().are_v8_optimizations_disabled()) { action = SpareProcessMaybeTakeAction::kRefusedForV8OptimizationMismatch; - } else { + } +#if BUILDFLAG(IS_ANDROID) + else if (features::kAndroidSpareRendererOnlyForNavigation.Get() && + !allocation_context.IsForNavigation() && + // Always allow test to allocate a spare renderer so as + // not to break existing tests. + allocation_context.source != ProcessAllocationSource::kTest) { + action = SpareProcessMaybeTakeAction::kRefusedNonNavigation; + } +#endif + else { action = SpareProcessMaybeTakeAction::kSpareTaken; } LogSpareProcessTakeActionUMAs(next_spare_rph, action, allocation_context);
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 9d30d71..234b46c 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -12018,6 +12018,7 @@ const blink::mojom::Referrer& referrer, const std::optional<url::Origin>& referring_origin, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, scoped_refptr<PreloadPipelineInfo> preload_pipeline_info, base::WeakPtr<PreloadingAttempt> attempt, std::optional<PreloadingHoldbackStatus> holdback_status_override, @@ -12037,7 +12038,7 @@ use_prefetch_proxy); auto container = std::make_unique<PrefetchContainer>( *this, prefetch_url, prefetch_type, embedder_histogram_suffix, referrer, - referring_origin, std::move(no_vary_search_hint), + referring_origin, std::move(no_vary_search_hint), std::move(priority), std::move(preload_pipeline_info), std::move(attempt), holdback_status_override, std::move(ttl));
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 64afb1a..81de3790 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -1013,6 +1013,7 @@ const blink::mojom::Referrer& referrer, const std::optional<url::Origin>& referring_origin, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, scoped_refptr<PreloadPipelineInfo> preload_pipeline_info, base::WeakPtr<PreloadingAttempt> attempt, std::optional<PreloadingHoldbackStatus> holdback_status_override,
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/media/capture/ScreenCapture.java b/content/public/android/java/src/org/chromium/content_public/browser/media/capture/ScreenCapture.java index 44bbdb5..70b4882 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/media/capture/ScreenCapture.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/media/capture/ScreenCapture.java
@@ -22,6 +22,7 @@ import android.view.WindowManager; import androidx.activity.result.ActivityResult; +import androidx.annotation.GuardedBy; import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; @@ -61,19 +62,28 @@ // until that foreground service is running. private static final ConditionVariable sLatch = new ConditionVariable(false); - // Since we run processing in a background thread, we need to prevent the native side from - // being destructed sometimes. See comments on `DesktopCapturerAndroid` for more information. - private final Object mNativeDestructionLock = new Object(); + // Lock to protect access to fields that are modified mainly on the background thread. This is + // also used to prevent destruction of the native side while JNI methods are running. See + // comments on `DesktopCapturerAndroid` for more information. + private final Object mBackgroundLock = new Object(); private long mNativeDesktopCapturerAndroid; private final HandlerThread mBackgroundThread = new HandlerThread("ScreenCapture"); private @Nullable Handler mBackgroundHandler; - private @Nullable WebContents mWebContents; + + @GuardedBy("mBackgroundLock") private @Nullable MediaProjection mMediaProjection; - // While capture is running these references should only be modified on the background thread. + @GuardedBy("mBackgroundLock") private @Nullable VirtualDisplay mVirtualDisplay; + + @GuardedBy("mBackgroundLock") private @Nullable ImageReader mImageReader; + + @GuardedBy("mBackgroundLock") + private @Nullable WebContents mWebContents; + + @GuardedBy("mBackgroundLock") private int mAcquiredImageCount; private ScreenCapture(long nativeDesktopCapturerAndroid) { @@ -102,6 +112,7 @@ assert oldPickState == null; } + @GuardedBy("mBackgroundLock") private @Nullable Context maybeGetContext() { final WindowAndroid window = assumeNonNull(mWebContents).getTopLevelNativeWindow(); if (window == null) return null; @@ -117,7 +128,6 @@ boolean startCapture() { final PickState pickState = sNextPickState.getAndSet(null); assert pickState != null; - mWebContents = pickState.mWebContents; final ActivityResult activityResult = pickState.mActivityResult; assert activityResult.getData() != null; @@ -126,46 +136,50 @@ // MediaProjection API. It's okay to block here since we are on the desktop capturer thread. sLatch.block(); - // TODO(crbug.com/352187279): Update the context if the WebContents is reparented. - final Context context = maybeGetContext(); - if (context == null) return false; + synchronized (mBackgroundLock) { + mWebContents = pickState.mWebContents; + // TODO(crbug.com/352187279): Update the context if the WebContents is reparented. + final Context context = maybeGetContext(); + if (context == null) return false; - var manager = - (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE); - if (manager == null) return false; + var manager = + (MediaProjectionManager) + context.getSystemService(Context.MEDIA_PROJECTION_SERVICE); + if (manager == null) return false; - mMediaProjection = - manager.getMediaProjection( - activityResult.getResultCode(), activityResult.getData()); - if (mMediaProjection == null) return false; + mMediaProjection = + manager.getMediaProjection( + activityResult.getResultCode(), activityResult.getData()); + if (mMediaProjection == null) return false; - mBackgroundThread.start(); - mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); + mBackgroundThread.start(); + mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); - // Take the MediaProjection callbacks on the background thread as we may call JNI methods or - // update references accessed by the ImageReader handling code. - mMediaProjection.registerCallback(new MediaProjectionCallback(), mBackgroundHandler); + // We must use a background thread and `Handler` here since the current thread + // (DesktopCapturer thread) does not have a `Looper` set up. + mMediaProjection.registerCallback(new MediaProjectionCallback(), mBackgroundHandler); - var windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - var windowMetrics = windowManager.getMaximumWindowMetrics(); - final Rect bounds = windowMetrics.getBounds(); - int width = bounds.width(); - int height = bounds.height(); - int dpi = context.getResources().getConfiguration().densityDpi; + var windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + var windowMetrics = windowManager.getMaximumWindowMetrics(); + final Rect bounds = windowMetrics.getBounds(); + int width = bounds.width(); + int height = bounds.height(); + int dpi = context.getResources().getConfiguration().densityDpi; - recreateListener(width, height, PixelFormat.RGBA_8888, dpi); + recreateListener(width, height, PixelFormat.RGBA_8888, dpi); + } return true; } @CalledByNative void destroy() { if (mBackgroundThread != null) { - // End the background thread before taking `mNativeDestructionLock` since messages run - // on this thread may need to take `mNativeDestructionLock` and could deadlock + // End the background thread before taking `mBackgroundLock` since messages run + // on this thread may need to take `mBackgroundLock` and could deadlock // otherwise. mBackgroundThread.quit(); } - synchronized (mNativeDestructionLock) { + synchronized (mBackgroundLock) { if (mMediaProjection != null) { mMediaProjection.stop(); mMediaProjection = null; @@ -176,6 +190,7 @@ } private class ImageListener implements ImageReader.OnImageAvailableListener { + @GuardedBy("mBackgroundLock") private @Nullable Image maybeAcquireImage(ImageReader reader) { assert mBackgroundThread.getLooper().isCurrentThread(); // If we have acquired the maximum number of images `acquireLatestImage` @@ -200,32 +215,35 @@ private void releaseImage(ImageReader reader, Image image) { assert mBackgroundThread.getLooper().isCurrentThread(); - // If we recreate the ImageReader, we may get an old release here. The image will - // already have been closed since the ImageReader is closed, but it's safe to call close - // again here. - image.close(); - // `mAcquiredImageCount` is only for the current ImageReader, so don't incorrectly - // decrement it for an old ImageReader. - if (reader == mImageReader) mAcquiredImageCount--; + synchronized (mBackgroundLock) { + // If we recreate the ImageReader, we may get an old release here. The image will + // already have been closed since the ImageReader is closed, but it's safe to call + // close + // again here. + image.close(); - // Now that we closed an image, we may be able to acquire a new image. - onImageAvailable(reader); + // `mAcquiredImageCount` is only for the current ImageReader, so don't incorrectly + // decrement it for an old ImageReader. + if (reader == mImageReader) mAcquiredImageCount--; + + // Now that we closed an image, we may be able to acquire a new image. + onImageAvailable(reader); + } } @Override public void onImageAvailable(ImageReader reader) { assert mBackgroundThread.getLooper().isCurrentThread(); - // If we recreate the ImageReader we may get a call with the old reader here. Skip this - // case. - if (reader != mImageReader) return; - - // Prevent native destruction until JNI methods are done. - synchronized (mNativeDestructionLock) { + synchronized (mBackgroundLock) { // If the native side was destroyed, then exit without calling JNI methods. if (mNativeDesktopCapturerAndroid == 0) return; + // If we recreate the ImageReader we may get a call with the old reader here. Skip + // this case. + if (reader != mImageReader) return; + // Note that we can't use `acquireLatestImage` here because we can't close older // images until the C++ side is finished using them. final Image image = maybeAcquireImage(reader); @@ -280,7 +298,7 @@ @Override public void onStop() { assert mBackgroundThread.getLooper().isCurrentThread(); - synchronized (mNativeDestructionLock) { + synchronized (mBackgroundLock) { if (mNativeDesktopCapturerAndroid == 0) return; mMediaProjection = null; ScreenCaptureJni.get().onStop(mNativeDesktopCapturerAndroid); @@ -288,6 +306,7 @@ } } + @GuardedBy("mBackgroundLock") private void destroyListener() { if (mImageReader != null) { mImageReader.close(); @@ -300,6 +319,7 @@ } } + @GuardedBy("mBackgroundLock") private void recreateListener(int width, int height, int format, int dpi) { destroyListener(); mImageReader = ImageReader.newInstance(width, height, format, /* maxImages= */ 2);
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 96e882e..01f516f 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -333,6 +333,7 @@ "popup_menu.h", "prefetch_handle.h", "prefetch_metrics.h", + "prefetch_priority.h", "prefetch_request_status_listener.h", "prefetch_service_delegate.cc", "prefetch_service_delegate.h",
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h index d9d30c0..4c67e4d4 100644 --- a/content/public/browser/browser_context.h +++ b/content/public/browser/browser_context.h
@@ -22,6 +22,7 @@ #include "content/common/content_export.h" #include "content/public/browser/k_anonymity_service_delegate.h" #include "content/public/browser/prefetch_handle.h" +#include "content/public/browser/prefetch_priority.h" #include "content/public/browser/prefetch_request_status_listener.h" #include "content/public/browser/zoom_level_delegate.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -202,7 +203,8 @@ // Starts a prefetch network request for the given `url`. // `embedder_histogram_suffix` is used for generating internal histogram names - // recorded per trigger. `ttl` (Time-To-Live) specifies how long + // recorded per trigger. `priority` is an optimization hint of how quickly + // this prefetch should be available. `ttl` (Time-To-Live) specifies how long // prefetched data remains valid in the cache. After this period, the data is // reset. `should_disable_block_until_head_timeout` specifies whether we // should have a timeout when this prefetch blocks the navigation until its @@ -214,6 +216,7 @@ const std::string& embedder_histogram_suffix, bool javascript_enabled, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, const net::HttpRequestHeaders& additional_headers, std::unique_ptr<PrefetchRequestStatusListener> request_status_listener, base::TimeDelta ttl,
diff --git a/content/public/browser/permission_result.cc b/content/public/browser/permission_result.cc index 77cbcdbb..9d71662 100644 --- a/content/public/browser/permission_result.cc +++ b/content/public/browser/permission_result.cc
@@ -6,6 +6,10 @@ namespace content { +PermissionResult::PermissionResult() + : status(PermissionStatus::ASK), + source(PermissionStatusSource::UNSPECIFIED) {} + PermissionResult::PermissionResult( PermissionStatus permission_status, PermissionStatusSource permission_status_source,
diff --git a/content/public/browser/permission_result.h b/content/public/browser/permission_result.h index d00c92a4..7510876 100644 --- a/content/public/browser/permission_result.h +++ b/content/public/browser/permission_result.h
@@ -52,6 +52,7 @@ }; struct CONTENT_EXPORT PermissionResult { + PermissionResult(); PermissionResult( PermissionStatus permission_status, PermissionStatusSource permission_status_source,
diff --git a/content/public/browser/prefetch_priority.h b/content/public/browser/prefetch_priority.h new file mode 100644 index 0000000..6d8f190 --- /dev/null +++ b/content/public/browser/prefetch_priority.h
@@ -0,0 +1,23 @@ +// 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 CONTENT_PUBLIC_BROWSER_PREFETCH_PRIORITY_H_ +#define CONTENT_PUBLIC_BROWSER_PREFETCH_PRIORITY_H_ + +namespace content { + +// An optimization hint that indicates the relative priority of a prefetch +// request. A higher priority suggests that the prefetch caller expects prefetch +// resources to be available sooner. +// TODO(crbug.com/426404355): Consider revisitting the name. +enum class PrefetchPriority { + kLow = 0, + kMedium = 1, + kHigh = 2, + kHighest = 3, +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_PREFETCH_PRIORITY_H_
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h index ff12574..c5daa64 100644 --- a/content/public/browser/web_contents.h +++ b/content/public/browser/web_contents.h
@@ -34,6 +34,7 @@ #include "content/public/browser/page.h" #include "content/public/browser/page_navigator.h" #include "content/public/browser/prefetch_handle.h" +#include "content/public/browser/prefetch_priority.h" #include "content/public/browser/preload_pipeline_info.h" #include "content/public/browser/preloading.h" #include "content/public/browser/preloading_trigger_type.h" @@ -1629,6 +1630,8 @@ // perspectives. Normally it should be nullopt and then the opaque origin is // used internally, but if necessary, custom value from trusted surfaces can // be embedded into it here. + // - `priority is an optimization hint of how quickly this prefetch should be + // available. Performs no relevant optimization if passing `std::nullopt` // - `preload_pipeline_info` is used to designate what pipeline this prefetch // belongs to. // - `attempt` is used to record some metrics associated with this prefetch @@ -1647,6 +1650,7 @@ const blink::mojom::Referrer& referrer, const std::optional<url::Origin>& referring_origin, std::optional<net::HttpNoVarySearchData> no_vary_search_hint, + std::optional<PrefetchPriority> priority, scoped_refptr<PreloadPipelineInfo> preload_pipeline_info, base::WeakPtr<PreloadingAttempt> attempt, std::optional<PreloadingHoldbackStatus> holdback_status_override,
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 028d483c..3a7b1c5 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -72,6 +72,10 @@ const base::FeatureParam<bool> kAndroidSpareRendererKillWhenBackgrounded{ &kAndroidWarmUpSpareRendererWithTimeout, "kill_when_backgrounded", false}; +// Only allow the navigation related allocation to use the spare renderer. +const base::FeatureParam<bool> kAndroidSpareRendererOnlyForNavigation{ + &kAndroidWarmUpSpareRendererWithTimeout, "only_for_navigation", false}; + // Whether to allow attaching an inner WebContents not owned by the outer // WebContents. This is for prototyping purposes and should not be enabled in // production.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 17a2aff..803ba25 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -45,6 +45,8 @@ kAndroidSpareRendererMemoryThreshold; CONTENT_EXPORT extern const base::FeatureParam<bool> kAndroidSpareRendererKillWhenBackgrounded; +CONTENT_EXPORT extern const base::FeatureParam<bool> + kAndroidSpareRendererOnlyForNavigation; CONTENT_EXPORT BASE_DECLARE_FEATURE(kAttachUnownedInnerWebContents); CONTENT_EXPORT BASE_DECLARE_FEATURE(kAudioServiceLaunchOnStartup); CONTENT_EXPORT BASE_DECLARE_FEATURE(kAudioServiceOutOfProcess);
diff --git a/device/fido/features.cc b/device/fido/features.cc index d5589f5..a0e94f1 100644 --- a/device/fido/features.cc +++ b/device/fido/features.cc
@@ -157,11 +157,6 @@ "kWebAuthenticationSyncSecurityDomainBeforePINRenewal", base::FEATURE_ENABLED_BY_DEFAULT); -// Default enabled in M136. Remove in or after M139. -BASE_FEATURE(kWebAuthnRemoteDesktopAllowedOriginsPolicy, - "WebAuthenticationRemoteDesktopAllowedOriginsPolicy", - base::FEATURE_ENABLED_BY_DEFAULT); - // Default enabled in M135. Remove in or after M138. BASE_FEATURE(kWebAuthnMicrosoftSoftwareUnexportableKeyProvider, "WebAuthenticationMicrosoftSoftwareUnexportableKeyProvider",
diff --git a/device/fido/features.h b/device/fido/features.h index 2dd0766e..949eb498 100644 --- a/device/fido/features.h +++ b/device/fido/features.h
@@ -111,11 +111,6 @@ COMPONENT_EXPORT(DEVICE_FIDO) BASE_DECLARE_FEATURE(kSyncSecurityDomainBeforePINRenewal); -// Feature flag for the -// `WebAuthenticationRemoteDesktopAllowedOrigins` enterprise policy. -COMPONENT_EXPORT(DEVICE_FIDO) -BASE_DECLARE_FEATURE(kWebAuthnRemoteDesktopAllowedOriginsPolicy); - // Enables using the Microsoft Software Key Storage Provider to store // unexportable keys when a TPM is not available. COMPONENT_EXPORT(DEVICE_FIDO)
diff --git a/gpu/command_buffer/client/client_shared_image.h b/gpu/command_buffer/client/client_shared_image.h index 93057b6..e658c887 100644 --- a/gpu/command_buffer/client/client_shared_image.h +++ b/gpu/command_buffer/client/client_shared_image.h
@@ -26,12 +26,10 @@ #include "ui/gfx/color_space.h" #include "ui/gfx/gpu_memory_buffer_handle.h" -namespace base { -namespace trace_event { +namespace base::trace_event { class ProcessMemoryDump; class MemoryAllocatorDumpGuid; -} // namespace trace_event -} // namespace base +} // namespace base::trace_event namespace gfx { class GpuMemoryBuffer;
diff --git a/infra/config/generated/builders/ci/android-15-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/ci/android-15-x64-rel/targets/chromium.android.json index f2a14e5..8611fdb 100644 --- a/infra/config/generated/builders/ci/android-15-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/ci/android-15-x64-rel/targets/chromium.android.json
@@ -944,7 +944,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 + "shards": 4 }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/"
diff --git a/infra/config/generated/builders/try/android-15-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-15-x64-rel/targets/chromium.android.json index f2a14e5..8611fdb 100644 --- a/infra/config/generated/builders/try/android-15-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/try/android-15-x64-rel/targets/chromium.android.json
@@ -944,7 +944,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 + "shards": 4 }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/"
diff --git a/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json index 529d9ceb..69e8589 100644 --- a/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json +++ b/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json
@@ -1001,7 +1001,7 @@ } }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 5 + "shards": 4 }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/"
diff --git a/infra/config/targets/autoshard_exceptions.json b/infra/config/targets/autoshard_exceptions.json index 14280c6..b97cd65 100644 --- a/infra/config/targets/autoshard_exceptions.json +++ b/infra/config/targets/autoshard_exceptions.json
@@ -16,7 +16,7 @@ "try_builder": "android-x64-rel" }, "components_browsertests": { - "shards": 5, + "shards": 4, "try_builder": "android-x64-rel" } },
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn index 87b7a1c..e775faf 100644 --- a/ios/chrome/app/application_delegate/BUILD.gn +++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -240,6 +240,7 @@ "//ios/chrome/common/app_group", "//ios/chrome/common/app_group:main_app", "//ios/chrome/common/credential_provider", + "//ios/components/ui_util", "//ios/public/provider/chrome/browser/app_distribution:app_distribution_api", "//ios/web/public", "//ios/web/public/thread",
diff --git a/ios/chrome/app/application_delegate/DEPS b/ios/chrome/app/application_delegate/DEPS new file mode 100644 index 0000000..04b4c18 --- /dev/null +++ b/ios/chrome/app/application_delegate/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ios/components/ui_util/dynamic_type_util.h" +] \ No newline at end of file
diff --git a/ios/chrome/app/application_delegate/metrics_mediator.mm b/ios/chrome/app/application_delegate/metrics_mediator.mm index 6b555992..ef1f34cd 100644 --- a/ios/chrome/app/application_delegate/metrics_mediator.mm +++ b/ios/chrome/app/application_delegate/metrics_mediator.mm
@@ -52,6 +52,7 @@ #import "ios/chrome/common/app_group/app_group_metrics.h" #import "ios/chrome/common/app_group/app_group_metrics_mainapp.h" #import "ios/chrome/common/credential_provider/constants.h" +#import "ios/components/ui_util/dynamic_type_util.h" #import "ios/public/provider/chrome/browser/app_distribution/app_distribution_api.h" #import "ios/web/public/thread/web_task_traits.h" #import "ios/web/public/thread/web_thread.h" @@ -532,6 +533,7 @@ [self recordStartupDuplicatedTabCount:duplicatedTabCount]; [self recordTabsAgeAtStartup:timesSinceCreation]; [self recordAndResetWarmStartCount]; + ui_util::RecordSystemFontSizeMetrics(); } else { [[PreviousSessionInfo sharedInstance] incrementWarmStartCount]; [self recordResumeTabCount:tabCount];
diff --git a/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.h b/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.h index f8315c4..e256796 100644 --- a/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.h +++ b/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.h
@@ -167,9 +167,12 @@ void DidUnshareGroup(std::optional<tab_groups::LocalTabGroupID> local_id, NSError* error); - // Callback called when the user acknowledge the error. + // Callback called when the user acknowledges the error. void ErrorAccepted(ResultCallback result); + // Callback called when the user accepts to update the app. + void Update(ResultCallback result); + // Returns the local tab group that matches `either_id`. const TabGroup* GetLocalGroup(const tab_groups::EitherGroupID& either_id);
diff --git a/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.mm b/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.mm index 5627e8c..1f94baa6 100644 --- a/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.mm +++ b/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.mm
@@ -170,10 +170,7 @@ NSString* title = base::SysUTF8ToNSString(error.error_header); NSString* message = base::SysUTF8ToNSString(error.error_body); - auto alert_action = base::CallbackToBlock( - base::BindOnce(&IOSCollaborationControllerDelegate::ErrorAccepted, - weak_ptr_factory_.GetWeakPtr(), std::move(result))); - // Make sure to present it on top of any visible view. + // Make sure to present the alert on top of any visible view. UIViewController* top_view_controller = top_view_controller::TopPresentedViewControllerFrom( base_view_controller_); @@ -183,10 +180,37 @@ browser:browser_ title:title message:message]; - [alert_coordinator_ - addItemWithTitle:l10n_util::GetNSString(IDS_IOS_SHARED_GROUP_ERROR_GOT_IT) - action:alert_action - style:UIAlertActionStyleDefault]; + + if (error.type() == ErrorInfo::Type::kUpdateChromeUiForVersionOutOfDate) { + auto update_action = base::CallbackToBlock( + base::BindOnce(&IOSCollaborationControllerDelegate::Update, + weak_ptr_factory_.GetWeakPtr(), std::move(result))); + [alert_coordinator_ + addItemWithTitle: + l10n_util::GetNSString( + IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_UPDATE_BUTTON) + action:update_action + style:UIAlertActionStyleDefault]; + + auto dismiss_action = base::CallbackToBlock( + base::BindOnce(&IOSCollaborationControllerDelegate::ErrorAccepted, + weak_ptr_factory_.GetWeakPtr(), std::move(result))); + [alert_coordinator_ + addItemWithTitle: + l10n_util::GetNSString( + IDS_COLLABORATION_CHROME_OUT_OF_DATE_ERROR_DIALOG_NOT_NOW_BUTTON) + action:dismiss_action + style:UIAlertActionStyleCancel]; + } else { + auto alert_action = base::CallbackToBlock( + base::BindOnce(&IOSCollaborationControllerDelegate::ErrorAccepted, + weak_ptr_factory_.GetWeakPtr(), std::move(result))); + [alert_coordinator_ addItemWithTitle:l10n_util::GetNSString( + IDS_IOS_SHARED_GROUP_ERROR_GOT_IT) + action:alert_action + style:UIAlertActionStyleDefault]; + } + [alert_coordinator_ start]; } @@ -576,6 +600,14 @@ std::move(result).Run(CollaborationControllerDelegate::Outcome::kSuccess); } +void IOSCollaborationControllerDelegate::Update(ResultCallback result) { + CommandDispatcher* dispatcher = browser_->GetCommandDispatcher(); + id<ApplicationCommands> application_handler = + HandlerForProtocol(dispatcher, ApplicationCommands); + [application_handler showAppStorePage]; + std::move(result).Run(CollaborationControllerDelegate::Outcome::kSuccess); +} + const TabGroup* IOSCollaborationControllerDelegate::GetLocalGroup( const tab_groups::EitherGroupID& either_id) { if (!tab_group_sync_service_) {
diff --git a/ios/chrome/browser/feature_engagement/model/BUILD.gn b/ios/chrome/browser/feature_engagement/model/BUILD.gn index e0cd907..6939830 100644 --- a/ios/chrome/browser/feature_engagement/model/BUILD.gn +++ b/ios/chrome/browser/feature_engagement/model/BUILD.gn
@@ -20,6 +20,7 @@ "//components/feature_engagement", "//components/leveldb_proto", "//ios/chrome/app:tests_hook", + "//ios/chrome/browser/shared/model/paths", "//ios/chrome/browser/shared/model/profile", "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory", "//ios/chrome/browser/shared/public/commands",
diff --git a/ios/chrome/browser/feature_engagement/model/DEPS b/ios/chrome/browser/feature_engagement/model/DEPS index f2a09a14..daf1b2f 100644 --- a/ios/chrome/browser/feature_engagement/model/DEPS +++ b/ios/chrome/browser/feature_engagement/model/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+ios/chrome/browser/default_browser/model", "+ios/chrome/browser/authentication/ui_bundled/signin", + "+ios/chrome/browser/shared/model/paths", ]
diff --git a/ios/chrome/browser/feature_engagement/model/tracker_factory_util.mm b/ios/chrome/browser/feature_engagement/model/tracker_factory_util.mm index 626b1c9..8ce4b607 100644 --- a/ios/chrome/browser/feature_engagement/model/tracker_factory_util.mm +++ b/ios/chrome/browser/feature_engagement/model/tracker_factory_util.mm
@@ -6,6 +6,7 @@ #import "base/memory/ptr_util.h" #import "base/memory/ref_counted.h" +#import "base/path_service.h" #import "base/task/sequenced_task_runner.h" #import "base/task/thread_pool.h" #import "components/feature_engagement/public/feature_activation.h" @@ -13,6 +14,7 @@ #import "ios/chrome/app/tests_hook.h" #import "ios/chrome/browser/feature_engagement/model/event_exporter.h" #import "ios/chrome/browser/feature_engagement/model/ios_tracker_session_controller.h" +#import "ios/chrome/browser/shared/model/paths/paths.h" #import "ios/chrome/browser/shared/model/profile/profile_ios.h" namespace { @@ -44,6 +46,11 @@ base::FilePath storage_dir = profile->GetStatePath().Append( kIOSFeatureEngagementTrackerStorageDirname); + base::FilePath device_storage_dir; + base::PathService::Get(ios::DIR_USER_DATA, &device_storage_dir); + device_storage_dir = + device_storage_dir.Append(kIOSFeatureEngagementTrackerStorageDirname); + leveldb_proto::ProtoDatabaseProvider* db_provider = profile->GetProtoDatabaseProvider(); @@ -52,7 +59,7 @@ auto session_controller = std::make_unique<IOSTrackerSessionController>(); return feature_engagement::Tracker::Create( - storage_dir, background_task_runner, db_provider, + storage_dir, device_storage_dir, background_task_runner, db_provider, std::move(event_exporter), feature_engagement::Tracker::GetDefaultConfigurationProviders(), std::move(session_controller));
diff --git a/ios/chrome/browser/saved_tab_groups/ui/face_pile_view.mm b/ios/chrome/browser/saved_tab_groups/ui/face_pile_view.mm index a3d8294..95b7b75 100644 --- a/ios/chrome/browser/saved_tab_groups/ui/face_pile_view.mm +++ b/ios/chrome/browser/saved_tab_groups/ui/face_pile_view.mm
@@ -135,7 +135,9 @@ // This is needed to avoid anti-aliasing artifacts around the border itself. UIView* plusXContainerView = [self createCircularContainerWithSize:containerSize]; - plusXContainerView.layer.cornerRadius = containerSize / 2.0; + [UIView performWithoutAnimation:^{ + plusXContainerView.layer.cornerRadius = containerSize / 2.0; + }]; [plusXContainerView addSubview:plusXLabel]; [_facesStackView addArrangedSubview:plusXContainerView]; @@ -174,7 +176,7 @@ [isDarkMode ? [UIColor colorNamed:kSolidWhiteColor] : [UIColor colorNamed:kSolidBlackColor] colorWithAlphaComponent:kPlusXlabelContainerBackgroundAlpha]; - _plusXLabel.textColor = [UIColor colorNamed:kTextPrimaryColor]; + _plusXLabel.textColor = [UIColor colorNamed:kSolidWhiteColor]; return; } if (isDarkMode) { @@ -231,12 +233,19 @@ plusXLabel.textAlignment = NSTextAlignmentCenter; plusXLabel.font = [UIFont systemFontOfSize:kPlusXlabelFontSize weight:UIFontWeightMedium]; + [plusXLabel setContentHuggingPriority:UILayoutPriorityRequired + forAxis:UILayoutConstraintAxisHorizontal]; + [plusXLabel + setContentCompressionResistancePriority:UILayoutPriorityRequired + forAxis:UILayoutConstraintAxisHorizontal]; // Configure a container in order to add an inner horizontal margin around the // label. UIView* plusXLabelContainer = [[UIView alloc] init]; plusXLabelContainer.translatesAutoresizingMaskIntoConstraints = NO; - plusXLabelContainer.layer.cornerRadius = _avatarSize / 2.0; + [UIView performWithoutAnimation:^{ + plusXLabelContainer.layer.cornerRadius = _avatarSize / 2.0; + }]; plusXLabelContainer.layer.masksToBounds = YES; [plusXLabelContainer addSubview:plusXLabel];
diff --git a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm index 2087397d..875f7d4 100644 --- a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm +++ b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
@@ -259,6 +259,9 @@ // received. const char kContextsToOpen[] = "IOS.NumberOfContextsToOpen"; +// The App Store page for Google Chrome. +NSString* const kChromeAppStoreURL = @"https://apps.apple.com/app/id535886823"; + // Enum for IOS.NumberOfContextsToOpen histogram. // Keep in sync with "ContextsToOpen" in tools/metrics/histograms/enums.xml. enum class ContextsToOpen { @@ -2397,6 +2400,13 @@ _safariImportCoordinator = safariDataImportCoordinator; } +- (void)showAppStorePage { + [[UIApplication sharedApplication] + openURL:[NSURL URLWithString:kChromeAppStoreURL] + options:@{} + completionHandler:nil]; +} + #pragma mark - SettingsCommands // TODO(crbug.com/41352590) : Remove show settings from MainController.
diff --git a/ios/chrome/browser/shared/public/commands/application_commands.h b/ios/chrome/browser/shared/public/commands/application_commands.h index a9027f73..46ff3b3 100644 --- a/ios/chrome/browser/shared/public/commands/application_commands.h +++ b/ios/chrome/browser/shared/public/commands/application_commands.h
@@ -177,6 +177,9 @@ - (void)displaySafariDataImportEntryPointWithUIHandler: (id<SafariDataImportUIHandler>)UIHandler; +// Shows the application App Store page, if any. +- (void)showAppStorePage; + @end #endif // IOS_CHROME_BROWSER_SHARED_PUBLIC_COMMANDS_APPLICATION_COMMANDS_H_
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_view_controller.mm index 7ab3aaf0..a4c2da0 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_view_controller.mm
@@ -959,8 +959,19 @@ [topToolbar.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor], [topToolbar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], - [topToolbar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor] + [topToolbar.trailingAnchor + constraintEqualToAnchor:self.view.trailingAnchor], ]]; + +#if defined(__IPHONE_26_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_26_0 + if (@available(iOS 26, *)) { + UIScrollEdgeElementContainerInteraction* edgeEffect = + [[UIScrollEdgeElementContainerInteraction alloc] init]; + edgeEffect.edge = UIRectEdgeTop; + edgeEffect.scrollView = self.scrollView; + [topToolbar addInteraction:edgeEffect]; + } +#endif } // Adds the bottom toolbar and sets constraints. @@ -980,6 +991,16 @@ [self.layoutGuideCenter referenceView:bottomToolbar underName:kTabGridBottomToolbarGuide]; + +#if defined(__IPHONE_26_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_26_0 + if (@available(iOS 26, *)) { + UIScrollEdgeElementContainerInteraction* edgeEffect = + [[UIScrollEdgeElementContainerInteraction alloc] init]; + edgeEffect.edge = UIRectEdgeBottom; + edgeEffect.scrollView = self.scrollView; + [bottomToolbar addInteraction:edgeEffect]; + } +#endif } // Adds the PinnedTabsViewController and sets constraints.
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_view_controller.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_view_controller.mm index 12c2adaa..bd792b2 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_view_controller.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_view_controller.mm
@@ -949,8 +949,7 @@ [bottomToolbar setScrollViewScrolledToEdge:self.gridViewController.scrolledToBottom]; } - [bottomToolbar setEditButtonHidden:YES]; - [bottomToolbar setDoneButtonHidden:YES]; + bottomToolbar.isInTabGroupView = YES; [_container addSubview:bottomToolbar];
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_bottom_toolbar.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_bottom_toolbar.h index afadcec..a7cd135c 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_bottom_toolbar.h +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_bottom_toolbar.h
@@ -35,6 +35,8 @@ // shown in toolbar and its background color. Setting this property will also // set it on `newTabButton`. @property(nonatomic, assign) TabGridPage page; +// Whether the toolbar is in a tab group view or not. +@property(nonatomic, assign) BOOL isInTabGroupView; // This property together with `page` and self.traitCollection control the // items shown in toolbar and its background color. @property(nonatomic, assign) TabGridMode mode; @@ -51,8 +53,6 @@ - (void)setNewTabButtonEnabled:(BOOL)enabled; // Sets `enabled` on the done button. - (void)setDoneButtonEnabled:(BOOL)enabled; -// Sets the visibility of the Done button. -- (void)setDoneButtonHidden:(BOOL)hidden; // Sets `enabled` on the closeAll button. - (void)setCloseAllButtonEnabled:(BOOL)enabled; // Uses undo or closeAll text on the close all button based on `useUndo` value. @@ -73,8 +73,6 @@ - (void)setEditButtonMenu:(UIMenu*)menu; // Sets `enabled` on the Edit button. - (void)setEditButtonEnabled:(BOOL)enabled; -// Sets the visibility of the Edit button. -- (void)setEditButtonHidden:(BOOL)hidden; // Hides components and uses a black background color for tab grid transition // animation.
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_bottom_toolbar.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_bottom_toolbar.mm index baee6a4..ea680583 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_bottom_toolbar.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_bottom_toolbar.mm
@@ -125,6 +125,14 @@ #pragma mark - Public +- (void)setIsInTabGroupView:(BOOL)isInTabGroupView { + if (_isInTabGroupView == isInTabGroupView) { + return; + } + _isInTabGroupView = isInTabGroupView; + [self updateLayout]; +} + - (void)setPage:(TabGridPage)page { if (_page == page) { return; @@ -161,10 +169,6 @@ _doneButton.enabled = enabled; } -- (void)setDoneButtonHidden:(BOOL)hidden { - _doneButton.hidden = hidden; -} - - (void)setCloseAllButtonEnabled:(BOOL)enabled { _closeAllOrUndoButton.enabled = enabled; } @@ -265,10 +269,6 @@ _editButton.enabled = enabled; } -- (void)setEditButtonHidden:(BOOL)hidden { - _editButton.hidden = hidden; -} - #pragma mark - Private - (void)setupViews { @@ -436,10 +436,13 @@ [_largeNewTabButton removeFromSuperview]; // For incognito/regular pages, display all 3 buttons; - // For Tab Groups and remote tabs page, only display trailing button. + // For Remote tabs page/TabGroup panel, only display trailing button. + // For Tab Group view only display the new tab button if (self.page == TabGridPageRemoteTabs || self.page == TabGridPageTabGroups) { [_toolbar setItems:@[ _spaceItem, trailingButton ]]; + } else if (self.isInTabGroupView) { + [_toolbar setItems:@[ _spaceItem, _newTabButtonItem, _spaceItem ]]; } else { [_toolbar setItems:@[ leadingButton, _spaceItem, _newTabButtonItem, _spaceItem, trailingButton @@ -452,7 +455,7 @@ } else { [NSLayoutConstraint deactivateConstraints:_compactConstraints]; [_toolbar removeFromSuperview]; - // Do not display new tab button for Tab Groups and remote tabs page. + // Do not display new tab button for remote tabs page/TabGroup panel. if (self.page == TabGridPageRemoteTabs || self.page == TabGridPageTabGroups) { [NSLayoutConstraint deactivateConstraints:_floatingConstraints]; @@ -485,28 +488,31 @@ // middle/scrolled to the top states. - (void)createScrolledBackgrounds { _scrolledToEdge = YES; - if (IsIOSSoftLockEnabled()) { - _scrollBackgroundView = [[TabGridToolbarScrollingBackground alloc] init]; - _scrollBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; - [self addSubview:_scrollBackgroundView]; - AddSameConstraintsToSides( - self, _scrollBackgroundView, - LayoutSides::kLeading | LayoutSides::kTop | LayoutSides::kTrailing); + if (@available(iOS 26, *)) { } else { - _backgroundView = - [[TabGridToolbarBackground alloc] initWithFrame:self.frame]; - _backgroundView.translatesAutoresizingMaskIntoConstraints = NO; - [self addSubview:_backgroundView]; - AddSameConstraintsToSides( - self, _backgroundView, - LayoutSides::kLeading | LayoutSides::kTop | LayoutSides::kTrailing); - } + if (IsIOSSoftLockEnabled()) { + _scrollBackgroundView = [[TabGridToolbarScrollingBackground alloc] init]; + _scrollBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_scrollBackgroundView]; + AddSameConstraintsToSides( + self, _scrollBackgroundView, + LayoutSides::kLeading | LayoutSides::kTop | LayoutSides::kTrailing); + } else { + _backgroundView = + [[TabGridToolbarBackground alloc] initWithFrame:self.frame]; + _backgroundView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_backgroundView]; + AddSameConstraintsToSides( + self, _backgroundView, + LayoutSides::kLeading | LayoutSides::kTop | LayoutSides::kTrailing); + } - // A non-nil UIImage has to be added in the background of the toolbar to avoid - // having an additional blur effect. - [_toolbar setBackgroundImage:[[UIImage alloc] init] - forToolbarPosition:UIBarPositionAny - barMetrics:UIBarMetricsDefault]; + // A non-nil UIImage has to be added in the background of the toolbar to + // avoid having an additional blur effect. + [_toolbar setBackgroundImage:[[UIImage alloc] init] + forToolbarPosition:UIBarPositionAny + barMetrics:UIBarMetricsDefault]; + } } // Updates the visibility of the backgrounds based on the state of the TabGrid.
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_page_control.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_page_control.mm index 5243da9..bad16c6 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_page_control.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_page_control.mm
@@ -79,8 +79,9 @@ const CGFloat kSliderMargin = 2.0; // Vertical margin between the slider and the segment on each side. -const CGFloat kSliderVerticalMargin = +const CGFloat kLegacySliderVerticalMargin = std::max((kSegmentHeight - kSliderHeight) / 2.0, 0.0); +const CGFloat kSliderVerticalMargin = -1.5; // Width and height of the separator bars between segments. const CGFloat kSeparatorWidth = 1.0; @@ -638,7 +639,11 @@ } } - iconNotSelected.tintColor = [UIColor colorNamed:kStaticGrey300Color]; + if (@available(iOS 26, *)) { + iconNotSelected.tintColor = UIColor.whiteColor; + } else { + iconNotSelected.tintColor = [UIColor colorNamed:kStaticGrey300Color]; + } iconSelected.tintColor = UIColor.blackColor; [self insertSubview:iconNotSelected belowSubview:self.sliderView]; @@ -650,17 +655,20 @@ - (void)setupViews { self.scrolledToEdge = YES; - UIView* backgroundView = [[UIView alloc] - initWithFrame:CGRectMake(0, 0, kOverallWidth, kSegmentHeight)]; - backgroundView.backgroundColor = - [UIColor colorWithWhite:1 alpha:kScrolledToTopBackgroundAlpha]; - backgroundView.userInteractionEnabled = NO; - backgroundView.layer.cornerRadius = kBackgroundCornerRadius; - backgroundView.layer.masksToBounds = YES; - [self addSubview:backgroundView]; - backgroundView.center = - CGPointMake(kOverallWidth / 2.0, kOverallHeight / 2.0); - self.background = backgroundView; + if (@available(iOS 26, *)) { + } else { + UIView* backgroundView = [[UIView alloc] + initWithFrame:CGRectMake(0, 0, kOverallWidth, kSegmentHeight)]; + backgroundView.backgroundColor = + [UIColor colorWithWhite:1 alpha:kScrolledToTopBackgroundAlpha]; + backgroundView.userInteractionEnabled = NO; + backgroundView.layer.cornerRadius = kBackgroundCornerRadius; + backgroundView.layer.masksToBounds = YES; + [self addSubview:backgroundView]; + backgroundView.center = + CGPointMake(kOverallWidth / 2.0, kOverallHeight / 2.0); + self.background = backgroundView; + } // Set up the layout guides for the segments. UILayoutGuide* incognitoGuide = [[UILayoutGuide alloc] init]; @@ -709,10 +717,20 @@ ]]; // Add the slider above the section images and labels. + CGFloat verticalMargin; + if (@available(iOS 26, *)) { + verticalMargin = kSliderVerticalMargin; + } else { + verticalMargin = kLegacySliderVerticalMargin; + } CGRect sliderFrame = - CGRectMake(0, kSliderVerticalMargin, kSliderWidth, kSliderHeight); + CGRectMake(0, verticalMargin, kSliderWidth, kSliderHeight); UIView* slider = [[UIView alloc] initWithFrame:sliderFrame]; - slider.layer.cornerRadius = kSliderCornerRadius; + if (@available(iOS 26, *)) { + slider.layer.cornerRadius = kSliderHeight / 2.0; + } else { + slider.layer.cornerRadius = kSliderCornerRadius; + } slider.layer.masksToBounds = YES; slider.backgroundColor = UIColor.whiteColor; if (ios::provider::IsRaccoonEnabled()) {
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_top_toolbar.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_top_toolbar.mm index 9b5b9b6c..ca1cc7aa 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_top_toolbar.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_top_toolbar.mm
@@ -222,12 +222,18 @@ } - (void)hide { - self.backgroundColor = UIColor.blackColor; + if (@available(iOS 26, *)) { + } else { + self.backgroundColor = UIColor.blackColor; + } self.pageControl.alpha = 0.0; } - (void)show { - self.backgroundColor = UIColor.clearColor; + if (@available(iOS 26, *)) { + } else { + self.backgroundColor = UIColor.clearColor; + } self.pageControl.alpha = 1.0; } @@ -548,28 +554,31 @@ - (void)createScrolledBackgrounds { _scrolledToEdge = YES; - if (IsIOSSoftLockEnabled()) { - _scrollBackgroundView = [[TabGridToolbarScrollingBackground alloc] init]; - _scrollBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; - [self insertSubview:_scrollBackgroundView atIndex:0]; - AddSameConstraintsToSides( - self, _scrollBackgroundView, - LayoutSides::kLeading | LayoutSides::kBottom | LayoutSides::kTrailing); + if (@available(iOS 26, *)) { } else { - _backgroundView = - [[TabGridToolbarBackground alloc] initWithFrame:self.frame]; - _backgroundView.translatesAutoresizingMaskIntoConstraints = NO; - [self addSubview:_backgroundView]; - AddSameConstraintsToSides( - self, _backgroundView, - LayoutSides::kLeading | LayoutSides::kBottom | LayoutSides::kTrailing); - } + if (IsIOSSoftLockEnabled()) { + _scrollBackgroundView = [[TabGridToolbarScrollingBackground alloc] init]; + _scrollBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; + [self insertSubview:_scrollBackgroundView atIndex:0]; + AddSameConstraintsToSides(self, _scrollBackgroundView, + LayoutSides::kLeading | LayoutSides::kBottom | + LayoutSides::kTrailing); + } else { + _backgroundView = + [[TabGridToolbarBackground alloc] initWithFrame:self.frame]; + _backgroundView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_backgroundView]; + AddSameConstraintsToSides(self, _backgroundView, + LayoutSides::kLeading | LayoutSides::kBottom | + LayoutSides::kTrailing); + } - // A non-nil UIImage has to be added in the background of the toolbar to - // avoid having an additional blur effect. - [self setBackgroundImage:[[UIImage alloc] init] - forToolbarPosition:UIBarPositionAny - barMetrics:UIBarMetricsDefault]; + // A non-nil UIImage has to be added in the background of the toolbar to + // avoid having an additional blur effect. + [self setBackgroundImage:[[UIImage alloc] init] + forToolbarPosition:UIBarPositionAny + barMetrics:UIBarMetricsDefault]; + } } // Returns YES if should use compact bottom toolbar layout.
diff --git a/ios/chrome/browser/web/model/font_size/font_size_tab_helper.mm b/ios/chrome/browser/web/model/font_size/font_size_tab_helper.mm index 3b8e708..363f3a6 100644 --- a/ios/chrome/browser/web/model/font_size/font_size_tab_helper.mm +++ b/ios/chrome/browser/web/model/font_size/font_size_tab_helper.mm
@@ -26,78 +26,6 @@ #import "ios/public/provider/chrome/browser/text_zoom/text_zoom_api.h" #import "services/metrics/public/cpp/ukm_builders.h" -namespace { - -// Content size category to report UMA metrics. -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. -enum class IOSContentSizeCategory { - kUnspecified = 0, - kExtraSmall = 1, - kSmall = 2, - kMedium = 3, - kLarge = 4, - kExtraLarge = 5, - kExtraExtraLarge = 6, - kExtraExtraExtraLarge = 7, - kAccessibilityMedium = 8, - kAccessibilityLarge = 9, - kAccessibilityExtraLarge = 10, - kAccessibilityExtraExtraLarge = 11, - kAccessibilityExtraExtraExtraLarge = 12, - kMaxValue = kAccessibilityExtraExtraExtraLarge, -}; - -// Converts a UIKit content size category to a content size category for -// reporting. -IOSContentSizeCategory IOSContentSizeCategoryForCurrentUIContentSizeCategory() { - UIContentSizeCategory size = - UIApplication.sharedApplication.preferredContentSizeCategory; - if ([size isEqual:UIContentSizeCategoryUnspecified]) { - return IOSContentSizeCategory::kUnspecified; - } - if ([size isEqual:UIContentSizeCategoryExtraSmall]) { - return IOSContentSizeCategory::kExtraSmall; - } - if ([size isEqual:UIContentSizeCategorySmall]) { - return IOSContentSizeCategory::kSmall; - } - if ([size isEqual:UIContentSizeCategoryMedium]) { - return IOSContentSizeCategory::kMedium; - } - if ([size isEqual:UIContentSizeCategoryLarge]) { - return IOSContentSizeCategory::kLarge; - } - if ([size isEqual:UIContentSizeCategoryExtraLarge]) { - return IOSContentSizeCategory::kExtraLarge; - } - if ([size isEqual:UIContentSizeCategoryExtraExtraLarge]) { - return IOSContentSizeCategory::kExtraExtraLarge; - } - if ([size isEqual:UIContentSizeCategoryExtraExtraExtraLarge]) { - return IOSContentSizeCategory::kExtraExtraExtraLarge; - } - if ([size isEqual:UIContentSizeCategoryAccessibilityMedium]) { - return IOSContentSizeCategory::kAccessibilityMedium; - } - if ([size isEqual:UIContentSizeCategoryAccessibilityLarge]) { - return IOSContentSizeCategory::kAccessibilityLarge; - } - if ([size isEqual:UIContentSizeCategoryAccessibilityExtraLarge]) { - return IOSContentSizeCategory::kAccessibilityExtraLarge; - } - if ([size isEqual:UIContentSizeCategoryAccessibilityExtraExtraLarge]) { - return IOSContentSizeCategory::kAccessibilityExtraExtraLarge; - } - if ([size isEqual:UIContentSizeCategoryAccessibilityExtraExtraExtraLarge]) { - return IOSContentSizeCategory::kAccessibilityExtraExtraExtraLarge; - } - - return IOSContentSizeCategory::kUnspecified; -} - -} // namespace - FontSizeTabHelper::FontSizeTabHelper(web::WebState* web_state) : web_state_(web_state), weak_factory_(this) { DCHECK(ios::provider::IsTextZoomEnabled()); @@ -142,8 +70,8 @@ void FontSizeTabHelper::LogZoomEvent(Zoom zoom) const { // Log when the user zooms to see if there are certain websites that are // broken when zooming. - IOSContentSizeCategory content_size_category = - IOSContentSizeCategoryForCurrentUIContentSizeCategory(); + ui_util::IOSContentSizeCategory content_size_category = + ui_util::GetPreferredContentSizeCategory(); ukm::UkmRecorder* ukm_recorder = GetApplicationContext()->GetUkmRecorder(); ukm::SourceId source_id = ukm::GetSourceIdForWebStateDocument(web_state_); ukm::builders::IOS_PageZoomChanged(source_id)
diff --git a/ios/components/ui_util/BUILD.gn b/ios/components/ui_util/BUILD.gn index 66618d83..8141f71 100644 --- a/ios/components/ui_util/BUILD.gn +++ b/ios/components/ui_util/BUILD.gn
@@ -1,5 +1,7 @@ source_set("ui_util") { sources = [ + "content_size_category_description.h", + "content_size_category_description.mm", "dynamic_type_util.h", "dynamic_type_util.mm", ]
diff --git a/ios/components/ui_util/content_size_category_description.h b/ios/components/ui_util/content_size_category_description.h new file mode 100644 index 0000000..fcce6f5 --- /dev/null +++ b/ios/components/ui_util/content_size_category_description.h
@@ -0,0 +1,26 @@ +// 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 IOS_COMPONENTS_UI_UTIL_CONTENT_SIZE_CATEGORY_DESCRIPTION_H_ +#define IOS_COMPONENTS_UI_UTIL_CONTENT_SIZE_CATEGORY_DESCRIPTION_H_ + +#import <UIKit/UIKit.h> + +namespace ui_util { +enum class IOSContentSizeCategory; +} // namespace ui_util + +// Description related for UIContentSizeCategory. +@interface ContentSizeCategoryDescription : NSObject + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithCategory:(ui_util::IOSContentSizeCategory)category + multiplier:(float)multiplier NS_DESIGNATED_INITIALIZER; + +@property(nonatomic, assign) ui_util::IOSContentSizeCategory category; +@property(nonatomic, assign) float multiplier; + +@end + +#endif // IOS_COMPONENTS_UI_UTIL_CONTENT_SIZE_CATEGORY_DESCRIPTION_H_
diff --git a/ios/components/ui_util/content_size_category_description.mm b/ios/components/ui_util/content_size_category_description.mm new file mode 100644 index 0000000..b3d50907 --- /dev/null +++ b/ios/components/ui_util/content_size_category_description.mm
@@ -0,0 +1,19 @@ +// 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. + +#import "ios/components/ui_util/content_size_category_description.h" + +@implementation ContentSizeCategoryDescription + +- (instancetype)initWithCategory:(ui_util::IOSContentSizeCategory)category + multiplier:(float)multiplier { + self = [super init]; + if (self) { + _category = category; + _multiplier = multiplier; + } + return self; +} + +@end
diff --git a/ios/components/ui_util/dynamic_type_util.h b/ios/components/ui_util/dynamic_type_util.h index 463eb01..96894d2 100644 --- a/ios/components/ui_util/dynamic_type_util.h +++ b/ios/components/ui_util/dynamic_type_util.h
@@ -9,6 +9,35 @@ namespace ui_util { +// Content size category to report UMA metrics. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// LINT.IfChange(IOSContentSizeCategory) +enum class IOSContentSizeCategory { + kUnspecified = 0, + kExtraSmall = 1, + kSmall = 2, + kMedium = 3, + kLarge = 4, // System default. + kExtraLarge = 5, + kExtraExtraLarge = 6, + kExtraExtraExtraLarge = 7, + kAccessibilityMedium = 8, + kAccessibilityLarge = 9, + kAccessibilityExtraLarge = 10, + kAccessibilityExtraExtraLarge = 11, + kAccessibilityExtraExtraExtraLarge = 12, + kMaxValue = kAccessibilityExtraExtraExtraLarge, +}; +// LINT.ThenChange(//tools/metrics/histograms/enums.xml:IOSContentSizeCategory) + +// Returns the `IOSContentSizeCategory` value for +// `UIApplication.sharedApplication.preferredContentSizeCategory`. +ui_util::IOSContentSizeCategory GetPreferredContentSizeCategory(); + +// Records metrics related to the system fonts. +void RecordSystemFontSizeMetrics(); + // Returns system suggested font size multiplier (e.g. 1.5 if the font size // should be 50% bigger) for the actual system preferred content size category. float SystemSuggestedFontSizeMultiplier();
diff --git a/ios/components/ui_util/dynamic_type_util.mm b/ios/components/ui_util/dynamic_type_util.mm index c823d51..4209bbc 100644 --- a/ios/components/ui_util/dynamic_type_util.mm +++ b/ios/components/ui_util/dynamic_type_util.mm
@@ -4,10 +4,88 @@ #import "ios/components/ui_util/dynamic_type_util.h" -#import "base/metrics/histogram_macros.h" +#import "base/metrics/histogram_functions.h" +#import "ios/components/ui_util/content_size_category_description.h" + +namespace { + +NSDictionary* const kFontDescriptionDictionary = @{ + UIContentSizeCategoryUnspecified : [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kUnspecified + multiplier:1], + UIContentSizeCategoryExtraSmall : [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kExtraSmall + multiplier:0.82], + UIContentSizeCategorySmall : [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kSmall + multiplier:0.88], + UIContentSizeCategoryMedium : [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kMedium + multiplier:0.94], + UIContentSizeCategoryLarge : [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kLarge + multiplier:1], + UIContentSizeCategoryExtraLarge : [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kExtraLarge + multiplier:1.12], + UIContentSizeCategoryExtraExtraLarge : [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kExtraExtraLarge + multiplier:1.24], + UIContentSizeCategoryExtraExtraExtraLarge : [[ContentSizeCategoryDescription + alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kExtraExtraExtraLarge + multiplier:1.35], + UIContentSizeCategoryAccessibilityMedium : + [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kAccessibilityMedium + multiplier:1.65], + UIContentSizeCategoryAccessibilityLarge : + [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory::kAccessibilityLarge + multiplier:1.94], + UIContentSizeCategoryAccessibilityExtraLarge : + [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory:: + kAccessibilityExtraLarge + multiplier:2.35], + UIContentSizeCategoryAccessibilityExtraExtraLarge : + [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory:: + kAccessibilityExtraExtraLarge + multiplier:2.76], + UIContentSizeCategoryAccessibilityExtraExtraExtraLarge : + [[ContentSizeCategoryDescription alloc] + initWithCategory:ui_util::IOSContentSizeCategory:: + kAccessibilityExtraExtraExtraLarge + multiplier:3.12], +}; + +} // namespace namespace ui_util { +ui_util::IOSContentSizeCategory GetPreferredContentSizeCategory() { + ContentSizeCategoryDescription* preferred_system_font_decription = + kFontDescriptionDictionary[UIApplication.sharedApplication + .preferredContentSizeCategory]; + return preferred_system_font_decription + ? preferred_system_font_decription.category + : IOSContentSizeCategory::kUnspecified; +} + +void RecordSystemFontSizeMetrics() { + ContentSizeCategoryDescription* preferred_system_font_decription = + kFontDescriptionDictionary[UIApplication.sharedApplication + .preferredContentSizeCategory]; + // In case there is a new accessibility value, log if there is a value we + // are missing. Use the sharedApplication value as this method can be called + // with an explicit value for the first time. + base::UmaHistogramBoolean("Accessibility.iOS.NewLargerTextCategory", + !preferred_system_font_decription); + base::UmaHistogramEnumeration("IOS.System.PreferredSystemFontSize", + preferred_system_font_decription.category); +} + float SystemSuggestedFontSizeMultiplier() { return SystemSuggestedFontSizeMultiplier( UIApplication.sharedApplication.preferredContentSizeCategory); @@ -17,32 +95,9 @@ // Scaling numbers are calculated by [UIFont // preferredFontForTextStyle:UIFontTextStyleBody].pointSize, which are [14, // 15, 16, 17(default), 19, 21, 23, 28, 33, 40, 47, 53]. - static NSDictionary* font_size_map = @{ - UIContentSizeCategoryUnspecified : @1, - UIContentSizeCategoryExtraSmall : @0.82, - UIContentSizeCategorySmall : @0.88, - UIContentSizeCategoryMedium : @0.94, - UIContentSizeCategoryLarge : @1, // system default - UIContentSizeCategoryExtraLarge : @1.12, - UIContentSizeCategoryExtraExtraLarge : @1.24, - UIContentSizeCategoryExtraExtraExtraLarge : @1.35, - UIContentSizeCategoryAccessibilityMedium : @1.65, - UIContentSizeCategoryAccessibilityLarge : @1.94, - UIContentSizeCategoryAccessibilityExtraLarge : @2.35, - UIContentSizeCategoryAccessibilityExtraExtraLarge : @2.76, - UIContentSizeCategoryAccessibilityExtraExtraExtraLarge : @3.12, - }; - NSNumber* font_size = font_size_map[category]; - static dispatch_once_t once_token; - dispatch_once(&once_token, ^{ - // In case there is a new accessibility value, log if there is a value we - // are missing. Use the sharedApplication value as this method can be called - // with an explicit value for the first time. - UMA_HISTOGRAM_BOOLEAN("Accessibility.iOS.NewLargerTextCategory", - !font_size_map[UIApplication.sharedApplication - .preferredContentSizeCategory]); - }); - return font_size ? font_size.floatValue : 1; + ContentSizeCategoryDescription* system_font_description = + kFontDescriptionDictionary[category]; + return system_font_description ? system_font_description.multiplier : 1; } float SystemSuggestedFontSizeMultiplier(UIContentSizeCategory category,
diff --git a/media/gpu/vaapi/test_utils.cc b/media/gpu/vaapi/test_utils.cc index d59b329c..9fadc3f 100644 --- a/media/gpu/vaapi/test_utils.cc +++ b/media/gpu/vaapi/test_utils.cc
@@ -19,11 +19,7 @@ #include "third_party/libyuv/include/libyuv.h" #include "ui/gfx/buffer_format_util.h" -// TODO(crbug.com/421698315): Remove. -#include "ui/gfx/gpu_memory_buffer.h" - #if BUILDFLAG(IS_CHROMEOS) -// TODO(crbug.com/421698315): Remove. #include "media/gpu/test/local_gpu_memory_buffer_manager.h" #endif
diff --git a/net/disk_cache/sql/sql_persistent_store.cc b/net/disk_cache/sql/sql_persistent_store.cc index 9484866..752bf634 100644 --- a/net/disk_cache/sql/sql_persistent_store.cc +++ b/net/disk_cache/sql/sql_persistent_store.cc
@@ -250,7 +250,11 @@ EntryInfoOrError OpenOrCreateEntry(const CacheEntryKey& key); OptionalEntryInfoOrError OpenEntry(const CacheEntryKey& key); EntryInfoOrError CreateEntry(const CacheEntryKey& key); - + Error DoomEntry(const CacheEntryKey& key, + const base::UnguessableToken& token); + Error DeleteDoomedEntry(const CacheEntryKey& key, + const base::UnguessableToken& token); + Error DeleteLiveEntry(const CacheEntryKey& key); Error DeleteAllEntries(); private: @@ -261,6 +265,13 @@ OptionalEntryInfoOrError OpenEntryInternal(const CacheEntryKey& key); EntryInfoOrError CreateEntryInternal(const CacheEntryKey& key, bool run_existance_check); + Error DoomEntryInternal(const CacheEntryKey& key, + const base::UnguessableToken& token, + bool& corruption_detected); + Error DeleteDoomedEntryInternal(const CacheEntryKey& key, + const base::UnguessableToken& token); + Error DeleteLiveEntryInternal(const CacheEntryKey& key, + bool& corruption_detected); Error DeleteAllEntriesInternal(); // Updates the in-memory `store_status_` by `entry_count_delta` and @@ -273,9 +284,22 @@ int64_t entry_count_delta, int64_t total_size_delta); + // Recalculates the store's status (entry count and total size) directly from + // the database. This is a recovery mechanism used when metadata might be + // inconsistent, e.g., after a numerical overflow. + bool RecalculateStoreStatusAndCommitTransaction( + sql::Transaction& transaction); + int64_t CalculateResourceEntryCount(); int64_t CalculateTotalSize(); + // A helper method for checking that the database initialization was + // successful before proceeding with any database operations. + void CheckDatabaseInitStatus() { + CHECK(db_init_status_.has_value()); + CHECK_EQ(*db_init_status_, Error::kOk); + } + const base::FilePath path_; const int64_t max_bytes_; sql::Database db_; @@ -443,9 +467,7 @@ } OptionalEntryInfoOrError Backend::OpenEntryInternal(const CacheEntryKey& key) { - CHECK(db_init_status_.has_value()); - CHECK_EQ(*db_init_status_, Error::kOk); - + CheckDatabaseInitStatus(); constexpr char kSqlSelectResources[] = // clang-format off "SELECT " @@ -520,9 +542,7 @@ EntryInfoOrError Backend::CreateEntryInternal(const CacheEntryKey& key, bool run_existance_check) { - CHECK(db_init_status_.has_value()); - CHECK_EQ(*db_init_status_, Error::kOk); - + CheckDatabaseInitStatus(); sql::Transaction transaction(&db_); if (!transaction.Begin()) { return base::unexpected(Error::kFailedToStartTransaction); @@ -591,6 +611,284 @@ return entry_info; } +Error Backend::DoomEntry(const CacheEntryKey& key, + const base::UnguessableToken& token) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DoomEntry", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("key", key.string()); + dict.Add("token", token.ToString()); + PopulateTraceDetails(store_status_, dict); + }); + base::ElapsedTimer timer; + bool corruption_detected = false; + auto result = DoomEntryInternal(key, token, corruption_detected); + RecordTimeAndErrorResultHistogram( + "DoomEntry", timer.Elapsed(), + corruption_detected ? Error::kInvalidData : result); + TRACE_EVENT_END1("disk_cache", "SqlBackend.DoomEntry", "result", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, store_status_, dict); + dict.Add("corruption_detected", corruption_detected); + }); + return result; +} + +Error Backend::DoomEntryInternal(const CacheEntryKey& key, + const base::UnguessableToken& token, + bool& corruption_detected) { + CheckDatabaseInitStatus(); + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToStartTransaction; + } + + int64_t doomed_count = 0; + // Use checked numerics to safely calculate the change in total size and + // detect potential metadata corruption from overflows. + base::CheckedNumeric<int64_t> total_size_delta = 0; + { + constexpr char kSqlMarkDoomedResources[] = + // clang-format off + "UPDATE resources " + "SET " + "doomed=? " // 0 + "WHERE " + "cache_key=? AND " // 1 + "token_high=? AND " // 2 + "token_low=? AND " // 3 + "doomed=? " // 4 + "RETURNING " + "bytes_usage"; // 0 + // clang-format on + + // Intentionally DCHECK() for performance + DCHECK(db_.IsSQLValid(kSqlMarkDoomedResources)); + sql::Statement statement( + db_.GetCachedStatement(SQL_FROM_HERE, kSqlMarkDoomedResources)); + // Set the new value: doomed = true. + statement.BindBool(0, true); + statement.BindString(1, key.string()); + statement.BindInt64(2, TokenHigh(token)); + statement.BindInt64(3, TokenLow(token)); + // Set the current value to match: doomed = false. + statement.BindBool(4, false); + // Iterate through the rows returned by the RETURNING clause. + while (statement.Step()) { + // Since we're dooming an entry, its size is subtracted from the total. + total_size_delta -= statement.ColumnInt64(0); + // Count how many entries were actually updated. + ++doomed_count; + } + } + + if (doomed_count > 1) { + // TODO(crbug.com/422065015): Add histograms to track how often this + // unexpected case is reached. A cache_key and token combination should + // uniquely identify a single non-doomed entry. + } + + // If no rows were updated, it means the entry was not found (or the token + // was wrong), so we report kNotFound. + if (doomed_count == 0) { + return transaction.Commit() ? Error::kNotFound + : Error::kFailedToCommitTransaction; + } + + // If the `total_size_delta` calculation resulted in an overflow, it suggests + // that the `bytes_usage` value in the database was corrupt. In this case, we + // trigger a full recalculation of the store's status to recover to a + // consistent state. + if (!total_size_delta.IsValid()) { + corruption_detected = true; + return RecalculateStoreStatusAndCommitTransaction(transaction) + ? Error::kOk + : Error::kFailedToCommitTransaction; + } + + if (!UpdateStoreStatusAndCommitTransaction( + transaction, + /*entry_count_delta=*/-doomed_count, + /*total_size_delta=*/total_size_delta.ValueOrDie())) { + return Error::kFailedToCommitTransaction; + } + + return Error::kOk; +} + +Error Backend::DeleteDoomedEntry(const CacheEntryKey& key, + const base::UnguessableToken& token) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DeleteDoomedEntry", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("key", key.string()); + dict.Add("token", token.ToString()); + PopulateTraceDetails(store_status_, dict); + }); + base::ElapsedTimer timer; + auto result = DeleteDoomedEntryInternal(key, token); + RecordTimeAndErrorResultHistogram("DeleteDoomedEntry", timer.Elapsed(), + result); + TRACE_EVENT_END1("disk_cache", "SqlBackend.DeleteDoomedEntry", "result", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, store_status_, dict); + }); + return result; +} + +Error Backend::DeleteDoomedEntryInternal(const CacheEntryKey& key, + const base::UnguessableToken& token) { + CheckDatabaseInitStatus(); + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToStartTransaction; + } + + int64_t deleted_count = 0; + { + constexpr char kSqlDeleteFromResources[] = + // clang-format off + "DELETE FROM resources " + "WHERE " + "cache_key=? AND " // 0 + "token_high=? AND " // 1 + "token_low=? AND " // 2 + "doomed=?"; // 3 + // clang-format on + + // Intentionally DCHECK() for performance + DCHECK(db_.IsSQLValid(kSqlDeleteFromResources)); + sql::Statement statement( + db_.GetCachedStatement(SQL_FROM_HERE, kSqlDeleteFromResources)); + statement.BindString(0, key.string()); + statement.BindInt64(1, TokenHigh(token)); + statement.BindInt64(2, TokenLow(token)); + // Target rows where doomed = true. + statement.BindBool(3, true); + if (!statement.Run()) { + return Error::kFailedToExecute; + } + deleted_count = db_.GetLastChangeCount(); + } + + if (deleted_count > 1) { + // TODO(crbug.com/422065015): Add histograms to track how often this + // unexpected case is reached. A cache_key and token combination should + // uniquely identify a single doomed entry. + } + + // If we didn't find any doomed entry matching the key and token, report it. + if (deleted_count == 0) { + return transaction.Commit() ? Error::kNotFound + : Error::kFailedToCommitTransaction; + } + + // TODO(crbug.com/422065015): delete body data from the `blobs` table. + + return transaction.Commit() ? Error::kOk : Error::kFailedToExecute; +} + +Error Backend::DeleteLiveEntry(const CacheEntryKey& key) { + TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DeleteLiveEntry", "data", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + dict.Add("key", key.string()); + PopulateTraceDetails(store_status_, dict); + }); + base::ElapsedTimer timer; + bool corruption_detected = false; + auto result = DeleteLiveEntryInternal(key, corruption_detected); + RecordTimeAndErrorResultHistogram( + "DeleteLiveEntry", timer.Elapsed(), + corruption_detected ? Error::kInvalidData : result); + TRACE_EVENT_END1("disk_cache", "SqlBackend.DeleteLiveEntry", "result", + [&](perfetto::TracedValue trace_context) { + auto dict = std::move(trace_context).WriteDictionary(); + PopulateTraceDetails(result, store_status_, dict); + dict.Add("corruption_detected", corruption_detected); + }); + return result; +} + +Error Backend::DeleteLiveEntryInternal(const CacheEntryKey& key, + bool& corruption_detected) { + CheckDatabaseInitStatus(); + sql::Transaction transaction(&db_); + if (!transaction.Begin()) { + return Error::kFailedToStartTransaction; + } + + // We need to collect the tokens of deleted entries to later remove their + // corresponding data from the `blobs` table. + std::vector<base::UnguessableToken> tokens_to_be_deleted; + // Use checked numerics to safely update the total cache size. + base::CheckedNumeric<int64_t> total_size_delta = 0; + int64_t deleted_count = 0; + { + constexpr char kSqlDeleteFromResources[] = + // clang-format off + "DELETE FROM resources " + "WHERE " + "cache_key=? AND " // 0 + "doomed=? " // 1 + "RETURNING " + "token_high," // 0 + "token_low," // 1 + "bytes_usage"; // 2 + // clang-format on + // Intentionally DCHECK() for performance + DCHECK(db_.IsSQLValid(kSqlDeleteFromResources)); + sql::Statement statement( + db_.GetCachedStatement(SQL_FROM_HERE, kSqlDeleteFromResources)); + statement.BindString(0, key.string()); + // Target rows where doomed = false. + statement.BindBool(1, false); + while (statement.Step()) { + ++deleted_count; + auto maybe_token = ToUnguessableToken(statement.ColumnInt64(0), + statement.ColumnInt64(1)); + // If deserializing the token fails, it's a sign of data corruption. + if (!maybe_token) { + corruption_detected = true; + continue; + } + // The size of the deleted entry is subtracted from the total. + total_size_delta -= statement.ColumnInt64(2); + tokens_to_be_deleted.emplace_back(*maybe_token); + } + } + + // If no entries were deleted, the key wasn't found. + if (deleted_count == 0) { + return transaction.Commit() ? Error::kNotFound + : Error::kFailedToCommitTransaction; + } + + // TODO(crbug.com/422065015): delete body data from the `blobs` table. + + // If we detected corruption, or if the size update calculation overflowed, + // our metadata is suspect. We recover by recalculating everything from + // scratch. + if (corruption_detected || !total_size_delta.IsValid()) { + corruption_detected = true; + return RecalculateStoreStatusAndCommitTransaction(transaction) + ? Error::kOk + : Error::kFailedToCommitTransaction; + } + + if (!UpdateStoreStatusAndCommitTransaction( + transaction, + /*entry_count_delta=*/ + -static_cast<int64_t>(tokens_to_be_deleted.size()), + /*total_size_delta=*/total_size_delta.ValueOrDie())) { + return Error::kFailedToCommitTransaction; + } + + return Error::kOk; +} + Error Backend::DeleteAllEntries() { TRACE_EVENT_BEGIN1("disk_cache", "SqlBackend.DeleteAllEntries", "data", [&](perfetto::TracedValue trace_context) { @@ -610,8 +908,7 @@ } Error Backend::DeleteAllEntriesInternal() { - CHECK(db_init_status_.has_value()); - CHECK_EQ(*db_init_status_, Error::kOk); + CheckDatabaseInitStatus(); sql::Transaction transaction(&db_); if (!transaction.Begin()) { return Error::kFailedToStartTransaction; @@ -701,6 +998,17 @@ return true; } +bool Backend::RecalculateStoreStatusAndCommitTransaction( + sql::Transaction& transaction) { + store_status_.entry_count = CalculateResourceEntryCount(); + store_status_.total_size = CalculateTotalSize(); + meta_table_.SetValue(kSqlBackendMetaTableKeyEntryCount, + store_status_.entry_count); + meta_table_.SetValue(kSqlBackendMetaTableKeyTotalSize, + store_status_.total_size); + return transaction.Commit(); +} + // Recalculates the number of non-doomed entries in the `resources` table. int64_t Backend::CalculateResourceEntryCount() { constexpr char kSqlSelectCountFromResources[] = @@ -782,7 +1090,26 @@ .WithArgs(key) .Then(WrapCallback(std::move(callback))); } - + void DoomEntry(const CacheEntryKey& key, + const base::UnguessableToken& token, + ErrorCallback callback) override { + backend_.AsyncCall(&Backend::DoomEntry) + .WithArgs(key, token) + .Then(WrapCallback(std::move(callback))); + } + void DeleteDoomedEntry(const CacheEntryKey& key, + const base::UnguessableToken& token, + ErrorCallback callback) override { + backend_.AsyncCall(&Backend::DeleteDoomedEntry) + .WithArgs(key, token) + .Then(WrapCallback(std::move(callback))); + } + void DeleteLiveEntry(const CacheEntryKey& key, + ErrorCallback callback) override { + backend_.AsyncCall(&Backend::DeleteLiveEntry) + .WithArgs(key) + .Then(WrapCallback(std::move(callback))); + } void DeleteAllEntries(ErrorCallback callback) override { backend_.AsyncCall(&Backend::DeleteAllEntries) .Then(WrapCallback(std::move(callback)));
diff --git a/net/disk_cache/sql/sql_persistent_store.h b/net/disk_cache/sql/sql_persistent_store.h index 974a2f4..6928c01 100644 --- a/net/disk_cache/sql/sql_persistent_store.h +++ b/net/disk_cache/sql/sql_persistent_store.h
@@ -56,7 +56,8 @@ kFailedToExecute = 10, kInvalidData = 11, kAlreadyExists = 12, - kMaxValue = kAlreadyExists + kNotFound = 13, + kMaxValue = kNotFound }; // LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:SqlDiskCacheStoreError) @@ -125,6 +126,29 @@ virtual void CreateEntry(const CacheEntryKey& key, EntryInfoOrErrorCallback callback) = 0; + // Marks an entry for future deletion. When an entry is "doomed", it is + // immediately removed from the cache's entry count and total size, but its + // data remains on disk until `DeleteDoomedEntry()` is called. The `token` + // ensures that only the correct instance of an entry is doomed. + virtual void DoomEntry(const CacheEntryKey& key, + const base::UnguessableToken& token, + ErrorCallback callback) = 0; + + // Physically deletes an entry that has been previously marked as doomed. This + // operation completes the deletion process by removing the entry's data from + // the database. The `token` ensures that only a specific, doomed instance of + // the entry is deleted. + virtual void DeleteDoomedEntry(const CacheEntryKey& key, + const base::UnguessableToken& token, + ErrorCallback callback) = 0; + + // Deletes a "live" entry, i.e., an entry whose `doomed` flag is not set. + // This is for use for entries which are not open; open entries should have + // `DoomEntry()` called, and then `DeleteDoomedEntry()` once they're no longer + // in used. + virtual void DeleteLiveEntry(const CacheEntryKey& key, + ErrorCallback callback) = 0; + // Deletes all entries from the cache. `callback` is invoked on completion. virtual void DeleteAllEntries(ErrorCallback callback) = 0;
diff --git a/net/disk_cache/sql/sql_persistent_store_unittest.cc b/net/disk_cache/sql/sql_persistent_store_unittest.cc index bcc8172..a4b674a 100644 --- a/net/disk_cache/sql/sql_persistent_store_unittest.cc +++ b/net/disk_cache/sql/sql_persistent_store_unittest.cc
@@ -214,6 +214,53 @@ return std::move(*maybe_result); } + // Synchronous wrapper for DoomEntry. + SqlPersistentStore::Error DoomEntry(const CacheEntryKey& key, + const base::UnguessableToken& token) { + base::RunLoop run_loop; + std::optional<SqlPersistentStore::Error> maybe_result; + store_->DoomEntry( + key, token, + base::BindLambdaForTesting([&](SqlPersistentStore::Error result) { + maybe_result = result; + run_loop.Quit(); + })); + run_loop.Run(); + CHECK(maybe_result.has_value()); + return *maybe_result; + } + + // Synchronous wrapper for DeleteDoomedEntry. + SqlPersistentStore::Error DeleteDoomedEntry( + const CacheEntryKey& key, + const base::UnguessableToken& token) { + base::RunLoop run_loop; + std::optional<SqlPersistentStore::Error> maybe_result; + store_->DeleteDoomedEntry( + key, token, + base::BindLambdaForTesting([&](SqlPersistentStore::Error result) { + maybe_result = result; + run_loop.Quit(); + })); + run_loop.Run(); + CHECK(maybe_result.has_value()); + return *maybe_result; + } + + // Synchronous wrapper for DeleteLiveEntry. + SqlPersistentStore::Error DeleteLiveEntry(const CacheEntryKey& key) { + base::RunLoop run_loop; + std::optional<SqlPersistentStore::Error> maybe_result; + store_->DeleteLiveEntry( + key, base::BindLambdaForTesting([&](SqlPersistentStore::Error result) { + maybe_result = result; + run_loop.Quit(); + })); + run_loop.Run(); + CHECK(maybe_result.has_value()); + return *maybe_result; + } + // Synchronous wrapper for DeleteAllEntries. SqlPersistentStore::Error DeleteAllEntries() { base::RunLoop run_loop; @@ -236,6 +283,17 @@ return s.ColumnInt(0); } + // Helper to count doomed rows in the resource table. + int64_t CountDoomedResourcesTable(const CacheEntryKey& key) { + auto db = ManuallyOpenDatabase(); + sql::Statement s(db->GetUniqueStatement( + "SELECT COUNT(*) FROM resources WHERE cache_key=? AND doomed=?")); + s.BindString(0, key.string()); + s.BindBool(1, true); // doomed = true + CHECK(s.Step()); + return s.ColumnInt64(0); + } + base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::DEFAULT}; base::ScopedTempDir temp_dir_; @@ -655,6 +713,368 @@ SqlPersistentStore::Error::kInvalidData); } +TEST_F(SqlPersistentStoreTest, DoomEntrySuccess) { + CreateAndInitStore(); + const CacheEntryKey kKeyToDoom("key-to-doom"); + const CacheEntryKey kKeyToKeep("key-to-keep"); + const int64_t size_to_doom = + kSqlBackendStaticResourceSize + kKeyToDoom.string().size(); + const int64_t size_to_keep = + kSqlBackendStaticResourceSize + kKeyToKeep.string().size(); + + // Create two entries. + auto create_result_to_doom = CreateEntry(kKeyToDoom); + ASSERT_TRUE(create_result_to_doom.has_value()); + auto create_result_to_keep = CreateEntry(kKeyToKeep); + ASSERT_TRUE(create_result_to_keep.has_value()); + + const auto token_to_doom = create_result_to_doom->token; + ASSERT_EQ(GetEntryCount(), 2); + ASSERT_EQ(GetSizeOfAllEntries(), size_to_doom + size_to_keep); + + // Doom one of the entries. + ASSERT_EQ(DoomEntry(kKeyToDoom, token_to_doom), + SqlPersistentStore::Error::kOk); + + // Verify that the entry count and size are updated, reflecting that one entry + // was logically removed. + EXPECT_EQ(GetEntryCount(), 1); + EXPECT_EQ(GetSizeOfAllEntries(), size_to_keep); + + // Verify the doomed entry can no longer be opened. + auto open_doomed_result = OpenEntry(kKeyToDoom); + ASSERT_TRUE(open_doomed_result.has_value()); + EXPECT_FALSE(open_doomed_result->has_value()); + + // Verify the other entry can still be opened. + auto open_kept_result = OpenEntry(kKeyToKeep); + ASSERT_TRUE(open_kept_result.has_value()); + ASSERT_TRUE(open_kept_result->has_value()); + EXPECT_EQ((*open_kept_result)->token, create_result_to_keep->token); + + // Verify the doomed entry still exists in the table but is marked as doomed, + // and the other entry is unaffected. + ClearStore(); + EXPECT_EQ(CountResourcesTable(), 2); + EXPECT_EQ(CountDoomedResourcesTable(kKeyToDoom), 1); + EXPECT_EQ(CountDoomedResourcesTable(kKeyToKeep), 0); +} + +TEST_F(SqlPersistentStoreTest, DoomEntryFailsNotFound) { + CreateAndInitStore(); + const CacheEntryKey kKey("non-existent-key"); + ASSERT_EQ(GetEntryCount(), 0); + + // Attempt to doom an entry that doesn't exist. + auto result = DoomEntry(kKey, base::UnguessableToken::Create()); + ASSERT_EQ(result, SqlPersistentStore::Error::kNotFound); + + // Verify that the counts remain unchanged. + EXPECT_EQ(GetEntryCount(), 0); + EXPECT_EQ(GetSizeOfAllEntries(), 0); +} + +TEST_F(SqlPersistentStoreTest, DoomEntryFailsWrongToken) { + CreateAndInitStore(); + const CacheEntryKey kKey1("key1"); + const CacheEntryKey kKey2("key2"); + const int64_t size1 = kSqlBackendStaticResourceSize + kKey1.string().size(); + const int64_t size2 = kSqlBackendStaticResourceSize + kKey2.string().size(); + + // Create two entries. + auto create_result1 = CreateEntry(kKey1); + ASSERT_TRUE(create_result1.has_value()); + auto create_result2 = CreateEntry(kKey2); + ASSERT_TRUE(create_result2.has_value()); + ASSERT_EQ(GetEntryCount(), 2); + + // Attempt to doom key1 with an incorrect token. + auto result = DoomEntry(kKey1, base::UnguessableToken::Create()); + ASSERT_EQ(result, SqlPersistentStore::Error::kNotFound); + + // Verify that the counts remain unchanged and both entries can still be + // opened. + EXPECT_EQ(GetEntryCount(), 2); + EXPECT_EQ(GetSizeOfAllEntries(), size1 + size2); + + auto open_result1 = OpenEntry(kKey1); + ASSERT_TRUE(open_result1.has_value()); + ASSERT_TRUE(open_result1->has_value()); + EXPECT_EQ((*open_result1)->token, create_result1->token); + + auto open_result2 = OpenEntry(kKey2); + ASSERT_TRUE(open_result2.has_value()); + ASSERT_TRUE(open_result2->has_value()); + EXPECT_EQ((*open_result2)->token, create_result2->token); +} + +TEST_F(SqlPersistentStoreTest, DoomEntryWithCorruptSizeRecovers) { + CreateAndInitStore(); + const CacheEntryKey kKeyToCorrupt("key-to-corrupt"); + const CacheEntryKey kKeyToKeep("key-to-keep"); + const int64_t keep_key_size = kKeyToKeep.string().size(); + const int64_t expected_size_after_recovery = + kSqlBackendStaticResourceSize + keep_key_size; + + // Create one entry to keep, and one to corrupt and doom. + auto create_corrupt_result = CreateEntry(kKeyToCorrupt); + ASSERT_TRUE(create_corrupt_result.has_value()); + ASSERT_TRUE(CreateEntry(kKeyToKeep).has_value()); + ASSERT_EQ(GetEntryCount(), 2); + const auto token_to_doom = create_corrupt_result->token; + ClearStore(); + + // Manually open the database and corrupt the `bytes_usage` for one entry + // to an extreme value that will cause an overflow during calculation. + { + auto db = ManuallyOpenDatabase(); + sql::Statement statement(db->GetUniqueStatement( + "UPDATE resources SET bytes_usage = ? WHERE cache_key = ?")); + statement.BindInt64(0, std::numeric_limits<int64_t>::min()); + statement.BindString(1, kKeyToCorrupt.string()); + ASSERT_TRUE(statement.Run()); + } + + // Re-initialize the store with the corrupted database. + CreateAndInitStore(); + + // Doom the entry with the corrupted size. This will trigger an overflow in + // `total_size_delta`, causing `!total_size_delta.IsValid()` to be true. + // The store should recover by recalculating its state from the database. + ASSERT_EQ(DoomEntry(kKeyToCorrupt, token_to_doom), + SqlPersistentStore::Error::kOk); + + // Verify that recovery was successful. The entry count should be 1 (for the + // entry we kept), and the total size should be correctly calculated for + // that single remaining entry, ignoring the corrupted value. + EXPECT_EQ(GetEntryCount(), 1); + EXPECT_EQ(GetSizeOfAllEntries(), expected_size_after_recovery); + + // Verify the state on disk. + ClearStore(); + // Both entries should still exist in the table. + EXPECT_EQ(CountResourcesTable(), 2); + // The corrupted entry should be marked as doomed. + EXPECT_EQ(CountDoomedResourcesTable(kKeyToCorrupt), 1); + // The other entry should be unaffected. + EXPECT_EQ(CountDoomedResourcesTable(kKeyToKeep), 0); +} + +TEST_F(SqlPersistentStoreTest, DeleteDoomedEntrySuccess) { + CreateAndInitStore(); + const CacheEntryKey kKey("my-key"); + + // Create and doom an entry. + auto create_result = CreateEntry(kKey); + ASSERT_TRUE(create_result.has_value()); + const auto token = create_result->token; + ASSERT_EQ(DoomEntry(kKey, token), SqlPersistentStore::Error::kOk); + ASSERT_EQ(GetEntryCount(), 0); + ClearStore(); + ASSERT_EQ(CountResourcesTable(), 1); + CreateAndInitStore(); + + // Delete the doomed entry. + ASSERT_EQ(DeleteDoomedEntry(kKey, token), SqlPersistentStore::Error::kOk); + + // Verify the entry is now physically gone from the database. + ClearStore(); + EXPECT_EQ(CountResourcesTable(), 0); +} + +TEST_F(SqlPersistentStoreTest, DeleteDoomedEntryFailsOnLiveEntry) { + CreateAndInitStore(); + const CacheEntryKey kKey("my-key"); + + // Create a live entry. + auto create_result = CreateEntry(kKey); + ASSERT_TRUE(create_result.has_value()); + const auto token = create_result->token; + ASSERT_EQ(GetEntryCount(), 1); + + // Attempt to delete it with DeleteDoomedEntry. This should fail because the + // entry is not marked as doomed. + auto result = DeleteDoomedEntry(kKey, token); + ASSERT_EQ(result, SqlPersistentStore::Error::kNotFound); + + // Verify the entry still exists. + EXPECT_EQ(GetEntryCount(), 1); + ClearStore(); + EXPECT_EQ(CountResourcesTable(), 1); +} + +TEST_F(SqlPersistentStoreTest, DeleteLiveEntrySuccess) { + CreateAndInitStore(); + const CacheEntryKey kKeyToDelete("key-to-delete"); + const CacheEntryKey kKeyToKeep("key-to-keep"); + const int64_t size_to_delete = + kSqlBackendStaticResourceSize + kKeyToDelete.string().size(); + const int64_t size_to_keep = + kSqlBackendStaticResourceSize + kKeyToKeep.string().size(); + + // Create two entries. + ASSERT_TRUE(CreateEntry(kKeyToDelete).has_value()); + auto create_result_to_keep = CreateEntry(kKeyToKeep); + ASSERT_TRUE(create_result_to_keep.has_value()); + ASSERT_EQ(GetEntryCount(), 2); + ASSERT_EQ(GetSizeOfAllEntries(), size_to_delete + size_to_keep); + + // Delete one of the live entries. + ASSERT_EQ(DeleteLiveEntry(kKeyToDelete), SqlPersistentStore::Error::kOk); + + // Verify the cache is updated correctly. + EXPECT_EQ(GetEntryCount(), 1); + EXPECT_EQ(GetSizeOfAllEntries(), size_to_keep); + + // Verify the deleted entry cannot be opened. + auto open_deleted_result = OpenEntry(kKeyToDelete); + ASSERT_TRUE(open_deleted_result.has_value()); + EXPECT_FALSE(open_deleted_result->has_value()); + + // Verify the other entry can still be opened. + auto open_kept_result = OpenEntry(kKeyToKeep); + ASSERT_TRUE(open_kept_result.has_value()); + ASSERT_TRUE(open_kept_result->has_value()); + EXPECT_EQ((*open_kept_result)->token, create_result_to_keep->token); + + // Verify the entry is physically gone from the database. + ClearStore(); + EXPECT_EQ(CountResourcesTable(), 1); +} + +TEST_F(SqlPersistentStoreTest, DeleteLiveEntryFailsNotFound) { + CreateAndInitStore(); + const CacheEntryKey kKey("non-existent-key"); + ASSERT_EQ(GetEntryCount(), 0); + + // Attempt to delete an entry that doesn't exist. + auto result = DeleteLiveEntry(kKey); + ASSERT_EQ(result, SqlPersistentStore::Error::kNotFound); +} + +TEST_F(SqlPersistentStoreTest, DeleteLiveEntryFailsOnDoomedEntry) { + CreateAndInitStore(); + const CacheEntryKey kDoomedKey("doomed-key"); + const CacheEntryKey kLiveKey("live-key"); + const int64_t live_key_size = + kSqlBackendStaticResourceSize + kLiveKey.string().size(); + + // Create one live entry and one entry that will be doomed. + auto create_doomed_result = CreateEntry(kDoomedKey); + ASSERT_TRUE(create_doomed_result.has_value()); + ASSERT_TRUE(CreateEntry(kLiveKey).has_value()); + + // Doom one of the entries. + ASSERT_EQ(DoomEntry(kDoomedKey, create_doomed_result->token), + SqlPersistentStore::Error::kOk); + // After dooming, one entry is live, one is doomed (logically removed). + ASSERT_EQ(GetEntryCount(), 1); + ASSERT_EQ(GetSizeOfAllEntries(), live_key_size); + + // Attempt to delete the doomed entry with DeleteLiveEntry. This should fail + // because it's not "live". + auto result = DeleteLiveEntry(kDoomedKey); + ASSERT_EQ(result, SqlPersistentStore::Error::kNotFound); + + // Verify that the live entry was not affected. + EXPECT_EQ(GetEntryCount(), 1); + auto open_live_result = OpenEntry(kLiveKey); + ASSERT_TRUE(open_live_result.has_value()); + ASSERT_TRUE(open_live_result->has_value()); + + // Verify the doomed entry still exists in the table (as doomed), and the + // live entry is also present. + ClearStore(); + EXPECT_EQ(CountResourcesTable(), 2); + EXPECT_EQ(CountDoomedResourcesTable(kDoomedKey), 1); + EXPECT_EQ(CountDoomedResourcesTable(kLiveKey), 0); +} + +TEST_F(SqlPersistentStoreTest, DeleteLiveEntryWithCorruptTokenRecovers) { + CreateAndInitStore(); + const CacheEntryKey kKeyToCorrupt("key-to-corrupt-token"); + const CacheEntryKey kKeyToKeep("key-to-keep"); + const int64_t keep_key_size = kKeyToKeep.string().size(); + const int64_t expected_size_after_recovery = + kSqlBackendStaticResourceSize + keep_key_size; + + // Create one entry to keep, and one to corrupt and delete. + ASSERT_TRUE(CreateEntry(kKeyToCorrupt).has_value()); + ASSERT_TRUE(CreateEntry(kKeyToKeep).has_value()); + ASSERT_EQ(GetEntryCount(), 2); + ClearStore(); + + // Manually open the database and corrupt the token for one entry so that + // it becomes invalid. + { + auto db = ManuallyOpenDatabase(); + sql::Statement statement(db->GetUniqueStatement( + "UPDATE resources SET token_high = 0, token_low = 0 WHERE cache_key = " + "?")); + statement.BindString(0, kKeyToCorrupt.string()); + ASSERT_TRUE(statement.Run()); + } + + // Re-initialize the store with the corrupted database. + CreateAndInitStore(); + + // Delete the entry with the corrupted token. This will trigger the + // `corruption_detected` path, forcing a full recalculation. + ASSERT_EQ(DeleteLiveEntry(kKeyToCorrupt), SqlPersistentStore::Error::kOk); + + // Verify that recovery was successful. The entry count and total size + // should now reflect only the entry that was kept. + EXPECT_EQ(GetEntryCount(), 1); + EXPECT_EQ(GetSizeOfAllEntries(), expected_size_after_recovery); + + // Verify the state on disk. Only the un-corrupted entry should remain. + ClearStore(); + EXPECT_EQ(CountResourcesTable(), 1); +} + +TEST_F(SqlPersistentStoreTest, DeleteLiveEntryWithCorruptSizeRecovers) { + CreateAndInitStore(); + const CacheEntryKey kKeyToCorrupt("key-to-corrupt-size"); + const CacheEntryKey kKeyToKeep("key-to-keep"); + const int64_t keep_key_size = kKeyToKeep.string().size(); + const int64_t expected_size_after_recovery = + kSqlBackendStaticResourceSize + keep_key_size; + + // Create one entry to keep, and one to corrupt and delete. + ASSERT_TRUE(CreateEntry(kKeyToCorrupt).has_value()); + ASSERT_TRUE(CreateEntry(kKeyToKeep).has_value()); + ASSERT_EQ(GetEntryCount(), 2); + ClearStore(); + + // Manually open the database and corrupt the `bytes_usage` for one entry + // to an extreme value that will cause an underflow during calculation. + { + auto db = ManuallyOpenDatabase(); + sql::Statement statement(db->GetUniqueStatement( + "UPDATE resources SET bytes_usage = ? WHERE cache_key = ?")); + statement.BindInt64(0, std::numeric_limits<int64_t>::max()); + statement.BindString(1, kKeyToCorrupt.string()); + ASSERT_TRUE(statement.Run()); + } + + // Re-initialize the store with the corrupted database. + CreateAndInitStore(); + + // Delete the entry with the corrupted size. This will trigger an underflow + // in `total_size_delta`, causing `!total_size_delta.IsValid()` to be true. + // The store should recover by recalculating its state from the database. + ASSERT_EQ(DeleteLiveEntry(kKeyToCorrupt), SqlPersistentStore::Error::kOk); + + // Verify that recovery was successful. The entry count and total size + // should now reflect only the entry that was kept. + EXPECT_EQ(GetEntryCount(), 1); + EXPECT_EQ(GetSizeOfAllEntries(), expected_size_after_recovery); + + // Verify the state on disk. Only the un-corrupted entry should remain. + ClearStore(); + EXPECT_EQ(CountResourcesTable(), 1); +} + TEST_F(SqlPersistentStoreTest, DeleteAllEntriesNonEmpty) { CreateAndInitStore(); const CacheEntryKey kKey1("key1"); @@ -908,6 +1328,59 @@ EXPECT_FALSE(callback_run); } +TEST_F(SqlPersistentStoreTest, DoomEntryCallbackNotRunOnStoreDestruction) { + CreateAndInitStore(); + const CacheEntryKey kKey("my-key"); + auto create_result = CreateEntry(kKey); + ASSERT_TRUE(create_result.has_value()); + + bool callback_run = false; + store_->DoomEntry(kKey, create_result->token, + base::BindLambdaForTesting([&](SqlPersistentStore::Error) { + callback_run = true; + })); + store_.reset(); + FlushPendingTask(); + + EXPECT_FALSE(callback_run); +} + +TEST_F(SqlPersistentStoreTest, + DeleteDoomedEntryCallbackNotRunOnStoreDestruction) { + CreateAndInitStore(); + const CacheEntryKey kKey("my-key"); + auto create_result = CreateEntry(kKey); + ASSERT_TRUE(create_result.has_value()); + ASSERT_EQ(DoomEntry(kKey, create_result->token), + SqlPersistentStore::Error::kOk); + + bool callback_run = false; + store_->DeleteDoomedEntry( + kKey, create_result->token, + base::BindLambdaForTesting( + [&](SqlPersistentStore::Error) { callback_run = true; })); + store_.reset(); + FlushPendingTask(); + + EXPECT_FALSE(callback_run); +} + +TEST_F(SqlPersistentStoreTest, + DeleteLiveEntryCallbackNotRunOnStoreDestruction) { + CreateAndInitStore(); + const CacheEntryKey kKey("my-key"); + ASSERT_TRUE(CreateEntry(kKey).has_value()); + + bool callback_run = false; + store_->DeleteLiveEntry( + kKey, base::BindLambdaForTesting( + [&](SqlPersistentStore::Error) { callback_run = true; })); + store_.reset(); + FlushPendingTask(); + + EXPECT_FALSE(callback_run); +} + TEST_F(SqlPersistentStoreTest, DeleteAllEntriesCallbackNotRunOnStoreDestruction) { CreateAndInitStore();
diff --git a/net/http/http_stream_pool_attempt_manager.cc b/net/http/http_stream_pool_attempt_manager.cc index a1084ca..fcad1f5e 100644 --- a/net/http/http_stream_pool_attempt_manager.cc +++ b/net/http/http_stream_pool_attempt_manager.cc
@@ -1197,6 +1197,11 @@ return nullptr; } + if (pool()->RequiresHTTP11(stream_key().destination(), + stream_key().network_anonymization_key())) { + return nullptr; + } + if (HasAvailableSpdySession()) { base::WeakPtr<SpdySession> spdy_session = pool()->FindAvailableSpdySession( stream_key(), spdy_session_key(), IsIpBasedPoolingEnabled(), net_log());
diff --git a/net/http/http_stream_pool_attempt_manager_unittest.cc b/net/http/http_stream_pool_attempt_manager_unittest.cc index 0679355..c73e06ff 100644 --- a/net/http/http_stream_pool_attempt_manager_unittest.cc +++ b/net/http/http_stream_pool_attempt_manager_unittest.cc
@@ -3145,6 +3145,52 @@ ASSERT_EQ(pool().TotalActiveStreamCount(), 2u); } +// Test that an IP pooled SPDY session is not used if the destination requires +// HTTP/1.1. +TEST_F(HttpStreamPoolAttemptManagerTest, SpdyMatchingIpSessionRequiresHttp11) { + const IPEndPoint kCommonEndPoint = MakeIPEndPoint("192.0.2.1", 443); + + // Create a SPDY session for www.example.org. + StreamRequester requester_a; + requester_a.set_destination("https://www.example.org"); + CreateFakeSpdySession(requester_a.GetStreamKey(), kCommonEndPoint); + requester_a.RequestStream(pool()); + requester_a.WaitForResult(); + EXPECT_THAT(requester_a.result(), Optional(IsOk())); + EXPECT_EQ(requester_a.negotiated_protocol(), NextProto::kProtoHTTP2); + ASSERT_EQ(pool().TotalActiveStreamCount(), 1u); + + // Mark example.test as requiring HTTP/1.1. + const HttpStreamKey stream_key_b = + StreamKeyBuilder().set_destination("https://example.test").Build(); + http_server_properties()->SetHTTP11Required( + stream_key_b.destination(), stream_key_b.network_anonymization_key()); + + // Set up DNS resolution for example.test to resolve to the same IP. + resolver() + ->AddFakeRequest() + ->add_endpoint( + ServiceEndpointBuilder().add_ip_endpoint(kCommonEndPoint).endpoint()) + .CompleteStartSynchronously(OK); + + // Set up socket data for a new TCP connection for example.test. + SequencedSocketData data; + socket_factory()->AddSocketDataProvider(&data); + SSLSocketDataProvider ssl(ASYNC, OK); + ssl.next_protos_expected_in_ssl_config = {NextProto::kProtoHTTP11}; + socket_factory()->AddSSLSocketDataProvider(&ssl); + + // Request a stream for example.test. + StreamRequester requester_b(stream_key_b); + requester_b.RequestStream(pool()); + requester_b.WaitForResult(); + + // The request should succeed by creating a new HTTP/1.1 connection. + EXPECT_THAT(requester_b.result(), Optional(IsOk())); + EXPECT_NE(requester_b.negotiated_protocol(), NextProto::kProtoHTTP2); + ASSERT_EQ(pool().TotalActiveStreamCount(), 2u); +} + // Regression test for crbug.com/385296757. // If an IP matching SPDY session is created during the stream attempt delay, // use that session instead of attempting a new connection after the delay.
diff --git a/services/device/public/cpp/device_feature_map.cc b/services/device/public/cpp/device_feature_map.cc index a4f075e..d9be9e13 100644 --- a/services/device/public/cpp/device_feature_map.cc +++ b/services/device/public/cpp/device_feature_map.cc
@@ -25,7 +25,6 @@ const base::Feature* const kFeaturesExposedToJava[] = { &device::kWebAuthnAndroidUsePasskeyCache, &device::kWebAuthnPasskeyUpgrade, - &device::kWebAuthnRemoteDesktopAllowedOriginsPolicy, &kGenericSensorExtraClasses, &kBatteryStatusManagerBroadcastReceiverInBackground, &device::features::kBluetoothRfcommAndroid,
diff --git a/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java b/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java index 4d50c528..9731425 100644 --- a/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java +++ b/services/device/public/java/src/org/chromium/device/DeviceFeatureList.java
@@ -27,8 +27,6 @@ public static final String BATTERY_STATUS_MANAGER_BROADCAST_RECEIVER_IN_BACKGROUND = "BatteryStatusManagerBroadcastReceiverInBackground"; public static final String WEBAUTHN_PASSKEY_UPGRADE = "WebAuthenticationPasskeyUpgrade"; - public static final String WEBAUTHN_REMOTE_DESKTOP_ALLOWED_ORIGINS = - "WebAuthenticationRemoteDesktopAllowedOriginsPolicy"; public static final String BLUETOOTH_RFCOMM_ANDROID = "BluetoothRfcommAndroid"; public static final MutableFlagWithSafeDefault sGmsCoreLocationRequestParamOverride =
diff --git a/services/network/network_service_network_delegate.cc b/services/network/network_service_network_delegate.cc index 5f3a7934..7f39e32 100644 --- a/services/network/network_service_network_delegate.cc +++ b/services/network/network_service_network_delegate.cc
@@ -108,13 +108,6 @@ request->traffic_annotation()); } - if (!loader) - return net::OK; - - if (network_service) { - loader->SetEnableReportingRawHeaders(network_service->HasRawHeadersAccess( - loader->GetProcessId(), *effective_url)); - } return net::OK; }
diff --git a/services/network/scheduler/network_service_task_queues.cc b/services/network/scheduler/network_service_task_queues.cc index 813478e..634ebba 100644 --- a/services/network/scheduler/network_service_task_queues.cc +++ b/services/network/scheduler/network_service_task_queues.cc
@@ -4,6 +4,7 @@ #include "services/network/scheduler/network_service_task_queues.h" +#include "base/memory/raw_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/notreached.h" #include "base/rand_util.h" @@ -14,15 +15,23 @@ namespace network { // Observes task execution on a specific network service task queue and records -// queuing time metrics. +// metrics. class NetworkServiceTaskObserver : public base::TaskObserver { public: - explicit NetworkServiceTaskObserver(std::string queue_name) - : queue_name_(std::move(queue_name)) {} + explicit NetworkServiceTaskObserver( + std::string queue_name, + base::sequence_manager::TaskQueue::Handle* queue) + : queue_name_(std::move(queue_name)), queue_(queue) {} + void WillProcessTask(const base::PendingTask& pending_task, bool was_blocked_or_low_priority) override { - // Sample queuing time with a 0.001 probability to reduce metrics overhead. + // Sample with a 0.001 probability to reduce metrics overhead. if (sampler_.ShouldSample(0.001)) { + base::UmaHistogramCounts100( + base::StrCat( + {"NetworkService.Scheduler.IOThread.NumberOfPendingTasks.", + queue_name_, "Queue"}), + (*queue_)->GetNumberOfPendingTasks()); base::UmaHistogramTimes( base::StrCat({"NetworkService.Scheduler.IOThread.QueuingTime.", queue_name_, "Queue"}), @@ -33,6 +42,8 @@ private: const std::string queue_name_; + // `queue_` outlives this task observer. + raw_ptr<base::sequence_manager::TaskQueue::Handle> queue_; const base::MetricsSubSampler sampler_; }; @@ -81,7 +92,7 @@ base::sequence_manager::TaskQueue::Spec( GetTaskQueueName(static_cast<QueueType>(i)))); task_observers_[i] = std::make_unique<NetworkServiceTaskObserver>( - QueueTypeToString(static_cast<QueueType>(i))); + QueueTypeToString(static_cast<QueueType>(i)), &task_queues_[i]); task_queues_[i]->AddTaskObserver(task_observers_[i].get()); }
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index d436300..3761ae66 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -1799,10 +1799,6 @@ return factory_params_->process_id; } -void URLLoader::SetEnableReportingRawHeaders(bool allow) { - enable_reporting_raw_headers_ = allow; -} - uint32_t URLLoader::GetResourceType() const { return resource_type_; } @@ -2190,19 +2186,9 @@ return; } - // This is gated by enable_reporting_raw_headers_ to be backwards compatible - // with the old report_raw_headers behavior, where we wouldn't even send - // raw_response_headers_ to the trusted browser process based devtools - // instrumentation. This is observed in the case of HSTS redirects, where - // url_request_->response_headers has the HSTS redirect headers, like - // Non-Authoritative-Reason, but raw_response_headers_ has something else - // which doesn't include HSTS information. This is tested by - // DevToolsTest.TestRawHeadersWithRedirectAndHSTS. - // TODO(crbug.com/40781698): Remove enable_reporting_raw_headers_ const net::HttpResponseHeaders* response_headers = - raw_response_headers_ && enable_reporting_raw_headers_ - ? raw_response_headers_.get() - : url_request_->response_headers(); + raw_response_headers_ ? raw_response_headers_.get() + : url_request_->response_headers(); std::vector<network::mojom::HttpRawHeaderPairPtr> header_array = ResponseHeaderToRawHeaderPairs(*response_headers);
diff --git a/services/network/url_loader.h b/services/network/url_loader.h index 99ac2f19..9975031 100644 --- a/services/network/url_loader.h +++ b/services/network/url_loader.h
@@ -289,8 +289,6 @@ return shared_storage_request_helper_.get(); } - void SetEnableReportingRawHeaders(bool enable); - void set_partial_decoder_decoding_buffer_size_for_testing( int partial_decoder_decoding_buffer_size) { partial_decoder_decoding_buffer_size_ =
diff --git a/services/webnn/ort/context_impl_ort.cc b/services/webnn/ort/context_impl_ort.cc index 331fc0c..ef86273 100644 --- a/services/webnn/ort/context_impl_ort.cc +++ b/services/webnn/ort/context_impl_ort.cc
@@ -114,7 +114,8 @@ /*sqrt_input=*/{DataTypeConstraint::kFloat16To32, kMaxRank}, /*tan_input=*/{DataTypeConstraint::kFloat16To32, kMaxRank}, /*elu_input=*/{}, - /*expand_input=*/{}, + /*expand_input=*/ + {DataTypeConstraint::kAllDataTypesAtLeast8bits, kMaxRank}, /*gather_input=*/{}, /*gather_indices=*/{}, /*gather_elements_input=*/{}, @@ -135,7 +136,7 @@ /*instance_normalization_input=*/{}, /*instance_normalization_scale=*/{}, /*layer_normalization_input=*/{}, - /*leaky_relu_input=*/{}, + /*leaky_relu_input=*/{DataTypeConstraint::kFloat16To32, kMaxRank}, /*linear_input=*/{}, /*lstm_input=*/{}, /*lstm_bias=*/{}, @@ -149,7 +150,7 @@ {DataTypeConstraint::kFloat16To32, {3, 8}}, /*max_pool2d_input=*/ {kInts8Float16To32, {3, 8}}, - /*prelu_input=*/{}, + /*prelu_input=*/{DataTypeConstraint::kFloat16To32Ints32To64, kMaxRank}, /*quantize_linear_input=*/{}, /*quantize_linear_zero_point=*/{}, /*reduce_l1_input=*/{},
diff --git a/services/webnn/ort/graph_builder_ort.cc b/services/webnn/ort/graph_builder_ort.cc index e35ba42..80a86bd 100644 --- a/services/webnn/ort/graph_builder_ort.cc +++ b/services/webnn/ort/graph_builder_ort.cc
@@ -50,9 +50,12 @@ constexpr base::cstring_view kOpTypeClamp = "Clip"; constexpr base::cstring_view kOpTypeConv2d = "Conv"; constexpr base::cstring_view kOpTypeConvTranspose2d = "ConvTranspose"; +constexpr base::cstring_view kOpTypeExpand = "Expand"; constexpr base::cstring_view kOpTypeGelu = "Gelu"; constexpr base::cstring_view kOpTypeGemm = "Gemm"; +constexpr base::cstring_view kOpTypeLeakyRelu = "LeakyRelu"; constexpr base::cstring_view kOpTypeHardSwish = "HardSwish"; +constexpr base::cstring_view kOpTypePRelu = "PRelu"; constexpr base::cstring_view kOpTypeRelu = "Relu"; constexpr base::cstring_view kOpTypeReshape = "Reshape"; constexpr base::cstring_view kOpTypeSigmoid = "Sigmoid"; @@ -231,6 +234,39 @@ /*shape=*/{}, base::span_from_ref(value)); } +std::string GraphBuilderOrt::CreateInitializerForShape( + base::span<const uint32_t> shape) { + std::array<int64_t, 1> new_shape_dims = { + base::checked_cast<int64_t>(shape.size())}; + std::vector<int64_t> new_shape_value(shape.begin(), shape.end()); + return CreateInitializer<int64_t>(new_shape_dims, new_shape_value); +} + +void GraphBuilderOrt::AddExpandNode(base::cstring_view node_name, + base::cstring_view input, + base::cstring_view output, + base::span<const uint32_t> shape) { + // `new_shape` should be the name of an int64 tensor that specifies the + // output's shape. + const std::string new_shape = CreateInitializerForShape(shape); + + std::array<const char*, 2> inputs = {input.c_str(), new_shape.c_str()}; + std::array<const char*, 1> outputs = {output.c_str()}; + + model_editor_.AddNode(kOpTypeExpand, node_name, inputs, outputs); +} + +std::string GraphBuilderOrt::CreateExpandNode( + base::cstring_view input, + base::span<const uint32_t> shape) { + const std::string node_name = GenerateNodeName( + base::JoinString({kInserted, kOpTypeExpand}, kUnderscore)); + const std::string output = GenerateOperandName(); + + AddExpandNode(node_name, input, output, shape); + return output; +} + template <typename T> void GraphBuilderOrt::AddBinaryOperation(const T& operation, base::cstring_view op_type) { @@ -585,6 +621,20 @@ model_editor_.AddNode(kOpTypeClamp, node_name, inputs, outputs); } +void GraphBuilderOrt::AddExpandOperation(const mojom::Expand& expand) { + const std::string node_name = GenerateNodeName(expand.label); + const std::string input = GetOperandNameById(expand.input_operand_id); + const std::string output = GetOperandNameById(expand.output_operand_id); + + CHECK(context_properties_.data_type_limits.expand_input.Supports( + GetOperand(expand.input_operand_id).descriptor)); + + const std::vector<uint32_t>& output_shape = + GetOperand(expand.output_operand_id).descriptor.shape(); + + AddExpandNode(node_name, input, output, output_shape); +} + void GraphBuilderOrt::AddGemmOperation(const mojom::Gemm& gemm) { const std::string node_name = GenerateNodeName(gemm.label); const std::string input_a = GetOperandNameById(gemm.a_operand_id); @@ -628,6 +678,25 @@ model_editor_.AddNode(kOpTypeGemm, node_name, inputs, outputs, attributes); } +void GraphBuilderOrt::AddLeakyReluOperation( + const mojom::LeakyRelu& leaky_relu) { + const std::string node_name = GenerateNodeName(leaky_relu.label); + const std::string input = GetOperandNameById(leaky_relu.input_operand_id); + const std::string output = GetOperandNameById(leaky_relu.output_operand_id); + + CHECK(context_properties_.data_type_limits.leaky_relu_input.Supports( + GetOperand(leaky_relu.input_operand_id).descriptor)); + + std::array<const char*, 1> inputs = {input.c_str()}; + std::array<const char*, 1> outputs = {output.c_str()}; + + constexpr base::cstring_view kAttrAlpha = "alpha"; + std::array<ScopedOrtOpAttr, 1> attributes = { + model_editor_.CreateAttribute(kAttrAlpha, leaky_relu.alpha)}; + model_editor_.AddNode(kOpTypeLeakyRelu, node_name, inputs, outputs, + attributes); +} + void GraphBuilderOrt::AddPool2dOperation(const mojom::Pool2d& pool2d) { std::vector<ScopedOrtOpAttr> attributes; constexpr base::cstring_view kAttrDilations = "dilations"; @@ -721,15 +790,11 @@ CHECK(context_properties_.data_type_limits.reshape_input.Supports( GetOperand(reshape.input_operand_id).descriptor)); - // `new_shape` should be an int64 tensor that specifies the output's shape. const std::vector<uint32_t>& output_shape = GetOperand(reshape.output_operand_id).descriptor.shape(); - std::array<int64_t, 1> new_shape_dims = { - base::checked_cast<int64_t>(output_shape.size())}; - std::vector<int64_t> new_shape_value(output_shape.begin(), - output_shape.end()); - const std::string new_shape = - CreateInitializer<int64_t>(new_shape_dims, new_shape_value); + // `new_shape` should be the name of an int64 tensor that specifies the + // output's shape. + const std::string new_shape = CreateInitializerForShape(output_shape); std::array<const char*, 2> inputs = {input.c_str(), new_shape.c_str()}; std::array<const char*, 1> outputs = {output.c_str()}; @@ -755,6 +820,34 @@ model_editor_.AddNode(kOpTypeSoftmax, node_name, inputs, outputs, attributes); } +void GraphBuilderOrt::AddPreluOperation(const mojom::Prelu& prelu) { + const std::string node_name = GenerateNodeName(prelu.label); + std::string input = GetOperandNameById(prelu.input_operand_id); + const std::string slope = GetOperandNameById(prelu.slope_operand_id); + const std::string output = GetOperandNameById(prelu.output_operand_id); + + const DataTypeLimits& data_type_limits = context_properties_.data_type_limits; + const OperandDescriptor& input_descriptor = + GetOperand(prelu.input_operand_id).descriptor; + CHECK(data_type_limits.prelu_input.Supports(input_descriptor)); + const OperandDescriptor& slope_descriptor = + GetOperand(prelu.slope_operand_id).descriptor; + CHECK(data_type_limits.prelu_input.Supports(slope_descriptor)); + + const std::vector<uint32_t>& input_shape = input_descriptor.shape(); + const std::vector<uint32_t>& slope_shape = slope_descriptor.shape(); + // ONNX Prelu requires slope's shape to be unidirectionally broadcastable to + // input when the shape of slope is smaller than the input. While WebNN allows + // input and slope to be bidirectionally broadcastable. + if (!BroadcastShapes(slope_shape, input_shape, /*bidirectional=*/false)) { + input = CreateExpandNode(input, slope_shape); + } + std::array<const char*, 2> inputs = {input.c_str(), slope.c_str()}; + std::array<const char*, 1> outputs = {output.c_str()}; + + model_editor_.AddNode(kOpTypePRelu, node_name, inputs, outputs); +} + void GraphBuilderOrt::AddTransposeOperation(const mojom::Transpose& transpose) { const std::string node_name = GenerateNodeName(transpose.label); const std::string input = GetOperandNameById(transpose.input_operand_id); @@ -809,6 +902,10 @@ AddElementWiseUnaryOperation(*operation->get_element_wise_unary()); break; } + case mojom::Operation::Tag::kExpand: { + AddExpandOperation(*operation->get_expand()); + break; + } case mojom::Operation::Tag::kGelu: { CHECK(data_type_limits.gelu_input.Supports( GetOperand(operation->get_gelu()->input_operand_id).descriptor)); @@ -830,6 +927,14 @@ AddPool2dOperation(*operation->get_pool2d()); break; } + case mojom::Operation::Tag::kLeakyRelu: { + AddLeakyReluOperation(*operation->get_leaky_relu()); + break; + } + case mojom::Operation::Tag::kPrelu: { + AddPreluOperation(*operation->get_prelu()); + break; + } case mojom::Operation::Tag::kRelu: { CHECK(data_type_limits.relu_input.Supports( GetOperand(operation->get_relu()->input_operand_id).descriptor)); @@ -873,7 +978,6 @@ case mojom::Operation::Tag::kCumulativeSum: case mojom::Operation::Tag::kDequantizeLinear: case mojom::Operation::Tag::kElu: - case mojom::Operation::Tag::kExpand: case mojom::Operation::Tag::kGather: case mojom::Operation::Tag::kGatherElements: case mojom::Operation::Tag::kGatherNd: @@ -886,9 +990,7 @@ case mojom::Operation::Tag::kLstm: case mojom::Operation::Tag::kLstmCell: case mojom::Operation::Tag::kMatmul: - case mojom::Operation::Tag::kLeakyRelu: case mojom::Operation::Tag::kPad: - case mojom::Operation::Tag::kPrelu: case mojom::Operation::Tag::kQuantizeLinear: case mojom::Operation::Tag::kReduce: case mojom::Operation::Tag::kResample2d:
diff --git a/services/webnn/ort/graph_builder_ort.h b/services/webnn/ort/graph_builder_ort.h index 5963693b..dc7e69fc 100644 --- a/services/webnn/ort/graph_builder_ort.h +++ b/services/webnn/ort/graph_builder_ort.h
@@ -107,6 +107,18 @@ requires internal::IsSupportedTensorType<DataType> std::string CreateScalarInitializer(const DataType& value); + // A helper method creating an int64 tensor with the given shape value. + // It can be used by `reshape` and `expand` to create an initializer that + // specifies the output's shape. + std::string CreateInitializerForShape(base::span<const uint32_t> shape); + + void AddExpandNode(base::cstring_view node_name, + base::cstring_view input, + base::cstring_view output, + base::span<const uint32_t> shape); + + std::string CreateExpandNode(base::cstring_view input, + base::span<const uint32_t> shape); template <typename T> void AddBinaryOperation(const T& operation, base::cstring_view op_type); template <typename T> @@ -120,8 +132,11 @@ const mojom::ElementWiseBinary& element_wise_binary); void AddElementWiseUnaryOperation( const mojom::ElementWiseUnary& element_wise_unary); + void AddExpandOperation(const mojom::Expand& expand); void AddGemmOperation(const mojom::Gemm& gemm); + void AddLeakyReluOperation(const mojom::LeakyRelu& leaky_relu); void AddPool2dOperation(const mojom::Pool2d& pool2d); + void AddPreluOperation(const mojom::Prelu& prelu); void AddReshapeOperation(const mojom::Reshape& reshape); void AddSoftmaxOperation(const mojom::Softmax& softmax); void AddTransposeOperation(const mojom::Transpose& transpose);
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index d5b3b56..dfe1d49 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -25178,6 +25178,21 @@ ] } ], + "UpdateStateBeforeUnbinding": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "UpdateStateBeforeUnbinding" + ] + } + ] + } + ], "UploadOfficeToCloud": [ { "platforms": [
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle index 59b9429..ed1cedbe 100644 --- a/third_party/androidx/build.gradle +++ b/third_party/androidx/build.gradle
@@ -307,7 +307,7 @@ google() maven { // This URL is generated by the fetch_all_androidx.py script. - url 'https://androidx.dev/snapshots/builds/13678680/artifacts/repository' + url 'https://androidx.dev/snapshots/builds/13679868/artifacts/repository' } mavenCentral() }
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index b51577c3..7c35b011 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -2675,6 +2675,10 @@ "WebRtcAudioSinkUseTimestampAligner", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kWebRtcPqcForDtls, + "WebRtcPqcForDtls", + base::FEATURE_DISABLED_BY_DEFAULT); + // Enable borderless mode for desktop PWAs. go/borderless-mode BASE_FEATURE(kWebAppBorderless, "WebAppBorderless",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index bfd82a5c..6d291f0a 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -1788,6 +1788,10 @@ // capture timestamps. This is disabled by default. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebRtcAudioSinkUseTimestampAligner); +// This feature enables using Post-Quantum Crypto(PQC) for DTLS to improve +// WebRTC's security. +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebRtcPqcForDtls); + BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebAppBorderless); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebAppEnableScopeExtensions); BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kWebAppEnableScopeExtensionsBySite);
diff --git a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc index 173bd8b6..909bd56 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc +++ b/third_party/blink/renderer/bindings/core/v8/js_based_event_listener.cc
@@ -56,8 +56,8 @@ Event* event) { DCHECK(execution_context_of_event_target); DCHECK(event); - DCHECK(event->target()); - DCHECK(event->currentTarget()); + DCHECK(event->RawTarget()); + DCHECK(event->RawCurrentTarget()); v8::Isolate* isolate = GetIsolate(); @@ -79,7 +79,8 @@ // difference but the advantage that we can use listener's |ScriptState| // after it get compiled. // https://html.spec.whatwg.org/C/#event-handler-value - v8::Local<v8::Value> listener = GetListenerObject(*event->currentTarget()); + v8::Local<v8::Value> listener = + GetListenerObject(*event->RawCurrentTarget()); if (listener.IsEmpty() || !listener->IsObject()) return; @@ -142,7 +143,7 @@ // Step 8-2: If |struct|’s invocation-target-in-shadow-tree is false (i.e., // event's target is in a shadow tree), then set |global|’s current // event to event. - Node* target_node = event->target()->ToNode(); + Node* target_node = event->RawTarget()->ToNode(); if (!(target_node && target_node->IsInShadowTree())) window->SetCurrentEvent(event); } @@ -155,7 +156,7 @@ // Step 10: Call a listener with event's currentTarget as receiver and event // and handle errors if thrown. - InvokeInternal(*event->currentTarget(), *event, js_event); + InvokeInternal(*event->RawCurrentTarget(), *event, js_event); if (try_catch.HasCaught()) { // Step 10-2: Set legacyOutputDidListenersThrowFlag if given.
diff --git a/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc b/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc index 5f73c85..56204a3 100644 --- a/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc +++ b/third_party/blink/renderer/bindings/core/v8/js_event_handler.cc
@@ -61,7 +61,7 @@ // event handler given eventTarget and name. // Step 2. If callback is null, then return. v8::Local<v8::Value> listener_value = - GetListenerObject(*event.currentTarget()); + GetListenerObject(*event.RawCurrentTarget()); if (listener_value.IsEmpty() || listener_value->IsNull()) return; DCHECK(HasCompiledHandler()); @@ -72,7 +72,7 @@ // handling be false. const bool special_error_event_handling = IsA<ErrorEvent>(event) && event.type() == event_type_names::kError && - event.currentTarget()->IsWindowOrWorkerGlobalScope(); + event.RawCurrentTarget()->IsWindowOrWorkerGlobalScope(); // Step 4. Process the Event object event as follows: // If special error event handling is true @@ -102,7 +102,8 @@ // https://html.spec.whatwg.org/C/#runtime-script-errors-2 ScriptValue error_attribute = error_event->error(script_state_of_listener); if (error_attribute.IsEmpty() || - error_event->target()->InterfaceName() == event_target_names::kWorker) { + error_event->RawTarget()->InterfaceName() == + event_target_names::kWorker) { error_attribute = ScriptValue::CreateNull(isolate); } arguments = { @@ -131,10 +132,11 @@ } ScriptValue result; if (!event_handler_ - ->InvokeWithoutRunnabilityCheck(event.currentTarget(), arguments) + ->InvokeWithoutRunnabilityCheck(event.RawCurrentTarget(), arguments) .To(&result) || - isolate->IsExecutionTerminating()) + isolate->IsExecutionTerminating()) { return; + } v8::Local<v8::Value> v8_return_value = result.V8Value(); // There is nothing to do if |v8_return_value| is null or undefined.
diff --git a/third_party/blink/renderer/core/css/css_to_length_conversion_data.h b/third_party/blink/renderer/core/css/css_to_length_conversion_data.h index d58a07f..e6159b2 100644 --- a/third_party/blink/renderer/core/css/css_to_length_conversion_data.h +++ b/third_party/blink/renderer/core/css/css_to_length_conversion_data.h
@@ -190,6 +190,14 @@ double DynamicWidth() const { return dynamic_width_; } double DynamicHeight() const { return dynamic_height_; } + String ToString() const { + return String::Format( + "large_width: %f, large_height: %f, small_width: %f, small_height: " + "%f, dynamic_width: %f, dynamic_height: %f", + large_width_, large_height_, small_width_, small_height_, + dynamic_width_, dynamic_height_); + } + private: // v*, lv* double large_width_ = 0;
diff --git a/third_party/blink/renderer/core/css/element_rule_collector.cc b/third_party/blink/renderer/core/css/element_rule_collector.cc index 7b85268..ca215b4b 100644 --- a/third_party/blink/renderer/core/css/element_rule_collector.cc +++ b/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -643,13 +643,23 @@ if (!match) { continue; } - // If matching was for pseudo-element with ancestors vector, - // check that we really reached the end of it. - // E.g. for div::column::scroll-marker, matching for column pseudo, - // vector would be just [column], index would be 1 (meaning matching - // found pseudo style ::scroll-marker), and for rule div::column, index - // would be 0 (meaning matching found actual style). - // Anything else would mean no match. + + // If matching was for a pseudo-element with a vector of ancestors, + // check that we really reached the end of it. E.g., when matching + // the selector div::column::scroll-marker against a ::column + // pseudo-element, the vector would be just {::column}, and the + // index would be 1 (meaning that the matcher found the ::column, + // but also went further and found the pseudo-element selector + // ::scroll-marker; this is fine, as we'd get dynamic_pseudo). + // + // Likewise, for the selector div::column, the index would be 0 + // (meaning that the entire selector matched, and nothing more), + // which is also a match. + // + // But for the opposite, namely the selector div::column against + // the pseudo-element ::column::scroll-marker (with the vector + // {::column, ::scroll-marker}), we'd get index 0, which isn't + // a match. if (context.pseudo_element && (result.pseudo_ancestor_index == kNotFound || result.pseudo_ancestor_index <
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h index 41badb7..990dc869 100644 --- a/third_party/blink/renderer/core/css/style_engine.h +++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -781,8 +781,8 @@ // See comment on viewport_size_. void UpdateViewportSize(); const CSSToLengthConversionData::ViewportSize& GetViewportSize() const { - DCHECK(viewport_size_ == CSSToLengthConversionData::ViewportSize( - GetDocument().GetLayoutView())); + DCHECK_EQ(viewport_size_, CSSToLengthConversionData::ViewportSize( + GetDocument().GetLayoutView())); return viewport_size_; }
diff --git a/third_party/blink/renderer/core/dom/create_element_flags.h b/third_party/blink/renderer/core/dom/create_element_flags.h index e430c75..c4b6ab08 100644 --- a/third_party/blink/renderer/core/dom/create_element_flags.h +++ b/third_party/blink/renderer/core/dom/create_element_flags.h
@@ -34,11 +34,6 @@ // https://dom.spec.whatwg.org/#dom-document-createelement static CreateElementFlags ByCreateElement() { return CreateElementFlags(); } - // https://wicg.github.io/webcomponents/proposals/Scoped-Custom-Element-Registries - static CreateElementFlags ByShadowRootCreateElement() { - return CreateElementFlags().SetAsyncCustomElements(); - } - // https://html.spec.whatwg.org/C/#create-an-element-for-the-token static CreateElementFlags ByFragmentParser(Document* document) { return CreateElementFlags()
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 59dbd9c..8d34bb4b 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -1272,39 +1272,34 @@ } // https://dom.spec.whatwg.org/#dom-document-createelement -// TODO(crbug.com/1304439): Move it to `tree_scope.cc` if the feature -// `ScopedCustomElementRegistry` can stabilize. -Element* TreeScope::CreateElementForBinding(const AtomicString& name, - ExceptionState& exception_state) { - Document& document = GetDocument(); - if (!IsValidElementName(&document, name)) { +Element* Document::CreateElementForBinding(const AtomicString& name, + ExceptionState& exception_state) { + if (!IsValidElementName(this, name)) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidCharacterError, StrCat({"The tag name provided ('", name, "') is not a valid name."})); return nullptr; } - if (document.IsXHTMLDocument() || IsA<HTMLDocument>(document)) { + if (IsXHTMLDocument() || IsA<HTMLDocument>(this)) { // 2. If the context object is an HTML document, let localName be // converted to ASCII lowercase. - AtomicString local_name = document.ConvertLocalName(name); + AtomicString local_name = ConvertLocalName(name); if (CustomElement::ShouldCreateCustomElement(local_name)) { return CustomElement::CreateCustomElement( *this, QualifiedName(g_null_atom, local_name, html_names::xhtmlNamespaceURI), - IsA<ShadowRoot>(this) - ? CreateElementFlags::ByShadowRootCreateElement() - : CreateElementFlags::ByCreateElement()); + CreateElementFlags::ByCreateElement()); } if (auto* element = HTMLElementFactory::Create( - local_name, document, CreateElementFlags::ByCreateElement())) { + local_name, *this, CreateElementFlags::ByCreateElement())) { return element; } QualifiedName q_name(g_null_atom, local_name, html_names::xhtmlNamespaceURI); - return MakeGarbageCollected<HTMLUnknownElement>(q_name, document); + return MakeGarbageCollected<HTMLUnknownElement>(q_name, *this); } - return MakeGarbageCollected<Element>(QualifiedName(name), &document); + return MakeGarbageCollected<Element>(QualifiedName(name), this); } AtomicString GetTypeExtension( @@ -1330,9 +1325,7 @@ } // https://dom.spec.whatwg.org/#dom-document-createelement -// TODO(crbug.com/1304439): Move it to `tree_scope.cc` if the feature -// `ScopedCustomElementRegistry` can stabilize. -Element* TreeScope::CreateElementForBinding( +Element* Document::CreateElementForBinding( const AtomicString& local_name, const V8UnionElementCreationOptionsOrString* string_or_options, ExceptionState& exception_state) { @@ -1340,10 +1333,8 @@ return CreateElementForBinding(local_name, exception_state); } - Document& document = GetDocument(); - // 1. If localName does not match Name production, throw InvalidCharacterError - if (!IsValidElementName(&document, local_name)) { + if (!IsValidElementName(this, local_name)) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidCharacterError, StrCat({"The tag name provided ('", local_name, @@ -1352,15 +1343,14 @@ } // 2. localName converted to ASCII lowercase - const AtomicString& converted_local_name = - document.ConvertLocalName(local_name); + const AtomicString& converted_local_name = ConvertLocalName(local_name); QualifiedName q_name(g_null_atom, converted_local_name, - document.IsXHTMLDocument() || IsA<HTMLDocument>(document) + IsXHTMLDocument() || IsA<HTMLDocument>(this) ? html_names::xhtmlNamespaceURI : g_null_atom); // 3. - const AtomicString& is = GetTypeExtension(&document, string_or_options); + const AtomicString& is = GetTypeExtension(this, string_or_options); // 5. Let element be the result of creating an element given ... Element* element = @@ -1393,11 +1383,9 @@ return q_name; } -// TODO(crbug.com/1304439): Move it to `tree_scope.cc` if the feature -// `ScopedCustomElementRegistry` can stabilize. -Element* TreeScope::createElementNS(const AtomicString& namespace_uri, - const AtomicString& qualified_name, - ExceptionState& exception_state) { +Element* Document::createElementNS(const AtomicString& namespace_uri, + const AtomicString& qualified_name, + ExceptionState& exception_state) { QualifiedName q_name( CreateQualifiedName(namespace_uri, qualified_name, exception_state, Document::QualifiedNameParsingMode::kParsingElement)); @@ -1406,18 +1394,13 @@ CreateElementFlags flags = CreateElementFlags::ByCreateElement(); if (CustomElement::ShouldCreateCustomElement(q_name)) { - return CustomElement::CreateCustomElement( - *this, q_name, - IsA<ShadowRoot>(this) ? CreateElementFlags::ByShadowRootCreateElement() - : CreateElementFlags::ByCreateElement()); + return CustomElement::CreateCustomElement(*this, q_name, flags); } - return GetDocument().CreateRawElement(q_name, flags); + return CreateRawElement(q_name, flags); } // https://dom.spec.whatwg.org/#internal-createelementns-steps -// TODO(crbug.com/1304439): Move it to `tree_scope.cc` if the feature -// `ScopedCustomElementRegistry` can stabilize. -Element* TreeScope::createElementNS( +Element* Document::createElementNS( const AtomicString& namespace_uri, const AtomicString& qualified_name, const V8UnionElementCreationOptionsOrString* string_or_options, @@ -1431,12 +1414,10 @@ if (q_name == QualifiedName::Null()) return nullptr; - Document& document = GetDocument(); - // 2. - const AtomicString& is = GetTypeExtension(&document, string_or_options); + const AtomicString& is = GetTypeExtension(this, string_or_options); - if (!IsValidElementName(&document, qualified_name)) { + if (!IsValidElementName(this, qualified_name)) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidCharacterError, StrCat({"The tag name provided ('", qualified_name, @@ -1453,11 +1434,9 @@ // Entry point of "create an element". // https://dom.spec.whatwg.org/#concept-create-element -// TODO(crbug.com/1304439): Move it to `tree_scope.cc` if the feature -// `ScopedCustomElementRegistry` can stabilize. -Element* TreeScope::CreateElement(const QualifiedName& q_name, - const CreateElementFlags flags, - const AtomicString& is) { +Element* Document::CreateElement(const QualifiedName& q_name, + const CreateElementFlags flags, + const AtomicString& is) { CustomElementDefinition* definition = nullptr; if (flags.IsCustomElements() && q_name.NamespaceURI() == html_names::xhtmlNamespaceURI) { @@ -1468,10 +1447,10 @@ } if (definition) - return definition->CreateElement(GetDocument(), q_name, flags); + return definition->CreateElement(*this, q_name, flags); - return CustomElement::CreateUncustomizedOrUndefinedElement(GetDocument(), - q_name, flags, is); + return CustomElement::CreateUncustomizedOrUndefinedElement(*this, q_name, + flags, is); } DocumentFragment* Document::createDocumentFragment() {
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 8693ebe..9e55499 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -263,6 +263,7 @@ class TrustedHTML; class V8DocumentReadyState; class V8NodeFilter; +class V8UnionElementCreationOptionsOrString; class V8UnionStringOrTrustedHTML; class ViewportData; class VisitedLinkState; @@ -489,6 +490,28 @@ CustomElementRegistry*, ExceptionState&); + Element* CreateElementForBinding(const AtomicString& local_name, + ExceptionState& = ASSERT_NO_EXCEPTION); + Element* CreateElementForBinding( + const AtomicString& local_name, + const V8UnionElementCreationOptionsOrString* string_or_options, + ExceptionState& exception_state); + + // "create an element" defined in DOM standard. This supports both of + // autonomous custom elements and customized built-in elements. + Element* CreateElement(const QualifiedName&, + const CreateElementFlags, + const AtomicString& is); + + Element* createElementNS(const AtomicString& namespace_uri, + const AtomicString& qualified_name, + ExceptionState&); + Element* createElementNS( + const AtomicString& namespace_uri, + const AtomicString& qualified_name, + const V8UnionElementCreationOptionsOrString* string_or_options, + ExceptionState& exception_state); + CustomElementRegistry* customElementRegistry() const override; // Creates an element without custom element processing.
diff --git a/third_party/blink/renderer/core/dom/events/event.cc b/third_party/blink/renderer/core/dom/events/event.cc index 061f421..68c8bab0 100644 --- a/third_party/blink/renderer/core/dom/events/event.cc +++ b/third_party/blink/renderer/core/dom/events/event.cc
@@ -26,6 +26,9 @@ #include "third_party/blink/renderer/core/dom/events/event_path.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/dom/events/window_event_context.h" +#include "third_party/blink/renderer/core/dom/scroll_button_pseudo_element.h" +#include "third_party/blink/renderer/core/dom/scroll_marker_group_pseudo_element.h" +#include "third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.h" #include "third_party/blink/renderer/core/dom/static_node_list.h" #include "third_party/blink/renderer/core/event_interface_names.h" #include "third_party/blink/renderer/core/events/focus_event.h" @@ -45,6 +48,33 @@ namespace blink { +namespace { + +// Retargets any pseudo element target to some element target. +EventTarget* RetargetPseudoElement(EventTarget* target) { + if (!target) { + return nullptr; + } + Node* node = target->ToNode(); + if (!node || !node->IsPseudoElement()) { + return target; + } + // For ::scroll-marker, the target should be the ultimate originating element + // of its ::scroll-marker-group. + if (auto* scroll_marker = DynamicTo<ScrollMarkerPseudoElement>(node)) { + CHECK(scroll_marker->ScrollMarkerGroup()); + return &scroll_marker->ScrollMarkerGroup()->UltimateOriginatingElement(); + } + // For ::scroll-button(), the target should be the ultimate originating + // element of its ::scroll-marker-group. + if (auto* scroll_button = DynamicTo<ScrollButtonPseudoElement>(node)) { + return &scroll_button->UltimateOriginatingElement(); + } + NOTREACHED() << "target can't be a pseudo element! found " << node; +} + +} // namespace + Event::Event() : Event(g_empty_atom, Bubbles::kNo, Cancelable::kNo) { was_initialized_ = false; } @@ -252,6 +282,10 @@ prevent_default_called_on_uncancelable_event_ = true; } +EventTarget* Event::target() const { + return RetargetPseudoElement(target_.Get()); +} + void Event::SetTarget(EventTarget* target) { if (target_ == target) return; @@ -275,9 +309,12 @@ Element* Event::Retarget(const Element* element) const { CHECK(RuntimeEnabledFeatures::ImprovedSourceRetargetingEnabled()); - EventTarget* retarget_against = currentTarget() ? currentTarget() : target(); - if (element && retarget_against && retarget_against->ToNode()) { - return &retarget_against->ToNode()->GetTreeScope().Retarget(*element); + EventTarget* raw_current_target = RawCurrentTarget(); + if (!raw_current_target) { + raw_current_target = RawTarget(); + } + if (element && raw_current_target && raw_current_target->ToNode()) { + return &raw_current_target->ToNode()->GetTreeScope().Retarget(*element); } return nullptr; } @@ -353,12 +390,18 @@ } EventTarget* Event::currentTarget() const { - if (!current_target_) + return RetargetPseudoElement(RawCurrentTarget()); +} + +EventTarget* Event::RawCurrentTarget() const { + if (!current_target_) { return nullptr; + } if (auto* curr_svg_element = DynamicTo<SVGElement>(current_target_->ToNode())) { - if (SVGElement* svg_element = curr_svg_element->CorrespondingElement()) + if (SVGElement* svg_element = curr_svg_element->CorrespondingElement()) { return svg_element; + } } return current_target_.Get(); }
diff --git a/third_party/blink/renderer/core/dom/events/event.h b/third_party/blink/renderer/core/dom/events/event.h index d3d71c7..d14e46c 100644 --- a/third_party/blink/renderer/core/dom/events/event.h +++ b/third_party/blink/renderer/core/dom/events/event.h
@@ -143,10 +143,18 @@ const AtomicString& type() const { return type_; } void SetType(const AtomicString& type) { type_ = type; } - EventTarget* target() const { return target_.Get(); } + // Retargeted target for IDL call: the return object can never be a pseudo + // element. + EventTarget* target() const; + // Raw target for internal usage, can be a pseudo element. + EventTarget* RawTarget() const { return target_.Get(); } void SetTarget(EventTarget*); + // Retargeted target for IDL call: the return object can never be a pseudo + // element. EventTarget* currentTarget() const; + // Raw target for internal usage, can be a pseudo element. + EventTarget* RawCurrentTarget() const; void SetCurrentTarget(EventTarget* current_target) { current_target_ = current_target; }
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index bfa53302..6a211d6 100644 --- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -200,7 +200,7 @@ } if (frame && window) { - eventTiming = EventTiming::TryCreate(window, *event_, event_->target()); + eventTiming = EventTiming::TryCreate(window, *event_, event_->RawTarget()); } if (event_->type() == event_type_names::kChange && event_->isTrusted() && @@ -258,7 +258,7 @@ #if DCHECK_IS_ON() DCHECK(!EventDispatchForbiddenScope::IsEventDispatchForbidden()); #endif - DCHECK(event_->target()); + DCHECK(event_->RawTarget()); DEVTOOLS_TIMELINE_TRACE_EVENT("EventDispatch", inspector_event_dispatch_event::Data, *event_, document.GetAgent().isolate()); @@ -373,7 +373,7 @@ // Fire an accessibility event indicating a node was clicked on. This is // safe if event_->target()->ToNode() returns null. if (AXObjectCache* cache = node_->GetDocument().ExistingAXObjectCache()) - cache->HandleClicked(event_->target()->ToNode()); + cache->HandleClicked(event_->RawTarget()->ToNode()); // Pass the data from the PreDispatchEventHandler to the // PostDispatchEventHandler. @@ -448,8 +448,9 @@ // 16. If target's root is a shadow root, then set event's target attribute // and event's relatedTarget to null. event_->SetTarget(event_->GetEventPath().GetWindowEventContext().Target()); - if (!event_->target()) + if (!event_->RawTarget()) { event_->SetRelatedTargetIfExists(nullptr); + } } } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/events/event_queue.cc b/third_party/blink/renderer/core/dom/events/event_queue.cc index 63a2f8dd..7168b19 100644 --- a/third_party/blink/renderer/core/dom/events/event_queue.cc +++ b/third_party/blink/renderer/core/dom/events/event_queue.cc
@@ -54,7 +54,7 @@ if (is_closed_) return false; - DCHECK(event.target()); + DCHECK(event.RawTarget()); DCHECK(GetExecutionContext()); event.async_task_context()->Schedule(GetExecutionContext(), event.type()); @@ -98,7 +98,7 @@ probe::AsyncTask async_task(GetExecutionContext(), event->async_task_context()); - EventTarget* target = event->target(); + EventTarget* target = event->RawTarget(); if (LocalDOMWindow* window = target->ToLocalDOMWindow()) window->DispatchEvent(*event, nullptr); else
diff --git a/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc b/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc index 1f32123..0311082 100644 --- a/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc +++ b/third_party/blink/renderer/core/dom/events/scoped_event_queue.cc
@@ -73,8 +73,8 @@ } void ScopedEventQueue::DispatchEvent(Event& event) const { - DCHECK(event.target()); - Node* node = event.target()->ToNode(); + DCHECK(event.RawTarget()); + Node* node = event.RawTarget()->ToNode(); EventDispatcher::DispatchEvent(*node, event); }
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index ee3c2c58..13081aa 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -3259,8 +3259,9 @@ } void Node::DefaultEventHandler(Event& event) { - if (event.target() != this) + if (event.RawTarget() != this) { return; + } const AtomicString& event_type = event.type(); if (event_type == event_type_names::kKeydown || event_type == event_type_names::kKeypress ||
diff --git a/third_party/blink/renderer/core/dom/scripted_animation_controller.cc b/third_party/blink/renderer/core/dom/scripted_animation_controller.cc index 485cf2f..6d5436a0 100644 --- a/third_party/blink/renderer/core/dom/scripted_animation_controller.cc +++ b/third_party/blink/renderer/core/dom/scripted_animation_controller.cc
@@ -45,14 +45,14 @@ bool ScriptedAnimationController::InsertToPerFrameEventsMap( const Event* event) { HashSet<const StringImpl*>& set = - per_frame_events_.insert(event->target(), HashSet<const StringImpl*>()) + per_frame_events_.insert(event->RawTarget(), HashSet<const StringImpl*>()) .stored_value->value; return set.insert(event->type().Impl()).is_new_entry; } void ScriptedAnimationController::EraseFromPerFrameEventsMap( const Event* event) { - EventTarget* target = event->target(); + EventTarget* target = event->RawTarget(); PerFrameEventsMap::iterator it = per_frame_events_.find(target); if (it != per_frame_events_.end()) { HashSet<const StringImpl*>& set = it->value; @@ -146,7 +146,7 @@ for (const auto& event : events) { did_dispatch = true; - EventTarget* event_target = event->target(); + EventTarget* event_target = event->RawTarget(); // FIXME: we should figure out how to make dispatchEvent properly virtual to // avoid special casting window. // FIXME: We should not fire events for nodes that are no longer in the @@ -211,8 +211,8 @@ } void ScriptedAnimationController::EnqueueEvent(Event* event) { - event->async_task_context()->Schedule(event->target()->GetExecutionContext(), - event->type()); + event->async_task_context()->Schedule( + event->RawTarget()->GetExecutionContext(), event->type()); event_queue_.push_back(event); ScheduleAnimationIfNeeded(); }
diff --git a/third_party/blink/renderer/core/dom/scroll_button_pseudo_element.cc b/third_party/blink/renderer/core/dom/scroll_button_pseudo_element.cc index e5edefb..31f077b 100644 --- a/third_party/blink/renderer/core/dom/scroll_button_pseudo_element.cc +++ b/third_party/blink/renderer/core/dom/scroll_button_pseudo_element.cc
@@ -127,7 +127,7 @@ is_key_down && (To<KeyboardEvent>(event).keyCode() == VKEY_RETURN || To<KeyboardEvent>(event).keyCode() == VKEY_SPACE); bool should_intercept = - event.target() == this && (is_click || is_enter_or_space); + event.RawTarget() == this && (is_click || is_enter_or_space); if (should_intercept) { HandleButtonActivation(); event.SetDefaultHandled();
diff --git a/third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.cc b/third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.cc index e614264..439f687 100644 --- a/third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.cc +++ b/third_party/blink/renderer/core/dom/scroll_marker_pseudo_element.cc
@@ -67,7 +67,7 @@ is_key_down && (To<KeyboardEvent>(event).keyCode() == VKEY_RIGHT || To<KeyboardEvent>(event).keyCode() == VKEY_DOWN); bool should_intercept = - event.target() == this && + event.RawTarget() == this && (is_click || is_enter_or_space || is_left_or_up_arrow_key || is_right_or_down_arrow_key); if (should_intercept) {
diff --git a/third_party/blink/renderer/core/dom/shadow_root.idl b/third_party/blink/renderer/core/dom/shadow_root.idl index 79492da..b1d827d 100644 --- a/third_party/blink/renderer/core/dom/shadow_root.idl +++ b/third_party/blink/renderer/core/dom/shadow_root.idl
@@ -54,32 +54,6 @@ // See https://crbug.com/346835896 [RuntimeEnabled=ShadowRootReferenceTarget] attribute DOMString referenceTarget; - // Scoped element creation APIs - // https://wicg.github.io/webcomponents/proposals/Scoped-Custom-Element-Registries#scoped-element-creation-apis - [ - NewObject, PerWorldBindings, RaisesException, CEReactions, - RuntimeEnabled=ScopedCustomElementRegistry, - ImplementedAs=CreateElementForBinding - ] - Element createElement(DOMString localName); - [ - NewObject, PerWorldBindings, RaisesException, CEReactions, - RuntimeEnabled=ScopedCustomElementRegistry, - ImplementedAs=CreateElementForBinding - ] - Element createElement(DOMString localName, (DOMString or ElementCreationOptions) options); - [ - NewObject, RaisesException, CEReactions, - RuntimeEnabled=ScopedCustomElementRegistry - ] - Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName); - [ - NewObject, RaisesException, CEReactions, - RuntimeEnabled=ScopedCustomElementRegistry - ] - Element createElementNS(DOMString? namespaceURI, DOMString qualifiedName, - (DOMString or ElementCreationOptions) options); - [RaisesException,MeasureAs=SetHTMLUnsafe,CEReactions] void setHTMLUnsafe(HTMLString string); [RuntimeEnabled=SanitizerAPI,RaisesException,MeasureAs=SetHTMLUnsafe,CEReactions] void setHTMLUnsafe(HTMLString html, SetHTMLUnsafeOptions options); [RuntimeEnabled=SanitizerAPI,RaisesException,MeasureAs=SetHTMLSafe,CEReactions] void setHTML(DOMString html, optional SetHTMLOptions options = {});
diff --git a/third_party/blink/renderer/core/dom/tree_scope.h b/third_party/blink/renderer/core/dom/tree_scope.h index 1a15c9b7..8f4ced65 100644 --- a/third_party/blink/renderer/core/dom/tree_scope.h +++ b/third_party/blink/renderer/core/dom/tree_scope.h
@@ -54,9 +54,6 @@ class SVGTreeScopeResources; class ScopedStyleResolver; class StyleSheetList; -class CreateElementFlags; -class QualifiedName; -class V8UnionElementCreationOptionsOrString; // The root node of a document tree (in which case this is a Document) or of a // shadow tree (in which case this is a ShadowRoot). Various things, like @@ -182,26 +179,6 @@ void SetAdoptedStyleSheetsForTesting(HeapVector<Member<CSSStyleSheet>>&); void ClearAdoptedStyleSheets(); - Element* CreateElementForBinding(const AtomicString& local_name, - ExceptionState& = ASSERT_NO_EXCEPTION); - Element* CreateElementForBinding( - const AtomicString& local_name, - const V8UnionElementCreationOptionsOrString* string_or_options, - ExceptionState& exception_state); - Element* createElementNS(const AtomicString& namespace_uri, - const AtomicString& qualified_name, - ExceptionState&); - Element* createElementNS( - const AtomicString& namespace_uri, - const AtomicString& qualified_name, - const V8UnionElementCreationOptionsOrString* string_or_options, - ExceptionState& exception_state); - - // "create an element" defined in DOM standard. This supports both of - // autonomous custom elements and customized built-in elements. - Element* CreateElement(const QualifiedName&, - const CreateElementFlags, - const AtomicString& is); virtual CustomElementRegistry* customElementRegistry() const = 0;
diff --git a/third_party/blink/renderer/core/editing/commands/insert_commands.cc b/third_party/blink/renderer/core/editing/commands/insert_commands.cc index 7fbea34..c68e20fd 100644 --- a/third_party/blink/renderer/core/editing/commands/insert_commands.cc +++ b/third_party/blink/renderer/core/editing/commands/insert_commands.cc
@@ -54,7 +54,7 @@ LocalFrame& InsertCommands::TargetFrame(LocalFrame& frame, Event* event) { if (!event) return frame; - const Node* node = event->target()->ToNode(); + const Node* node = event->RawTarget()->ToNode(); if (!node) return frame; LocalFrame* local_frame = node->GetDocument().GetFrame();
diff --git a/third_party/blink/renderer/core/editing/editor.cc b/third_party/blink/renderer/core/editing/editor.cc index c50482b..0bf3584 100644 --- a/third_party/blink/renderer/core/editing/editor.cc +++ b/third_party/blink/renderer/core/editing/editor.cc
@@ -118,11 +118,12 @@ return selection; // If the target is a text control, and the current selection is outside of // its shadow tree, then use the saved selection for that text control. - if (!IsTextControl(*event->target()->ToNode())) + if (!IsTextControl(*event->RawTarget()->ToNode())) { return selection; + } auto* text_control_of_selection_start = EnclosingTextControl(selection.Anchor()); - auto* text_control_of_target = ToTextControl(event->target()->ToNode()); + auto* text_control_of_target = ToTextControl(event->RawTarget()->ToNode()); if (!selection.IsNone() && text_control_of_target == text_control_of_selection_start) return selection; @@ -571,7 +572,7 @@ WebFeature feature_on_text_area, WebFeature feature_on_content_editable, WebFeature feature_on_non_node) { - EventTarget* event_target = event.target(); + EventTarget* event_target = event.RawTarget(); Node* node = event_target->ToNode(); if (!node) { UseCounter::Count(execution_context, feature_on_non_node);
diff --git a/third_party/blink/renderer/core/editing/editor_key_bindings.cc b/third_party/blink/renderer/core/editing/editor_key_bindings.cc index 29706cc..a6d54f758 100644 --- a/third_party/blink/renderer/core/editing/editor_key_bindings.cc +++ b/third_party/blink/renderer/core/editing/editor_key_bindings.cc
@@ -84,7 +84,7 @@ // text to the focused element. if (auto* edit_context = GetFrame().GetInputMethodController().GetActiveEditContext()) { - if (DispatchBeforeInputInsertText(evt->target()->ToNode(), + if (DispatchBeforeInputInsertText(evt->RawTarget()->ToNode(), key_event->text.data()) != DispatchEventResult::kNotCanceled) { return true; @@ -110,7 +110,7 @@ return false; // Return true to prevent default action. e.g. Space key scroll. - if (DispatchBeforeInputInsertText(evt->target()->ToNode(), + if (DispatchBeforeInputInsertText(evt->RawTarget()->ToNode(), key_event->text.data()) != DispatchEventResult::kNotCanceled) { return true;
diff --git a/third_party/blink/renderer/core/events/mouse_event.cc b/third_party/blink/renderer/core/events/mouse_event.cc index 346fb2f..819e799 100644 --- a/third_party/blink/renderer/core/events/mouse_event.cc +++ b/third_party/blink/renderer/core/events/mouse_event.cc
@@ -454,7 +454,7 @@ } void MouseEvent::ComputeRelativePosition() { - Node* target_node = target() ? target()->ToNode() : nullptr; + Node* target_node = RawTarget() ? RawTarget()->ToNode() : nullptr; if (!target_node) return; @@ -525,7 +525,7 @@ } void MouseEvent::RecordLayerXYMetrics() { - Node* node = target() ? target()->ToNode() : nullptr; + Node* node = RawTarget() ? RawTarget()->ToNode() : nullptr; if (!node) return; // Using the target for these metrics is a heuristic for measuring the impact
diff --git a/third_party/blink/renderer/core/frame/cached_permission_status.cc b/third_party/blink/renderer/core/frame/cached_permission_status.cc index a713098..90cd917 100644 --- a/third_party/blink/renderer/core/frame/cached_permission_status.cc +++ b/third_party/blink/renderer/core/frame/cached_permission_status.cc
@@ -36,7 +36,6 @@ permission_service_(local_dom_window), permission_observer_receivers_(this, local_dom_window) { CHECK(local_dom_window); - CHECK(RuntimeEnabledFeatures::PermissionElementEnabled(local_dom_window)); } void CachedPermissionStatus::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/frame/cached_permission_status.h b/third_party/blink/renderer/core/frame/cached_permission_status.h index aa74f4f..e22cb10 100644 --- a/third_party/blink/renderer/core/frame/cached_permission_status.h +++ b/third_party/blink/renderer/core/frame/cached_permission_status.h
@@ -71,6 +71,7 @@ private: friend class HTMLPermissionElement; + friend class Screen; friend class DocumentLoader; friend class CachedPermissionStatusTest;
diff --git a/third_party/blink/renderer/core/frame/screen.cc b/third_party/blink/renderer/core/frame/screen.cc index 51c1a235..4325717 100644 --- a/third_party/blink/renderer/core/frame/screen.cc +++ b/third_party/blink/renderer/core/frame/screen.cc
@@ -41,7 +41,24 @@ namespace blink { Screen::Screen(LocalDOMWindow* window, int64_t display_id) - : ExecutionContextClient(window), display_id_(display_id) {} + : ExecutionContextClient(window), display_id_(display_id) { + // If we're potentially reducing information about the screen size, register + // ourselves as a client of CachedPermissionStatus to listen for changes to + // the WINDOW_MANAGEMENT permission. We're going to rely on this cache because + // we'd otherwise need to block each synchronous property getter on a call to + // retrieve the current permission status, which is quite expensive for this + // commonly-used object. + if (RuntimeEnabledFeatures::ReduceScreenSizeEnabled() && DomWindow() && + DomWindow()->IsFeatureEnabled( + network::mojom::PermissionsPolicyFeature::kWindowManagement)) { + auto descriptor = mojom::blink::PermissionDescriptor::New(); + descriptor->name = mojom::blink::PermissionName::WINDOW_MANAGEMENT; + Vector<mojom::blink::PermissionDescriptorPtr> descriptors; + descriptors.push_back(std::move(descriptor)); + CachedPermissionStatus::From(DomWindow()) + ->RegisterClient(this, std::move(descriptors)); + } +} // static bool Screen::AreWebExposedScreenPropertiesEqual( @@ -195,7 +212,8 @@ bool Screen::ShouldReduceScreenSize() const { // TODO(408932088): Take the current state of the window management permission // (`mojom::blink::PermissionName::WINDOW_MANAGEMENT`) into account here. - return RuntimeEnabledFeatures::ReduceScreenSizeEnabled(); + return RuntimeEnabledFeatures::ReduceScreenSizeEnabled() && + !window_management_permission_granted_; } bool Screen::isExtended() const { @@ -235,4 +253,24 @@ return kEmptyScreenInfo; } +void Screen::OnPermissionStatusChange(mojom::blink::PermissionName name, + mojom::blink::PermissionStatus status) { + CHECK(name == mojom::blink::PermissionName::WINDOW_MANAGEMENT); + window_management_permission_granted_ = + status == mojom::blink::PermissionStatus::GRANTED; +} + +void Screen::OnPermissionStatusInitialized( + CachedPermissionStatus::PermissionStatusMap map) { + // Window management permission is granted if the map we're given has entries, + // and they're all GRANTED: + window_management_permission_granted_ = + map.size() > 0U && std::ranges::all_of(map, [](const auto& status) { + return status.value == mojom::blink::PermissionStatus::GRANTED; + }); + + // If the permission is granted, it should be the only item in the map: + CHECK(!window_management_permission_granted_ || map.size() == 1U); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/screen.h b/third_party/blink/renderer/core/frame/screen.h index 8efac99..431dfbd 100644 --- a/third_party/blink/renderer/core/frame/screen.h +++ b/third_party/blink/renderer/core/frame/screen.h
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" +#include "third_party/blink/renderer/core/frame/cached_permission_status.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/supplementable.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" @@ -47,6 +48,7 @@ class CORE_EXPORT Screen : public EventTarget, public ExecutionContextClient, + public CachedPermissionStatus::Client, public Supplementable<Screen> { DEFINE_WRAPPERTYPEINFO(); @@ -93,8 +95,18 @@ gfx::Rect GetRect(bool available) const; const display::ScreenInfo& GetScreenInfo() const; + // CachedPermissionStatus::Client overrides: + void OnPermissionStatusChange(mojom::blink::PermissionName, + mojom::blink::PermissionStatus) override; + + void OnPermissionStatusInitialized( + CachedPermissionStatus::PermissionStatusMap) override; + // The internal id of the underlying display, to support multi-screen devices. int64_t display_id_; + + private: + bool window_management_permission_granted_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc index 0aca515..95a0cc0 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -430,7 +430,6 @@ void CanvasRenderingContextHost::DiscardResources() { resource_provider_for_canvas2d_ = nullptr; resource_provider_for_image_bitmap_ = nullptr; - resource_provider_for_webgl_ = nullptr; resource_provider_for_webgpu_ = nullptr; UpdateMemoryUsage(); }
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h index 327064dc..8fe6f3c 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
@@ -67,6 +67,9 @@ virtual DispatchEventResult HostDispatchEvent(Event*) = 0; virtual const KURL& GetExecutionContextUrl() const = 0; + virtual void UpdateMemoryUsage() = 0; + virtual size_t GetMemoryUsage() const = 0; + // If WebGL1 is disabled by enterprise policy or command line switch. virtual bool IsWebGL1Enabled() const = 0; // If WebGL2 is disabled by enterprise policy or command line switch. @@ -101,9 +104,9 @@ // Partial CanvasResourceHost implementation void InitializeForRecording(cc::PaintCanvas*) const final; - CanvasResourceProvider* GetOrCreateCanvasResourceProviderForCanvas2D() - override; - void PageVisibilityChanged() override; + virtual CanvasResourceProvider* + GetOrCreateCanvasResourceProviderForCanvas2D(); + virtual void PageVisibilityChanged(); CanvasResourceProvider* GetOrCreateCanvasResourceProviderForWebGPU(); @@ -140,18 +143,6 @@ bool IsContextLost() const override; - // `resource_provider_` must be null. - void SetResourceProviderForWebGL( - std::unique_ptr<CanvasResourceProvider> resource_provider) { - CHECK(IsWebGL()); - CHECK(!resource_provider_for_webgl_); - resource_provider_for_webgl_ = std::move(resource_provider); - UpdateMemoryUsage(); - } - CanvasResourceProvider* GetResourceProviderForWebGL() const { - CHECK(IsWebGL()); - return resource_provider_for_webgl_.get(); - } CanvasResourceProvider* GetResourceProviderForWebGPU() const { CHECK(IsWebGPU()); return resource_provider_for_webgpu_.get(); @@ -214,7 +205,6 @@ std::unique_ptr<CanvasResourceProvider> resource_provider_for_canvas2d_; std::unique_ptr<CanvasResourceProvider> resource_provider_for_image_bitmap_; - std::unique_ptr<CanvasResourceProvider> resource_provider_for_webgl_; std::unique_ptr<CanvasResourceProvider> resource_provider_for_webgpu_; bool did_record_canvas_size_to_uma_ = false; HostType host_type_ = HostType::kNone;
diff --git a/third_party/blink/renderer/core/html/custom/custom_element.cc b/third_party/blink/renderer/core/html/custom/custom_element.cc index b0efce2..9c79c5a 100644 --- a/third_party/blink/renderer/core/html/custom/custom_element.cc +++ b/third_party/blink/renderer/core/html/custom/custom_element.cc
@@ -126,25 +126,24 @@ } static CustomElementDefinition* DefinitionFor( - const TreeScope& tree_scope, + const Document& document, const CustomElementDescriptor desc) { - if (CustomElementRegistry* registry = CustomElement::Registry(tree_scope)) { + if (CustomElementRegistry* registry = CustomElement::Registry(document)) { return registry->DefinitionFor(desc); } return nullptr; } // https://dom.spec.whatwg.org/#concept-create-element -HTMLElement* CustomElement::CreateCustomElement(TreeScope& tree_scope, +HTMLElement* CustomElement::CreateCustomElement(Document& document, const QualifiedName& tag_name, CreateElementFlags flags) { DCHECK(ShouldCreateCustomElement(tag_name)) << tag_name; - Document& document = tree_scope.GetDocument(); // 4. Let definition be the result of looking up a custom element // definition given document, namespace, localName, and is. if (auto* definition = DefinitionFor( - tree_scope, CustomElementDescriptor(tag_name.LocalName(), - tag_name.LocalName()))) { + document, CustomElementDescriptor(tag_name.LocalName(), + tag_name.LocalName()))) { DCHECK(definition->Descriptor().IsAutonomous()); // 6. Otherwise, if definition is non-null, then: return definition->CreateElement(document, tag_name, flags);
diff --git a/third_party/blink/renderer/core/html/custom/custom_element.h b/third_party/blink/renderer/core/html/custom/custom_element.h index df8f382..5ecc47f 100644 --- a/third_party/blink/renderer/core/html/custom/custom_element.h +++ b/third_party/blink/renderer/core/html/custom/custom_element.h
@@ -109,7 +109,7 @@ // Look up a definition, and create an autonomous custom element if // it's found. - static HTMLElement* CreateCustomElement(TreeScope&, + static HTMLElement* CreateCustomElement(Document&, const QualifiedName&, const CreateElementFlags);
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc index 4620a44..a4834369 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -423,7 +423,7 @@ if (popover.popover) { bool event_target_was_nested_popover = false; - if (auto* target_node = event.target()->ToNode()) { + if (auto* target_node = event.RawTarget()->ToNode()) { bool button_is_ancestor_of_popover = IsShadowIncludingAncestorOf(*popover.popover); event_target_was_nested_popover =
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.cc b/third_party/blink/renderer/core/html/forms/html_form_element.cc index 7a447113..0b4a9ae 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -193,7 +193,7 @@ } void HTMLFormElement::HandleLocalEvents(Event& event) { - Node* target_node = event.target()->ToNode(); + Node* target_node = event.RawTarget()->ToNode(); if (event.eventPhase() != Event::PhaseType::kCapturingPhase && target_node && target_node != this && (event.type() == event_type_names::kSubmit ||
diff --git a/third_party/blink/renderer/core/html/forms/html_label_element.cc b/third_party/blink/renderer/core/html/forms/html_label_element.cc index 4b08f5c3..5c38594 100644 --- a/third_party/blink/renderer/core/html/forms/html_label_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_label_element.cc
@@ -174,7 +174,7 @@ // event, then there's no need for us to do anything. if (!element) return; - Node* target_node = evt.target() ? evt.target()->ToNode() : nullptr; + Node* target_node = evt.RawTarget() ? evt.RawTarget()->ToNode() : nullptr; if (target_node) { if (element->IsShadowIncludingInclusiveAncestorOf(*target_node)) return;
diff --git a/third_party/blink/renderer/core/html/forms/range_input_type.cc b/third_party/blink/renderer/core/html/forms/range_input_type.cc index 5018322..87a46a52 100644 --- a/third_party/blink/renderer/core/html/forms/range_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/range_input_type.cc
@@ -179,7 +179,7 @@ if (GetElement().IsDisabledFormControl()) return; - Node* target_node = event.target()->ToNode(); + Node* target_node = event.RawTarget()->ToNode(); if (event.button() != static_cast<int16_t>(WebPointerProperties::Button::kLeft) || !target_node)
diff --git a/third_party/blink/renderer/core/html/forms/select_type.cc b/third_party/blink/renderer/core/html/forms/select_type.cc index d81cf6fb..3efc5fe 100644 --- a/third_party/blink/renderer/core/html/forms/select_type.cc +++ b/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -81,7 +81,7 @@ namespace { HTMLOptionElement* EventTargetOption(const Event& event) { - auto* element = DynamicTo<Element>(event.target()->ToNode()); + auto* element = DynamicTo<Element>(event.RawTarget()->ToNode()); if (!element) { return nullptr; }
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc index 046c3c4..6dffe01 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -209,8 +209,8 @@ if (!mouse_event) return; - DCHECK(event->target()); - Node* target = event->target()->ToNode(); + DCHECK(event->RawTarget()); + Node* target = event->RawTarget()->ToNode(); DCHECK(target); auto* image_element = DynamicTo<HTMLImageElement>(target); if (!image_element || !image_element->IsServerMap())
diff --git a/third_party/blink/renderer/core/html/html_summary_element.cc b/third_party/blink/renderer/core/html/html_summary_element.cc index 93211e7..685f1e5 100644 --- a/third_party/blink/renderer/core/html/html_summary_element.cc +++ b/third_party/blink/renderer/core/html/html_summary_element.cc
@@ -63,7 +63,7 @@ void HTMLSummaryElement::DefaultEventHandler(Event& event) { if (IsMainSummary()) { if (event.type() == event_type_names::kDOMActivate && - !IsClickableControl(event.target()->ToNode())) { + !IsClickableControl(event.RawTarget()->ToNode())) { if (HTMLDetailsElement* details = DetailsElement()) details->ToggleOpen(); event.SetDefaultHandled();
diff --git a/third_party/blink/renderer/core/html/media/media_document.cc b/third_party/blink/renderer/core/html/media/media_document.cc index 6bd2466..c01d14e0 100644 --- a/third_party/blink/renderer/core/html/media/media_document.cc +++ b/third_party/blink/renderer/core/html/media/media_document.cc
@@ -137,7 +137,7 @@ } void MediaDocument::DefaultEventHandler(Event& event) { - Node* target_node = event.target()->ToNode(); + Node* target_node = event.RawTarget()->ToNode(); if (!target_node) return;
diff --git a/third_party/blink/renderer/core/html/track/cue_timeline.h b/third_party/blink/renderer/core/html/track/cue_timeline.h index 6f96c2042..e242eeca 100644 --- a/third_party/blink/renderer/core/html/track/cue_timeline.h +++ b/third_party/blink/renderer/core/html/track/cue_timeline.h
@@ -19,13 +19,13 @@ class HTMLMediaElement; class TextTrackCueList; -// TODO(Oilpan): This needs to be PODIntervalTree<double, Member<TextTrackCue>>. -// However, it is not easy to move PODIntervalTree to the heap (for a +// TODO(Oilpan): This needs to be PodIntervalTree<double, Member<TextTrackCue>>. +// However, it is not easy to move PodIntervalTree to the heap (for a // C++-template reason) so we leave it as a raw pointer at the moment. This is // safe because CueTimeline and TextTrackCue are guaranteed to die at the same // time when the owner HTMLMediaElement dies. Thus the raw TextTrackCue* cannot // become stale pointers. -typedef WTF::PODIntervalTree<double, TextTrackCue*> CueIntervalTree; +using CueIntervalTree = PodIntervalTree<double, TextTrackCue*>; typedef CueIntervalTree::IntervalType CueInterval; typedef Vector<CueInterval> CueList; @@ -111,18 +111,14 @@ bool update_requested_while_ignoring_; }; -} // namespace blink - -namespace WTF { #ifndef NDEBUG // Template specializations required by PodIntervalTree in debug mode. template <> -struct ValueToString<blink::TextTrackCue*> { - static String ToString(blink::TextTrackCue* const& cue) { - return cue->ToString(); - } +struct ValueToString<TextTrackCue*> { + static String ToString(TextTrackCue* const& cue) { return cue->ToString(); } }; #endif -} + +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_TRACK_CUE_TIMELINE_H_
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc index 951cd79..48510501 100644 --- a/third_party/blink/renderer/core/input/event_handler.cc +++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -2447,7 +2447,7 @@ EventTarget* target; if (underlying_event) - target = underlying_event->target(); + target = underlying_event->RawTarget(); else target = EventTargetNodeForDocument(frame_->GetDocument()); if (!target)
diff --git a/third_party/blink/renderer/core/layout/layout_flow_thread.h b/third_party/blink/renderer/core/layout/layout_flow_thread.h index 0a0c5dc..9bd2de4 100644 --- a/third_party/blink/renderer/core/layout/layout_flow_thread.h +++ b/third_party/blink/renderer/core/layout/layout_flow_thread.h
@@ -181,8 +181,8 @@ typedef WTF::PODInterval<LayoutUnit, LayoutMultiColumnSet*> MultiColumnSetInterval; - typedef WTF::PODIntervalTree<LayoutUnit, LayoutMultiColumnSet*> - MultiColumnSetIntervalTree; + using MultiColumnSetIntervalTree = + PodIntervalTree<LayoutUnit, LayoutMultiColumnSet*>; class MultiColumnSetSearchAdapter { STACK_ALLOCATED(); @@ -214,24 +214,22 @@ } }; -} // namespace blink - -namespace WTF { -// These structures are used by PODIntervalTree for debugging. +// These structures are used by PodIntervalTree for debugging. #ifndef NDEBUG template <> -struct ValueToString<blink::LayoutMultiColumnSet*> { - static String ToString(const blink::LayoutMultiColumnSet* value) { +struct ValueToString<LayoutMultiColumnSet*> { + static String ToString(const LayoutMultiColumnSet* value) { return String::Format("%p", value); } }; template <> -struct ValueToString<blink::LayoutUnit> { - static String ToString(const blink::LayoutUnit value) { +struct ValueToString<LayoutUnit> { + static String ToString(const LayoutUnit value) { return String::Number(value.ToFloat()); } }; #endif -} // namespace WTF + +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FLOW_THREAD_H_
diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/third_party/blink/renderer/core/page/context_menu_controller.cc index 4d749ab..a81090b 100644 --- a/third_party/blink/renderer/core/page/context_menu_controller.cc +++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -202,7 +202,8 @@ void ContextMenuController::HandleContextMenuEvent(MouseEvent* mouse_event) { DCHECK(mouse_event->type() == event_type_names::kContextmenu); - LocalFrame* frame = mouse_event->target()->ToNode()->GetDocument().GetFrame(); + LocalFrame* frame = + mouse_event->RawTarget()->ToNode()->GetDocument().GetFrame(); PhysicalOffset location = PhysicalOffset::FromPointFRound(mouse_event->AbsoluteLocation()); @@ -482,7 +483,7 @@ ->GetEditor()); if (mouse_event && source_type == kMenuSourceKeyboard) { - Node* target_node = mouse_event->target()->ToNode(); + Node* target_node = mouse_event->RawTarget()->ToNode(); if (target_node && IsA<Element>(target_node)) { // Get the url from an explicitly set target, e.g. the focused element // when the context menu is evoked from the keyboard. Note: the innerNode
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller.cc b/third_party/blink/renderer/core/page/focusgroup_controller.cc index 935b7ef8..4892537 100644 --- a/third_party/blink/renderer/core/page/focusgroup_controller.cc +++ b/third_party/blink/renderer/core/page/focusgroup_controller.cc
@@ -39,7 +39,7 @@ return false; Element* focused = frame->GetDocument()->FocusedElement(); - if (!focused || focused != event->target()) { + if (!focused || focused != event->RawTarget()) { // The FocusgroupController shouldn't handle this arrow key event when the // focus already moved to a different element than where it came from. The // webpage likely had a key-handler that moved the focus.
diff --git a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc index 368c462..d07cec6 100644 --- a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc +++ b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
@@ -179,7 +179,7 @@ // If the focus has already moved by a previous handler, return false. const Element* focused = GetFocusedElement(); - if (focused && focused != event->target()) { + if (focused && focused != event->RawTarget()) { // SpatNav does not need to handle this arrow key because // the webpage had a key-handler that already moved focus. return false;
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc index d687e2fb..6099594 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
@@ -164,7 +164,8 @@ return SoftNavigationHeuristics::EventScope::Type::kNavigate; } if (event.IsKeyboardEvent()) { - Node* target_node = event.target() ? event.target()->ToNode() : nullptr; + Node* target_node = + event.RawTarget() ? event.RawTarget()->ToNode() : nullptr; if (target_node && target_node->IsHTMLElement() && DynamicTo<HTMLElement>(target_node)->IsHTMLBodyElement()) { if (event.type() == event_type_names::kKeydown) { @@ -424,12 +425,29 @@ return; } - // We have met all criteria! + // We have met all Soft-Nav criteria! + + // At this point, this navigation should be "committed" to the performance + // timeline. Thus, we increment the navigation id here, in the animation frame + // Paint where the criteria are first met. However, the navigation will not be + // ready for reporting until it also has an FCP measurement. + // We must *not* wait on this presentation time callback, because all other + // new performance entries created need to use this new navigation id, in + // order to match with the eventual soft-nav entry. + // + // TODO(crbug.com/424448145): Ideally, we should carefully ensure that this + // happens exactly where we want our timeOrigin, and also ensure that all + // performance entries are created at the time of the measurement they are + // reporting, rather than some time later, which risks assigning the wrong + // navigationId-- but this might be impossible. Instead, we might need to + // re-write history when we get a new navigationId with a timeOrigin in the + // past. ++soft_navigation_count_; window_->GenerateNewNavigationId(); + context->SetNavigationId(window_->GetNavigationId()); - needs_paint_timing_callback_ = true; + context_for_first_contentful_paint_ = context; } SoftNavigationContext* @@ -464,14 +482,11 @@ OptionalPaintTimingCallback SoftNavigationHeuristics::TakePaintTimingCallback() { - // If we need paint timing, we must have a context that needs FCP. - CHECK(!needs_paint_timing_callback_ || - (context_for_current_url_ && - !context_for_current_url_->HasFirstContentfulPaint())); - if (!needs_paint_timing_callback_) { + if (!context_for_first_contentful_paint_) { return {}; } - needs_paint_timing_callback_ = false; + // If we need paint timing, we must have a context that needs FCP. + CHECK(!context_for_first_contentful_paint_->HasFirstContentfulPaint()); // TODO(crbug.com/40871933): We are already only marking dom nodes when we // have a frame, and we are already limiting paints attribution to contexts @@ -511,9 +526,11 @@ context->FirstContentfulPaint(), "context", *context, "frame", frameIdForTracing); }, - WrapWeakPersistent(this), WrapPersistent(context_for_current_url_.Get()), + WrapWeakPersistent(this), + WrapPersistent(context_for_first_contentful_paint_.Get()), frameIdForTracing); + context_for_first_contentful_paint_ = nullptr; return std::move(callback); } @@ -586,6 +603,7 @@ void SoftNavigationHeuristics::Trace(Visitor* visitor) const { visitor->Trace(active_interaction_context_); visitor->Trace(context_for_current_url_); + visitor->Trace(context_for_first_contentful_paint_); visitor->Trace(window_); visitor->Trace(paint_attribution_tracker_); // Register a custom weak callback, which runs after processing weakness for
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h index 71c5b35..2068f95 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.h
@@ -202,13 +202,26 @@ // continue measuring paints for a while. Member<SoftNavigationContext> context_for_current_url_; + // Save a strong reference to the most recent context that painted for the + // first time, and needs an FCP presentation callback. This will be picked + // up by PaintTimingMixin, cleared, but held strongly until presententation + // feedback. Soft-navigation entries are not reported to the performance + // timeline until after FCP is measured. + // TODO(crbug.com/424448145): Needs some changes: + // - measure first paint update, not the update after criteria met. + // - measure first paint of first contentful candidate, not fully loaded + // paint. + // - support multiple context in a single animation frame, rather than + // single value here. Will become more important when all interactions + // measure paint. + Member<SoftNavigationContext> context_for_first_contentful_paint_; + // Used to map DOM modifications to `SoftNavigationContext`s for paint // attribution. Only set when `IsPrePaintBasedAttributionEnabled()` is true. Member<SoftNavigationPaintAttributionTracker> paint_attribution_tracker_; uint32_t soft_navigation_count_ = 0; bool has_active_event_scope_ = false; - bool needs_paint_timing_callback_ = false; const features::SoftNavigationHeuristicsMode paint_attribution_mode_; // `task_attribution_tracker_` is cleared during `Shutdown()` (frame detach),
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc index a82518e..472b162 100644 --- a/third_party/blink/renderer/core/timing/window_performance.cc +++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -693,11 +693,11 @@ #endif // BUILDFLAG(IS_MAC) } - if (event.target()) { - // `event->target()` is assigned as part of EventDispatch, and will be unset - // whenever we skip dispatch. (See: crbug.com/1367329). - // Note: target may be dom detached, and even GC-ed, before Observer fires. - entry->SetTarget(event.target()->ToNode()); + if (EventTarget* raw_target = event.RawTarget()) { + // `event->RawTarget()` is assigned as part of EventDispatch, and will be + // unset whenever we skip dispatch. (See: crbug.com/1367329). Note: target + // may be dom detached, and even GC-ed, before Observer fires. + entry->SetTarget(raw_target->ToNode()); } // Request presentation time first, because this might increment presentation
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc index b26284b..1be3507 100644 --- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -41,6 +41,7 @@ #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" +#include "third_party/blink/renderer/core/workers/worker_navigator.h" #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h" #include "third_party/blink/renderer/core/workers/worker_thread.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h index d88978d..2d711b7f 100644 --- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h +++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.h
@@ -25,8 +25,8 @@ #include "third_party/blink/renderer/core/loader/back_forward_cache_loader_helper_impl.h" #include "third_party/blink/renderer/core/script/modulator.h" #include "third_party/blink/renderer/core/workers/worker_clients.h" -#include "third_party/blink/renderer/core/workers/worker_navigator.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h" +#include "third_party/blink/renderer/platform/heap/cross_thread_persistent.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_load_scheduler.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" #include "third_party/blink/renderer/platform/scheduler/public/worker_scheduler.h" @@ -43,6 +43,7 @@ class SubresourceFilter; class WebContentSettingsClient; class WebWorkerFetchContext; +class WorkerNavigator; class WorkerOrWorkletScriptController; class WorkerReportingProxy; class WorkerThread;
diff --git a/third_party/blink/renderer/modules/locks/lock_manager.cc b/third_party/blink/renderer/modules/locks/lock_manager.cc index 9833658..0e7adeb 100644 --- a/third_party/blink/renderer/modules/locks/lock_manager.cc +++ b/third_party/blink/renderer/modules/locks/lock_manager.cc
@@ -19,6 +19,7 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_lock_manager_snapshot.h" #include "third_party/blink/renderer/core/dom/abort_signal.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" +#include "third_party/blink/renderer/core/execution_context/navigator_base.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/web_feature.h"
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc index 9d54c49..d3d38c1 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_playback_speed_list_element.cc
@@ -128,7 +128,7 @@ event.SetDefaultHandled(); } else if (event.type() == event_type_names::kChange) { // Identify which input element was selected and update playback speed - Node* target = event.target()->ToNode(); + Node* target = event.RawTarget()->ToNode(); if (!target || !target->IsElementNode()) return;
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc index 068f2ef..123d701 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_popup_menu_element.cc
@@ -97,7 +97,8 @@ break; case VKEY_RETURN: case VKEY_SPACE: - To<Element>(event->target()->ToNode())->DispatchSimulatedClick(event); + To<Element>(event->RawTarget()->ToNode()) + ->DispatchSimulatedClick(event); popup_menu_->FocusPopupAnchorIfOverflowClosed(); break; default: @@ -153,10 +154,10 @@ void MediaControlPopupMenuElement::DefaultEventHandler(Event& event) { if (event.type() == event_type_names::kPointermove && - event.target() != this) { - To<Element>(event.target()->ToNode()) + event.RawTarget() != this) { + To<Element>(event.RawTarget()->ToNode()) ->Focus(FocusParams(FocusTrigger::kUserGesture)); - last_focused_element_ = To<Element>(event.target()->ToNode()); + last_focused_element_ = To<Element>(event.RawTarget()->ToNode()); } else if (event.type() == event_type_names::kFocusout) { GetDocument() .GetTaskRunner(TaskType::kMediaElementEvent) @@ -165,15 +166,15 @@ WTF::BindOnce(&MediaControlPopupMenuElement::HideIfNotFocused, WrapWeakPersistent(this))); } else if (event.type() == event_type_names::kClick && - event.target() != this) { - // Since event.target() != this, we know that one of our children was + event.RawTarget() != this) { + // Since event.RawTarget() != this, we know that one of our children was // clicked. OnItemSelected(); event.stopPropagation(); event.SetDefaultHandled(); } else if (event.type() == event_type_names::kFocus && - event.target() == this) { + event.RawTarget() == this) { // When the popup menu gains focus from scrolling, switch focus // back to the last focused item in the menu. if (last_focused_element_) {
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc index 68e3d6e..d807420 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_text_track_list_element.cc
@@ -86,7 +86,7 @@ event.SetDefaultHandled(); } else if (event.type() == event_type_names::kChange) { // Identify which input element was selected and set track to showing - Node* target = event.target()->ToNode(); + Node* target = event.RawTarget()->ToNode(); if (!target || !target->IsElementNode()) return;
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_track_selector_list_element.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_track_selector_list_element.cc index dc8b5b3..cb41b25 100644 --- a/third_party/blink/renderer/modules/media_controls/elements/media_control_track_selector_list_element.cc +++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_track_selector_list_element.cc
@@ -125,7 +125,7 @@ } else if (event.type() == event_type_names::kChange) { // Identify which input element was selected and select the corresponding // track. - Node* target = event.target()->ToNode(); + Node* target = event.RawTarget()->ToNode(); if (!target || !target->IsElementNode()) { return; }
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc b/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc index 8ff85ea2..33e3f08 100644 --- a/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc +++ b/third_party/blink/renderer/modules/media_controls/media_controls_shared_helper.cc
@@ -55,8 +55,9 @@ void MediaControlsSharedHelpers::TransitionEventListener::Invoke( ExecutionContext* context, Event* event) { - if (event->target() != element_) + if (event->RawTarget() != element_) { return; + } if (event->type() == event_type_names::kTransitionend) { callback_.Run();
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc index e81a3216..e988ded 100644 --- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc +++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
@@ -16,7 +16,9 @@ #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" +#include "media/base/media_switches.h" #include "media/base/timestamp_constants.h" +#include "media/base/video_color_space.h" #include "media/base/video_frame.h" #include "media/base/video_util.h" #include "third_party/blink/public/common/features.h" @@ -204,7 +206,7 @@ // WebRtcIgnoreUnspecifiedColorSpace. If the feature is enabled we won't try // to guess a color space if the webrtc::ColorSpace is unspecified. If the // feature is disabled (default), an unspecified color space will get - // converted into a gfx::ColorSpace set to BT709. + // converted into a gfx::ColorSpace set to BT601. if (incoming_frame.color_space() && !(ignore_unspecified_color_space_ && incoming_frame.color_space()->primaries() == @@ -213,8 +215,19 @@ webrtc::ColorSpace::TransferID::kUnspecified && incoming_frame.color_space()->matrix() == webrtc::ColorSpace::MatrixID::kUnspecified)) { - video_frame->set_color_space( - WebRtcToGfxColorSpace(*incoming_frame.color_space())); + gfx::ColorSpace color_space = + WebRtcToGfxColorSpace(*incoming_frame.color_space()); + if (!color_space.IsValid()) { + color_space = media::VideoColorSpace::FromGfxColorSpace(color_space) + .GuessGfxColorSpace(); + } + if (color_space.IsValid()) { + video_frame->set_color_space(color_space); + } + } + if (base::FeatureList::IsEnabled(media::kWebRTCColorAccuracy) && + !incoming_frame.color_space()) { + video_frame->set_color_space(gfx::ColorSpace::CreateREC601()); } // Run render smoothness algorithm only when we don't have to render
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_features.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_features.cc index 5286e06f..05349b2 100644 --- a/third_party/blink/renderer/modules/peerconnection/peer_connection_features.cc +++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_features.cc
@@ -23,12 +23,6 @@ "WebRtcEncryptedRtpHeaderExtensions", base::FEATURE_ENABLED_BY_DEFAULT); -// This feature enables using Post-Quantum Crypto(PQC) for DTLS to improve -// WebRTC's security. -BASE_FEATURE(kWebRtcPQCForDTLS, - "WebRtcPQCForDTLS", - base::FEATURE_DISABLED_BY_DEFAULT); - // This features enables the restriction that frames sent to an // RTCRtpScriptTransformer's writable must come from the transformer's readable // and must be written in the same order in which they are read. This feature
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_features.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_features.h index b49e1e7..027e69d 100644 --- a/third_party/blink/renderer/modules/peerconnection/peer_connection_features.h +++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_features.h
@@ -9,7 +9,6 @@ namespace blink { MODULES_EXPORT BASE_DECLARE_FEATURE(kWebRtcEncodedTransformDirectCallback); MODULES_EXPORT BASE_DECLARE_FEATURE(kWebRtcEncryptedRtpHeaderExtensions); -MODULES_EXPORT BASE_DECLARE_FEATURE(kWebRtcPQCForDTLS); MODULES_EXPORT BASE_DECLARE_FEATURE( kWebRtcRtpScriptTransformerFrameRestrictions); } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc index a907df9..e5370ed 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
@@ -885,7 +885,7 @@ configuration_.crypto_options->srtp.enable_encrypted_rtp_header_extensions = base::FeatureList::IsEnabled(kWebRtcEncryptedRtpHeaderExtensions); configuration_.enable_implicit_rollback = true; - if (base::FeatureList::IsEnabled(kWebRtcPQCForDTLS)) { + if (base::FeatureList::IsEnabled(features::kWebRtcPqcForDtls)) { configuration_.crypto_options->ephemeral_key_exchange_cipher_groups .AddFirst(webrtc::CryptoOptions::EphemeralKeyExchangeCipherGroups:: kX25519_MLKEM768);
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_event.cc b/third_party/blink/renderer/modules/service_worker/fetch_event.cc index 7aa4cc3..7f578f97 100644 --- a/third_party/blink/renderer/modules/service_worker/fetch_event.cc +++ b/third_party/blink/renderer/modules/service_worker/fetch_event.cc
@@ -10,6 +10,7 @@ #include "base/memory/scoped_refptr.h" #include "third_party/blink/public/mojom/timing/performance_mark_or_measure.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h" +#include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/platform/web_url_response.h" #include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/core/dom/abort_signal.h"
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index 779b6ba0..155e587 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -89,6 +89,7 @@ #include "third_party/blink/renderer/core/workers/worker_backing_thread.h" #include "third_party/blink/renderer/core/workers/worker_classic_script_loader.h" #include "third_party/blink/renderer/core/workers/worker_clients.h" +#include "third_party/blink/renderer/core/workers/worker_navigator.h" #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h" #include "third_party/blink/renderer/modules/background_fetch/background_fetch_event.h" #include "third_party/blink/renderer/modules/background_fetch/background_fetch_registration.h"
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 3a4667c..50f49136 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -1695,6 +1695,11 @@ return submitted_frame; } +void WebGLRenderingContextBase::Dispose() { + resource_provider_.reset(); + CanvasRenderingContext::Dispose(); +} + bool WebGLRenderingContextBase::PushFrameWithCopy() { bool submitted_frame = false; @@ -1868,7 +1873,7 @@ } bool WebGLRenderingContextBase::IsAccelerated() const { - auto* resource_provider = Host()->GetResourceProviderForWebGL(); + auto* resource_provider = resource_provider_.get(); return resource_provider ? resource_provider->IsAccelerated() : Host()->ShouldTryToUseGpuRaster(); } @@ -1884,6 +1889,7 @@ void WebGLRenderingContextBase::SizeChanged() { did_fail_to_create_resource_provider_ = false; + resource_provider_.reset(); } scoped_refptr<StaticBitmapImage> @@ -1907,7 +1913,7 @@ } PaintRenderingResultsToCanvas(source_buffer); if (has_dispatcher && was_dirty && GetOrCreateCanvasResourceProvider()) { - return Host()->GetResourceProviderForWebGL()->ProduceCanvasResource(reason); + return resource_provider_.get()->ProduceCanvasResource(reason); } return nullptr; } @@ -1992,11 +1998,12 @@ CanvasResourceProvider* WebGLRenderingContextBase::GetOrCreateCanvasResourceProvider() { - auto* provider = Host()->GetResourceProviderForWebGL(); + auto* provider = resource_provider_.get(); if (!provider && !did_fail_to_create_resource_provider_) { if (Host()->IsValidImageSize()) { - Host()->SetResourceProviderForWebGL(CreateCanvasResourceProvider()); - provider = Host()->GetResourceProviderForWebGL(); + resource_provider_ = CreateCanvasResourceProvider(); + Host()->UpdateMemoryUsage(); + provider = resource_provider_.get(); } if (!provider) { did_fail_to_create_resource_provider_ = true; @@ -2021,23 +2028,22 @@ } if (isContextLost() || !GetDrawingBuffer()) { - return Host()->GetResourceProviderForWebGL(); + return resource_provider_.get(); } bool must_clear_now = ClearIfComposited(kClearCallerOther) != kSkipped; - if (Host()->GetResourceProviderForWebGL() && - Host()->GetResourceProviderForWebGL()->Size() != - GetDrawingBuffer()->Size()) { + if (resource_provider_.get() && + resource_provider_.get()->Size() != GetDrawingBuffer()->Size()) { + resource_provider_.reset(); Host()->DiscardResources(); } // The host's ResourceProvider is purged to save memory when the tab // is backgrounded. - if (!must_paint_to_canvas_ && !must_clear_now && - Host()->GetResourceProviderForWebGL()) { - return Host()->GetResourceProviderForWebGL(); + if (!must_paint_to_canvas_ && !must_clear_now && resource_provider_.get()) { + return resource_provider_.get(); } must_paint_to_canvas_ = false; @@ -2076,7 +2082,7 @@ return resource_provider; bool copy_succeeded = CopyRenderingResultsFromDrawingBuffer( - Host()->GetResourceProviderForWebGL(), source_buffer); + resource_provider_.get(), source_buffer); if (resource_provider_was_updated != nullptr) { *resource_provider_was_updated = copy_succeeded; } @@ -9174,7 +9180,7 @@ return buffer_count; } - auto* provider = Host()->GetResourceProviderForWebGL(); + auto* provider = resource_provider_.get(); if (provider) { buffer_count++; if (provider->IsAccelerated()) {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h index 7c4b5cdf..6c5420c 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -1996,6 +1996,8 @@ GLenum precision_type, WebGLShaderPrecisionFormat* format); + void Dispose() override; + // PushFrameWithCopy will make a potential copy if the resource is accelerated // or a drawImage if the resource is non accelerated. bool PushFrameWithCopy(); @@ -2003,6 +2005,7 @@ // ExtenralCanvasResource. bool PushFrameNoCopy(); + std::unique_ptr<CanvasResourceProvider> resource_provider_; static bool webgl_context_limits_initialized_; static unsigned max_active_webgl_contexts_; static unsigned max_active_webgl_contexts_on_worker_;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc index e7903b7..dd7814a 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc
@@ -3494,25 +3494,9 @@ int WebGLRenderingContextWebGPUBase::AllocatedBufferCountPerPixel() { // Front and back buffers. // TODO(413078308): Add support configuring MSAA and depth-stencil. - int buffer_count = 2; - - if (!Host()) { - return buffer_count; - } - - auto* provider = Host()->GetResourceProviderForWebGL(); - if (provider) { - buffer_count++; - if (provider->IsAccelerated()) { - // The number of internal GPU buffers vary between one (stable - // non-displayed state) and three (triple-buffered animations). - // Adding 2 is a pessimistic but relevant estimate. - // Note: These buffers might be allocated in GPU memory. - buffer_count += 2; - } - } - - return buffer_count; + // Note: If/once this class creates a CanvasResourceProvider it should track + // the memory of the provider here as well. + return 2; } bool WebGLRenderingContextWebGPUBase::isContextLost() const {
diff --git a/third_party/blink/renderer/platform/geometry/float_polygon.h b/third_party/blink/renderer/platform/geometry/float_polygon.h index c64c4b7..0a7862a 100644 --- a/third_party/blink/renderer/platform/geometry/float_polygon.h +++ b/third_party/blink/renderer/platform/geometry/float_polygon.h
@@ -65,7 +65,7 @@ private: typedef WTF::PODInterval<float, FloatPolygonEdge*> EdgeInterval; - typedef WTF::PODIntervalTree<float, FloatPolygonEdge*> EdgeIntervalTree; + using EdgeIntervalTree = PodIntervalTree<float, FloatPolygonEdge*>; Vector<gfx::PointF> vertices_; gfx::RectF bounding_box_; @@ -136,21 +136,18 @@ raw_ptr<const FloatPolygon> polygon_; }; -} // namespace blink - -namespace WTF { -// These structures are used by PODIntervalTree for debugging. +// These structures are used by PodIntervalTree for debugging. #ifndef NDEBUG template <> -struct ValueToString<blink::FloatPolygonEdge*> { +struct ValueToString<FloatPolygonEdge*> { STATIC_ONLY(ValueToString); - static String ToString(const blink::FloatPolygonEdge* edge) { + static String ToString(const FloatPolygonEdge* edge) { return String::Format("%p (%f,%f %f,%f)", edge, edge->Vertex1().x(), edge->Vertex1().y(), edge->Vertex2().x(), edge->Vertex2().y()); } }; #endif -} // namespace WTF +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_FLOAT_POLYGON_H_
diff --git a/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler_test.cc b/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler_test.cc index 9aabd0a..e407596 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler_test.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_hibernation_handler_test.cc
@@ -110,7 +110,7 @@ return result; } -void Draw(CanvasResourceHost& host) { +void Draw(FakeCanvasResourceHost& host) { CanvasResourceProvider* provider = host.GetOrCreateCanvasResourceProviderForCanvas2D(); provider->Canvas().drawLine(0, 0, 2, 2, cc::PaintFlags());
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_host.h b/third_party/blink/renderer/platform/graphics/canvas_resource_host.h index af62713..f6d4c65 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_host.h +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_host.h
@@ -46,11 +46,6 @@ virtual bool IsContextLost() const = 0; virtual void SetNeedsCompositingUpdate() = 0; virtual void InitializeForRecording(cc::PaintCanvas* canvas) const = 0; - virtual void UpdateMemoryUsage() = 0; - virtual size_t GetMemoryUsage() const = 0; - virtual void PageVisibilityChanged() {} - virtual CanvasResourceProvider* - GetOrCreateCanvasResourceProviderForCanvas2D() = 0; // Initialize the indicated cc::Layer with the HTMLCanvasElement's CSS // properties. This is a no-op if `this` is not an HTMLCanvasElement.
diff --git a/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc b/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc index 09ecafa8..2811786 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context_test.cc
@@ -15,8 +15,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h" +#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h" #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" -#include "third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h" #include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h" #include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h" #include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
diff --git a/third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h b/third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h index af91439..d804f9e 100644 --- a/third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h +++ b/third_party/blink/renderer/platform/graphics/test/fake_canvas_resource_host.h
@@ -27,7 +27,6 @@ bool IsContextLost() const override { return false; } void SetNeedsCompositingUpdate() override {} void InitializeForRecording(cc::PaintCanvas*) const override {} - void UpdateMemoryUsage() override {} bool PrintedInCurrentTask() const override { return false; } bool IsPageVisible() const override { return page_visible_; } bool IsHibernating() const override { return is_hibernating_; } @@ -45,44 +44,26 @@ return old_provider; } - size_t GetMemoryUsage() const override { return 0; } - CanvasResourceProvider* GetOrCreateCanvasResourceProviderForCanvas2D() - override { + CanvasResourceProvider* GetOrCreateCanvasResourceProviderForCanvas2D() { if (GetResourceProviderForCanvas2D()) { return GetResourceProviderForCanvas2D(); } constexpr auto kShouldInitialize = CanvasResourceProvider::ShouldInitialize::kCallClear; - std::unique_ptr<CanvasResourceProvider> provider; constexpr gpu::SharedImageUsageSet kSharedImageUsageFlags = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ | gpu::SHARED_IMAGE_USAGE_SCANOUT; - provider = CanvasResourceProvider::CreateSharedImageProvider( + resource_provider_ = CanvasResourceProvider::CreateSharedImageProvider( Size(), GetN32FormatForCanvas(), kPremul_SkAlphaType, gfx::ColorSpace::CreateSRGB(), kShouldInitialize, SharedGpuContext::ContextProviderWrapper(), RasterMode::kGPU, kSharedImageUsageFlags, this); - if (!provider) { - provider = CanvasResourceProvider:: - CreateSharedImageProviderForSoftwareCompositor( - Size(), GetN32FormatForCanvas(), kPremul_SkAlphaType, - gfx::ColorSpace::CreateSRGB(), kShouldInitialize, - SharedGpuContext::SharedImageInterfaceProvider(), this); - } - if (!provider) { - provider = CanvasResourceProvider::CreateBitmapProvider( - Size(), GetN32FormatForCanvas(), kPremul_SkAlphaType, - gfx::ColorSpace::CreateSRGB(), kShouldInitialize, this); - } - resource_provider_ = std::move(provider); - - return GetResourceProviderForCanvas2D(); + return resource_provider_.get(); } void SetPageVisible(bool visible) { if (page_visible_ != visible) { page_visible_ = visible; - PageVisibilityChanged(); } }
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc index 3070f4fe..c72713e4 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
@@ -1225,11 +1225,10 @@ // is not a black frame. #if BUILDFLAG(IS_WIN) { - // Check if the incoming frame is backed by owned or unowned memory type. - // This could happen when: 1. Zero-copy capture feature is turned on but - // device does not support MediaFoundation; 2. Zero-copy is enabled and - // video frame is backed up by an ArrayBuffer; 3. The video track gets - // disabled so black frames are sent. + // Check if the incoming frame is backed by unowned memory. This could + // happen when: 1. Zero-copy capture feature is turned on but device does + // not support MediaFoundation; 2. The video track gets disabled so black + // frames are sent. scoped_refptr<media::VideoFrame> frame; webrtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_buffer = frame_chunk.video_frame_buffer; @@ -1239,8 +1238,7 @@ if (frame_buffer->type() == webrtc::VideoFrameBuffer::Type::kNative) { frame = static_cast<WebRtcVideoFrameAdapterInterface*>(frame_buffer.get()) ->getMediaVideoFrame(); - if (frame->storage_type() == media::VideoFrame::STORAGE_UNOWNED_MEMORY || - frame->storage_type() == media::VideoFrame::STORAGE_OWNED_MEMORY) { + if (frame->storage_type() == media::VideoFrame::STORAGE_UNOWNED_MEMORY) { if (use_native_input_) { use_native_input_ = false; }
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc index a8a1355..ccae910 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_test.cc
@@ -128,9 +128,7 @@ public: FakeNativeBufferI420(int width, int height, bool allow_to_i420) : blink::WebRtcVideoFrameAdapter( - media::VideoFrame::CreateBlackFrame(gfx::Size(480, 360)), - base::MakeRefCounted<WebRtcVideoFrameAdapter::SharedResources>( - nullptr)), + media::VideoFrame::CreateBlackFrame(gfx::Size(480, 360))), width_(width), height_(height), allow_to_i420_(allow_to_i420), @@ -1320,12 +1318,8 @@ ASSERT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_encoder_->InitEncode(&codec, kVideoEncoderSettings)); -#if !BUILDFLAG(IS_WIN) auto frame = media::VideoFrame::CreateBlackFrame( gfx::Size(kInputFrameWidth, kInputFrameHeight)); -#else - auto frame = media::VideoFrame::CreateEOSFrame(); -#endif frame->set_timestamp(base::Milliseconds(1)); webrtc::scoped_refptr<webrtc::VideoFrameBuffer> frame_adapter( new webrtc::RefCountedObject<WebRtcVideoFrameAdapter>(
diff --git a/third_party/blink/renderer/platform/wtf/pod_interval.h b/third_party/blink/renderer/platform/wtf/pod_interval.h index 0ba0816..13f9869 100644 --- a/third_party/blink/renderer/platform/wtf/pod_interval.h +++ b/third_party/blink/renderer/platform/wtf/pod_interval.h
@@ -33,6 +33,13 @@ #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/gc_plugin.h" +#ifndef NDEBUG +namespace blink { +template <class T> +struct ValueToString; +} +#endif + namespace WTF { // Class representing a closed interval which can hold an arbitrary @@ -64,20 +71,14 @@ // available: // // template<> struct ValueToString<T> { -// static String toString(const T& t); +// static String ToString(const T& t); // }; // template<> struct ValueToString<UserData> { -// static String toString(const UserData& t); +// static String ToString(const UserData& t); // }; // // Note that this class requires a copy constructor and assignment // operator in order to be stored in the red-black tree. - -#ifndef NDEBUG -template <class T> -struct ValueToString; -#endif - template <class T, class UserData = void*> class PODInterval { DISALLOW_NEW(); @@ -131,15 +132,15 @@ String ToString() const { StringBuilder builder; builder.Append("[PODInterval ("); - builder.Append(ValueToString<T>::ToString(Low())); + builder.Append(blink::ValueToString<T>::ToString(Low())); builder.Append(", "); - builder.Append(ValueToString<T>::ToString(High())); + builder.Append(blink::ValueToString<T>::ToString(High())); builder.Append("), data="); - builder.Append(ValueToString<UserData>::ToString(Data())); + builder.Append(blink::ValueToString<UserData>::ToString(Data())); builder.Append(", minLow="); - builder.Append(ValueToString<T>::ToString(MinLow())); + builder.Append(blink::ValueToString<T>::ToString(MinLow())); builder.Append(", maxHigh="); - builder.Append(ValueToString<T>::ToString(MaxHigh())); + builder.Append(blink::ValueToString<T>::ToString(MaxHigh())); builder.Append(']'); return builder.ToString(); } @@ -153,7 +154,10 @@ T max_high_; }; +} // namespace WTF + #ifndef NDEBUG +namespace blink { template <> struct ValueToString<float> { STATIC_ONLY(ValueToString); @@ -167,8 +171,7 @@ struct ValueToString<int> { static String ToString(const int& value) { return String::Number(value); } }; +} // namespace blink #endif -} // namespace WTF - #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_POD_INTERVAL_H_
diff --git a/third_party/blink/renderer/platform/wtf/pod_interval_tree.h b/third_party/blink/renderer/platform/wtf/pod_interval_tree.h index 2d58b5d..ce2da06 100644 --- a/third_party/blink/renderer/platform/wtf/pod_interval_tree.h +++ b/third_party/blink/renderer/platform/wtf/pod_interval_tree.h
@@ -33,21 +33,16 @@ #include "third_party/blink/renderer/platform/wtf/pod_red_black_tree.h" #include "third_party/blink/renderer/platform/wtf/vector.h" -namespace WTF { - -#ifndef NDEBUG -template <class T> -struct ValueToString; -#endif +namespace blink { template <class T, class UserData = void*> -class PODIntervalSearchAdapter { +class PodIntervalSearchAdapter { DISALLOW_NEW(); public: - typedef PODInterval<T, UserData> IntervalType; + using IntervalType = WTF::PODInterval<T, UserData>; - PODIntervalSearchAdapter(Vector<IntervalType>& result, + PodIntervalSearchAdapter(Vector<IntervalType>& result, const T& low_value, const T& high_value) : result_(result), low_value_(low_value), high_value_(high_value) {} @@ -69,27 +64,28 @@ // supports efficient (O(lg n)) insertion, removal and querying of // intervals in the tree. template <class T, class UserData = void*> -class PODIntervalTree final : public PODRedBlackTree<PODInterval<T, UserData>> { +class PodIntervalTree final + : public WTF::PODRedBlackTree<WTF::PODInterval<T, UserData>> { public: // Typedef to reduce typing when declaring intervals to be stored in // this tree. - typedef PODInterval<T, UserData> IntervalType; - typedef PODIntervalSearchAdapter<T, UserData> IntervalSearchAdapterType; + using IntervalType = WTF::PODInterval<T, UserData>; + using IntervalSearchAdapterType = PodIntervalSearchAdapter<T, UserData>; - PODIntervalTree(UninitializedTreeEnum unitialized_tree) - : PODRedBlackTree<IntervalType>(unitialized_tree) { + explicit PodIntervalTree(WTF::UninitializedTreeEnum unitialized_tree) + : WTF::PODRedBlackTree<IntervalType>(unitialized_tree) { Init(); } - PODIntervalTree() : PODRedBlackTree<IntervalType>() { Init(); } + PodIntervalTree() : WTF::PODRedBlackTree<IntervalType>() { Init(); } - explicit PODIntervalTree(scoped_refptr<PODArena> arena) - : PODRedBlackTree<IntervalType>(arena) { + explicit PodIntervalTree(scoped_refptr<WTF::PODArena> arena) + : WTF::PODRedBlackTree<IntervalType>(arena) { Init(); } - PODIntervalTree(const PODIntervalTree&) = delete; - PODIntervalTree& operator=(const PODIntervalTree&) = delete; + PodIntervalTree(const PodIntervalTree&) = delete; + PodIntervalTree& operator=(const PodIntervalTree&) = delete; // Returns all intervals in the tree which overlap the given query // interval. The returned intervals are sorted by increasing low @@ -126,8 +122,9 @@ } bool CheckInvariants() const override { - if (!PODRedBlackTree<IntervalType>::CheckInvariants()) + if (!WTF::PODRedBlackTree<IntervalType>::CheckInvariants()) { return false; + } if (!this->Root()) return true; return CheckInvariantsFromNode(this->Root()); @@ -140,7 +137,7 @@ } private: - typedef typename PODRedBlackTree<IntervalType>::Node IntervalNode; + using IntervalNode = typename WTF::PODRedBlackTree<IntervalType>::Node; // Initializes the tree. void Init() { @@ -323,7 +320,7 @@ #ifndef NDEBUG static void LogVerificationFailedAtNode(IntervalNode const* node) { - DLOG(ERROR) << "PODIntervalTree verification failed at node " << node + DLOG(ERROR) << "PodIntervalTree verification failed at node " << node << ": data=" << node->Data().ToString(); } #else @@ -334,13 +331,13 @@ #ifndef NDEBUG // Support for printing PODIntervals at the PODRedBlackTree level. template <class T, class UserData> -struct ValueToString<PODInterval<T, UserData>> { - static String ToString(const PODInterval<T, UserData>& interval) { +struct ValueToString<WTF::PODInterval<T, UserData>> { + static String ToString(const WTF::PODInterval<T, UserData>& interval) { return interval.ToString(); } }; #endif -} // namespace WTF +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_POD_INTERVAL_TREE_H_
diff --git a/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc b/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc index 8a00fa0..12b2c1bd 100644 --- a/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc +++ b/third_party/blink/renderer/platform/wtf/pod_interval_tree_test.cc
@@ -34,10 +34,11 @@ #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/vector.h" -namespace WTF { +namespace blink { -using tree_test_helpers::InitRandom; -using tree_test_helpers::NextRandom; +using WTF::PODInterval; +using WTF::tree_test_helpers::InitRandom; +using WTF::tree_test_helpers::NextRandom; #ifndef NDEBUG template <> @@ -48,14 +49,14 @@ }; #endif -TEST(PODIntervalTreeTest, TestInsertion) { - PODIntervalTree<float> tree; +TEST(PodIntevalTreeTest, TestInsertion) { + PodIntervalTree<float> tree; tree.Add(PODInterval<float>(2, 4)); ASSERT_TRUE(tree.CheckInvariants()); } -TEST(PODIntervalTreeTest, TestInsertionAndQuery) { - PODIntervalTree<float> tree; +TEST(PodIntevalTreeTest, TestInsertionAndQuery) { + PodIntervalTree<float> tree; tree.Add(PODInterval<float>(2, 4)); ASSERT_TRUE(tree.CheckInvariants()); Vector<PODInterval<float>> overlap = @@ -80,8 +81,8 @@ EXPECT_FALSE(next_point.has_value()); } -TEST(PODIntervalTreeTest, TestQueryAgainstZeroSizeInterval) { - PODIntervalTree<float> tree; +TEST(PodIntevalTreeTest, TestQueryAgainstZeroSizeInterval) { + PodIntervalTree<float> tree; tree.Add(PODInterval<float>(1, 2.5)); tree.Add(PODInterval<float>(3.5, 5)); tree.Add(PODInterval<float>(2, 4)); @@ -102,11 +103,11 @@ }; #endif -TEST(PODIntervalTreeTest, TestDuplicateElementInsertion) { - PODIntervalTree<float, int*> tree; +TEST(PodIntevalTreeTest, TestDuplicateElementInsertion) { + PodIntervalTree<float, int*> tree; int tmp1 = 1; int tmp2 = 2; - typedef PODIntervalTree<float, int*>::IntervalType IntervalType; + using IntervalType = PodIntervalTree<float, int*>::IntervalType; IntervalType interval1(1, 3, &tmp1); IntervalType interval2(1, 3, &tmp2); tree.Add(interval1); @@ -143,8 +144,8 @@ }; #endif -TEST(PODIntervalTreeTest, TestInsertionOfComplexUserData) { - PODIntervalTree<float, UserData1> tree; +TEST(PodIntevalTreeTest, TestInsertionOfComplexUserData) { + PodIntervalTree<float, UserData1> tree; UserData1 data1; data1.a = 5; data1.b = 6; @@ -152,8 +153,8 @@ ASSERT_TRUE(tree.CheckInvariants()); } -TEST(PODIntervalTreeTest, TestQueryingOfComplexUserData) { - PODIntervalTree<float, UserData1> tree; +TEST(PodIntevalTreeTest, TestQueryingOfComplexUserData) { + PodIntervalTree<float, UserData1> tree; UserData1 data1; data1.a = 5; data1.b = 6; @@ -204,8 +205,8 @@ }; #endif -TEST(PODIntervalTreeTest, TestTreeDoesNotRequireMostOperators) { - PODIntervalTree<EndpointType1> tree; +TEST(PodIntevalTreeTest, TestTreeDoesNotRequireMostOperators) { + PodIntervalTree<EndpointType1> tree; tree.Add(tree.CreateInterval(EndpointType1(1), EndpointType1(2))); ASSERT_TRUE(tree.CheckInvariants()); } @@ -220,7 +221,7 @@ InitRandom(seed); int maximum_value = tree_size; // Build the tree - PODIntervalTree<int> tree; + PodIntervalTree<int> tree; Vector<PODInterval<int>> added_elements; Vector<PODInterval<int>> removed_elements; for (int i = 0; i < tree_size; i++) { @@ -289,18 +290,18 @@ } // anonymous namespace -TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest1) { +TEST(PodIntevalTreeTest, RandomDeletionAndInsertionRegressionTest1) { TreeInsertionAndDeletionTest(13972, 100); } -TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest2) { +TEST(PodIntevalTreeTest, RandomDeletionAndInsertionRegressionTest2) { TreeInsertionAndDeletionTest(1283382113, 10); } -TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest3) { +TEST(PodIntevalTreeTest, RandomDeletionAndInsertionRegressionTest3) { // This is the sequence of insertions and deletions that triggered // the failure in RandomDeletionAndInsertionRegressionTest2. - PODIntervalTree<int> tree; + PodIntervalTree<int> tree; tree.Add(tree.CreateInterval(0, 5)); ASSERT_TRUE(tree.CheckInvariants()); tree.Add(tree.CreateInterval(4, 5)); @@ -335,10 +336,10 @@ ASSERT_TRUE(tree.CheckInvariants()); } -TEST(PODIntervalTreeTest, RandomDeletionAndInsertionRegressionTest4) { +TEST(PodIntevalTreeTest, RandomDeletionAndInsertionRegressionTest4) { // Even further reduced test case for // RandomDeletionAndInsertionRegressionTest3. - PODIntervalTree<int> tree; + PodIntervalTree<int> tree; tree.Add(tree.CreateInterval(0, 5)); ASSERT_TRUE(tree.CheckInvariants()); tree.Add(tree.CreateInterval(8, 9)); @@ -353,4 +354,4 @@ ASSERT_TRUE(tree.CheckInvariants()); } -} // namespace WTF +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h b/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h index f1d753b..2c65a71 100644 --- a/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h +++ b/third_party/blink/renderer/platform/wtf/pod_red_black_tree.h
@@ -80,13 +80,15 @@ #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #endif -namespace WTF { - #ifndef NDEBUG +namespace blink { template <class T> struct ValueToString; +} #endif +namespace WTF { + enum UninitializedTreeEnum { kUninitializedTree }; template <class T> @@ -776,7 +778,7 @@ builder.Append('-'); if (node) { builder.Append(' '); - builder.Append(ValueToString<T>::GetString(node->Data())); + builder.Append(blink::ValueToString<T>::GetString(node->Data())); builder.Append((node->GetColor() == kBlack) ? " (black)" : " (red)"); } DLOG(ERROR) << builder.ToString();
diff --git a/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h b/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h index fd36446..127617b 100644 --- a/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h +++ b/third_party/blink/renderer/platform/wtf/text/ascii_fast_path.h
@@ -32,17 +32,16 @@ #include "base/dcheck_is_on.h" #include "base/types/zip.h" #include "build/build_config.h" -#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/text/ascii_ctype.h" #include "third_party/blink/renderer/platform/wtf/text/character_visitor.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_uchar.h" #include "third_party/blink/renderer/platform/wtf/wtf_size_t.h" -namespace WTF { +namespace blink { // Assuming that a pointer is the size of a "machine word", then // uintptr_t is an integer type that is also a machine word. -typedef uintptr_t MachineWord; +using MachineWord = uintptr_t; const uintptr_t kMachineWordAlignmentMask = sizeof(MachineWord) - 1; inline bool IsAlignedToMachineWord(const void* pointer) { @@ -56,31 +55,31 @@ } template <size_t size, typename CharacterType> -struct NonASCIIMask; +struct NonAsciiMask; template <> -struct NonASCIIMask<4, UChar> { +struct NonAsciiMask<4, UChar> { static inline uint32_t Value() { return 0xFF80FF80U; } }; template <> -struct NonASCIIMask<4, LChar> { +struct NonAsciiMask<4, LChar> { static inline uint32_t Value() { return 0x80808080U; } }; template <> -struct NonASCIIMask<8, UChar> { +struct NonAsciiMask<8, UChar> { static inline uint64_t Value() { return 0xFF80FF80FF80FF80ULL; } }; template <> -struct NonASCIIMask<8, LChar> { +struct NonAsciiMask<8, LChar> { static inline uint64_t Value() { return 0x8080808080808080ULL; } }; template <typename CharacterType> -inline bool IsAllASCII(MachineWord word) { - return !(word & NonASCIIMask<sizeof(MachineWord), CharacterType>::Value()); +inline bool IsAllAscii(MachineWord word) { + return !(word & NonAsciiMask<sizeof(MachineWord), CharacterType>::Value()); } -struct ASCIIStringAttributes { - ASCIIStringAttributes(bool contains_only_ascii, bool is_lower_ascii) +struct AsciiStringAttributes { + AsciiStringAttributes(bool contains_only_ascii, bool is_lower_ascii) : contains_only_ascii(contains_only_ascii), is_lower_ascii(is_lower_ascii) {} unsigned contains_only_ascii : 1; @@ -90,7 +89,7 @@ // Note: This function assumes the input is likely all ASCII, and // does not leave early if it is not the case. template <typename CharacterType> -ALWAYS_INLINE ASCIIStringAttributes +ALWAYS_INLINE AsciiStringAttributes CharacterAttributes(base::span<const CharacterType> chars) { DCHECK_GT(chars.size(), 0u); @@ -103,11 +102,11 @@ contains_upper_case |= IsASCIIUpper(ch); } - return ASCIIStringAttributes(IsASCII(all_char_bits), !contains_upper_case); + return AsciiStringAttributes(IsASCII(all_char_bits), !contains_upper_case); } template <typename CharacterType> -ALWAYS_INLINE bool IsLowerASCII(base::span<const CharacterType> chars) { +ALWAYS_INLINE bool IsLowerAscii(base::span<const CharacterType> chars) { bool contains_upper_case = false; for (CharacterType ch : chars) { contains_upper_case |= IsASCIIUpper(ch); @@ -116,7 +115,7 @@ } template <typename CharacterType> -ALWAYS_INLINE bool IsUpperASCII(base::span<const CharacterType> chars) { +ALWAYS_INLINE bool IsUpperAscii(base::span<const CharacterType> chars) { bool contains_lower_case = false; for (CharacterType ch : chars) { contains_lower_case |= IsASCIILower(ch); @@ -128,7 +127,7 @@ public: template <typename CharType> ALWAYS_INLINE static bool IsCorrectCase(base::span<const CharType> chars) { - return IsLowerASCII(chars); + return IsLowerAscii(chars); } template <typename CharType> @@ -141,7 +140,7 @@ public: template <typename CharType> ALWAYS_INLINE static bool IsCorrectCase(base::span<const CharType> chars) { - return IsUpperASCII(chars); + return IsUpperAscii(chars); } template <typename CharType> @@ -151,7 +150,7 @@ }; template <typename StringType, typename Converter, typename Allocator> -ALWAYS_INLINE typename Allocator::ResultStringType ConvertASCIICase( +ALWAYS_INLINE typename Allocator::ResultStringType ConvertAsciiCase( const StringType& string, Converter&& converter, Allocator&& allocator) { @@ -172,14 +171,6 @@ }); } -} // namespace WTF - -// TODO(crbug.com/422768753): Remove these `using` directives. -namespace blink { -using WTF::AlignToMachineWord; -using WTF::IsAlignedToMachineWord; -using WTF::IsAllASCII; -using WTF::MachineWord; } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_ASCII_FAST_PATH_H_
diff --git a/third_party/blink/renderer/platform/wtf/text/case_map.cc b/third_party/blink/renderer/platform/wtf/text/case_map.cc index 87e3187..e0930bb 100644 --- a/third_party/blink/renderer/platform/wtf/text/case_map.cc +++ b/third_party/blink/renderer/platform/wtf/text/case_map.cc
@@ -16,7 +16,7 @@ #include "third_party/blink/renderer/platform/wtf/text/unicode.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -namespace WTF { +namespace blink { namespace { @@ -434,4 +434,4 @@ return String(); } -} // namespace WTF +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/case_map.h b/third_party/blink/renderer/platform/wtf/text/case_map.h index 8c8df61f..85770f1 100644 --- a/third_party/blink/renderer/platform/wtf/text/case_map.h +++ b/third_party/blink/renderer/platform/wtf/text/case_map.h
@@ -9,9 +9,8 @@ #include "third_party/blink/renderer/platform/wtf/text/unicode.h" #include "third_party/blink/renderer/platform/wtf/wtf_export.h" -namespace WTF { +namespace blink { -class String; class TextOffsetMap; // This class performs the full Unicode case-mapping. @@ -78,8 +77,6 @@ const char* case_map_locale_; }; -} // namespace WTF - -using WTF::CaseMap; +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_CASE_MAP_H_
diff --git a/third_party/blink/renderer/platform/wtf/text/case_map_test.cc b/third_party/blink/renderer/platform/wtf/text/case_map_test.cc index eed4a6e..e814005 100644 --- a/third_party/blink/renderer/platform/wtf/text/case_map_test.cc +++ b/third_party/blink/renderer/platform/wtf/text/case_map_test.cc
@@ -12,7 +12,7 @@ using testing::ElementsAreArray; -namespace WTF { +namespace blink { namespace { @@ -466,4 +466,4 @@ EXPECT_EQ(result6, String::FromUTF8("ja")); } -} // namespace WTF +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/string_impl.cc b/third_party/blink/renderer/platform/wtf/text/string_impl.cc index 1125b2ba..49276b1 100644 --- a/third_party/blink/renderer/platform/wtf/text/string_impl.cc +++ b/third_party/blink/renderer/platform/wtf/text/string_impl.cc
@@ -168,9 +168,9 @@ } unsigned StringImpl::ComputeASCIIFlags() const { - ASCIIStringAttributes ascii_attributes = VisitCharacters( - *this, [](auto chars) { return CharacterAttributes(chars); }); - uint32_t new_flags = ASCIIStringAttributesToFlags(ascii_attributes); + blink::AsciiStringAttributes ascii_attributes = VisitCharacters( + *this, [](auto chars) { return blink::CharacterAttributes(chars); }); + uint32_t new_flags = AsciiStringAttributesToFlags(ascii_attributes); const uint32_t previous_flags = hash_and_flags_.fetch_or(new_flags, std::memory_order_relaxed); static constexpr uint32_t mask = @@ -340,12 +340,12 @@ scoped_refptr<StringImpl> StringImpl::Create( base::span<const LChar> characters, - ASCIIStringAttributes ascii_attributes) { + blink::AsciiStringAttributes ascii_attributes) { scoped_refptr<StringImpl> ret = Create(characters); if (!characters.empty()) { // If length is 0 then `ret` is empty_ and should not have its // attributes calculated or changed. - uint32_t new_flags = ASCIIStringAttributesToFlags(ascii_attributes); + uint32_t new_flags = AsciiStringAttributesToFlags(ascii_attributes); ret->hash_and_flags_.fetch_or(new_flags, std::memory_order_relaxed); } @@ -447,11 +447,13 @@ }; scoped_refptr<StringImpl> StringImpl::LowerASCII() { - return ConvertASCIICase(*this, LowerConverter(), StringImplAllocator()); + return blink::ConvertAsciiCase(*this, blink::LowerConverter(), + StringImplAllocator()); } scoped_refptr<StringImpl> StringImpl::UpperASCII() { - return ConvertASCIICase(*this, UpperConverter(), StringImplAllocator()); + return blink::ConvertAsciiCase(*this, blink::UpperConverter(), + StringImplAllocator()); } scoped_refptr<StringImpl> StringImpl::Fill(UChar character) {
diff --git a/third_party/blink/renderer/platform/wtf/text/string_impl.h b/third_party/blink/renderer/platform/wtf/text/string_impl.h index 231dc71a..b94aa6a 100644 --- a/third_party/blink/renderer/platform/wtf/text/string_impl.h +++ b/third_party/blink/renderer/platform/wtf/text/string_impl.h
@@ -160,7 +160,7 @@ static scoped_refptr<StringImpl> Create(base::span<const LChar>); static scoped_refptr<StringImpl> Create( base::span<const LChar>, - ASCIIStringAttributes ascii_attributes); + blink::AsciiStringAttributes ascii_attributes); static scoped_refptr<StringImpl> Create8BitIfPossible( base::span<const UChar>); @@ -545,8 +545,8 @@ : kAsciiPropertyCheckDone | kContainsOnlyAscii | kIsLowerAscii; } - static inline uint32_t ASCIIStringAttributesToFlags( - ASCIIStringAttributes ascii_attributes) { + static inline uint32_t AsciiStringAttributesToFlags( + blink::AsciiStringAttributes ascii_attributes) { uint32_t flags = kAsciiPropertyCheckDone; if (ascii_attributes.contains_only_ascii) flags |= kContainsOnlyAscii;
diff --git a/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc b/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc index ac36b5cc..96b788f 100644 --- a/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc +++ b/third_party/blink/renderer/platform/wtf/text/string_impl_test.cc
@@ -64,7 +64,7 @@ test_string_impl.get(), StringImpl::Create(base::span_from_cstring("lInk"))->LowerASCII().get())); - CaseMap case_map(g_empty_atom); + blink::CaseMap case_map(g_empty_atom); EXPECT_TRUE(Equal( case_map.ToLower(StringImpl::Create(base::span_from_cstring("LINK"))) .Impl(), @@ -137,7 +137,7 @@ test_string_impl.get(), StringImpl::Create(base::span_from_cstring("lInk"))->UpperASCII().get())); - CaseMap case_map(g_empty_atom); + blink::CaseMap case_map(g_empty_atom); EXPECT_TRUE(Equal( case_map.ToUpper(StringImpl::Create(base::span_from_cstring("LINK"))) .Impl(),
diff --git a/third_party/blink/renderer/platform/wtf/text/string_view.cc b/third_party/blink/renderer/platform/wtf/text/string_view.cc index 47a54b2..01dd5c25 100644 --- a/third_party/blink/renderer/platform/wtf/text/string_view.cc +++ b/third_party/blink/renderer/platform/wtf/text/string_view.cc
@@ -165,7 +165,7 @@ return impl->IsLowerASCII(); } return VisitCharacters(*this, - [](auto chars) { return WTF::IsLowerASCII(chars); }); + [](auto chars) { return blink::IsLowerAscii(chars); }); } bool StringView::ContainsOnlyASCIIOrEmpty() const { @@ -173,8 +173,8 @@ return impl->ContainsOnlyASCIIOrEmpty(); if (empty()) return true; - ASCIIStringAttributes attrs = VisitCharacters( - *this, [](auto chars) { return CharacterAttributes(chars); }); + blink::AsciiStringAttributes attrs = VisitCharacters( + *this, [](auto chars) { return blink::CharacterAttributes(chars); }); return attrs.contains_only_ascii; } @@ -298,8 +298,8 @@ StringView StringView::LowerASCIIMaybeUsingBuffer( StackBackingStore& buffer) const { - return ConvertASCIICase(*this, LowerConverter(), - StackStringViewAllocator(buffer)); + return blink::ConvertAsciiCase(*this, blink::LowerConverter(), + StackStringViewAllocator(buffer)); } UChar32 StringView::CodepointAt(unsigned i) const {
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 a10ae79..38d07fc 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
@@ -84,11 +84,11 @@ }; inline void CopyAsciiMachineWord(LChar* destination, const uint8_t* source) { - UCharByteFiller<sizeof(WTF::MachineWord)>::Copy(destination, source); + UCharByteFiller<sizeof(MachineWord)>::Copy(destination, source); } inline void CopyAsciiMachineWord(UChar* destination, const uint8_t* source) { - UCharByteFiller<sizeof(WTF::MachineWord)>::Copy(destination, source); + UCharByteFiller<sizeof(MachineWord)>::Copy(destination, source); } } // 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 cabf8d1..82569e6 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
@@ -132,8 +132,9 @@ while (source < aligned_end) { MachineWord chunk = *reinterpret_cast_ptr<const MachineWord*>(source); - if (!IsAllASCII<LChar>(chunk)) + if (!IsAllAscii<LChar>(chunk)) { goto useLookupTable; + } CopyAsciiMachineWord(destination, source); source += sizeof(MachineWord); @@ -184,8 +185,9 @@ while (source < aligned_end) { MachineWord chunk = *reinterpret_cast_ptr<const MachineWord*>(source); - if (!IsAllASCII<LChar>(chunk)) + if (!IsAllAscii<LChar>(chunk)) { goto useLookupTable16; + } CopyAsciiMachineWord(destination16, source); source += sizeof(MachineWord);
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 29aadbd..3f8d0222 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
@@ -399,8 +399,9 @@ while (source.data() < aligned_end) { MachineWord chunk = *reinterpret_cast_ptr<const MachineWord*>(source.data()); - if (!IsAllASCII<LChar>(chunk)) + if (!IsAllAscii<LChar>(chunk)) { break; + } CopyAsciiMachineWord( destination.take_first<sizeof(MachineWord)>().data(), source.take_first<sizeof(MachineWord)>().data()); @@ -485,8 +486,9 @@ while (source.data() < aligned_end) { MachineWord chunk = *reinterpret_cast_ptr<const MachineWord*>(source.data()); - if (!IsAllASCII<LChar>(chunk)) + if (!IsAllAscii<LChar>(chunk)) { break; + } CopyAsciiMachineWord( destination16.take_first<sizeof(MachineWord)>().data(),
diff --git a/third_party/blink/renderer/platform/wtf/text/text_offset_map.cc b/third_party/blink/renderer/platform/wtf/text/text_offset_map.cc index a4c81319..7fd3e208 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_offset_map.cc +++ b/third_party/blink/renderer/platform/wtf/text/text_offset_map.cc
@@ -6,7 +6,7 @@ #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -namespace WTF { +namespace blink { std::ostream& operator<<(std::ostream& stream, const TextOffsetMap::Entry& entry) { @@ -142,4 +142,4 @@ return map; } -} // namespace WTF +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/text_offset_map.h b/third_party/blink/renderer/platform/wtf/text/text_offset_map.h index 5b86ba6..205401c5 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_offset_map.h +++ b/third_party/blink/renderer/platform/wtf/text/text_offset_map.h
@@ -11,7 +11,7 @@ #include "third_party/blink/renderer/platform/wtf/vector.h" #include "third_party/blink/renderer/platform/wtf/wtf_export.h" -namespace WTF { +namespace blink { // Represents a mapping of text offset when |CaseMap| changes the length of the // input string. Similar to [icu::Edits], but tracks only when the length @@ -75,8 +75,6 @@ std::ostream& stream, const Vector<TextOffsetMap::Entry>& entries); -} // namespace WTF - -using WTF::TextOffsetMap; +} // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_TEXT_OFFSET_MAP_H_
diff --git a/third_party/blink/renderer/platform/wtf/text/text_offset_map_test.cc b/third_party/blink/renderer/platform/wtf/text/text_offset_map_test.cc index 6715313..ddcd2558 100644 --- a/third_party/blink/renderer/platform/wtf/text/text_offset_map_test.cc +++ b/third_party/blink/renderer/platform/wtf/text/text_offset_map_test.cc
@@ -9,7 +9,7 @@ #include "third_party/blink/renderer/platform/wtf/text/case_map.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -namespace WTF { +namespace blink { TEST(TextOffsetMapTest, MergeConstructor) { using Entry = TextOffsetMap::Entry; @@ -116,4 +116,4 @@ EXPECT_EQ(1000u, length_map[0]); } -} // namespace WTF +} // namespace blink
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.cc b/third_party/blink/renderer/platform/wtf/text/wtf_string.cc index 8f0135d2..7eb8b912 100644 --- a/third_party/blink/renderer/platform/wtf/text/wtf_string.cc +++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.cc
@@ -131,7 +131,7 @@ String String::DeprecatedLower() const { if (!impl_) return String(); - return CaseMap::FastToLowerInvariant(impl_.get()); + return blink::CaseMap::FastToLowerInvariant(impl_.get()); } String String::LowerASCII() const { @@ -468,7 +468,7 @@ if (!length) return g_empty_string; - ASCIIStringAttributes attributes = CharacterAttributes(bytes); + blink::AsciiStringAttributes attributes = blink::CharacterAttributes(bytes); if (attributes.contains_only_ascii) return StringImpl::Create(bytes, attributes);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-button-event-target.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-button-event-target.html new file mode 100644 index 0000000..f9be3f4f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-button-event-target.html
@@ -0,0 +1,60 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Overflow: event.target and event.currentTarget for ::scroll-button is scroller</title> +<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#active-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<style> + body { + margin: 0; + } + + #scroller { + width: 600px; + height: 300px; + overflow: auto; + white-space: nowrap; + } + + #scroller div { + display: inline-block; + width: 600px; + height: 270px; + } + + #scroller::scroll-button(inline-end) { + position: absolute; + top: 0; + left: 0; + content: ""; + width: 100px; + height: 20px; + } +</style> +<div id="scroller"> + <div></div> + <div></div> +</div> +<script> + var target; + var currentTarget; + + scroller.addEventListener('click', (e) => { + target = e.target; + currentTarget = e.currentTarget; + }); + + promise_test(async t => { + actions_promise = new test_driver.Actions() + .pointerMove(15, 15) + .pointerDown() + .pointerUp() + .send(); + await actions_promise; + assert_equals(currentTarget, scroller, "event.currentTarget for ::scroll-button click is scroller"); + assert_equals(target, scroller, "event.target for ::scroll-button click is scroller"); + }); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-marker-event-target.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-marker-event-target.html new file mode 100644 index 0000000..ed862d0c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/scroll-marker-event-target.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Overflow: event.target and event.currentTarget for ::scroll-marker is scroller</title> +<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#active-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<style> + body { + margin: 0; + } + + #scroller { + width: 600px; + height: 300px; + overflow: auto; + scroll-marker-group: before; + white-space: nowrap; + } + + #scroller div { + display: inline-block; + width: 600px; + height: 270px; + } + + #scroller::scroll-marker-group { + display: flex; + height: 20px; + width: 40px; + } + + #scroller div::scroll-marker { + content: ""; + width: 100px; + height: 20px; + display: inline-block; + } +</style> +<div id="scroller"> + <div></div> + <div></div> +</div> +<script> + var target; + var currentTarget; + + scroller.addEventListener('click', (e) => { + target = e.target; + currentTarget = e.currentTarget; + }); + + promise_test(async t => { + actions_promise = new test_driver.Actions() + .pointerMove(15, 15) + .pointerDown() + .pointerUp() + .send(); + await actions_promise; + assert_equals(currentTarget, scroller, "event.currentTarget for ::scroll-marker click is scroller"); + assert_equals(target, scroller, "event.target for ::scroll-marker click is scroller"); + }); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/wasm/OWNERS b/third_party/blink/web_tests/external/wpt/wasm/OWNERS index 67907d6..088ab44 100644 --- a/third_party/blink/web_tests/external/wpt/wasm/OWNERS +++ b/third_party/blink/web_tests/external/wpt/wasm/OWNERS
@@ -1 +1,3 @@ +jkummerow@chromium.org +clemensb@chromium.org ahaas@chromium.org
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-cross-origin-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-cross-origin-expected.txt new file mode 100644 index 0000000..4115c04 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-cross-origin-expected.txt
@@ -0,0 +1,5 @@ +Verifies that cached cross-origin responses contain correct headers + +response code=200 +response code=304 +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-cross-origin.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-cross-origin.js new file mode 100644 index 0000000..a0c1aa97 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/extra-info-cross-origin.js
@@ -0,0 +1,22 @@ +(async function(/** @type {import('test_runner').TestRunner} */ testRunner) { + const {session, dp} = await testRunner.startURL( + '../resources/test-page.html', + `Verifies that cached cross-origin responses contain correct headers\n`); + + await dp.Network.enable(); + + dp.Network.onResponseReceivedExtraInfo(event => { + testRunner.log('response code=' + event.params.statusCode); + }); + + async function fetch() { + await session.evaluateAsync(async (url) => { + await fetch(url); + }, testRunner.url('http://devtools.oopif.test:8000/inspector-protocol/network/resources/cached-revalidate.php')); + } + + await fetch(); // initial response is a 200. + await fetch(); // subsequent response is a 304. + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/cached-revalidate.php b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/cached-revalidate.php new file mode 100644 index 0000000..0a834aa --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network/resources/cached-revalidate.php
@@ -0,0 +1,18 @@ +<?php + $HTTP_IF_NON_MATCH = $_SERVER["HTTP_IF_NONE_MATCH"] ?? null; + if ($HTTP_IF_NON_MATCH) { + header("HTTP/1.0 304 Not Modified"); + header("Access-Control-Allow-Origin: *"); + exit; + } + + header("ETag: \"ABC\""); + header("Access-Control-Allow-Origin: *"); + header("Cache-Control: max-age=0;must-revalidate"); + header("Content-Type: text/html; charset=UTF-8"); +?> +<html> +<body> +Today's lucky number: <?php echo(rand()) ?> +</body> +</body>
diff --git a/third_party/blink/web_tests/wpt_internal/reduce_screen_size/screen.https.window.js b/third_party/blink/web_tests/wpt_internal/reduce_screen_size/screen.https.window.js index ed4d7fc0..2902eb9 100644 --- a/third_party/blink/web_tests/wpt_internal/reduce_screen_size/screen.https.window.js +++ b/third_party/blink/web_tests/wpt_internal/reduce_screen_size/screen.https.window.js
@@ -1,11 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/subset-tests-by-key.js +// META: variant=?include=denied +// META: variant=?include=granted + // Testing the impact of the `ReduceScreenSize` flag. -// Opens a new 300x400 window to `about:blank`, positioned at (100,200). -function open_window(test) { - let popup = window.open("", "_blank", "popup, left=100, top=200, width=300, height=400"); +// Opens a new 300x400 window positioned at (100,200), and wait for its notification. +async function open_window(test) { + let popup_promise = async _ => { + return new Promise(resolve => { + let w = window.open("/html/browsers/windows/resources/post-to-opener.html", "_blank", "popup, left=100, top=200, width=300, height=400"); + window.addEventListener('message', e => { + if (e.source === w) { + assert_equals(w.innerWidth, 300, "Inner Width"); + assert_equals(w.innerHeight, 400, "Inner Height"); + assert_equals(typeof w.screen, "object", "Screen available."); - assert_equals(popup.innerWidth, 300, "Inner Width"); - assert_equals(popup.innerHeight, 400, "Inner Height"); + resolve(w); + } + }); + }); + }; + const popup = await popup_promise(); test.add_cleanup(() => { popup.close(); @@ -14,58 +31,99 @@ return popup; } -test(t => { - let popup = open_window(t); - assert_not_equals(popup.screen.width, popup.innerWidth, "Width"); - assert_not_equals(popup.screen.height, popup.innerHeight, "Height"); - assert_not_equals(popup.screen.availWidth, popup.innerWidth, "Avail Width"); - assert_not_equals(popup.screen.availHeight, popup.innerHeight, "Avail Height"); +const FLAG_ENABLED = true; +const FLAG_DISABLED = false; - // Media Queries - // - // If we're not reducing size information, then `device-width` will be - // larger than `innerWidth`, so asking for a minimum width that's just wider will pass. - assert_true(popup.matchMedia(`(min-device-width: ${popup.innerWidth + 1}px)`).matches, "Device Width"); - assert_true(popup.matchMedia(`(min-device-height: ${popup.innerHeight + 1}px)`).matches, "Device Height"); +const PERMISSION_GRANTED = 'granted'; +const PERMISSION_DENIED = 'denied'; - // `window.screen*` doesn't work in content_shell (and we force content_shell - // for `wpt_internal` tests). - // - // assert_equals(popup.screenX, 100, "screenX"); - // assert_equals(popup.screenLeft, 100, "screenLeft"); - // assert_equals(popup.screenY, 200, "screenY"); - // assert_equals(popup.screenTop, 200, "screenY"); - // - // TODO: There doesn't seem to be any way to pretend that `isExtended` should - // be true, which makes it hard to test in its unreduced state. - // - // TODO: There doesn't seem to be any way to pretend that the color depth is - // anything other than the default value. -}, "Verify default behavior."); +const EXPECT_REDUCTION = true; +const EXPECT_NO_REDUCTION = false; -test(t => { - internals.runtimeFlags.reduceScreenSizeEnabled = true; +function generate_test(flagState, permissionState, expectReduction) { + subsetTestByKey(permissionState, promise_test, async t => { + // Set the runtime flag here so it will take effect when the popup loads: + internals.runtimeFlags.reduceScreenSizeEnabled = flagState; - let popup = open_window(t); - assert_equals(popup.screen.width, popup.innerWidth, "Width"); - assert_equals(popup.screen.height, popup.innerHeight, "Height"); - assert_equals(popup.screen.availWidth, popup.innerWidth, "Avail Width"); - assert_equals(popup.screen.availHeight, popup.innerHeight, "Avail Height"); + // Open the popup for testing: + let popup = await open_window(t); - assert_equals(popup.screenX, 0, "screenX"); - assert_equals(popup.screenLeft, 0, "screenLeft"); - assert_equals(popup.screenY, 0, "screenY"); - assert_equals(popup.screenTop, 0, "screenY"); + const permission = await navigator.permissions.query({ name: "window-management" }); + assert_equals(permission.state, permissionState); - assert_false(popup.screen.isExtended, "isExtended"); + if (expectReduction === EXPECT_REDUCTION) { + // When reducing the available information: + // + // 1. Screen heights and widths should match the window's height + // and width. + assert_equals(popup.screen.width, popup.innerWidth, "Width"); + assert_equals(popup.screen.height, popup.innerHeight, "Height"); + assert_equals(popup.screen.availWidth, popup.innerWidth, "Avail Width"); + assert_equals(popup.screen.availHeight, popup.innerHeight, "Avail Height"); + assert_true(popup.matchMedia(`(device-width: ${popup.innerWidth}px)`).matches, "Device Width") + assert_true(popup.matchMedia(`(device-height: ${popup.innerHeight}px)`).matches, "Device Height"); - assert_equals(popup.screen.colorDepth, 24, "Color Depth"); - assert_equals(popup.screen.pixelDepth, 24, "Pixel Depth"); + // 2. Windows should all appear positioned at the top-left corner. + assert_equals(popup.screenX, 0, "screenX"); + assert_equals(popup.screenLeft, 0, "screenLeft"); + assert_equals(popup.screenY, 0, "screenY"); + assert_equals(popup.screenTop, 0, "screenY"); - // Media Queries - // - // If we're reducing size information, then `device-width` will be - // `innerWidth`, so asking for a minimum width that's just wider will fail. - assert_false(popup.matchMedia(`(min-device-width: ${popup.innerWidth + 1}px)`).matches, "Device Width") - assert_false(popup.matchMedia(`(min-device-height: ${popup.innerHeight + 1}px)`).matches, "Device Height"); -}, "Verify reduced behavior."); + // 3. No information about secondary screens should be available. + assert_false(popup.screen.isExtended, "isExtended"); + + // 4. Color/pixel depth is 24. + assert_equals(popup.screen.colorDepth, 24, "Color Depth"); + assert_equals(popup.screen.pixelDepth, 24, "Pixel Depth"); + } else { + // Height/Width + assert_not_equals(popup.screen.width, popup.innerWidth, "Width"); + assert_not_equals(popup.screen.height, popup.innerHeight, "Height"); + assert_not_equals(popup.screen.availWidth, popup.innerWidth, "Avail Width"); + assert_not_equals(popup.screen.availHeight, popup.innerHeight, "Avail Height"); + + // If we're not reducing size information, then `device-width` will be + // larger than `innerWidth`, so asking for a minimum width that's just wider will pass. + assert_true(popup.matchMedia(`(min-device-width: ${popup.innerWidth + 1}px)`).matches, "Device Width"); + assert_true(popup.matchMedia(`(min-device-height: ${popup.innerHeight + 1}px)`).matches, "Device Height"); + + // TODO: `window.screen*` doesn't work in content_shell (and we force content_shell + // for `wpt_internal` tests). + // + // TODO: There doesn't seem to be any way to pretend that `isExtended` should + // be true, which makes it hard to test in its unreduced state. + // + // TODO: There doesn't seem to be any way to pretend that the color depth is + // anything other than the default value. + } + }, `Flag ${flagState ? "enabled" : "disabled"}, ` + + `Permission ${permissionState}: ` + + `${expectReduction ? "reduced" : "unreduced"}`); +} + +// (Ab)using the variant mechanism to set the permission status for the +// relevant tests. Since it's global state, setting it from within each +// test would otherwise risk stomping on other test's expectations: +// +// Permission Granted +// +subsetTestByKey("granted", promise_test, async _ => { + return test_driver.set_permission({name: 'window-management'}, 'granted'); + const permission = await navigator.permissions.query({ name: "window-management" }); + assert_equals(permission.state, 'granted'); +}, "Precondition: Grant permission."); + +generate_test(FLAG_DISABLED, PERMISSION_GRANTED, EXPECT_NO_REDUCTION); +generate_test(FLAG_ENABLED, PERMISSION_GRANTED, EXPECT_NO_REDUCTION); + +// +// Permission Denied +// +subsetTestByKey("denied", promise_test, async _ => { + return test_driver.set_permission({name: 'window-management'}, 'denied'); + const permission = await navigator.permissions.query({ name: "window-management" }); + assert_equals(permission.state, 'denied'); +}, "Precondition: Deny permission."); + +generate_test(FLAG_DISABLED, PERMISSION_DENIED, EXPECT_NO_REDUCTION); +generate_test(FLAG_ENABLED, PERMISSION_DENIED, EXPECT_REDUCTION);
diff --git a/third_party/compiler-rt/src b/third_party/compiler-rt/src index d3919a2..2a4f69a 160000 --- a/third_party/compiler-rt/src +++ b/third_party/compiler-rt/src
@@ -1 +1 @@ -Subproject commit d3919a20084ce47e31983ffa3724f6318f34390c +Subproject commit 2a4f69a118bdc5d03c415de1b9b166b2f1d4084f
diff --git a/third_party/crossbench b/third_party/crossbench index 6acc0ec..749d1a4 160000 --- a/third_party/crossbench +++ b/third_party/crossbench
@@ -1 +1 @@ -Subproject commit 6acc0ec6a547f0d9cfc307fedd515459d239fa24 +Subproject commit 749d1a4f48bb0ae63aa8559ef96180a677b65307
diff --git a/third_party/dawn b/third_party/dawn index d03fe7e..830dc86 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit d03fe7eda12dfce1578bf69da2814f89fd78c1e9 +Subproject commit 830dc86845102bb7c45f45ca14251b92add5dbb9
diff --git a/third_party/depot_tools b/third_party/depot_tools index ae91718..8f87843 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit ae917185501cda874f12f3e1d870de8505b0807c +Subproject commit 8f878438075a8d5d76f57bd10ab866d58d706319
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index ea58b67..fee355f 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit ea58b6707370f3b440b362fe178e7f6cd4a9170b +Subproject commit fee355f9b7f54daccee81b9ef82034656243e834
diff --git a/third_party/pdfium b/third_party/pdfium index b6457bc..1dbcd29 160000 --- a/third_party/pdfium +++ b/third_party/pdfium
@@ -1 +1 @@ -Subproject commit b6457bcccc5c86ac7159f957fa8dbea3d5e13f49 +Subproject commit 1dbcd29c45a96d9717e040662bba05395d790145
diff --git a/third_party/perfetto b/third_party/perfetto index cca1748..faeba3e 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit cca1748cb16b9dc0cac21515813c3855a983917d +Subproject commit faeba3e4b27b5adb924ece5548a61bef8013faed
diff --git a/third_party/skia b/third_party/skia index 35d5edf..47766ee 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 35d5edfa0d50984c22ff94f5438c31e0db12c6f8 +Subproject commit 47766ee60ccc6e9e0a024348192ba72391e5785e
diff --git a/tools/clang/spanify/Spanifier.cpp b/tools/clang/spanify/Spanifier.cpp index e4637e1..d01de08f 100644 --- a/tools/clang/spanify/Spanifier.cpp +++ b/tools/clang/spanify/Spanifier.cpp
@@ -1103,15 +1103,17 @@ static void DecaySpanToBooleanOp(const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const std::string& key = GetRHS(result); - const auto* operand = - result.Nodes.getNodeAs<clang::Expr>("boolean_op_operand"); if (const auto* logical_not_op = result.Nodes.getNodeAs<clang::UnaryOperator>("logical_not_op")) { + const clang::SourceRange logical_not_range{ + logical_not_op->getBeginLoc(), + logical_not_op->getBeginLoc().getLocWithOffset(1)}; EmitReplacement( - key, GetReplacementDirective(logical_not_op->getSourceRange(), "", - source_manager)); + key, GetReplacementDirective(logical_not_range, "", source_manager)); } else { + const auto* operand = + result.Nodes.getNodeAs<clang::Expr>("boolean_op_operand"); EmitReplacement(key, GetReplacementDirective(operand->getBeginLoc(), "!", source_manager)); } @@ -1300,15 +1302,13 @@ static void EmitSingleVariableSpan(const std::string& key, const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; - const clang::ASTContext& ast_context = *result.Context; - const auto& lang_opts = ast_context.getLangOpts(); + const auto& lang_opts = result.Context->getLangOpts(); - const auto* expr = result.Nodes.getNodeAs<clang::Expr>("address_expr"); - const auto* operand_decl = result.Nodes.getNodeAs<clang::DeclaratorDecl>( - "address_expr_operand_decl"); + const auto* expr = + result.Nodes.getNodeAs<clang::UnaryOperator>("address_expr"); const auto* operand_expr = result.Nodes.getNodeAs<clang::Expr>("address_expr_operand"); - if (!expr || !operand_decl || !operand_expr) { + if (!expr || !operand_expr) { llvm::errs() << "\n" "Error: EmitSingleVariableSpan() encountered an unexpected match.\n"; @@ -1316,16 +1316,24 @@ assert(false && "Unexpected match in EmitSingleVariableSpan()"); } - clang::SourceRange expr_range = {expr->getBeginLoc()}; - std::string type = GetTypeAsString(operand_decl->getType(), ast_context); - std::string replacement_text = llvm::formatv("base::span<{0}, 1>(", type); - EmitReplacement( - key, GetReplacementDirective(expr_range, replacement_text, source_manager, - kEmitSingleVariableSpanPrecedence)); + // This range is just one character, covering the '&' symbol. + clang::SourceLocation ampersand_loc = expr->getOperatorLoc(); + clang::SourceRange ampersand_range = { + ampersand_loc, clang::Lexer::getLocForEndOfToken( + ampersand_loc, 0u, source_manager, lang_opts)}; + + EmitReplacement(key, GetReplacementDirective( + ampersand_range, "base::SpanFromSingleElement(", + source_manager, kEmitSingleVariableSpanPrecedence)); EmitReplacement( key, GetReplacementDirective( getExprRange(operand_expr, source_manager, lang_opts).getEnd(), - ", 1u)", source_manager, -kEmitSingleVariableSpanPrecedence)); + ")", source_manager, -kEmitSingleVariableSpanPrecedence)); + + // Include the header for `base::SpanFromSingleElement()`. + EmitReplacement( + key, GetIncludeDirective(operand_expr->getSourceRange(), source_manager, + kBaseAutoSpanificationHelperIncludePath)); } // Rewrites unsafe third-party member function calls to helper macro calls. @@ -2836,19 +2844,24 @@ has(memberExpr().bind("data_member_expr"))) .bind("member_data_call"); - // Matchers |&var| where |var| is a local variable, a parameter or member - // field. Doesn't match when |var| is a function. + auto has_std_array_type = hasType(hasCanonicalType(hasDeclaration( + classTemplateSpecializationDecl(hasName("::std::array"))))); + + // Array excluded because it might be used as a buffer with >1 size. + auto single_var_span_exclusions = + unless(anyOf(exclusions, hasType(arrayType()), hasType(functionType()), + has_std_array_type)); + + // Matches |&var| where |var| is a local variable, a parameter or member + // field. Doesn't match when |var| is a function or an array. auto buff_address_from_single_var = unaryOperator( hasOperatorName("&"), hasUnaryOperand(anyOf( - declRefExpr(to(anyOf(varDecl(unless(exclusions)) - .bind("address_expr_operand_decl"), - parmVarDecl(unless(exclusions)) - .bind("address_expr_operand_decl")))) + declRefExpr(to(anyOf(varDecl(single_var_span_exclusions), + parmVarDecl(single_var_span_exclusions)))) .bind("address_expr_operand"), - memberExpr(member(fieldDecl(unless(exclusions)) - .bind("address_expr_operand_decl"))) + memberExpr(member(fieldDecl(single_var_span_exclusions))) .bind("address_expr_operand")))) .bind("address_expr"); @@ -2996,15 +3009,6 @@ .bind("deref_expr")); Match(deref_expression, DecaySpanToPointer); - auto rhs_exprs_without_size_nodes_ignoring_non_spelled_nodes = - traverse(clang::TK_IgnoreUnlessSpelledInSource, - expr(rhs_exprs_without_size_nodes)); - auto raw_ptr_op_bool = cxxMemberCallExpr( - on(expr().bind("boolean_op_operand")), - callee(cxxMethodDecl(hasName("operator bool"), - ofClass(hasName("raw_ptr")))), - has(memberExpr(has(expr(ignoringParenCasts( - rhs_exprs_without_size_nodes_ignoring_non_spelled_nodes)))))); // Handles boolean operations that need to be adapted after a span rewrite. // if(expr) => if(!expr.empty()) // if(!expr) => if(expr.empty()) @@ -3015,17 +3019,21 @@ // `clang::TK_IgnoreUnlessSpelledInSource`, while very useful in simplifying // the matchers, wouldn't detect boolean operations on pointers hence the // need for a hybrid traversal mode in this matcher. - auto boolean_op = expr( - anyOf( - implicitCastExpr( - hasCastKind(clang::CastKind::CK_PointerToBoolean), - hasSourceExpression( - expr( - rhs_exprs_without_size_nodes_ignoring_non_spelled_nodes) - .bind("boolean_op_operand"))), - raw_ptr_op_bool), - optionally(hasParent( - unaryOperator(hasOperatorName("!")).bind("logical_not_op")))); + auto boolean_op_operand = + traverse(clang::TK_IgnoreUnlessSpelledInSource, + expr(rhs_exprs_without_size_nodes).bind("boolean_op_operand")); + auto raw_ptr_op_bool_call_expr = + cxxMemberCallExpr(on(boolean_op_operand), + callee(cxxMethodDecl(hasName("operator bool"), + ofClass(hasName("raw_ptr"))))); + auto boolean_op = traverse( + clang::TK_AsIs, + expr(anyOf(implicitCastExpr( + hasCastKind(clang::CastKind::CK_PointerToBoolean), + hasSourceExpression(boolean_op_operand)), + implicitCastExpr(has(raw_ptr_op_bool_call_expr))), + optionally(hasParent( + unaryOperator(hasOperatorName("!")).bind("logical_not_op"))))); Match(boolean_op, DecaySpanToBooleanOp); // This is needed to remove the `.get()` call on raw_ptr from rewritten
diff --git a/tools/clang/spanify/tests/field-init-expected.cc b/tools/clang/spanify/tests/field-init-expected.cc index 95f9533..60be7cb 100644 --- a/tools/clang/spanify/tests/field-init-expected.cc +++ b/tools/clang/spanify/tests/field-init-expected.cc
@@ -4,6 +4,7 @@ #include <tuple> #include <vector> +#include "base/containers/auto_spanification_helper.h" #include "base/containers/span.h" // Expected rewrite: @@ -28,9 +29,8 @@ // base::span<int> buffer4 = getPtr(); base::span<int> buffer4 = getPtr(); // Expected rewrite: - // base::span<const int> buffer5 = base::span<const int, 1>(&default_value, - // 1u); - base::span<const int> buffer5 = base::span<const int, 1>(&default_value, 1u); + // base::span<const int> buffer5 = base::SpanFromSingleElement(default_value); + base::span<const int> buffer5 = base::SpanFromSingleElement(default_value); // Expected rewrite: // base::span<const int> buffer6 = default_data; base::span<const int> buffer6 = default_data;
diff --git a/tools/clang/spanify/tests/field-init-original.cc b/tools/clang/spanify/tests/field-init-original.cc index 77a45d73..4ecff53 100644 --- a/tools/clang/spanify/tests/field-init-original.cc +++ b/tools/clang/spanify/tests/field-init-original.cc
@@ -26,8 +26,7 @@ // base::span<int> buffer4 = getPtr(); int* buffer4 = getPtr(); // Expected rewrite: - // base::span<const int> buffer5 = base::span<const int, 1>(&default_value, - // 1u); + // base::span<const int> buffer5 = base::SpanFromSingleElement(default_value); const int* buffer5 = &default_value; // Expected rewrite: // base::span<const int> buffer6 = default_data;
diff --git a/tools/clang/spanify/tests/operator-bool-expected.cc b/tools/clang/spanify/tests/operator-bool-expected.cc index a2a4127..1c7ad8a 100644 --- a/tools/clang/spanify/tests/operator-bool-expected.cc +++ b/tools/clang/spanify/tests/operator-bool-expected.cc
@@ -70,6 +70,47 @@ // IMPLICITLY_CONVERT_TO_BOOL(!buf.empty()); IMPLICITLY_CONVERT_TO_BOOL(!buf.empty()); // Expected rewrite: + // IMPLICITLY_CONVERT_TO_BOOL(buf.empty()); + IMPLICITLY_CONVERT_TO_BOOL(buf.empty()); + // Expected rewrite: + // IMPLICITLY_CONVERT_TO_BOOL(!buf.empty()); + IMPLICITLY_CONVERT_TO_BOOL(!buf.empty()); + + // Expected rewrite: // IMPLICITLY_CONVERT_TO_BOOL(!ptr.empty()); IMPLICITLY_CONVERT_TO_BOOL(!ptr.empty()); + // Expected rewrite: + // IMPLICITLY_CONVERT_TO_BOOL(ptr.empty()); + IMPLICITLY_CONVERT_TO_BOOL(ptr.empty()); + // Expected rewrite: + // IMPLICITLY_CONVERT_TO_BOOL(!ptr.empty()); + IMPLICITLY_CONVERT_TO_BOOL(!ptr.empty()); +} + +// A function that will return a base::span. +// Expected rewrite: +// base::span<int> get_span() { +base::span<int> get_span() { + static int buf[] = {1, 2, 3}; + return buf; +} + +void test_get_span() { + // Expected rewrite: + // base::span<int> buf = get_span(); + base::span<int> buf = get_span(); + buf[0] = 0; + + // Expected rewrite: + // if (!get_span().empty()) { + if (!get_span().empty()) { + } + // Expected rewrite: + // if (get_span().empty()) { + if (get_span().empty()) { + } + // Expected rewrite: + // if (!get_span().empty()) { + if (!get_span().empty()) { + } }
diff --git a/tools/clang/spanify/tests/operator-bool-original.cc b/tools/clang/spanify/tests/operator-bool-original.cc index 5f79a68..0ea1f42 100644 --- a/tools/clang/spanify/tests/operator-bool-original.cc +++ b/tools/clang/spanify/tests/operator-bool-original.cc
@@ -68,6 +68,47 @@ // IMPLICITLY_CONVERT_TO_BOOL(!buf.empty()); IMPLICITLY_CONVERT_TO_BOOL(buf); // Expected rewrite: + // IMPLICITLY_CONVERT_TO_BOOL(buf.empty()); + IMPLICITLY_CONVERT_TO_BOOL(!buf); + // Expected rewrite: + // IMPLICITLY_CONVERT_TO_BOOL(!buf.empty()); + IMPLICITLY_CONVERT_TO_BOOL(!!buf); + + // Expected rewrite: // IMPLICITLY_CONVERT_TO_BOOL(!ptr.empty()); IMPLICITLY_CONVERT_TO_BOOL(ptr); + // Expected rewrite: + // IMPLICITLY_CONVERT_TO_BOOL(ptr.empty()); + IMPLICITLY_CONVERT_TO_BOOL(!ptr); + // Expected rewrite: + // IMPLICITLY_CONVERT_TO_BOOL(!ptr.empty()); + IMPLICITLY_CONVERT_TO_BOOL(!!ptr); +} + +// A function that will return a base::span. +// Expected rewrite: +// base::span<int> get_span() { +int* get_span() { + static int buf[] = {1, 2, 3}; + return buf; +} + +void test_get_span() { + // Expected rewrite: + // base::span<int> buf = get_span(); + int* buf = get_span(); + buf[0] = 0; + + // Expected rewrite: + // if (!get_span().empty()) { + if (get_span()) { + } + // Expected rewrite: + // if (get_span().empty()) { + if (!get_span()) { + } + // Expected rewrite: + // if (!get_span().empty()) { + if (!!get_span()) { + } }
diff --git a/tools/clang/spanify/tests/single-variable-span-expected.cc b/tools/clang/spanify/tests/single-variable-span-expected.cc index e795e29b..0caa4e7 100644 --- a/tools/clang/spanify/tests/single-variable-span-expected.cc +++ b/tools/clang/spanify/tests/single-variable-span-expected.cc
@@ -2,21 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <array> +#include <cstdint> #include <vector> // Tests related to single_element_expr matcher. +#include "base/containers/auto_spanification_helper.h" #include "base/containers/span.h" void processIntBuffer(base::span<int> buf) { std::ignore = buf[0]; } +void processUint8Buffer(base::span<uint8_t> buf) { + std::ignore = buf[0]; +} + void testPointerPassing() { int singleInt; // Expected rewrite: - // processIntBuffer(base::span<int, 1>(&singleInt, 1u)) - processIntBuffer(base::span<int, 1>(&singleInt, 1u)); + // processIntBuffer(base::SpanFromSingleElement(singleInt)); + processIntBuffer(base::SpanFromSingleElement(singleInt)); + // processUint8Buffer(base::as_writable_byte_span( + // base::SpanFromSingleElement(singleInt))); + processUint8Buffer( + base::as_writable_byte_span(base::SpanFromSingleElement(singleInt))); int intArray[10]; // Not using &. @@ -26,6 +37,14 @@ // Expected rewrite: // processIntBuffer(intArray); processIntBuffer(intArray); + // Do not rewrite because code may be expecting an buffer with >1 size. + // No rewrite expected. + processUint8Buffer(reinterpret_cast<uint8_t*>(&intArray)); + + std::array<int, 5> stdArray; + // Do not rewrite because code may be expecting an buffer with >1 size. + // No rewrite expected. + processUint8Buffer(reinterpret_cast<uint8_t*>(&stdArray)); std::vector<int> intVector; // We know how to get size from Vector so just leave it alone to @@ -33,6 +52,14 @@ // Expected rewrite: // processIntBuffer(intVector); processIntBuffer(intVector); + + void* voidPtr; + // void** should get rewritten. + // Expected rewrite: + // processUint8Buffer( + // base::as_writable_byte_span(base::SpanFromSingleElement(voidPtr))); + processUint8Buffer( + base::as_writable_byte_span(base::SpanFromSingleElement(voidPtr))); } // Function that takes a pointer to an integer pointer. @@ -43,8 +70,8 @@ void testPointerToPointerPassing() { int* singleIntPointer; // Expected rewrite: - // processIntPointerBuffer(base::span<int*, 1>(&singleIntPointer, 1u)); - processIntPointerBuffer(base::span<int*, 1>(&singleIntPointer, 1u)); + // processIntPointerBuffer(base::SpanFromSingleElement(singleIntPointer)); + processIntPointerBuffer(base::SpanFromSingleElement(singleIntPointer)); int* intArrayOfPointers[10]; // Not using &. @@ -69,12 +96,12 @@ void testFieldPointerPassing() { MyStruct myStruct; // Expected rewrite: - // processIntBuffer(base::span<int, 1>(&myStruct.field, 1u)); - processIntBuffer(base::span<int, 1>(&myStruct.field, 1u)); + // processIntBuffer(base::SpanFromSingleElement(myStruct.field)); + processIntBuffer(base::SpanFromSingleElement(myStruct.field)); } void testParamPointerPassing(int param) { // Expected rewrite: - // processIntBuffer(base::span<int, 1>(¶m, 1u)); - processIntBuffer(base::span<int, 1>(¶m, 1u)); + // processIntBuffer(base::SpanFromSingleElement(param)); + processIntBuffer(base::SpanFromSingleElement(param)); }
diff --git a/tools/clang/spanify/tests/single-variable-span-original.cc b/tools/clang/spanify/tests/single-variable-span-original.cc index b0dc29a4..ab5fa4ae 100644 --- a/tools/clang/spanify/tests/single-variable-span-original.cc +++ b/tools/clang/spanify/tests/single-variable-span-original.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <array> +#include <cstdint> #include <vector> // Tests related to single_element_expr matcher. @@ -10,11 +12,18 @@ std::ignore = buf[0]; } +void processUint8Buffer(uint8_t* buf) { + std::ignore = buf[0]; +} + void testPointerPassing() { int singleInt; // Expected rewrite: - // processIntBuffer(base::span<int, 1>(&singleInt, 1u)) + // processIntBuffer(base::SpanFromSingleElement(singleInt)); processIntBuffer(&singleInt); + // processUint8Buffer(base::as_writable_byte_span( + // base::SpanFromSingleElement(singleInt))); + processUint8Buffer(reinterpret_cast<uint8_t*>(&singleInt)); int intArray[10]; // Not using &. @@ -24,6 +33,14 @@ // Expected rewrite: // processIntBuffer(intArray); processIntBuffer(&intArray[0]); + // Do not rewrite because code may be expecting an buffer with >1 size. + // No rewrite expected. + processUint8Buffer(reinterpret_cast<uint8_t*>(&intArray)); + + std::array<int, 5> stdArray; + // Do not rewrite because code may be expecting an buffer with >1 size. + // No rewrite expected. + processUint8Buffer(reinterpret_cast<uint8_t*>(&stdArray)); std::vector<int> intVector; // We know how to get size from Vector so just leave it alone to @@ -31,6 +48,13 @@ // Expected rewrite: // processIntBuffer(intVector); processIntBuffer(&intVector[0]); + + void* voidPtr; + // void** should get rewritten. + // Expected rewrite: + // processUint8Buffer( + // base::as_writable_byte_span(base::SpanFromSingleElement(voidPtr))); + processUint8Buffer(reinterpret_cast<uint8_t*>(&voidPtr)); } // Function that takes a pointer to an integer pointer. @@ -41,7 +65,7 @@ void testPointerToPointerPassing() { int* singleIntPointer; // Expected rewrite: - // processIntPointerBuffer(base::span<int*, 1>(&singleIntPointer, 1u)); + // processIntPointerBuffer(base::SpanFromSingleElement(singleIntPointer)); processIntPointerBuffer(&singleIntPointer); int* intArrayOfPointers[10]; @@ -67,12 +91,12 @@ void testFieldPointerPassing() { MyStruct myStruct; // Expected rewrite: - // processIntBuffer(base::span<int, 1>(&myStruct.field, 1u)); + // processIntBuffer(base::SpanFromSingleElement(myStruct.field)); processIntBuffer(&myStruct.field); } void testParamPointerPassing(int param) { // Expected rewrite: - // processIntBuffer(base::span<int, 1>(¶m, 1u)); + // processIntBuffer(base::SpanFromSingleElement(param)); processIntBuffer(¶m); }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 252f07c..cbdd1b31 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -6575,12 +6575,14 @@ <int value="2" label="User leaves the interstitial by closing the page"/> </enum> +<!-- LINT.IfChange(IOSContentSizeCategory) --> + <enum name="IOSContentSizeCategory"> <int value="0" label="Unspecified"/> <int value="1" label="ExtraSmall"/> <int value="2" label="Small"/> <int value="3" label="Medium"/> - <int value="4" label="Large"/> + <int value="4" label="Large (default)"/> <int value="5" label="ExtraLarge"/> <int value="6" label="ExtraExtraLarge"/> <int value="7" label="ExtraExtraExtraLarge"/> @@ -6591,6 +6593,8 @@ <int value="12" label="AccessibilityExtraExtraExtraLarge"/> </enum> +<!-- LINT.ThenChange(//ios/components/ui_util/dynamic_type_util.h:IOSContentSizeCategory) --> + <!-- LINT.IfChange(IOSContextualPanelDismissedReason) --> <enum name="IOSContextualPanelDismissedReason"> @@ -10387,6 +10391,7 @@ <int value="-1338237485" label="HardwareSecureDecryptionExperiment:disabled"/> <int value="-1337873095" label="CompareManagementInterface:disabled"/> <int value="-1337433513" label="FilesGoogleDriveSettingsPage:disabled"/> + <int value="-1337331698" label="WebRtcPqcForDtls:enabled"/> <int value="-1337185440" label="enable-webvr"/> <int value="-1336110789" label="CastMediaRouteProvider:disabled"/> <int value="-1335360580" label="ReduceTransferSizeUpdatedIPC:enabled"/> @@ -16173,6 +16178,7 @@ <int value="816907702" label="GlobalMediaControlsSeamlessTransfer:disabled"/> <int value="817080398" label="PreinstalledWebAppDuplicationFixer:disabled"/> <int value="817393533" label="GlobalMediaControlsModernUI:disabled"/> + <int value="818248688" label="WebRtcPqcForDtls:disabled"/> <int value="819620541" label="AccessibilityManifestV3AccessibilityCommon:enabled"/> <int value="820645399"
diff --git a/tools/metrics/histograms/metadata/browser/enums.xml b/tools/metrics/histograms/metadata/browser/enums.xml index ac9280e6..fdc6d46e 100644 --- a/tools/metrics/histograms/metadata/browser/enums.xml +++ b/tools/metrics/histograms/metadata/browser/enums.xml
@@ -483,6 +483,7 @@ <int value="6" label="RefusedForPdfContent"/> <int value="7" label="RefusedForJitMismatch"/> <int value="8" label="RefusedForV8OptimizationMismatch"/> + <int value="9" label="RefusedNonNavigation"/> </enum> <!-- LINT.ThenChange(//content/browser/renderer_host/render_process_host_impl.h:SpareProcessMaybeTakeAction) -->
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml index c1c7f2c..9b797cc 100644 --- a/tools/metrics/histograms/metadata/browser/histograms.xml +++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -77,6 +77,7 @@ <variant name="RefusedForJitMismatch"/> <variant name="RefusedForPdfContent"/> <variant name="RefusedForV8OptimizationMismatch"/> + <variant name="RefusedNonNavigation"/> <variant name="SpareTaken"/> </variants>
diff --git a/tools/metrics/histograms/metadata/image/histograms.xml b/tools/metrics/histograms/metadata/image/histograms.xml index b4aaf3a..78c7ea2 100644 --- a/tools/metrics/histograms/metadata/image/histograms.xml +++ b/tools/metrics/histograms/metadata/image/histograms.xml
@@ -181,7 +181,7 @@ </histogram> <histogram name="ImageAnnotationService.AccessibilityV1.EngineKnown" - enum="BooleanKnown" expires_after="2025-07-31"> + enum="BooleanKnown" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -197,7 +197,7 @@ <histogram name="ImageAnnotationService.AccessibilityV1.ImageRequestIncludesDesc" - enum="BooleanIncluded" expires_after="2025-07-31"> + enum="BooleanIncluded" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -217,7 +217,7 @@ <histogram name="ImageAnnotationService.AccessibilityV1.ImageRequestIncludesIcon" - enum="BooleanIncluded" expires_after="2025-07-31"> + enum="BooleanIncluded" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -235,7 +235,7 @@ </histogram> <histogram name="ImageAnnotationService.AccessibilityV1.JsonParseSuccess" - enum="BooleanSuccess" expires_after="2025-07-31"> + enum="BooleanSuccess" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -250,7 +250,7 @@ </histogram> <histogram name="ImageAnnotationService.AccessibilityV1.PixelFetchSuccess" - enum="BooleanSuccess" expires_after="2025-07-31"> + enum="BooleanSuccess" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -281,7 +281,7 @@ </histogram> <histogram name="ImageAnnotationService.AccessibilityV1.ServerLatencyMs" - units="ms" expires_after="2025-07-31"> + units="ms" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -296,7 +296,7 @@ </histogram> <histogram name="ImageAnnotationService.AccessibilityV1.ServerNetError" - enum="NetErrorCodes" expires_after="2025-07-31"> + enum="NetErrorCodes" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -328,7 +328,7 @@ <histogram name="ImageAnnotationService.AccessibilityV1.ServerResponseSizeBytes" - units="bytes" expires_after="2025-07-31"> + units="bytes" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -343,7 +343,7 @@ </histogram> <histogram name="ImageAnnotationService.AccessibilityV1.SourcePixelCount" - units="pixels" expires_after="2025-07-31"> + units="pixels" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -360,7 +360,7 @@ <histogram name="ImageAnnotationService.{ImageAnnotationServiceAnnotationType}AccessibilityV1.Confidence" - units="%" expires_after="2025-07-31"> + units="%" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -379,7 +379,7 @@ <histogram name="ImageAnnotationService.{ImageAnnotationServiceAnnotationType}AccessibilityV1.Empty" - enum="BooleanEmpty" expires_after="2025-07-31"> + enum="BooleanEmpty" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner> @@ -399,7 +399,7 @@ <histogram name="ImageAnnotationService.{ImageAnnotationServiceAnnotationType}AccessibilityV1.Status" - enum="GoogleRpcCode" expires_after="2025-07-31"> + enum="GoogleRpcCode" expires_after="2026-01-31"> <owner>dtseng@chromium.org</owner> <owner>amoylan@chromium.org</owner> <owner>mschillaci@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml index fb3a36e..d2cc1e5 100644 --- a/tools/metrics/histograms/metadata/ios/histograms.xml +++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -5514,6 +5514,16 @@ </summary> </histogram> +<histogram name="IOS.System.PreferredSystemFontSize" + enum="IOSContentSizeCategory" expires_after="2026-06-01"> + <owner>jlebel@chromium.org</owner> + <owner>bling-team@google.com</owner> + <summary> + Records the preferred system font size from iOS device. Recorded at cold + start. + </summary> +</histogram> + <histogram name="IOS.TabGrid.CloseTabs" units="Tabs" expires_after="2026-06-01"> <owner>ewannpv@chromium.org</owner> <owner>gambard@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/net/enums.xml b/tools/metrics/histograms/metadata/net/enums.xml index c3623c35..a2fd27b 100644 --- a/tools/metrics/histograms/metadata/net/enums.xml +++ b/tools/metrics/histograms/metadata/net/enums.xml
@@ -2820,6 +2820,7 @@ <int value="10" label="FailedToExecute"/> <int value="11" label="InvalidData"/> <int value="12" label="AlreadyExists"/> + <int value="13" label="NotFound"/> </enum> <!-- LINT.ThenChange(//net/disk_cache/sql/sql_persistent_store.h:SqlDiskCacheStoreError) -->
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml index 2310825..e987f72 100644 --- a/tools/metrics/histograms/metadata/net/histograms.xml +++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -134,6 +134,9 @@ <variants name="SqlPersistentStoreMethodName"> <variant name="CreateEntry"/> <variant name="DeleteAllEntries"/> + <variant name="DeleteDoomedEntry"/> + <variant name="DeleteLiveEntry"/> + <variant name="DoomEntry"/> <variant name="Initialize"/> <variant name="OpenEntry"/> <variant name="OpenOrCreateEntry"/>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml index 0c94f0c..2d87339 100644 --- a/tools/metrics/histograms/metadata/network/histograms.xml +++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -5786,6 +5786,22 @@ </histogram> <histogram + name="NetworkService.Scheduler.IOThread.NumberOfPendingTasks.{QueueName}Queue" + units="count" expires_after="2025-12-25"> + <owner>hayato@chromium.org</owner> + <owner>net-dev@chromium.org</owner> + <summary> + Records the number of pending tasks in {QueueName}Queue of + NetworkServiceScheduler. Recorded with 0.001 probability when a task + scheduled on the IO thread starts. + </summary> + <token key="QueueName"> + <variant name="Default"/> + <variant name="HighPriority"/> + </token> +</histogram> + +<histogram name="NetworkService.Scheduler.IOThread.QueuingTime.{QueueName}Queue" units="ms" expires_after="2025-12-25"> <owner>hayato@chromium.org</owner>
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py index 9cd45c5..766c041 100644 --- a/tools/perf/core/bot_platforms.py +++ b/tools/perf/core/bot_platforms.py
@@ -513,6 +513,13 @@ arguments=arguments) +def _crossbench_embedder(estimated_runtime=20, arguments=None): + return CrossbenchConfig('embedder.crossbench', + 'embedder', + estimated_runtime=estimated_runtime, + arguments=arguments) + + _CROSSBENCH_JETSTREAM_SPEEDOMETER = frozenset([ _jetstream2_crossbench(), _speedometer3_crossbench(), @@ -577,6 +584,18 @@ '--stories=cnn', ] ), + _crossbench_embedder( + estimated_runtime=900, + arguments=[ + '--wpr=crossbench_android_embedder_000.wprgo', + '--embedder=com.google.android.googlequicksearchbox', + '--splashscreen=skip', + '--cuj-config=../../third_party/crossbench/config/team/woa/embedder_cuj_config.hjson', + '--probe-config=../../clank/android_webview/tools/crossbench_config/' + 'agsa_probe_config.hjson', + '--repetitions=50', + ] + ), ]) _CHROME_HEALTH_BENCHMARK_CONFIGS_DESKTOP = PerfSuite(
diff --git a/tools/perf/core/shard_maps/android-pixel4_webview-perf-pgo_map.json b/tools/perf/core/shard_maps/android-pixel4_webview-perf-pgo_map.json index 1250168..13fe069 100644 --- a/tools/perf/core/shard_maps/android-pixel4_webview-perf-pgo_map.json +++ b/tools/perf/core/shard_maps/android-pixel4_webview-perf-pgo_map.json
@@ -8,7 +8,7 @@ "abridged": false }, "blink_perf.bindings": { - "end": 46, + "end": 43, "abridged": false }, "speedometer2": { @@ -22,14 +22,11 @@ "1": { "benchmarks": { "blink_perf.bindings": { - "begin": 46, + "begin": 43, "abridged": false }, "blink_perf.css": { - "abridged": false - }, - "blink_perf.dom": { - "end": 3, + "end": 74, "abridged": false }, "speedometer2": { @@ -42,8 +39,11 @@ }, "2": { "benchmarks": { + "blink_perf.css": { + "begin": 74, + "abridged": false + }, "blink_perf.dom": { - "begin": 3, "abridged": false }, "blink_perf.events": { @@ -53,7 +53,7 @@ "abridged": false }, "blink_perf.layout": { - "end": 25, + "end": 21, "abridged": false }, "speedometer2": { @@ -67,7 +67,7 @@ "3": { "benchmarks": { "blink_perf.layout": { - "begin": 25, + "begin": 21, "end": 99, "abridged": false }, @@ -92,7 +92,10 @@ "abridged": false }, "blink_perf.shadow_dom": { - "end": 37, + "abridged": false + }, + "blink_perf.webaudio": { + "end": 1, "abridged": false }, "speedometer2": { @@ -105,11 +108,8 @@ }, "5": { "benchmarks": { - "blink_perf.shadow_dom": { - "begin": 37, - "abridged": false - }, "blink_perf.webaudio": { + "begin": 1, "abridged": false }, "blink_perf.webcodecs": { @@ -127,16 +127,6 @@ "dummy_benchmark.stable_benchmark_1": { "abridged": false }, - "media.mobile": { - "abridged": false - }, - "octane": { - "abridged": false - }, - "rasterize_and_record_micro.top_25": { - "end": 12, - "abridged": false - }, "speedometer2": { "abridged": false }, @@ -145,6 +135,17 @@ } }, "crossbench": { + "embedder": { + "display_name": "embedder.crossbench", + "arguments": [ + "--wpr=crossbench_android_embedder_000.wprgo", + "--embedder=com.google.android.googlequicksearchbox", + "--splashscreen=skip", + "--cuj-config=../../third_party/crossbench/config/team/woa/embedder_cuj_config.hjson", + "--probe-config=../../clank/android_webview/tools/crossbench_config/agsa_probe_config.hjson", + "--repetitions=50" + ] + }, "loading": { "display_name": "loading.crossbench", "arguments": [ @@ -158,12 +159,17 @@ }, "6": { "benchmarks": { + "media.mobile": { + "abridged": false + }, + "octane": { + "abridged": false + }, "rasterize_and_record_micro.top_25": { - "begin": 12, "abridged": false }, "rendering.mobile": { - "end": 46, + "end": 38, "abridged": false }, "speedometer2": { @@ -177,8 +183,8 @@ "7": { "benchmarks": { "rendering.mobile": { - "begin": 46, - "end": 96, + "begin": 38, + "end": 88, "abridged": false }, "speedometer2": { @@ -192,8 +198,8 @@ "8": { "benchmarks": { "rendering.mobile": { - "begin": 96, - "end": 155, + "begin": 88, + "end": 145, "abridged": false }, "speedometer2": { @@ -207,8 +213,8 @@ "9": { "benchmarks": { "rendering.mobile": { - "begin": 155, - "end": 208, + "begin": 145, + "end": 200, "abridged": false }, "speedometer2": { @@ -222,8 +228,8 @@ "10": { "benchmarks": { "rendering.mobile": { - "begin": 208, - "end": 267, + "begin": 200, + "end": 263, "abridged": false }, "speedometer2": { @@ -237,8 +243,8 @@ "11": { "benchmarks": { "rendering.mobile": { - "begin": 267, - "end": 328, + "begin": 263, + "end": 324, "abridged": false }, "speedometer2": { @@ -252,8 +258,8 @@ "12": { "benchmarks": { "rendering.mobile": { - "begin": 328, - "end": 377, + "begin": 324, + "end": 372, "abridged": false }, "speedometer2": { @@ -267,7 +273,7 @@ "13": { "benchmarks": { "rendering.mobile": { - "begin": 377, + "begin": 372, "abridged": false }, "rendering.mobile.notracing": { @@ -295,7 +301,7 @@ "abridged": false }, "system_health.common_mobile": { - "end": 22, + "end": 19, "abridged": false } } @@ -303,11 +309,11 @@ "14": { "benchmarks": { "system_health.common_mobile": { - "begin": 22, + "begin": 19, "abridged": false }, "system_health.memory_mobile": { - "end": 3, + "end": 1, "abridged": false }, "speedometer2": { @@ -321,8 +327,8 @@ "15": { "benchmarks": { "system_health.memory_mobile": { - "begin": 3, - "end": 25, + "begin": 1, + "end": 24, "abridged": false }, "speedometer2": { @@ -336,8 +342,8 @@ "16": { "benchmarks": { "system_health.memory_mobile": { - "begin": 25, - "end": 43, + "begin": 24, + "end": 42, "abridged": false }, "speedometer2": { @@ -351,8 +357,8 @@ "17": { "benchmarks": { "system_health.memory_mobile": { - "begin": 43, - "end": 60, + "begin": 42, + "end": 59, "abridged": false }, "speedometer2": { @@ -366,7 +372,7 @@ "18": { "benchmarks": { "system_health.memory_mobile": { - "begin": 60, + "begin": 59, "abridged": false }, "system_health.webview_startup": { @@ -400,30 +406,30 @@ } }, "extra_infos": { - "num_stories": 1115, - "predicted_min_shard_time": 2510.0, + "num_stories": 1117, + "predicted_min_shard_time": 2617.0, "predicted_min_shard_index": 19, - "predicted_max_shard_time": 3490.0, + "predicted_max_shard_time": 3606.0, "predicted_max_shard_index": 18, - "shard #0": 3075.0, - "shard #1": 3045.0, - "shard #2": 3087.0, - "shard #3": 3065.0, - "shard #4": 3080.0, - "shard #5": 3081.0, - "shard #6": 3061.0, - "shard #7": 3074.0, - "shard #8": 3077.0, - "shard #9": 3078.0, - "shard #10": 3047.0, - "shard #11": 3107.0, - "shard #12": 3073.0, - "shard #13": 3041.0, - "shard #14": 3078.0, - "shard #15": 3190.0, - "shard #16": 3052.0, - "shard #17": 3010.0, - "shard #18": 3490.0, - "shard #19": 2510.0 + "shard #0": 3092.0, + "shard #1": 3104.0, + "shard #2": 3111.0, + "shard #3": 3107.0, + "shard #4": 3071.0, + "shard #5": 3122.0, + "shard #6": 3120.0, + "shard #7": 3089.0, + "shard #8": 3102.0, + "shard #9": 3109.0, + "shard #10": 3099.0, + "shard #11": 3101.0, + "shard #12": 3130.0, + "shard #13": 3105.0, + "shard #14": 3122.0, + "shard #15": 3068.0, + "shard #16": 3200.0, + "shard #17": 3041.0, + "shard #18": 3606.0, + "shard #19": 2617.0 } }
diff --git a/tools/perf/core/shard_maps/android-pixel4_webview-perf_map.json b/tools/perf/core/shard_maps/android-pixel4_webview-perf_map.json index cb1a52a..cf58f02 100644 --- a/tools/perf/core/shard_maps/android-pixel4_webview-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel4_webview-perf_map.json
@@ -8,7 +8,7 @@ "abridged": false }, "blink_perf.bindings": { - "end": 33, + "end": 22, "abridged": false }, "speedometer2": { @@ -22,11 +22,11 @@ "1": { "benchmarks": { "blink_perf.bindings": { - "begin": 33, + "begin": 22, "abridged": false }, "blink_perf.css": { - "end": 61, + "end": 56, "abridged": false }, "speedometer2": { @@ -40,7 +40,7 @@ "2": { "benchmarks": { "blink_perf.css": { - "begin": 61, + "begin": 56, "abridged": false }, "blink_perf.dom": { @@ -49,10 +49,6 @@ "blink_perf.events": { "abridged": false }, - "blink_perf.image_decoder": { - "end": 2, - "abridged": false - }, "speedometer2": { "abridged": false }, @@ -64,11 +60,10 @@ "3": { "benchmarks": { "blink_perf.image_decoder": { - "begin": 2, "abridged": false }, "blink_perf.layout": { - "end": 51, + "end": 50, "abridged": false }, "speedometer2": { @@ -82,7 +77,7 @@ "4": { "benchmarks": { "blink_perf.layout": { - "begin": 51, + "begin": 50, "end": 110, "abridged": false }, @@ -107,7 +102,7 @@ "abridged": false }, "blink_perf.shadow_dom": { - "end": 18, + "end": 23, "abridged": false }, "speedometer2": { @@ -121,7 +116,7 @@ "6": { "benchmarks": { "blink_perf.shadow_dom": { - "begin": 18, + "begin": 23, "abridged": false }, "blink_perf.webaudio": { @@ -159,9 +154,6 @@ "abridged": false }, "rasterize_and_record_micro.top_25": { - "abridged": false - }, - "rendering.mobile": { "end": 4, "abridged": false }, @@ -173,6 +165,17 @@ } }, "crossbench": { + "embedder": { + "display_name": "embedder.crossbench", + "arguments": [ + "--wpr=crossbench_android_embedder_000.wprgo", + "--embedder=com.google.android.googlequicksearchbox", + "--splashscreen=skip", + "--cuj-config=../../third_party/crossbench/config/team/woa/embedder_cuj_config.hjson", + "--probe-config=../../clank/android_webview/tools/crossbench_config/agsa_probe_config.hjson", + "--repetitions=50" + ] + }, "loading": { "display_name": "loading.crossbench", "arguments": [ @@ -186,9 +189,12 @@ }, "8": { "benchmarks": { - "rendering.mobile": { + "rasterize_and_record_micro.top_25": { "begin": 4, - "end": 50, + "abridged": false + }, + "rendering.mobile": { + "end": 33, "abridged": false }, "speedometer2": { @@ -202,8 +208,8 @@ "9": { "benchmarks": { "rendering.mobile": { - "begin": 50, - "end": 99, + "begin": 33, + "end": 84, "abridged": false }, "speedometer2": { @@ -217,8 +223,8 @@ "10": { "benchmarks": { "rendering.mobile": { - "begin": 99, - "end": 144, + "begin": 84, + "end": 132, "abridged": false }, "speedometer2": { @@ -232,8 +238,8 @@ "11": { "benchmarks": { "rendering.mobile": { - "begin": 144, - "end": 189, + "begin": 132, + "end": 180, "abridged": false }, "speedometer2": { @@ -247,8 +253,8 @@ "12": { "benchmarks": { "rendering.mobile": { - "begin": 189, - "end": 247, + "begin": 180, + "end": 241, "abridged": false }, "speedometer2": { @@ -262,8 +268,8 @@ "13": { "benchmarks": { "rendering.mobile": { - "begin": 247, - "end": 317, + "begin": 241, + "end": 314, "abridged": false }, "speedometer2": { @@ -277,8 +283,8 @@ "14": { "benchmarks": { "rendering.mobile": { - "begin": 317, - "end": 365, + "begin": 314, + "end": 363, "abridged": false }, "speedometer2": { @@ -292,7 +298,7 @@ "15": { "benchmarks": { "rendering.mobile": { - "begin": 365, + "begin": 363, "abridged": false }, "rendering.mobile.notracing": { @@ -312,6 +318,13 @@ }, "speedometer3": { "abridged": false + } + } + }, + "16": { + "benchmarks": { + "speedometer3": { + "abridged": false }, "speedometer3-future": { "abridged": false @@ -320,34 +333,22 @@ "abridged": false }, "system_health.common_mobile": { - "end": 5, - "abridged": false - } - } - }, - "16": { - "benchmarks": { - "system_health.common_mobile": { - "begin": 5, - "end": 62, + "end": 52, "abridged": false }, "speedometer2": { "abridged": false - }, - "speedometer3": { - "abridged": false } } }, "17": { "benchmarks": { "system_health.common_mobile": { - "begin": 62, + "begin": 52, "abridged": false }, "system_health.memory_mobile": { - "end": 13, + "end": 9, "abridged": false }, "speedometer2": { @@ -361,8 +362,8 @@ "18": { "benchmarks": { "system_health.memory_mobile": { - "begin": 13, - "end": 26, + "begin": 9, + "end": 24, "abridged": false }, "speedometer2": { @@ -376,8 +377,8 @@ "19": { "benchmarks": { "system_health.memory_mobile": { - "begin": 26, - "end": 45, + "begin": 24, + "end": 41, "abridged": false }, "speedometer2": { @@ -391,8 +392,8 @@ "20": { "benchmarks": { "system_health.memory_mobile": { - "begin": 45, - "end": 62, + "begin": 41, + "end": 59, "abridged": false } } @@ -400,16 +401,16 @@ "21": { "benchmarks": { "system_health.memory_mobile": { - "begin": 62, - "abridged": false - }, - "system_health.webview_startup": { + "begin": 59, "abridged": false } } }, "22": { "benchmarks": { + "system_health.webview_startup": { + "abridged": false + }, "v8.browsing_mobile": { "abridged": false }, @@ -422,33 +423,33 @@ } }, "extra_infos": { - "num_stories": 1115, - "predicted_min_shard_time": 1814.0, - "predicted_min_shard_index": 22, - "predicted_max_shard_time": 2327.0, - "predicted_max_shard_index": 21, - "shard #0": 2113.0, - "shard #1": 2116.0, - "shard #2": 2124.0, - "shard #3": 2137.0, - "shard #4": 2138.0, - "shard #5": 2114.0, - "shard #6": 1998.0, - "shard #7": 2100.0, - "shard #8": 2136.0, - "shard #9": 2152.0, - "shard #10": 2125.0, - "shard #11": 2125.0, - "shard #12": 2130.0, - "shard #13": 2150.0, - "shard #14": 2131.0, - "shard #15": 2120.0, - "shard #16": 2139.0, - "shard #17": 2156.0, - "shard #18": 2199.0, - "shard #19": 2166.0, - "shard #20": 2139.0, - "shard #21": 2327.0, - "shard #22": 1814.0 + "num_stories": 1117, + "predicted_min_shard_time": 1925.0, + "predicted_min_shard_index": 6, + "predicted_max_shard_time": 2577.0, + "predicted_max_shard_index": 22, + "shard #0": 2241.0, + "shard #1": 2219.0, + "shard #2": 2230.0, + "shard #3": 2223.0, + "shard #4": 2213.0, + "shard #5": 2230.0, + "shard #6": 1925.0, + "shard #7": 2239.0, + "shard #8": 2250.0, + "shard #9": 2257.0, + "shard #10": 2236.0, + "shard #11": 2234.0, + "shard #12": 2252.0, + "shard #13": 2238.0, + "shard #14": 2237.0, + "shard #15": 2256.0, + "shard #16": 2243.0, + "shard #17": 2210.0, + "shard #18": 2167.0, + "shard #19": 2215.0, + "shard #20": 2346.0, + "shard #21": 1935.0, + "shard #22": 2577.0 } }
diff --git a/tools/perf/crossbench_result_converter.py b/tools/perf/crossbench_result_converter.py index ddfb087..3203498 100755 --- a/tools/perf/crossbench_result_converter.py +++ b/tools/perf/crossbench_result_converter.py
@@ -12,7 +12,7 @@ import json import pathlib import sys -from typing import Optional +from typing import List, Optional tracing_dir = (pathlib.Path(__file__).absolute().parents[2] / 'third_party/catapult/tracing') @@ -22,7 +22,7 @@ from tracing.value.diagnostics import reserved_infos -def _get_crossbench_json_path(out_dir: pathlib.Path) -> pathlib.Path: +def _get_crossbench_json_paths(out_dir: pathlib.Path) -> List[pathlib.Path]: """Given a crossbench output directory, find the result json file. Args: @@ -30,7 +30,7 @@ as --out-dir to crossbench. Returns: - Path to the result json file created by crossbench. + A list of paths to the result json files created by crossbench probes. """ if not out_dir.exists(): @@ -55,7 +55,7 @@ browser_info = list(browsers.values())[0] debug_info += f'browser_info={browser_info}\n' - probe_json_path = None + probe_json_paths = [] try: for probe, probe_data in browser_info.get('probes', {}).items(): if probe.startswith('cb.') or not probe_data: @@ -65,19 +65,15 @@ raise ValueError(f'Probe {probe} generated multiple json files, ' f'debug_info={debug_info}') if len(candidates) == 1: - if probe_json_path: - raise ValueError( - f'Multiple output json files found in {cb_results_json_path}, ' - f'debug_info={debug_info}') - probe_json_path = pathlib.Path(candidates[0]) + probe_json_paths.append(pathlib.Path(candidates[0])) except AttributeError as e: raise AttributeError(f'debug_info={debug_info}') from e - if not probe_json_path: + if not probe_json_paths: raise ValueError(f'No output json file found in {cb_results_json_path}, ' f'debug_info={debug_info}') - return probe_json_path + return probe_json_paths def convert(crossbench_out_dir: pathlib.Path, @@ -94,9 +90,11 @@ _loadline(crossbench_out_dir, out_filename, benchmark, results_label) return - crossbench_json_filename = _get_crossbench_json_path(crossbench_out_dir) - with crossbench_json_filename.open() as f: - crossbench_result = json.load(f) + crossbench_json_filenames = _get_crossbench_json_paths(crossbench_out_dir) + crossbench_result = {} + for filename in crossbench_json_filenames: + with filename.open() as f: + crossbench_result.update(json.load(f)) results = histogram_set.HistogramSet() for key, value in crossbench_result.items():
diff --git a/tools/perf/crossbench_result_converter_unittest.py b/tools/perf/crossbench_result_converter_unittest.py index d1a1bde..cd8ffe8 100644 --- a/tools/perf/crossbench_result_converter_unittest.py +++ b/tools/perf/crossbench_result_converter_unittest.py
@@ -46,10 +46,10 @@ def process_crossbench_result(self, subdir): return self.list_to_dict(self.call_converter(subdir)) - def check_result(self, result, metric, value, unit): + def check_result(self, result, metric, value, unit, sample_size=1): sample_values = result[metric]['sampleValues'] self.assertIsInstance(sample_values, list) - self.assertEqual(len(sample_values), 1) + self.assertEqual(len(sample_values), sample_size) self.assertAlmostEqual(sample_values[0], value) self.assertEqual(result[metric]['unit'], unit) @@ -88,6 +88,13 @@ self.check_result(result, 'TodoMVC-jQuery', 259.5599999189377, 'ms_smallerIsBetter') + def test_embedder(self): + result = self.process_crossbench_result('embedder') + self.check_result(result, 'Some.Histogram1_mean', 165.0, + 'ms_smallerIsBetter', sample_size=50) + self.check_result(result, 'MetricFoo', 207, + 'ms_smallerIsBetter', sample_size=50) + if __name__ == '__main__': unittest.main()
diff --git a/tools/perf/testdata/crossbench_output/embedder/cb.results.json b/tools/perf/testdata/crossbench_output/embedder/cb.results.json new file mode 100644 index 0000000..ed33207 --- /dev/null +++ b/tools/perf/testdata/crossbench_output/embedder/cb.results.json
@@ -0,0 +1,79 @@ +{ + "cwd": "/example/path", + "browsers": { + "chrome_v139_android.arm64.remote_0": { + "cwd": "/example/path/chrome_v139_android.arm64.remote_0/stories", + "probes": { + "embedder": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/embedder.json" + ], + "csv": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/embedder.csv" + ] + }, + "chrome_histograms": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/chrome_histograms.json" + ], + "csv": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/chrome_histograms.csv" + ] + }, + "cb.thermal_monitor": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/cb.thermal_monitor.json" + ] + }, + "cb.system.details": null, + "cb.log": null, + "cb.errors": null, + "cb.durations": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/cb.durations.json" + ] + } + }, + "errors": [] + } + }, + "probes": { + "embedder": { + "json": [ + "/example/path/embedder.json" + ], + "csv": [ + "/example/path/embedder.csv" + ], + "xlsx": [ + "/example/path/embedder.xlsx" + ] + }, + "chrome_histograms": { + "json": [ + "/example/path/chrome_histograms.json" + ], + "csv": [ + "/example/path/chrome_histograms.csv" + ], + "xlsx": [ + "/example/path/chrome_histograms.xlsx" + ] + }, + "cb.thermal_monitor": { + "json": [ + "/example/path/cb.thermal_monitor.json" + ] + }, + "cb.system.details": null, + "cb.log": null, + "cb.errors": null, + "cb.durations": { + "json": [ + "/example/path/cb.durations.json" + ] + } + }, + "success": true, + "errors": [] +} \ No newline at end of file
diff --git a/tools/perf/testdata/crossbench_output/embedder/chrome_histograms.json b/tools/perf/testdata/crossbench_output/embedder/chrome_histograms.json new file mode 100644 index 0000000..01dc6a2 --- /dev/null +++ b/tools/perf/testdata/crossbench_output/embedder/chrome_histograms.json
@@ -0,0 +1,142 @@ +{ + "chrome_v139_android.arm64.remote_0": { + "info": { + "label": "android.arm64.remote_0", + "browser": "Chrome", + "version": "139.0.7251.0", + "major_version": 139, + "channel": "stable", + "os": "android 11 arm64", + "device": "Pixel 4", + "cpu": "cortex-a76 msmnile 8 cores", + "binary": "com.google.android.googlequicksearchbox", + "flags": "--no-default-browser-check --disable-component-update --disable-sync --no-first-run --disable-search-engine-choice-screen --disable-background-timer-throttling --disable-renderer-backgrounding --disable-field-trial-config --enable-features=DisablePrivacySandboxPrompts --disable-extensions", + "runs": 50, + "failed runs": 0 + }, + "data": { + "Some.Histogram1_mean": { + "values": [ + 165.0, + 260.0, + 233.0, + 217.0, + 203.0, + 230.0, + 238.0, + 219.0, + 256.0, + 229.0, + 253.0, + 223.0, + 267.0, + 216.0, + 247.0, + 219.0, + 219.0, + 245.0, + 228.0, + 253.0, + 246.0, + 219.0, + 224.0, + 259.0, + 249.0, + 246.0, + 234.0, + 251.0, + 217.0, + 134.0, + 253.0, + 263.0, + 222.0, + 251.0, + 245.0, + 256.0, + 289.0, + 218.0, + 222.0, + 256.0, + 245.0, + 260.0, + 261.0, + 251.0, + 262.0, + 269.0, + 248.0, + 213.0, + 256.0, + 260.0 + ], + "min": 134.0, + "average": 237.98, + "geomean": 236.3340412079503, + "max": 289.0, + "sum": 11899.0, + "stddev": 26.149093713565225, + "stddevPercent": 10.98793752145778 + }, + "Other.Histogram2_mean": { + "values": [ + 21.0, + 13.0, + 17.0, + 13.0, + 16.0, + 19.0, + 21.0, + 13.0, + 14.0, + 14.0, + 19.0, + 16.0, + 18.0, + 15.0, + 15.0, + 15.0, + 21.0, + 13.0, + 14.0, + 20.0, + 16.0, + 14.0, + 15.0, + 15.0, + 13.0, + 14.0, + 15.0, + 12.0, + 15.0, + 15.0, + 16.0, + 14.0, + 15.0, + 19.0, + 16.0, + 17.0, + 16.0, + 18.0, + 15.0, + 13.0, + 11.0, + 15.0, + 14.0, + 13.0, + 16.0, + 16.0, + 16.0, + 13.0, + 15.0, + 13.0 + ], + "min": 11.0, + "average": 15.44, + "geomean": 15.271810862762067, + "max": 21.0, + "sum": 772.0, + "stddev": 2.366086927172959, + "stddevPercent": 15.324397196716056 + } + } + } +} \ No newline at end of file
diff --git a/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/cb.results.json b/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/cb.results.json new file mode 100644 index 0000000..4f7f288 --- /dev/null +++ b/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/cb.results.json
@@ -0,0 +1,115 @@ +{ + "cwd": "/example/path/chrome_v139_android.arm64.remote_0/stories", + "browser": { + "label": "android.arm64.remote_0", + "browser": "chrome", + "unique_name": "chrome_v139_android.arm64.remote_0", + "app_name": "chrome", + "version": "139.0.7251.0", + "channel": "stable", + "flags": [ + "--no-default-browser-check", + "--disable-component-update", + "--disable-sync", + "--no-first-run", + "--disable-search-engine-choice-screen", + "--disable-background-timer-throttling", + "--disable-renderer-backgrounding", + "--disable-field-trial-config", + "--enable-features=DisablePrivacySandboxPrompts", + "--disable-extensions" + ], + "js_flags": [], + "path": "com.google.android.googlequicksearchbox", + "clear_cache_dir": true, + "major_version": 139 + }, + "stories": { + "agsa-simple": { + "cwd": "/example/path/chrome_v139_android.arm64.remote_0/stories/agsa-simple", + "duration": 30.0, + "probes": { + "embedder": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/agsa-simple/embedder.json" + ], + "csv": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/agsa-simple/embedder.csv" + ] + }, + "chrome_histograms": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/agsa-simple/chrome_histograms.json" + ], + "csv": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/agsa-simple/chrome_histograms.csv" + ] + }, + "cb.thermal_monitor": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/agsa-simple/cb.thermal_monitor.json" + ] + }, + "cb.system.details": null, + "cb.log": null, + "cb.errors": null, + "cb.durations": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/agsa-simple/cb.durations.json" + ], + "csv": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/agsa-simple/cb.durations.csv" + ] + } + }, + "errors": [] + } + }, + "group": { + "label": "android.arm64.remote_0", + "browser": "Chrome", + "version": "139.0.7251.0", + "major_version": 139, + "channel": "stable", + "os": "android 11 arm64", + "device": "Pixel 4", + "cpu": "cortex-a76 msmnile 8 cores", + "binary": "com.google.android.googlequicksearchbox", + "flags": "--no-default-browser-check --disable-component-update --disable-sync --no-first-run --disable-search-engine-choice-screen --disable-background-timer-throttling --disable-renderer-backgrounding --disable-field-trial-config --enable-features=DisablePrivacySandboxPrompts --disable-extensions", + "runs": 50, + "failed runs": 0 + }, + "probes": { + "embedder": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/embedder.json" + ], + "csv": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/embedder.csv" + ] + }, + "chrome_histograms": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/chrome_histograms.json" + ], + "csv": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/chrome_histograms.csv" + ] + }, + "cb.thermal_monitor": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/cb.thermal_monitor.json" + ] + }, + "cb.system.details": null, + "cb.log": null, + "cb.errors": null, + "cb.durations": { + "json": [ + "/example/path/chrome_v139_android.arm64.remote_0/stories/cb.durations.json" + ] + } + }, + "success": true, + "errors": [] +} \ No newline at end of file
diff --git a/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/chrome_histograms.json b/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/chrome_histograms.json new file mode 100644 index 0000000..55cbfaf0 --- /dev/null +++ b/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/chrome_histograms.json
@@ -0,0 +1,124 @@ +{ + "Some.Histogram1_mean": { + "values": [ + 165.0, + 260.0, + 233.0, + 217.0, + 203.0, + 230.0, + 238.0, + 219.0, + 256.0, + 229.0, + 253.0, + 223.0, + 267.0, + 216.0, + 247.0, + 219.0, + 219.0, + 245.0, + 228.0, + 253.0, + 246.0, + 219.0, + 224.0, + 259.0, + 249.0, + 246.0, + 234.0, + 251.0, + 217.0, + 134.0, + 253.0, + 263.0, + 222.0, + 251.0, + 245.0, + 256.0, + 289.0, + 218.0, + 222.0, + 256.0, + 245.0, + 260.0, + 261.0, + 251.0, + 262.0, + 269.0, + 248.0, + 213.0, + 256.0, + 260.0 + ], + "min": 134.0, + "average": 237.98, + "geomean": 236.3340412079503, + "max": 289.0, + "sum": 11899.0, + "stddev": 26.149093713565225, + "stddevPercent": 10.98793752145778 + }, + "Other.Histogram2_mean": { + "values": [ + 21.0, + 13.0, + 17.0, + 13.0, + 16.0, + 19.0, + 21.0, + 13.0, + 14.0, + 14.0, + 19.0, + 16.0, + 18.0, + 15.0, + 15.0, + 15.0, + 21.0, + 13.0, + 14.0, + 20.0, + 16.0, + 14.0, + 15.0, + 15.0, + 13.0, + 14.0, + 15.0, + 12.0, + 15.0, + 15.0, + 16.0, + 14.0, + 15.0, + 19.0, + 16.0, + 17.0, + 16.0, + 18.0, + 15.0, + 13.0, + 11.0, + 15.0, + 14.0, + 13.0, + 16.0, + 16.0, + 16.0, + 13.0, + 15.0, + 13.0 + ], + "min": 11.0, + "average": 15.44, + "geomean": 15.271810862762067, + "max": 21.0, + "sum": 772.0, + "stddev": 2.366086927172959, + "stddevPercent": 15.324397196716056 + } +} \ No newline at end of file
diff --git a/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/embedder.json b/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/embedder.json new file mode 100644 index 0000000..7e6b9c4 --- /dev/null +++ b/tools/perf/testdata/crossbench_output/embedder/chrome_v139_android.arm64.remote_0/stories/embedder.json
@@ -0,0 +1,124 @@ +{ + "MetricFoo": { + "values": [ + 207, + 305, + 285, + 267, + 240, + 266, + 279, + 269, + 296, + 267, + 303, + 261, + 306, + 251, + 302, + 259, + 256, + 281, + 268, + 291, + 283, + 257, + 263, + 296, + 292, + 283, + 279, + 288, + 251, + 174, + 303, + 307, + 267, + 290, + 292, + 297, + 326, + 256, + 273, + 292, + 284, + 304, + 304, + 309, + 301, + 305, + 293, + 271, + 303, + 299 + ], + "min": 174, + "average": 280.02, + "geomean": 278.5924527064356, + "max": 326, + "sum": 14001, + "stddev": 26.76541325925635, + "stddevPercent": 9.558393421632866 + }, + "MetricBar": { + "values": [ + 21, + 13, + 17, + 13, + 16, + 19, + 21, + 13, + 14, + 14, + 19, + 16, + 18, + 15, + 15, + 15, + 21, + 13, + 14, + 20, + 16, + 14, + 15, + 15, + 13, + 14, + 15, + 12, + 15, + 15, + 16, + 14, + 15, + 19, + 16, + 17, + 16, + 18, + 15, + 13, + 11, + 15, + 14, + 13, + 16, + 16, + 16, + 13, + 15, + 13 + ], + "min": 11, + "average": 15.44, + "geomean": 15.271810862762067, + "max": 21, + "sum": 772, + "stddev": 2.366086927172959, + "stddevPercent": 15.324397196716056 + } +} \ No newline at end of file
diff --git a/tools/perf/testdata/crossbench_output/embedder/embedder.json b/tools/perf/testdata/crossbench_output/embedder/embedder.json new file mode 100644 index 0000000..74860e2 --- /dev/null +++ b/tools/perf/testdata/crossbench_output/embedder/embedder.json
@@ -0,0 +1,142 @@ +{ + "chrome_v139_android.arm64.remote_0": { + "info": { + "label": "android.arm64.remote_0", + "browser": "Chrome", + "version": "139.0.7251.0", + "major_version": 139, + "channel": "stable", + "os": "android 11 arm64", + "device": "Pixel 4", + "cpu": "cortex-a76 msmnile 8 cores", + "binary": "com.google.android.googlequicksearchbox", + "flags": "--no-default-browser-check --disable-component-update --disable-sync --no-first-run --disable-search-engine-choice-screen --disable-background-timer-throttling --disable-renderer-backgrounding --disable-field-trial-config --enable-features=DisablePrivacySandboxPrompts --disable-extensions", + "runs": 50, + "failed runs": 0 + }, + "data": { + "MetricFoo": { + "values": [ + 207, + 305, + 285, + 267, + 240, + 266, + 279, + 269, + 296, + 267, + 303, + 261, + 306, + 251, + 302, + 259, + 256, + 281, + 268, + 291, + 283, + 257, + 263, + 296, + 292, + 283, + 279, + 288, + 251, + 174, + 303, + 307, + 267, + 290, + 292, + 297, + 326, + 256, + 273, + 292, + 284, + 304, + 304, + 309, + 301, + 305, + 293, + 271, + 303, + 299 + ], + "min": 174, + "average": 280.02, + "geomean": 278.5924527064356, + "max": 326, + "sum": 14001, + "stddev": 26.76541325925635, + "stddevPercent": 9.558393421632866 + }, + "MetricBar": { + "values": [ + 21, + 13, + 17, + 13, + 16, + 19, + 21, + 13, + 14, + 14, + 19, + 16, + 18, + 15, + 15, + 15, + 21, + 13, + 14, + 20, + 16, + 14, + 15, + 15, + 13, + 14, + 15, + 12, + 15, + 15, + 16, + 14, + 15, + 19, + 16, + 17, + 16, + 18, + 15, + 13, + 11, + 15, + 14, + 13, + 16, + 16, + 16, + 13, + 15, + 13 + ], + "min": 11, + "average": 15.44, + "geomean": 15.271810862762067, + "max": 21, + "sum": 772, + "stddev": 2.366086927172959, + "stddevPercent": 15.324397196716056 + } + } + } +} \ No newline at end of file
diff --git a/v8 b/v8 index 9541b18..4d7c9f1 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 9541b18ce700cdef8cce07fef49f1ac9d74a1dd2 +Subproject commit 4d7c9f183f3c41ac42eb0d622a4d8e58a0982693