diff --git a/.gitmodules b/.gitmodules index 7104cdc..a35f9c6 100644 --- a/.gitmodules +++ b/.gitmodules
@@ -222,6 +222,9 @@ [submodule "third_party/fast_float/src"] path = third_party/fast_float/src url = https://chromium.googlesource.com/external/github.com/fastfloat/fast_float +[submodule "third_party/federated_compute/src"] + path = third_party/federated_compute/src + url = https://chromium.googlesource.com/external/github.com/google-parfait/federated-compute [submodule "third_party/ffmpeg"] path = third_party/ffmpeg url = https://chromium.googlesource.com/chromium/third_party/ffmpeg
diff --git a/DEPS b/DEPS index dc60130..c6734af0a 100644 --- a/DEPS +++ b/DEPS
@@ -291,15 +291,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': 'c9abe897da1efecb78ad3207f7c1493b3a33b1f0', + 'src_internal_revision': 'e988acaa4e16e19cacdca3b6bb9565872c40072c', # 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': '1d458db1cd0d4739c4e15977113b769296342d85', + 'skia_revision': '724306df8a6703bd212017f3c4b2978665add579', # 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': '4ec2f43a229069d6124c88527ee7bb9cc642edc3', + 'v8_revision': '22b4de0c06965bfc5c40c617132760db7bc0bd41', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -315,7 +315,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. - 'boringssl_revision': 'd55aba9db303cf2b445b29645c941671bc7ffdf8', + 'boringssl_revision': '6cd35e8ba6aa0b8bb3eaff35a7aa6b6385e34fa0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. @@ -383,7 +383,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': '50d161857a463c22b6631b3a134a52833e626187', + 'devtools_frontend_revision': '11d82284b93d46bc94adcd42d8adbabe8f7569bf', # 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. @@ -407,11 +407,11 @@ # 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': '86578e2fc035b73a2853b6a0639b1ef347ee9bad', + 'dawn_revision': 'fb93247bf550691da20ff349400839499c744a01', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': 'e7874f26f3bf5b88f155190994cbb2cee8fd42c2', + 'quiche_revision': '3254739b95207731898c7eae118d109009a76c10', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ink # and whatever else without interference from each other. @@ -431,7 +431,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling jetstream-main # and whatever else without interference from each other. - 'jetstream_main_revision': '553d3f7faca708ed7c30ac8fee1c57c7eb027740', + 'jetstream_main_revision': '67cfc6e50c5c8760cb81fb9378a25217a06d1e55', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling jetstream-v2.2 # and whatever else without interference from each other. @@ -515,7 +515,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': 'afc28bd7ad797280bd1b31f532745c1a33862738', + 'compiler_rt_revision': '693bb2c75d48037e5ce35c61d3cbde3cf59622b6', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling clusterfuzz-data # and whatever else without interference from each other. @@ -526,7 +526,7 @@ 'libcxx_revision': '6f8fe913d64254ab2231e0e98d2b6b5650ef4917', # GN CIPD package version. - 'gn_version': 'git_revision:19281424d4eeefb3c4342431703534c47d260bfb', + 'gn_version': 'git_revision:cc7c61e105fb56183fd6c5c52bbe3c37ff724a0d', # ninja CIPD package. 'ninja_package': 'infra/3pp/tools/ninja/', @@ -1186,7 +1186,7 @@ 'packages': [ { 'package': 'chromium/chrome/android/orderfiles/arm', - 'version': '4AYKe10OUv7qNHLW7MVFOMk1bx77mztMkWkaJUk-VwUC', + 'version': 'Yr0KMSDxWbil3ad7bXvfpHmmJirMMuwxUl7807ZfLm0C', }, ], 'condition': 'checkout_android', @@ -1197,7 +1197,7 @@ 'packages': [ { 'package': 'chromium/chrome/android/orderfiles/arm64', - 'version': 'Kfnf5fwq3VYGLPB4Uxf5fo4XFO0fCNAYYcTYNNxmoV0C', + 'version': 'mWQ_wj-CGRrvn3S9me_MbkESrCuxmtBY98E4EyVWk7cC', }, ], 'condition': 'checkout_android', @@ -1374,7 +1374,7 @@ 'packages': [ { 'package': 'chromium/third_party/updater/chromium_linux64', - 'version': 'version:2@1496001', + 'version': 'version:2@1497009', }, ], }, @@ -1420,7 +1420,7 @@ 'packages': [ { 'package': 'chromium/third_party/updater/chromium_win_x86', - 'version': 'version:2@1496001', + 'version': 'version:2@1497005', }, ], }, @@ -1431,7 +1431,7 @@ 'packages': [ { 'package': 'chromium/third_party/updater/chromium_win_x86_64', - 'version': 'version:2@1496004', + 'version': 'version:2@1497036', }, ], }, @@ -1509,7 +1509,7 @@ 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_linux64', - 'version': 'c-3HHiNKBHRve_MJrrUnwxI5SZ7giWyIaaGJHU8pjTEC', + 'version': 'Zf0sHTROh4aRqgDixBQf6fQC0dyDYbQvwNxeBaFXtNsC', }, ], }, @@ -1520,7 +1520,7 @@ 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_mac_amd64', - 'version': 'ZXik2MzB8S6g1-HZA6oFeGDAt_0wJc8FSis7qRKpkEYC', + 'version': 'Mdbtvu7-pJUze7pKE0U1BGHu3Yqu2QAAMJREQBH0F7sC', }, ], }, @@ -1531,7 +1531,7 @@ 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_mac_arm64', - 'version': 'kPgLQAjvoRkS1vb_CENY8g5YWhaRhSzZyrHyz3GaMF4C', + 'version': 'TipoR97RttJOrr39yznQ-6KzDb6U3XoRejYKXzTJKa8C', }, ], }, @@ -1542,7 +1542,7 @@ 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_win_x86', - 'version': 'YoKJcQ41yn2CLo3UEebIJ6ba7nqV_6EJHRHW3f0FhjAC', + 'version': 'wMOaOefFIUALEZFQ6neYTqIdY_IIxk6WiUu09esVTIMC', }, ], }, @@ -1553,7 +1553,7 @@ 'packages': [ { 'package': 'chromium/third_party/enterprise_companion/chromium_win_x86_64', - 'version': 'c6fb8bBjJbS3FTvo7ahNm30kd-zLLc-YO13KTDe60ZcC', + 'version': 'P1KR_Mpi1jjRjvYCOFQuiThiKJFYdoYIN-X4PCmTyA4C', }, ], }, @@ -1589,7 +1589,7 @@ 'packages': [ { 'package': 'chromium/chrome/test/data/variations/cipd', - 'version': 'Qc6-C4fw6FBWzq5m4U5V-Nb9WJd0RKxBNkdyi1W2JQsC', + 'version': 'JJQIJXUVCB9YTwvoIKi1Hye_isAmAWtIPTqo3UBzxcMC', }, ], 'dep_type': 'cipd', @@ -1600,12 +1600,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '1629330ef8eb9d5030577c64fb7121ed7c12aa23', + 'da266c809240f37f6b564ad0034021f70c44ae52', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'a89f6810f6a5b0e11e4ec00387e9f97e8f6c23ae', + 'url': Var('chromium_git') + '/website.git' + '@' + 'fce2849a37a995b7d506faa923885369d45cd9c2', }, 'src/ios/third_party/earl_grey2/src': { @@ -2083,7 +2083,7 @@ Var('chromium_git') + '/chromium/web-tests.git' + '@' + Var('crossbench_web_tests_revision'), 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b66d188607bca258f277b7a4410c7302c48b8193', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '55b7745daa200ac8f8956da2478841335168d874', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -2119,6 +2119,9 @@ 'src/third_party/fast_float/src': Var('chromium_git') + '/external/github.com/fastfloat/fast_float.git' + '@' + 'cb1d42aaa1e14b09e1452cfdef373d051b8c02a4', + 'src/third_party/federated_compute/src': + Var('chromium_git') + '/external/github.com/google-parfait/federated-compute.git' + '@' + 'd9608bf1a16ee03a5451e15c8f3e262617472a38', + 'src/third_party/ffmpeg': Var('chromium_git') + '/chromium/third_party/ffmpeg.git' + '@' + Var('ffmpeg_revision'), @@ -2359,7 +2362,7 @@ Var('chromium_git') + '/external/libaddressinput.git' + '@' + '2610f7b1043d6784ada41392fc9392d1ea09ea07', 'src/third_party/libaom/source/libaom': - Var('aomedia_git') + '/aom.git' + '@' + '930f7e2b9c58779edb2aa1ffb6f55a64fb6fd7fd', + Var('aomedia_git') + '/aom.git' + '@' + '1f097193b0353e32c5f0b010642d89d146234804', 'src/third_party/crabbyavif/src': Var('chromium_git') + '/external/github.com/webmproject/CrabbyAvif.git' + '@' + Var('crabbyavif_revision'), @@ -2482,7 +2485,7 @@ Var('chromium_git') + '/webm/libwebp.git' + '@' + 'b0e8039062eedbcb20ebb1bad62bfeaee2b94ec6', 'src/third_party/libyuv': - Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'cdd3bae84818e78466fec1ce954eead8f403d10c', + Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'b7d97d5f3f8f897b88872b6935e4c996b955bc1f', 'src/third_party/lighttpd': { 'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'), @@ -2622,7 +2625,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '79987e4753ec3572794821544b5f00a1e1b08fa8', + Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '27062b54dde5b49c79f4b85e0a21bde2345219a8', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -2793,7 +2796,7 @@ }, 'src/third_party/re2/src': - Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'c2c6a2eb663fe21e0cd9f2b1886821bdecb1e988', + Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '85c7c0fb1163b0bd83a7951f5a205ee7b489e33e', 'src/third_party/r8/cipd': { 'packages': [ @@ -2941,13 +2944,13 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@6316acd63c017e93d4e589ba465a9181d780bced', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@1909eee37eb8bec071d0d37a9a79d30cef17253f', 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@0d614c24699d986afd590b93a8c0f0946e997919', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', - 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@97e96f9e9defeb4bba3cfbd034dec516671dd7a3', - 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@3aeaaa088d37b86cff036eee1a9bf452abad7d9d', + 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@a7361efd139bf65de0e86d43b01b01e0b34d387f', + 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@cb2f796b2d6da09a4fea123b061f177f767e63c8', 'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@a01329f307fa6067da824de9f587f292d761680b', - 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@ffd25df8da11ee13627a9a00d9efb0f6d3aab9ed', + 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@046e658417e1c1454791c1f080e26c6a22e1dd78', 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@f766b30b2de3ffe2cf6b656d943720882617ec58', 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@b149d5c52c06836ab333ba571791f79a9fb8eb50', 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@f0cc60f0d3e8e082fd8f0145ac4a9ae0166b30d3', @@ -2993,7 +2996,7 @@ Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'), 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '8f712e0ae30b56cd52166dfb50c2937d2223db1a', + Var('webrtc_git') + '/src.git' + '@' + '15152cd7782178a65f862b82cb6957af8d464207', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -3115,7 +3118,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/boca_app/app', - 'version': 'xgl9jD_VmFlx7HFsx-IJAklV9b1882ggreXnX68nO8UC', + 'version': 'ls5CsclM5CwEVFIU4SR77lQbr5Fe39jAnxhEwWcE72wC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -3197,7 +3200,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_deps/autorolled', - 'version': 'RcN7kx5OuQtBLrhCRBTO9NABzT2sjw-ogJBZmT3nOdAC', + 'version': 'ywLef-7rK_zL0qLcTNa_wmcOKCYOyx817He_Jry8jLQC', }, ], 'condition': 'checkout_android and non_git_source', @@ -3517,7 +3520,7 @@ 'src/chrome/browser/glic/e2e_test/internal': { 'url': Var('chrome_git') + '/chrome/browser/glic/test/internal.git' + '@' + - 'f4ab390c247970f942a1a850b4866c7e3ab43e69', + 'f27c9a46ebb7c3a2e484de830a1094c033e4a781', 'condition': 'checkout_glic_e2e_tests', }, @@ -3762,7 +3765,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '17f72536aae764cb30b113ed93602009f43baca9', + '11c95229a646ddfa592300ac5b7b566bd2f9466b', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/WATCHLISTS b/WATCHLISTS index 16819ee..b29ddcb556 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -1154,11 +1154,6 @@ 'disk_cache': { 'filepath': 'net/disk_cache/|http_cache', }, - 'display': { - 'filepath': 'ui/display/|'\ - 'ash/display/|'\ - 'chrome/browser/ui/webui/ash/settings/pages/device/display_settings/', - }, 'dom_storage': { 'filepath': 'content/common/dom_storage/|'\ 'content/browser/dom_storage/|'\ @@ -2183,6 +2178,10 @@ '|chrome/browser/ui/views/tabs/tab_renderer_data'\ '|media/audio/audio_(output_controller|power_monitor)', }, + 'tab_alerts': { + 'filepath': 'chrome/browser/ui/tabs/alert/'\ + '|chrome/browser/ui/views/tabs/tab_renderer_data' + }, 'tab_capture': { # TODO: Watch code in media/audio & audio service for tab audio capture 'filepath': 'chrome/browser/extensions/api/tab_capture/'\ @@ -2490,7 +2489,6 @@ 'accelerators': ['jimmyxgong+watch-accelerators@chromium.org', 'cambickel+watch-accelerators@google.com', 'longbowei+watch-accelerators@google.com', - 'zhangwenyu+watch-accelerators@google.com', 'michaelcheco+watch-accelerators@google.com'], 'accessibility': ['abigailbklein+watch@google.com', 'akihiroota@chromium.org', @@ -2588,11 +2586,9 @@ 'assistive': ['croissant-eng+reviews@chromium.org'], 'attribution_reporting': ['apaseltiner+watch@chromium.org'], 'audio_service': ['marinaciocea+watch@chromium.org', - 'olka+watch@chromium.org', - 'zhangwenyu+watch@google.com'], + 'olka+watch@chromium.org'], 'audio_settings': ['michaelcheco+audio-settings-watch@google.com', - 'owenzhang+audio-settings-watch@google.com', - 'zhangwenyu+audio-settings-watch@google.com'], + 'owenzhang+audio-settings-watch@google.com'], 'aura': ['sadrul@chromium.org'], 'aura_compositor': ['jbauman+watch@chromium.org'], 'autofill': ['rouslan+autofillwatch@chromium.org'], @@ -2932,16 +2928,13 @@ 'devtools': ['devtools-reviews@chromium.org'], 'diagnostics_mojo': ['ashleydp+watch-diagnostics_mojo@google.com', 'gavindodd+watch-diagnostics_mojo@google.com', - 'michaelcheco+watch-diagnostics_mojo@google.com', - 'zhangwenyu+watch-diagnostics_mojo@google.com'], + 'michaelcheco+watch-diagnostics_mojo@google.com'], 'diagnostics_ui': ['gavinwill+diagnostics-watch@chromium.org', 'michaelcheco+diagnostics-watch@google.com', 'gavindodd+diagnostics-watch@google.com', - 'ashleydp+diagnostics-watch@google.com', - 'zhangwenyu+diagnostics-watch@google.com'], + 'ashleydp+diagnostics-watch@google.com'], 'discardable_memory': ['thiabaud+watch-discardable-memory@google.com'], 'disk_cache': ['gavinp+disk@chromium.org'], - 'display': ['zhangwenyu+watch@google.com'], 'dom_storage': ['dmurph+watchingdomstorage@chromium.org', 'edgestoragedev@microsoft.com'], 'download': ['dtrainor+watch@chromium.org'], @@ -3164,8 +3157,7 @@ 'longbowei+feedback-watch@google.com', 'wangdanny+feedback-watch@google.com', 'xiangdongkong+feedback-watch@google.com', - 'yyhyyh+feedback-watch@google.com', - 'zhangwenyu+feedback-watch@google.com'], + 'yyhyyh+feedback-watch@google.com'], 'ozone': ['ozone-reviews@chromium.org'], 'ozone_fuchsia': ['dworsham@google.com', 'emircan@google.com', @@ -3319,6 +3311,7 @@ 'switch_access': ['anastasi+watch@google.com'], 'syncfs': ['kinuko+fileapi@chromium.org'], 'tab_alert_indicators': ['jophba+watch@chromium.org'], + 'tab_alerts': ['stluong@chromium.org'], 'tab_capture': ['jophba+watch@chromium.org', 'mfoltz+watch@chromium.org'], 'tab_contents': ['ajwong+watch@chromium.org',
diff --git a/agents/extensions/PRESUBMIT.py b/agents/extensions/PRESUBMIT.py new file mode 100644 index 0000000..9dacfc6 --- /dev/null +++ b/agents/extensions/PRESUBMIT.py
@@ -0,0 +1,14 @@ +# 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. + +PRESUBMIT_VERSION = '2.0.0' + + +def CheckPythonTests(input_api, output_api): + return input_api.RunTests( + input_api.canned_checks.GetUnitTestsInDirectory( + input_api, + output_api, + input_api.PresubmitLocalPath(), + files_to_check=[r'.+_(?:unit)?test\.py$']))
diff --git a/agents/extensions/build_information/tests/promptfoo/host_arch.yaml b/agents/extensions/build_information/tests/promptfoo/host_arch.yaml new file mode 100644 index 0000000..cdd3163 --- /dev/null +++ b/agents/extensions/build_information/tests/promptfoo/host_arch.yaml
@@ -0,0 +1,16 @@ +prompts: + - 'What is the architecture of the current host?' + +# The provider is our custom Python script. +providers: + - id: python:../../../../testing/gemini_provider.py + config: + timeoutSeconds: 30 + system_prompt: file://../../../../../GEMINI.md + +# The test cases will run on the output returned by our Python script. +tests: + - description: 'Host architecture determination' + assert: + - type: icontains + value: 'x64'
diff --git a/agents/extensions/build_information/tests/promptfoo/host_os.yaml b/agents/extensions/build_information/tests/promptfoo/host_os.yaml new file mode 100644 index 0000000..c394fd2 --- /dev/null +++ b/agents/extensions/build_information/tests/promptfoo/host_os.yaml
@@ -0,0 +1,16 @@ +prompts: + - 'What is the OS of the current host?' + +# The provider is our custom Python script. +providers: + - id: python:../../../../testing/gemini_provider.py + config: + timeoutSeconds: 30 + system_prompt: file://../../../../../GEMINI.md + +# The test cases will run on the output returned by our Python script. +tests: + - description: 'Host OS determination' + assert: + - type: icontains + value: 'linux'
diff --git a/agents/extensions/install.py b/agents/extensions/install.py index 43fcd96..f228c27 100755 --- a/agents/extensions/install.py +++ b/agents/extensions/install.py
@@ -112,20 +112,28 @@ def get_dir_hash(directory: Path) -> bytes | None: """Calculates a hash for the contents of a directory.""" hashes = [] - for path in sorted(Path(directory).rglob('*')): - if path.is_file(): - try: - hashes.append( - subprocess.check_output(['git', 'hash-object', - str(path)]).strip()) - except (subprocess.CalledProcessError, FileNotFoundError): - # Fallback for non-git environments - import hashlib - hasher = hashlib.sha1() - with open(path, 'rb') as f: - while chunk := f.read(8192): - hasher.update(chunk) - hashes.append(hasher.hexdigest().encode('utf-8')) + files_to_hash = [] + for root, dirs, files in os.walk(directory): + # We do not want changes to test-only data to count as a change to + # the extension. + if 'tests' in dirs: + dirs.remove('tests') + for name in files: + files_to_hash.append(os.path.join(root, name)) + + for path in sorted(files_to_hash): + try: + hashes.append( + subprocess.check_output(['git', 'hash-object', + str(path)]).strip()) + except (subprocess.CalledProcessError, FileNotFoundError): + # Fallback for non-git environments + import hashlib + hasher = hashlib.sha1() + with open(path, 'rb') as f: + while chunk := f.read(8192): + hasher.update(chunk) + hashes.append(hasher.hexdigest().encode('utf-8')) if not hashes: return None @@ -196,7 +204,7 @@ def add_extension(extension_name: str, source_extensions_dir: Path, - target_extensions_dir: Path) -> None: + target_extensions_dir: Path, symlink: bool) -> None: """Adds an extension.""" source_dir = source_extensions_dir / extension_name dest_dir = target_extensions_dir / extension_name @@ -216,7 +224,12 @@ if dest_dir.exists(): shutil.rmtree(dest_dir) - shutil.copytree(source_dir, dest_dir) + if symlink: + os.symlink(source_dir, dest_dir) + else: + shutil.copytree(source_dir, + dest_dir, + ignore=shutil.ignore_patterns('tests')) print(f"Added/updated '{extension_name}' to {dest_dir}") @@ -240,7 +253,9 @@ if dest_dir.exists(): shutil.rmtree(dest_dir) - shutil.copytree(source_dir, dest_dir) + shutil.copytree(source_dir, + dest_dir, + ignore=shutil.ignore_patterns('tests')) print(f"Updated '{extension_name}' in {dest_dir}") @@ -276,6 +291,12 @@ dest='use_global', action='store_true', help='Install to the global extensions directory.') + add_parser.add_argument( + '-l', + '--symlink', + action='store_true', + help='Use symlinks rather than directory copies so ' + 'that extensions automatically stays up-to-date.') add_parser.add_argument('extensions', nargs='+', help='A list of extension directory names to add.') @@ -333,15 +354,18 @@ if args.command == 'add': add_extension(extension, source_extensions_dir, - target_extensions_dir) + target_extensions_dir, args.symlink) elif args.command == 'update': update_extension(extension, source_extensions_dir, target_extensions_dir) elif args.command == 'remove': remove_extension(extension, target_extensions_dir) - elif args.command == 'list' or args.command is None: + elif args.command == 'list': list_extensions(extensions_dirs) + else: + parser.print_help() + sys.exit(1) if __name__ == '__main__':
diff --git a/agents/extensions/install_integration_test.py b/agents/extensions/install_integration_test.py index be6be57..12e9d35 100755 --- a/agents/extensions/install_integration_test.py +++ b/agents/extensions/install_integration_test.py
@@ -39,6 +39,11 @@ 'w', encoding='utf-8') as f: f.write('{"name": "sample_1", "version": "1.0.0"}') + (self.extension1_dir / 'tests').mkdir() + with open(self.extension1_dir / 'tests' / 'test.py', + 'w', + encoding='utf-8') as f: + f.write('print("hello")') self.extension2_dir = self.source_extensions_dir / 'sample_2' self.extension2_dir.mkdir() @@ -106,6 +111,8 @@ with patch('sys.argv', ['install.py', 'add', 'sample_1']): install.main() self.assertTrue((self.target_extensions_dir / 'sample_1').exists()) + self.assertFalse( + (self.target_extensions_dir / 'sample_1' / 'tests').exists()) with patch('sys.argv', ['install.py', 'remove', 'sample_1']): install.main() @@ -116,6 +123,17 @@ with patch('sys.argv', ['install.py', 'add', 'sample_1']): install.main() + # Check that changes in the tests directory don't trigger an update + with open(self.extension1_dir / 'tests' / 'test.py', + 'w', + encoding='utf-8') as f: + f.write('print("goodbye")') + with patch('sys.stdout', new_callable=io.StringIO) as mock_stdout: + with patch('sys.argv', ['install.py', 'update', 'sample_1']): + install.main() + self.assertIn('already up to date', mock_stdout.getvalue()) + + # Check that a legitimate change does trigger an update with open(self.extension1_dir / 'gemini-extension.json', 'w', encoding='utf-8') as f: @@ -211,11 +229,12 @@ self.assertIn('not found', mock_stderr.getvalue()) def test_default_command(self): - """Tests that the script defaults to the list command.""" + """Tests that the script defaults to --help.""" with patch('sys.stdout', new_callable=io.StringIO) as mock_stdout: with patch('sys.argv', ['install.py']): - install.main() - self.assertIn('Extension', mock_stdout.getvalue()) + with self.assertRaises(SystemExit): + install.main() + self.assertIn('usage:', mock_stdout.getvalue()) def test_missing_extension_arguments(self): """Tests that missing extension arguments are handled."""
diff --git a/agents/extensions/install_unittest.py b/agents/extensions/install_unittest.py index 7d8f4abc7..ffe0bf1 100755 --- a/agents/extensions/install_unittest.py +++ b/agents/extensions/install_unittest.py
@@ -102,6 +102,30 @@ self.assertIn(self.source_extensions_dir, extensions_dirs) self.assertIn(self.internal_extensions_dir, extensions_dirs) + def test_get_dir_hash_ignores_tests(self): + """Tests that get_dir_hash ignores the 'tests' directory.""" + # Create a tests directory and get the hash + (self.extension1_dir / 'tests').mkdir() + with open(self.extension1_dir / 'tests' / 'test.py', + 'w', + encoding='utf-8') as f: + f.write('print("test")') + hash1 = install.get_dir_hash(self.extension1_dir) + + # Modify a file in the tests directory and check the hash is the same + with open(self.extension1_dir / 'tests' / 'test.py', + 'w', + encoding='utf-8') as f: + f.write('print("test2")') + hash2 = install.get_dir_hash(self.extension1_dir) + self.assertEqual(hash1, hash2) + + # Modify a file outside the tests directory and check the hash changes + with open(self.extension1_dir / 'main.py', 'w', encoding='utf-8') as f: + f.write('print("new world")') + hash3 = install.get_dir_hash(self.extension1_dir) + self.assertNotEqual(hash1, hash3) + @patch('subprocess.check_output', side_effect=FileNotFoundError) def test_get_dir_hash_fallback(self, mock_check_output): """Tests the get_dir_hash function's fallback mechanism.""" @@ -119,7 +143,7 @@ self.target_extensions_dir)) install.add_extension('sample_1', self.source_extensions_dir, - self.target_extensions_dir) + self.target_extensions_dir, False) mock_get_dir_hash.side_effect = [b'some_hash', b'some_hash'] self.assertTrue( install.is_up_to_date('sample_1', self.source_extensions_dir, @@ -134,9 +158,16 @@ def test_add_extension(self, mock_input): """Tests the add_extension function.""" install.add_extension('sample_1', self.source_extensions_dir, - self.target_extensions_dir) + self.target_extensions_dir, False) self.assertTrue((self.target_extensions_dir / 'sample_1').exists()) + @patch('builtins.input', return_value='y') + def test_add_extension_symlink(self, mock_input): + """Tests the add_extension function with symlinking.""" + install.add_extension('sample_1', self.source_extensions_dir, + self.target_extensions_dir, True) + self.assertTrue((self.target_extensions_dir / 'sample_1').is_symlink()) + @patch('builtins.input', return_value='n') @patch('install.is_up_to_date', return_value=False) def test_add_extension_decline_update(self, mock_is_up_to_date, @@ -144,10 +175,10 @@ """Tests that adding an existing extension is skipped if the user declines.""" install.add_extension('sample_1', self.source_extensions_dir, - self.target_extensions_dir) + self.target_extensions_dir, False) with patch('shutil.copytree') as mock_copy: install.add_extension('sample_1', self.source_extensions_dir, - self.target_extensions_dir) + self.target_extensions_dir, False) mock_copy.assert_not_called() def test_update_extension(self): @@ -160,7 +191,7 @@ # Test updating an up-to-date extension install.add_extension('sample_1', self.source_extensions_dir, - self.target_extensions_dir) + self.target_extensions_dir, False) with patch('install.is_up_to_date', return_value=True): with patch('sys.stdout', new_callable=io.StringIO) as mock_stdout: install.update_extension('sample_1', @@ -188,7 +219,8 @@ install.main() mock_add_extension.assert_called_once_with('sample_1', self.source_extensions_dir, - self.global_extension_dir) + self.global_extension_dir, + False) @patch('install.update_extension') @patch('install.get_installed_extensions', return_value=['sample_1'])
diff --git a/agents/prompts/common.minimal.md b/agents/prompts/common.minimal.md index b0a8244..c525b8d0 100644 --- a/agents/prompts/common.minimal.md +++ b/agents/prompts/common.minimal.md
@@ -49,3 +49,28 @@ ``` * Fix errors / warnings related to your change, but do not fix pre-existing warnings (from lines that you did not change). + +## JNI + +Chrome on Android uses both Java and C++ frequently. Our JNI uses codegen from +`//third_party/jni_zero`. + +Identifying JNI methods: + * In Java, methods annotated with `@CalledByNative` are called by C++. + * In C++, these appear as methods with a "Java_" prefix. + * In Java, methods within interfaces annotated with `@NativeMethods` are calls + into C++. + * In C++, these appear as methods with a "JNI_" prefix. + * If the first parameter is of type `long` and has a prefix of "native", + then it maps to a method of the same name on the C++ class that comes + after the "native" prefix. Eg. `void foo(long nativeBarImpl)` means you + need to find `BarImpl::Foo` in C++. + +Finding JNI methods: + * To find the Java side of JNI: search for the file named `{JavaClass}.java` + (where {JavaClass} is taken from the `#include "{JavaClass}_jni.h"`. + * To find the C++ side of JNI: Search for the text `{JavaClass}_jni.h` in C++ + files (where {JavaClass} is taken from the .java file name). + +When making changes to JNI methods, always make changes to both the .java and +.cc/.h files involved.
diff --git a/agents/prompts/common.minimal.tmpl.md b/agents/prompts/common.minimal.tmpl.md index e7f668c..4dbdbab 100644 --- a/agents/prompts/common.minimal.tmpl.md +++ b/agents/prompts/common.minimal.tmpl.md
@@ -57,3 +57,34 @@ ``` * Fix errors / warnings related to your change, but do not fix pre-existing warnings (from lines that you did not change). + +## JNI + +<!-- +We have a separate //agents/prompts/templates/android.md, but the purpose +of that file is to tell the agent to build / test on Android. There are a lot +of shared source files that contain JNI, so including this short explanation +improves outcomes even when Android-specific changes are not the focus. +--> +Chrome on Android uses both Java and C++ frequently. Our JNI uses codegen from +`//third_party/jni_zero`. + +Identifying JNI methods: + * In Java, methods annotated with `@CalledByNative` are called by C++. + * In C++, these appear as methods with a "Java_" prefix. + * In Java, methods within interfaces annotated with `@NativeMethods` are calls + into C++. + * In C++, these appear as methods with a "JNI_" prefix. + * If the first parameter is of type `long` and has a prefix of "native", + then it maps to a method of the same name on the C++ class that comes + after the "native" prefix. Eg. `void foo(long nativeBarImpl)` means you + need to find `BarImpl::Foo` in C++. + +Finding JNI methods: + * To find the Java side of JNI: search for the file named `{JavaClass}.java` + (where {JavaClass} is taken from the `#include "{JavaClass}_jni.h"`. + * To find the C++ side of JNI: Search for the text `{JavaClass}_jni.h` in C++ + files (where {JavaClass} is taken from the .java file name). + +When making changes to JNI methods, always make changes to both the .java and +.cc/.h files involved.
diff --git a/agents/prompts/templates/android.md b/agents/prompts/templates/android.md index 2bbbacb..c5cc1c69 100644 --- a/agents/prompts/templates/android.md +++ b/agents/prompts/templates/android.md
@@ -22,27 +22,3 @@ `out/Debug/bin/chrome_public_apk install`. * "Launch" installs and starts the app - eg. `out/Release/bin/trichrome_chrome_google_bundle launch`. - -## JNI -Chrome on Android uses both Java and C++ frequently. Our JNI uses codegen from -`//third_party/jni_zero`. - -Identifying JNI methods: - * In Java, methods annotated with `@CalledByNative` are called by C++. - * In C++, these appear as methods with a "Java_" prefix. - * In Java, methods within interfaces annotated with `@NativeMethods` are calls - into C++. - * In C++, these appear as methods with a "JNI_" prefix. - * If the first parameter is of type `long` and has a prefix of "native", - then it maps to a method of the same name on the C++ class that comes - after the "native" prefix. Eg. `void foo(long nativeBarImpl)` means you - need to find `BarImpl::Foo` in C++. - -Finding JNI methods: - * To find the Java side of JNI: search for the file named `{JavaClass}.java` - (where {JavaClass} is taken from the `#include "{JavaClass}_jni.h"`. - * To find the C++ side of JNI: Search for the text `{JavaClass}_jni.h` in C++ - files (where {JavaClass} is taken from the .java file name). - -When making changes to JNI methods, always make changes to both the .java and -.cc/.h files involved.
diff --git a/agents/testing/.style.yapf b/agents/testing/.style.yapf new file mode 100644 index 0000000..557fa7b --- /dev/null +++ b/agents/testing/.style.yapf
@@ -0,0 +1,2 @@ +[style] +based_on_style = pep8
diff --git a/agents/testing/OWNERS b/agents/testing/OWNERS new file mode 100644 index 0000000..f1a9e484 --- /dev/null +++ b/agents/testing/OWNERS
@@ -0,0 +1,2 @@ +bsheedy@chromium.org +jewoo@google.com
diff --git a/agents/testing/README.md b/agents/testing/README.md new file mode 100644 index 0000000..0ea04de --- /dev/null +++ b/agents/testing/README.md
@@ -0,0 +1,37 @@ +# Prompt Evaluation + +This directory contains an experimental script for running prompt evaluation +tests on extensions and prompts under `//agents`. It currently only works +locally and will make temporary changes to your Chromium repo. + +## Usage + +Existing tests can be run via the `//agents/testing/eval_prompts.py` script. It +should handle everything automatically, although it is advised to commit any +changes before running this script. It will automatically retrieve a temporary +copy of promptfoo, perform repo setup, run configured tests, and perform +teardown. + +By default, it will build promptfoo from ToT, but specific behavior can be +configured via command line arguments, including use of stable releases via npm +which will likely result in faster setup. + +## Adding Extensions + +The script only installs the extensions in the `EXTENSIONS_TO_INSTALL` list at +the top of the file. If an extension should be present for testing, add the +extension name to this list. + +## Adding Tests + +Each independent test case should have its own promptfoo yaml config file. See +the [promptfoo documentation](https://www.promptfoo.dev/docs/configuration/guide/) +for more information on this. If multiple prompts are expected to result in the +same behavior, and thus can be tested in the same way, the config file can +contain multiple prompts. promptfoo will automatically test each prompt +individually. + +Config files should be placed in a `tests/promptfoo/` subdirectory of the +relevant prompt or extension directory. After they exist on disk, new yaml +files will need to be added to the `PROMPTFOO_CONFIG_COMPONENTS` list at the +top of the script for the tests to actually be run.
diff --git a/agents/testing/eval_prompts.py b/agents/testing/eval_prompts.py new file mode 100755 index 0000000..e6083e8 --- /dev/null +++ b/agents/testing/eval_prompts.py
@@ -0,0 +1,355 @@ +#!/usr/bin/env python3 +# 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. +"""A script to evaluate prompts using promptfoo.""" + +import argparse +import atexit +import os +import shutil +import subprocess +import sys +import tempfile + +CHROMIUM_SRC = os.path.realpath( + os.path.join(os.path.dirname(__file__), '..', '..')) + +PROMPTFOO_CONFIG_COMPONENTS = [ + ('agents', 'extensions', 'build_information', 'tests', 'promptfoo', + 'host_os.yaml'), + ('agents', 'extensions', 'build_information', 'tests', 'promptfoo', + 'host_arch.yaml'), +] +PROMPTFOO_CONFIGS = [ + os.path.join(CHROMIUM_SRC, *c) for c in PROMPTFOO_CONFIG_COMPONENTS +] + +EXTENSIONS_TO_INSTALL = [ + 'build_information', + 'depot_tools', + 'landmines', +] + + +class PromptfooInstallation: + """Interface for a temporary promptfoo installation.""" + + def setup(self) -> None: + """Called once to set up the promptfoo installation.""" + raise NotImplementedError() + + def cleanup(self) -> None: + """Called once to clean up the promptfoo installation.""" + raise NotImplementedError() + + def run(self, cmd: list[str]) -> int: + """Runs a promptfoo command. + + Args: + cmd: The command to run + + Returns: + The returncode of the command. + """ + raise NotImplementedError() + + +class FromNpmPromptfooInstallation(PromptfooInstallation): + """A promptfoo installation retrieved via npm.""" + + def __init__(self, version: str | None): + self._directory = None + self._version = version or 'latest' + + def setup(self) -> None: + assert self._directory is None + self._directory = tempfile.mkdtemp() + atexit.register(self.cleanup) + print(f'Creating promptfoo copy at {self._directory}') + subprocess.run(['npm', 'init', '-y'], cwd=self._directory, check=True) + subprocess.run(['npm', 'install', f'promptfoo@{self._version}'], + cwd=self._directory, + check=True) + + def cleanup(self) -> None: + if not self._directory: + return + print(f'Removing promptfoo copy at {self._directory}') + shutil.rmtree(self._directory) + self._directory = None + + def run(self, cmd: list[str]) -> int: + promptfoo_executable = os.path.join(self._directory, 'node_modules', + '.bin', 'promptfoo') + proc = subprocess.run([promptfoo_executable] + cmd, check=False) + return proc.returncode + + +class FromSourcePromptfooInstallation(PromptfooInstallation): + """A promptfoo installation built from source.""" + + def __init__(self, revision: str | None): + self._parent_dir = None + self._promptfoo_dir = None + self._revision = revision + + def setup(self) -> None: + assert self._parent_dir is None + self._parent_dir = tempfile.mkdtemp() + atexit.register(self.cleanup) + print(f'Creating promptfoo copy at {self._parent_dir}') + + cmd = [ + 'git', + 'clone', + 'https://github.com/promptfoo/promptfoo', + ] + subprocess.run(cmd, check=True, cwd=self._parent_dir) + self._promptfoo_dir = os.path.join(self._parent_dir, 'promptfoo') + + if self._revision: + cmd = ['git', 'checkout', self._revision] + subprocess.run(cmd, check=True, cwd=self._promptfoo_dir) + + cmd = [ + 'npm', + 'install', + ] + subprocess.run(cmd, check=True, cwd=self._promptfoo_dir) + + cmd = [ + 'npm', + 'run', + 'build', + ] + subprocess.run(cmd, check=True, cwd=self._promptfoo_dir) + + def cleanup(self) -> None: + if not self._parent_dir: + return + print(f'Removing promptfoo copy at {self._parent_dir}') + shutil.rmtree(self._parent_dir) + self._parent_dir = None + + def run(self, cmd: list[str]) -> int: + node_cmd = [ + 'npm', + 'run', + '--prefix', + self._promptfoo_dir, + 'local', + '--', + ] + proc = subprocess.run(node_cmd + cmd, check=False) + return proc.returncode + + +def _prompt_user_to_continue() -> None: + response = input( + f'WARNING: This script will potentially make changes to your local ' + f'repo at {CHROMIUM_SRC}, including untracked files. It will attempt ' + f'move untracked files to a safe location and restore them on exit, ' + f'but it is always possible something will go wrong. Do you want to ' + f'continue? y/N: ') + if response.lower() != 'y': + sys.exit(1) + + +def _move_untracked_files() -> None: + """Moves any untracked files to a temporary location. + + If any files are moved, cleanup will be automatically performed + when the script exits to restore the files to their original + locations. + """ + cmd = [ + 'git', + 'ls-files', + '--others', + '--exclude-standard', + '--directory', + '--no-empty-directory', + ] + proc = subprocess.run(cmd, + cwd=CHROMIUM_SRC, + capture_output=True, + check=True, + text=True) + + untracked_files = [] + for line in proc.stdout.splitlines(): + line = line.strip() + if line: + untracked_files.append(line) + if not untracked_files: + return + + tmpdir = tempfile.mkdtemp() + print(f'Moving untracked files to {tmpdir}') + for f in untracked_files: + parent_dirs = os.path.dirname(f) + if parent_dirs: + os.makedirs(os.path.join(tmpdir, parent_dirs), exist_ok=True) + shutil.move(os.path.join(CHROMIUM_SRC, f), + os.path.join(tmpdir, parent_dirs)) + atexit.register(_restore_untracked_files, tmpdir, untracked_files) + + +def _restore_untracked_files(directory: str, file_list: list[str]) -> None: + """Restores untracked files to their original locations. + + Args: + directory: The directory that contains the untracked files to + restore. + file_list: The list of untracked files to actually copy. This + should be the list that git originally generated. + """ + print(f'Restoring untracked files from {directory}') + for f in file_list: + shutil.move(os.path.join(directory, f), os.path.join(CHROMIUM_SRC, f)) + shutil.rmtree(directory) + + +def _setup_promptfoo(from_npm: bool, promptfoo_revision: str | None, + promptfoo_version: str | None) -> PromptfooInstallation: + """Sets up a temporary promptfoo installation. + + This installation will be automatically cleaned up when the script + exits. + + Args: + from_npm: Whether the installation should come from npm instead + of being built from source. + promptfoo_revision: When building from source, an optional git + revision to build at instead of ToT. + promptfoo_version: When installing from npm, an optional + version to use instead of latest. + """ + if from_npm: + promptfoo = FromNpmPromptfooInstallation(promptfoo_version) + else: + promptfoo = FromSourcePromptfooInstallation(promptfoo_revision) + promptfoo.setup() + return promptfoo + + +def _move_installed_extensions() -> None: + """Moves any installed Gemini extensions to a temporary location. + + If any extensions are moved, they will be automatically moved back + when the script exits. + """ + extensions_dir = os.path.join(CHROMIUM_SRC, '.gemini', 'extensions') + if not os.path.isdir(extensions_dir): + print('Did not find any installed extensions') + return + + tmpdir = tempfile.mkdtemp() + print(f'Moving installed extensions to {tmpdir}') + shutil.move(extensions_dir, tmpdir) + atexit.register(_restore_installed_extensions, tmpdir) + + +def _restore_installed_extensions(directory: str) -> None: + """Restores any previously installed extensions. + + Args: + directory: The directory containing the moved extensions. + """ + print(f'Restoring installed extensions from {directory}') + extensions_dir = os.path.join(CHROMIUM_SRC, '.gemini', 'extensions') + shutil.move(os.path.join(directory, 'extensions'), extensions_dir) + + +def _install_extensions() -> None: + """Installs extensions for testing. + + Any extensions installed this way will be automatically removed + when the script exits. + """ + print(f'Installing extensions {" ".join(EXTENSIONS_TO_INSTALL)}') + install_script = os.path.join(CHROMIUM_SRC, 'agents', 'extensions', + 'install.py') + subprocess.run([install_script, 'add'] + EXTENSIONS_TO_INSTALL, check=True) + atexit.register(_uninstall_extensions) + + +def _uninstall_extensions() -> None: + """Uninstalls extensions that were installed for testing.""" + print('Uninstalling extensions') + shutil.rmtree(os.path.join(CHROMIUM_SRC, '.gemini', 'extensions')) + + +def _clean_repo() -> None: + """Gets the repo into a clean state.""" + print('Cleaning repo') + cmd = [ + 'git', + 'reset', + '--hard', + 'HEAD', + ] + subprocess.run(cmd, check=True) + + cmd = [ + 'git', + 'clean', + '-f', + ] + subprocess.run(cmd, check=True) + + +def main() -> int: + """Evaluates prompts using promptfoo. + + This will get a temporary copy of promptfoo and attempt to get the + repo into a clean state before running tests. Any changes to the + repo will be undone at the end of the script to the best of its + ability. + """ + parser = argparse.ArgumentParser() + parser.add_argument( + '--bypass-confirmation', + action='store_true', + default=False, + help='Bypasses the prompt for user confirmation at the beginning of ' + 'the script.') + parser.add_argument( + '--install-from-npm', + action='store_true', + default=False, + help='Install a release version of promptfoo via npm instead of ' + 'building from source.') + parser.add_argument( + '--promptfoo-revision', + help='The promptfoo revision to build at if building from source. If ' + 'unspecified, ToT will be used.') + parser.add_argument( + '--promptfoo-version', + help='The promptfoo release version to use if installing through npm. ' + 'If unspecified, latest will be used.') + args = parser.parse_args() + + if not args.bypass_confirmation: + _prompt_user_to_continue() + + _move_untracked_files() + promptfoo = _setup_promptfoo(args.install_from_npm, + args.promptfoo_revision, + args.promptfoo_version) + _move_installed_extensions() + _install_extensions() + + returncode = 0 + for config in PROMPTFOO_CONFIGS: + _clean_repo() + rc = promptfoo.run(['eval', '-j', '1', '-c', config]) + returncode = returncode or rc + _clean_repo() + + return returncode + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/agents/testing/gemini_provider.py b/agents/testing/gemini_provider.py new file mode 100644 index 0000000..a0c716f --- /dev/null +++ b/agents/testing/gemini_provider.py
@@ -0,0 +1,113 @@ +# 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 subprocess +import os +import sys +import json +from datetime import datetime +import threading + +# --- Constants for File Paths --- +RUN_OUTPUTS_DIR = os.path.expanduser(os.path.join('~', + 'promptfoo_run_outputs')) +GEMINI_LOG_FILE = "gemini.log" +GIT_DIFF_FILE = "git_diff.txt" +DEFAULT_TIMEOUT_SECONDS = 600 + + +def _stream_reader(stream, log_file, full_output_list, all_output_list): + """Reads a stream line-by-line and logs it.""" + try: + for line in iter(stream.readline, ''): + sys.stderr.write(line) + sys.stderr.flush() + log_file.write(line) + full_output_list.append(line) + all_output_list.append(line) + finally: + stream.close() + + +def call_api(prompt: str, options: dict, context: dict): + """ + A promptfoo provider that runs 'gemini -y', saves artifacts, and streams + its output with a reliable timeout. + """ + provider_config = options.get('config', {}) + + # --- 1. Set up unique directory for this run --- + run_id = datetime.now().strftime('%Y-%m-%d_%H%M%S') + run_dir = os.path.join(RUN_OUTPUTS_DIR, run_id) + os.makedirs(run_dir, exist_ok=True) + + log_file_path = os.path.join(run_dir, GEMINI_LOG_FILE) + output_file_path = os.path.join(run_dir, GIT_DIFF_FILE) + + # --- 2. Get prompts and config --- + system_prompt = provider_config.get('system_prompt', '') + combined_input = f"{system_prompt}\n\n{prompt}" + + try: + timeout_seconds = int( + provider_config.get("timeoutSeconds", DEFAULT_TIMEOUT_SECONDS)) + except (ValueError, TypeError): + timeout_seconds = DEFAULT_TIMEOUT_SECONDS + + # --- 3. Execute and stream the command with a timeout --- + process = None + try: + process = subprocess.Popen(["gemini", "-y"], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + text=True, + universal_newlines=True) + process.stdin.write(combined_input) + process.stdin.close() + + print( + f"--- Streaming Gemini Output (Run ID: {run_id}, Timeout: {timeout_seconds}s) ---", + file=sys.stderr) + + with open(log_file_path, "w") as log_f: + log_f.write("--- System Prompt ---\n") + log_f.write(system_prompt) + log_f.write("\n\n--- User Prompt ---\n") + log_f.write(prompt) + log_f.write("\n\n--- Gemini Output ---\n") + + stdout_output = [] + all_output = [] + + stdout_thread = threading.Thread(target=_stream_reader, + args=(process.stdout, log_f, + stdout_output, all_output)) + + stdout_thread.start() + + # Wait for the process to finish, with a timeout. + process.wait(timeout=timeout_seconds) + + # Wait for the stream readers to finish *before* the log file is closed. + stdout_thread.join() + + print("\n--- End of Stream ---", file=sys.stderr) + + if process.returncode != 0: + return { + "error": + f"'gemini -y' failed with return code {process.returncode}. Output:\n{''.join(all_output)}" + } + + sys.stderr.write('All output: %s\n' % all_output) + + return {"output": all_output} + + except subprocess.TimeoutExpired: + if process: + process.kill() + return {"error": f"Command timed out after {timeout_seconds} seconds."} + except Exception as e: + return {"error": f"An unexpected error occurred: {e}"}
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index d7d58dd6..fe25ee2 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -1002,10 +1002,6 @@ + " - caches any chromium startup exception and rethrows it if startup is" + " retried without a restart."), Flag.baseFeature( - CcFeatures.EXPORT_FRAME_TIMING_AFTER_FRAME_DONE, - "When enabled, moves the layer tree client's metric export call for from beginning" - + " of the subsequent frame to the end of the subsequent frame."), - Flag.baseFeature( BlinkFeatures.ASYNC_SET_COOKIE, "When enabled, the communication between renderer and network service is " + "asynchronous when setting cookies."),
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProfileBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProfileBoundaryInterface.java index 9a76ab96..0ba4ec4a 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProfileBoundaryInterface.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/ProfileBoundaryInterface.java
@@ -59,4 +59,6 @@ void clearOriginMatchedHeader(String headerName); void clearAllOriginMatchedHeaders(); + + void preconnect(String url); }
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java index d40daf6..1a9cb9a 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/util/Features.java
@@ -373,4 +373,7 @@ // WebSettingsCompat.setBackForwardCacheSettings // WebSettingsCompat.getBackForwardCacheSettings public static final String BACK_FORWARD_CACHE_SETTINGS = "BACK_FORWARD_CACHE_SETTINGS"; + + // Profile.preconnect + public static final String PRECONNECT = "PRECONNECT"; }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProfile.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProfile.java index 4aa16a9..52a8516 100644 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProfile.java +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibProfile.java
@@ -267,4 +267,12 @@ mProfileImpl.clearAllOriginMatchedHeaders(); } } + + @Override + public void preconnect(String url) { + recordApiCall(ApiCall.PRECONNECT); + try (TraceEvent event = TraceEvent.scoped("WebView.APICall.AndroidX.PRECONNECT")) { + mProfileImpl.preconnect(url); + } + } }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java index 7e5393df..faaa8a4 100644 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java
@@ -119,6 +119,7 @@ Features.WARM_UP_RENDERER_PROCESS, Features.EXTRA_HEADER_FOR_ORIGINS, Features.BACK_FORWARD_CACHE_SETTINGS, + Features.PRECONNECT + Features.DEV_SUFFIX, // Add new features above. New features must include `+ Features.DEV_SUFFIX` // when they're initially added (this can be removed in a future CL). The final // feature should have a trailing comma for cleaner diffs. @@ -287,6 +288,7 @@ ApiCall.GET_BACK_FORWARD_CACHE_SETTINGS, ApiCall.BACK_FORWARD_CACHE_SETTINGS_GET_TIMEOUT_IN_SECONDS, ApiCall.BACK_FORWARD_CACHE_SETTINGS_GET_MAX_PAGES_IN_CACHE, + ApiCall.PRECONNECT, // Add new constants above. The final constant should have a trailing comma for cleaner // diffs. @@ -455,9 +457,10 @@ int GET_BACK_FORWARD_CACHE_SETTINGS = 156; int BACK_FORWARD_CACHE_SETTINGS_GET_TIMEOUT_IN_SECONDS = 157; int BACK_FORWARD_CACHE_SETTINGS_GET_MAX_PAGES_IN_CACHE = 158; + int PRECONNECT = 159; // Remember to update AndroidXWebkitApiCall in enums.xml when adding new values here - int COUNT = 159; + int COUNT = 160; } // LINT.ThenChange(/tools/metrics/histograms/metadata/android/enums.xml:AndroidXWebkitApiCall)
diff --git a/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 0406645a..6b15b86 100644 --- a/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -4843,6 +4843,7 @@ method get method getAll method getAllKeys + method getAllRecords method getKey method openCursor method openKeyCursor @@ -4876,6 +4877,7 @@ method get method getAll method getAllKeys + method getAllRecords method getKey method index method openCursor @@ -4889,6 +4891,12 @@ method constructor setter onblocked setter onupgradeneeded +interface IDBRecord + attribute @@toStringTag + getter key + getter primaryKey + getter value + method constructor interface IDBRequest : EventTarget attribute @@toStringTag getter error
diff --git a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt index 5ff5335..eda6807 100644 --- a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt +++ b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
@@ -6909,15 +6909,15 @@ getter name getter password method constructor -interface PatchEvent : Event - attribute @@toStringTag - getter patch - method constructor -interface PatchStatus +interface Patch attribute @@toStringTag getter finished getter source method constructor +interface PatchEvent : Event + attribute @@toStringTag + getter patch + method constructor interface Path2D attribute @@toStringTag method addPath
diff --git a/ash/accessibility/chromevox/touch_exploration_controller_unittest.cc b/ash/accessibility/chromevox/touch_exploration_controller_unittest.cc index bf21abc..2b517725 100644 --- a/ash/accessibility/chromevox/touch_exploration_controller_unittest.cc +++ b/ash/accessibility/chromevox/touch_exploration_controller_unittest.cc
@@ -1159,14 +1159,13 @@ for (int j = 0; j < num_fingers; j++) { start_points.push_back(gfx::Point(j * 10 + 100, j * 10 + 200)); } - gfx::Point* start_points_array = &start_points[0]; // A swipe is made when a fling starts float delta_time = distance / gesture_detector_config_.maximum_fling_velocity; // delta_time is in seconds, so we convert to ms. int delta_time_ms = floor(delta_time * 1000); - generator_->GestureMultiFingerScroll(num_fingers, start_points_array, + generator_->GestureMultiFingerScroll(num_fingers, start_points, delta_time_ms, kSteps, move_x, move_y); EXPECT_EQ(expected_gesture, delegate_.GetLastGesture()); EXPECT_TRUE(IsInNoFingersDownState()); @@ -1221,14 +1220,13 @@ for (int j = 0; j < num_fingers; j++) { start_points.push_back(gfx::Point(j * 10 + 100, j * 10 + 200)); } - gfx::Point* start_points_array = &start_points[0]; // A swipe is made when a fling starts float delta_time = distance / gesture_detector_config_.maximum_fling_velocity; // delta_time is in seconds, so we convert to ms. int delta_time_ms = floor(delta_time * 1000); - generator_->GestureMultiFingerScroll(num_fingers, start_points_array, + generator_->GestureMultiFingerScroll(num_fingers, start_points, delta_time_ms, kSteps, move_x, move_y); EXPECT_EQ(expected_gesture, delegate_.GetLastGesture()); EXPECT_TRUE(IsInNoFingersDownState());
diff --git a/ash/app_list/views/app_list_toast_view.cc b/ash/app_list/views/app_list_toast_view.cc index 6f5633d..9dd56e7 100644 --- a/ash/app_list/views/app_list_toast_view.cc +++ b/ash/app_list/views/app_list_toast_view.cc
@@ -226,8 +226,7 @@ chromeos::features::IsSystemBlurEnabled() ? cros_tokens::kCrosSysSystemBaseElevated : cros_tokens::kCrosSysSystemBaseElevatedOpaque; - SetBackground( - views::CreateRoundedRectBackground(background_color_id, kCornerRadius)); + SetBackground(views::CreateSolidBackground(background_color_id)); SetBorder(std::make_unique<views::HighlightBorder>( kCornerRadius, views::HighlightBorder::Type::kHighlightBorderNoShadow)); } else {
diff --git a/ash/hud_display/memory_status.cc b/ash/hud_display/memory_status.cc index 29bba86..f36556c 100644 --- a/ash/hud_display/memory_status.cc +++ b/ash/hud_display/memory_status.cc
@@ -163,10 +163,10 @@ } void MemoryStatus::UpdateMeminfo() { - base::SystemMemoryInfoKB meminfo; + base::SystemMemoryInfo meminfo; base::GetSystemMemoryInfo(&meminfo); - total_ram_size_ = meminfo.total * 1024LL; - total_free_ = meminfo.free * 1024LL; + total_ram_size_ = meminfo.total.InBytes(); + total_free_ = meminfo.free.InBytes(); base::GraphicsMemoryInfoKB gpu_meminfo; if (base::GetGraphicsMemoryInfo(&gpu_meminfo))
diff --git a/ash/system/focus_mode/sounds/playlist_image_button.cc b/ash/system/focus_mode/sounds/playlist_image_button.cc index 7575dbc..5a884c5c 100644 --- a/ash/system/focus_mode/sounds/playlist_image_button.cc +++ b/ash/system/focus_mode/sounds/playlist_image_button.cc
@@ -9,6 +9,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/style/rounded_rect_cutout_path_builder.h" #include "base/i18n/rtl.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h"
diff --git a/ash/system/mahi/mahi_panel_view.cc b/ash/system/mahi/mahi_panel_view.cc index 646b3b93..29939e58 100644 --- a/ash/system/mahi/mahi_panel_view.cc +++ b/ash/system/mahi/mahi_panel_view.cc
@@ -512,8 +512,7 @@ chromeos::features::IsSystemBlurEnabled() ? cros_tokens::kCrosSysSystemBaseElevated : cros_tokens::kCrosSysSystemBaseElevatedOpaque; - SetBackground(views::CreateRoundedRectBackground( - background_color_id, mahi_constants::kPanelCornerRadius)); + SetBackground(views::CreateSolidBackground(background_color_id)); // Create a layer for the view for background blur and rounded corners. SetPaintToLayer();
diff --git a/ash/system/mahi/mahi_panel_view_pixeltest.cc b/ash/system/mahi/mahi_panel_view_pixeltest.cc index c1e25be..4d019623 100644 --- a/ash/system/mahi/mahi_panel_view_pixeltest.cc +++ b/ash/system/mahi/mahi_panel_view_pixeltest.cc
@@ -126,7 +126,7 @@ views::test::RunScheduledLayout(widget()); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( - "panel_view", /*revision_number=*/14, panel_view())); + "panel_view", /*revision_number=*/15, panel_view())); } TEST_F(MahiPanelViewPixelTest, ContentSourceButton) {
diff --git a/ash/system/phonehub/app_stream_connection_error_dialog.cc b/ash/system/phonehub/app_stream_connection_error_dialog.cc index 1cb5eae..6c8ea69 100644 --- a/ash/system/phonehub/app_stream_connection_error_dialog.cc +++ b/ash/system/phonehub/app_stream_connection_error_dialog.cc
@@ -89,9 +89,8 @@ layer()->SetRoundedCornerRadius( gfx::RoundedCornersF(kDialogRoundedCornerRadius)); - SetBackground(views::CreateRoundedRectBackground( - static_cast<ui::ColorId>(cros_tokens::kCrosSysBaseElevated), - kDialogRoundedCornerRadius)); + SetBackground(views::CreateSolidBackground( + static_cast<ui::ColorId>(cros_tokens::kCrosSysBaseElevated))); SetBorder(std::make_unique<views::HighlightBorder>( kDialogRoundedCornerRadius, views::HighlightBorder::Type::kHighlightBorder1));
diff --git a/ash/test/ash_test_base.cc b/ash/test/ash_test_base.cc index 4bb6a64..7955ad18 100644 --- a/ash/test/ash_test_base.cc +++ b/ash/test/ash_test_base.cc
@@ -329,8 +329,8 @@ chromeos::AppType app_type, int shell_window_id, views::WidgetDelegate* delegate) { - TestWidgetBuilder builder; - builder.SetWindowTitle(u"Window " + base::NumberToString16(shell_window_id)); + TestWidgetBuilder builder( + {.window_title = u"Window " + base::NumberToString16(shell_window_id)}); if (app_type != chromeos::AppType::NON_APP) { builder.SetWindowProperty(chromeos::kAppTypeKey, app_type); }
diff --git a/ash/test/test_widget_builder.cc b/ash/test/test_widget_builder.cc index 79115431..2022265 100644 --- a/ash/test/test_widget_builder.cc +++ b/ash/test/test_widget_builder.cc
@@ -37,7 +37,8 @@ } }; -TestWidgetBuilder::TestWidgetBuilder() = default; +TestWidgetBuilder::TestWidgetBuilder(WidgetBuilderParams params) + : params_(std::move(params)) {} TestWidgetBuilder::~TestWidgetBuilder() = default; @@ -96,20 +97,20 @@ TestWidgetBuilder& TestWidgetBuilder::SetWindowId(int window_id) { DCHECK(!built_); - window_id_ = window_id; + params_.window_id = window_id; return *this; } TestWidgetBuilder& TestWidgetBuilder::SetWindowTitle( const std::u16string& title) { DCHECK(!built_); - window_title_ = title; + params_.window_title = title; return *this; } TestWidgetBuilder& TestWidgetBuilder::SetShow(bool show) { DCHECK(!built_); - show_ = show; + params_.show = show; return *this; } @@ -136,13 +137,15 @@ std::unique_ptr<views::Widget> widget = std::make_unique<views::Widget>(); widget_init_params_.ownership = ownership; widget->Init(std::move(widget_init_params_)); - if (window_id_ != aura::Window::kInitialId) - widget->GetNativeWindow()->SetId(window_id_); - if (!window_title_.empty()) { - widget->GetNativeWindow()->SetTitle(window_title_); + if (params_.window_id != aura::Window::kInitialId) { + widget->GetNativeWindow()->SetId(params_.window_id); } - if (show_) + if (!params_.window_title.empty()) { + widget->GetNativeWindow()->SetTitle(params_.window_title); + } + if (params_.show) { widget->Show(); + } return widget; } @@ -154,13 +157,15 @@ widget_init_params_.ownership = views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET; widget->Init(std::move(widget_init_params_)); - if (window_id_ != aura::Window::kInitialId) - widget->GetNativeWindow()->SetId(window_id_); - if (!window_title_.empty()) { - widget->GetNativeWindow()->SetTitle(window_title_); + if (params_.window_id != aura::Window::kInitialId) { + widget->GetNativeWindow()->SetId(params_.window_id); } - if (show_) + if (!params_.window_title.empty()) { + widget->GetNativeWindow()->SetTitle(params_.window_title); + } + if (params_.show) { widget->Show(); + } return widget; }
diff --git a/ash/test/test_widget_builder.h b/ash/test/test_widget_builder.h index 7c30bfd..ba4d65f 100644 --- a/ash/test/test_widget_builder.h +++ b/ash/test/test_widget_builder.h
@@ -17,6 +17,12 @@ namespace ash { +struct WidgetBuilderParams { + int window_id = aura::Window::kInitialId; + std::u16string window_title = std::u16string(); + bool show = true; +}; + // A builder to create a views::Widget for testing purpose. There are three // ways to create a widget: `BuildOwnedByNativeWidget()`, // `BuildOwnsNativeWidget()`, and `BuildClientOwnsWidget()`. Please refer @@ -24,7 +30,7 @@ // test cases as there are subtle differences. class ASH_EXPORT TestWidgetBuilder { public: - TestWidgetBuilder(); + explicit TestWidgetBuilder(WidgetBuilderParams params = {}); TestWidgetBuilder(const TestWidgetBuilder& other) = delete; TestWidgetBuilder& operator=(const TestWidgetBuilder& other) = delete; ~TestWidgetBuilder(); @@ -101,11 +107,11 @@ [[nodiscard]] std::unique_ptr<views::Widget> BuildWidgetWithOwnership( views::Widget::InitParams::Ownership ownership); + // Note: ownership is a placeholder. It is overridden when building + // a widget. views::Widget::InitParams widget_init_params_{ - views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET}; - int window_id_ = aura::Window::kInitialId; - std::u16string window_title_ = std::u16string(); - bool show_ = true; + views::Widget::InitParams::CLIENT_OWNS_WIDGET}; + WidgetBuilderParams params_; bool built_ = false; };
diff --git a/ash/test/test_window_builder.cc b/ash/test/test_window_builder.cc index 175e327..50fd3a5 100644 --- a/ash/test/test_window_builder.cc +++ b/ash/test/test_window_builder.cc
@@ -124,11 +124,13 @@ std::unique_ptr<aura::Window> TestWindowBuilder::Build() { auto window = CreateWindowInternal(); - if (parent()) { + auto* parent = release_parent(); + + if (parent) { if (!params().bounds.IsEmpty()) { window->SetBounds(params().bounds); } - parent()->AddChild(window.get()); + parent->AddChild(window.get()); } else { aura::Window* context = nullptr; // Resolve context to find a parent.
diff --git a/ash/wm/desks/templates/saved_desk_item_view.cc b/ash/wm/desks/templates/saved_desk_item_view.cc index 4d2b5953e1..d74bcfe 100644 --- a/ash/wm/desks/templates/saved_desk_item_view.cc +++ b/ash/wm/desks/templates/saved_desk_item_view.cc
@@ -132,9 +132,8 @@ .CopyAddressTo(&background_view) .SetPreferredSize(kPreferredSize) .SetUseDefaultFillLayout(true) - .SetBackground(views::CreateRoundedRectBackground( - cros_tokens::kCrosSysSystemBaseElevated, - kSaveDeskCornerRadius)), + .SetBackground(views::CreateSolidBackground( + cros_tokens::kCrosSysSystemBaseElevated)), views::Builder<views::FlexLayoutView>() .SetOrientation(views::LayoutOrientation::kVertical) .CopyAddressTo(&box_layout_view)
diff --git a/ash/wm/snap_group/snap_group_pixeltest.cc b/ash/wm/snap_group/snap_group_pixeltest.cc index b748de187..5c197d7 100644 --- a/ash/wm/snap_group/snap_group_pixeltest.cc +++ b/ash/wm/snap_group/snap_group_pixeltest.cc
@@ -181,13 +181,13 @@ // Verify the visuals with secondary-snapped window gets focused. EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "window_cycle_with_snap_group_secondary_focused", - /*revision_number=*/4, window_cycle_widget)); + /*revision_number=*/5, window_cycle_widget)); // Verify the visuals with primary-snapped window gets focused. event_generator->PressAndReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "window_cycle_with_snap_group_primary_focused", - /*revision_number=*/4, window_cycle_widget)); + /*revision_number=*/5, window_cycle_widget)); // Verify the visuals after one of the windows in the group got destroyed // while stepping. @@ -203,7 +203,7 @@ EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "window_cycle_with_snap_group_window_destruction", - /*revision_number=*/4, updated_window_cycle_widget)); + /*revision_number=*/5, updated_window_cycle_widget)); } // ----------------------------------------------------------------------------- @@ -271,7 +271,7 @@ // Verify the `OverviewGroupItem` visuals in portrait. EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "overviewgroupitem_in_portrait", - /*revision_number=*/4, group_item_widget)); + /*revision_number=*/5, group_item_widget)); } // Portrait mode visual regression test for Snap Group visuals in window cycle @@ -312,13 +312,13 @@ // Verify the visuals with secondary-snapped window gets focused. EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "window_cycle_with_snap_group_secondary_focused_in_portrait", - /*revision_number=*/4, window_cycle_widget)); + /*revision_number=*/5, window_cycle_widget)); // Verify the visuals with primary-snapped window gets focused. event_generator->PressAndReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "window_cycle_with_snap_group_primary_focused_in_portrait", - /*revision_number=*/4, window_cycle_widget)); + /*revision_number=*/5, window_cycle_widget)); } } // namespace ash
diff --git a/ash/wm/system_gesture_event_filter_unittest.cc b/ash/wm/system_gesture_event_filter_unittest.cc index dccbfb4..2933237 100644 --- a/ash/wm/system_gesture_event_filter_unittest.cc +++ b/ash/wm/system_gesture_event_filter_unittest.cc
@@ -104,18 +104,17 @@ ui::test::EventGenerator generator(root_window, toplevel->GetNativeWindow()); WindowState* toplevel_state = WindowState::Get(toplevel->GetNativeWindow()); - const base::span<const gfx::Point> points_span(kInitialPoints); // Swipe down to minimize. - generator.GestureMultiFingerScroll(kTouchPoints, points_span.data(), 15, - kSteps, 0, 150); + generator.GestureMultiFingerScroll(kTouchPoints, kInitialPoints, 15, kSteps, + 0, 150); EXPECT_TRUE(toplevel_state->IsMinimized()); toplevel->Restore(); toplevel->GetNativeWindow()->SetBounds(bounds); // Swipe up to maximize. - generator.GestureMultiFingerScroll(kTouchPoints, points_span.data(), 15, - kSteps, 0, -150); + generator.GestureMultiFingerScroll(kTouchPoints, kInitialPoints, 15, kSteps, + 0, -150); EXPECT_TRUE(toplevel_state->IsMaximized()); toplevel->Restore(); @@ -123,27 +122,25 @@ // Swipe right to snap. gfx::Rect normal_bounds = toplevel->GetWindowBoundsInScreen(); - generator.GestureMultiFingerScroll(kTouchPoints, points_span.data(), 15, - kSteps, 150, 0); + generator.GestureMultiFingerScroll(kTouchPoints, kInitialPoints, 15, kSteps, + 150, 0); gfx::Rect right_tile_bounds = toplevel->GetWindowBoundsInScreen(); EXPECT_NE(normal_bounds.ToString(), right_tile_bounds.ToString()); // Swipe left to snap. - std::array<gfx::Point, kTouchPoints> left_points; - base::span<gfx::Point> left_span(left_points); - left_span.copy_from(points_span); - for (gfx::Point& point : left_span) { + std::array<gfx::Point, kTouchPoints> left_points = kInitialPoints; + for (gfx::Point& point : left_points) { point.Offset(right_tile_bounds.x(), right_tile_bounds.y()); } - generator.GestureMultiFingerScroll(kTouchPoints, left_span.data(), 15, kSteps, + generator.GestureMultiFingerScroll(kTouchPoints, left_points, 15, kSteps, -150, 0); gfx::Rect left_tile_bounds = toplevel->GetWindowBoundsInScreen(); EXPECT_NE(normal_bounds.ToString(), left_tile_bounds.ToString()); EXPECT_NE(right_tile_bounds.ToString(), left_tile_bounds.ToString()); // Swipe right again. - generator.GestureMultiFingerScroll(kTouchPoints, points_span.data(), 15, - kSteps, 150, 0); + generator.GestureMultiFingerScroll(kTouchPoints, kInitialPoints, 15, kSteps, + 150, 0); gfx::Rect current_bounds = toplevel->GetWindowBoundsInScreen(); EXPECT_NE(current_bounds.ToString(), left_tile_bounds.ToString()); EXPECT_EQ(current_bounds.ToString(), right_tile_bounds.ToString());
diff --git a/ash/wm/test/wm_pixel_diff_test.cc b/ash/wm/test/wm_pixel_diff_test.cc index 58d186ca..38f607eb 100644 --- a/ash/wm/test/wm_pixel_diff_test.cc +++ b/ash/wm/test/wm_pixel_diff_test.cc
@@ -129,7 +129,8 @@ // A basic window cycle pixel test that shows three windows and the window cycle // tab slider. -TEST_F(WmPixelDiffTest, WindowCycleBasic) { +// TODO(crbug.com/436618646): enable the test. +TEST_F(WmPixelDiffTest, DISABLED_WindowCycleBasic) { UpdateDisplay("1600x1000"); // Create a second desk so the window cycle tab slider shows up. This slider @@ -164,7 +165,7 @@ EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "window_cycle_basic", - /*revision_number=*/26, widget)); + /*revision_number=*/25, widget)); } TEST_F(WmPixelDiffTest, InformedRestoreNoScreenshotDialog) {
diff --git a/ash/wm/window_cycle/window_cycle_view.cc b/ash/wm/window_cycle/window_cycle_view.cc index 20296a9..a48decf 100644 --- a/ash/wm/window_cycle/window_cycle_view.cc +++ b/ash/wm/window_cycle/window_cycle_view.cc
@@ -166,11 +166,10 @@ layer()->SetBackdropFilterQuality(ColorProvider::kBackgroundBlurQuality); } - SetBackground(views::CreateRoundedRectBackground( + SetBackground(views::CreateSolidBackground( chromeos::features::IsSystemBlurEnabled() ? cros_tokens::kCrosSysScrim2 - : cros_tokens::kCrosSysSystemBaseElevatedOpaque, - kBackgroundCornerRadius)); + : cros_tokens::kCrosSysSystemBaseElevatedOpaque)); SetBorder(std::make_unique<views::HighlightBorder>( kBackgroundCornerRadius, views::HighlightBorder::Type::kHighlightBorderOnShadow));
diff --git a/ash/wm/wm_shadow_controller_delegate_unittest.cc b/ash/wm/wm_shadow_controller_delegate_unittest.cc index 38c50167..3c306b5 100644 --- a/ash/wm/wm_shadow_controller_delegate_unittest.cc +++ b/ash/wm/wm_shadow_controller_delegate_unittest.cc
@@ -13,7 +13,6 @@ #include "ui/compositor_extra/shadow.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/shadow_controller.h" -#include "ui/wm/core/window_util.h" namespace ash { @@ -70,45 +69,4 @@ EXPECT_TRUE(shadow->layer()->visible()); } -TEST_F(WmShadowControllerDelegateTest, HideShadowForOccludedWindow) { - auto* shadow_controller = Shell::Get()->shadow_controller(); - - constexpr gfx::Rect kBoundsA(200, 300); - constexpr gfx::Rect kBoundsB(100, 100, 400, 300); - - auto window1 = CreateAppWindow(kBoundsA); - window1->SetName("w1"); - auto window2 = CreateAppWindow(kBoundsA); - window2->SetName("w2"); - auto window3 = CreateAppWindow(kBoundsB); - window3->SetName("w3"); - - auto* shadow1 = shadow_controller->GetShadowForWindow(window1.get()); - auto* shadow2 = shadow_controller->GetShadowForWindow(window2.get()); - auto* shadow3 = shadow_controller->GetShadowForWindow(window3.get()); - - // window2 occludes window1 - EXPECT_FALSE(shadow1->layer()->visible()); - EXPECT_TRUE(shadow2->layer()->visible()); - EXPECT_TRUE(shadow3->layer()->visible()); - - // Bring the window 1 to the front. - wm::ActivateWindow(window1.get()); - - EXPECT_TRUE(shadow1->layer()->visible()); - EXPECT_FALSE(shadow2->layer()->visible()); - EXPECT_TRUE(shadow3->layer()->visible()); - - // Move window1 on top of window3. - window1->SetBounds(kBoundsB); - EXPECT_TRUE(shadow1->layer()->visible()); - EXPECT_TRUE(shadow2->layer()->visible()); - EXPECT_FALSE(shadow3->layer()->visible()); - - // Hide window1. - window1->Hide(); - EXPECT_TRUE(shadow2->layer()->visible()); - EXPECT_TRUE(shadow3->layer()->visible()); -} - } // namespace ash
diff --git a/base/byte_count.h b/base/byte_count.h index 5d5399f9..e064309 100644 --- a/base/byte_count.h +++ b/base/byte_count.h
@@ -17,8 +17,9 @@ namespace base { // Represents an integral number of bytes. Supports arithmetic operations and -// conversions to/from KiB, MiB and GiB. Any operation that overflows will -// result in a crash and thus this should only be used for trusted inputs. +// conversions to/from KiB, MiB, GiB, TiB, PiB, and EiB. Any operation that +// overflows will result in a crash and thus this should only be used for +// trusted inputs. // // Sample usage: // @@ -60,12 +61,28 @@ constexpr int64_t InKiB() const { return bytes_ / 1024; } constexpr int64_t InMiB() const { return bytes_ / 1024 / 1024; } constexpr int64_t InGiB() const { return bytes_ / 1024 / 1024 / 1024; } + constexpr int64_t InTiB() const { return bytes_ / 1024 / 1024 / 1024 / 1024; } + constexpr int64_t InPiB() const { + return bytes_ / 1024 / 1024 / 1024 / 1024 / 1024; + } + constexpr int64_t InEiB() const { + return bytes_ / 1024 / 1024 / 1024 / 1024 / 1024 / 1024; + } // Conversion to floating point values. constexpr double InBytesF() const { return bytes_; } constexpr double InKiBF() const { return bytes_ / 1024.0; } constexpr double InMiBF() const { return bytes_ / 1024.0 / 1024.0; } constexpr double InGiBF() const { return bytes_ / 1024.0 / 1024.0 / 1024.0; } + constexpr double InTiBF() const { + return bytes_ / 1024.0 / 1024.0 / 1024.0 / 1024.0; + } + constexpr double InPiBF() const { + return bytes_ / 1024.0 / 1024.0 / 1024.0 / 1024.0 / 1024.0; + } + constexpr double InEiBF() const { + return bytes_ / 1024.0 / 1024.0 / 1024.0 / 1024.0 / 1024.0 / 1024.0; + } // Conversion to an unsigned amount of bytes. Only use when it is guaranteed // that the value is positive. Fails if the value is negative. @@ -173,6 +190,48 @@ CheckedNumeric<int64_t>(gib * 1024.0 * 1024.0 * 1024.0)); } +template <typename T> + requires std::is_integral_v<T> +constexpr ByteCount TiB(T tib) { + return ByteCount::FromChecked(CheckedNumeric<int64_t>(tib) * 1024 * 1024 * + 1024 * 1024); +} + +template <typename T> + requires std::is_floating_point_v<T> +constexpr ByteCount TiB(T gib) { + return ByteCount::FromChecked( + CheckedNumeric<int64_t>(gib * 1024.0 * 1024.0 * 1024.0 * 1024.0)); +} + +template <typename T> + requires std::is_integral_v<T> +constexpr ByteCount PiB(T pib) { + return ByteCount::FromChecked(CheckedNumeric<int64_t>(pib) * 1024 * 1024 * + 1024 * 1024 * 1024); +} + +template <typename T> + requires std::is_floating_point_v<T> +constexpr ByteCount PiB(T pib) { + return ByteCount::FromChecked(CheckedNumeric<int64_t>( + pib * 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)); +} + +template <typename T> + requires std::is_integral_v<T> +constexpr ByteCount EiB(T eib) { + return ByteCount::FromChecked(CheckedNumeric<int64_t>(eib) * 1024 * 1024 * + 1024 * 1024 * 1024 * 1024); +} + +template <typename T> + requires std::is_floating_point_v<T> +constexpr ByteCount EiB(T eib) { + return ByteCount::FromChecked(CheckedNumeric<int64_t>( + eib * 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)); +} + BASE_EXPORT std::ostream& operator<<(std::ostream& os, ByteCount byte_count); } // namespace base
diff --git a/base/power_monitor/power_monitor.h b/base/power_monitor/power_monitor.h index 14c9d74..4ad0026 100644 --- a/base/power_monitor/power_monitor.h +++ b/base/power_monitor/power_monitor.h
@@ -14,7 +14,7 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" -#include "third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h" +#include "third_party/perfetto/include/perfetto/tracing/track.h" namespace base {
diff --git a/base/process/process_metrics.cc b/base/process/process_metrics.cc index f885e563..4956f651 100644 --- a/base/process/process_metrics.cc +++ b/base/process/process_metrics.cc
@@ -39,11 +39,11 @@ } // namespace -SystemMemoryInfoKB::SystemMemoryInfoKB() = default; +SystemMemoryInfo::SystemMemoryInfo() = default; -SystemMemoryInfoKB::SystemMemoryInfoKB(const SystemMemoryInfoKB&) = default; +SystemMemoryInfo::SystemMemoryInfo(const SystemMemoryInfo&) = default; -SystemMemoryInfoKB& SystemMemoryInfoKB::operator=(const SystemMemoryInfoKB&) = +SystemMemoryInfo& SystemMemoryInfo::operator=(const SystemMemoryInfo&) = default; SystemMetrics::SystemMetrics() {
diff --git a/base/process/process_metrics.h b/base/process/process_metrics.h index 4ade83b..254a8f4 100644 --- a/base/process/process_metrics.h +++ b/base/process/process_metrics.h
@@ -15,6 +15,7 @@ #include <string_view> #include "base/base_export.h" +#include "base/byte_count.h" #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/process/process_handle.h" @@ -98,7 +99,7 @@ #endif // BUILDFLAG(IS_WIN) // On iOS, - // TBD: https://crbug.com/714961 + // TBD: https://crbug.com/41315025 }; // Provides performance metrics for a specified process (CPU usage and IO @@ -311,25 +312,28 @@ #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \ BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX) || \ BUILDFLAG(IS_FUCHSIA) -// Data about system-wide memory consumption. Values are in KB. Available on -// Windows, Mac, Linux, Android and Chrome OS. +// Data about system-wide memory consumption. Available on Windows, Mac, Linux, +// Android and Chrome OS. +// +// The values are kept in ByteCount but depending on the platform, the +// granularity might be at the KB level or higher. // // Total memory are available on all platforms that implement // GetSystemMemoryInfo(). Total/free swap memory are available on all platforms // except on Mac. Buffers/cached/active_anon/inactive_anon/active_file/ // inactive_file/dirty/reclaimable/pswpin/pswpout/pgmajfault are available on // Linux/Android/Chrome OS. Shmem/slab are Chrome OS only. -// Speculative/file_backed/purgeable are Mac and iOS only. -// Free is absent on Windows (see "avail_phys" below). -struct BASE_EXPORT SystemMemoryInfoKB { - SystemMemoryInfoKB(); - SystemMemoryInfoKB(const SystemMemoryInfoKB& other); - SystemMemoryInfoKB& operator=(const SystemMemoryInfoKB& other); +// Speculative/file_backed/purgeable are Mac and iOS only. Free is absent on +// Windows (see "avail_phys" below). +struct BASE_EXPORT SystemMemoryInfo { + SystemMemoryInfo(); + SystemMemoryInfo(const SystemMemoryInfo& other); + SystemMemoryInfo& operator=(const SystemMemoryInfo& other); - int total = 0; + ByteCount total; #if !BUILDFLAG(IS_WIN) - int free = 0; + ByteCount free; #endif #if BUILDFLAG(IS_WIN) @@ -338,7 +342,7 @@ // size of the standby, free, and zero lists." (MSDN). // Standby: not modified pages of physical ram (file-backed memory) that are // not actively being used. - int avail_phys = 0; + ByteCount avail_phys; #endif #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \ @@ -348,36 +352,36 @@ // NOTE: this is ONLY valid in kernels 3.14 and up. Its value will always // be 0 in earlier kernel versions. // Note: it includes _all_ file-backed memory (active + inactive). - int available = 0; + ByteCount available; #endif #if !BUILDFLAG(IS_APPLE) - int swap_total = 0; - int swap_free = 0; + ByteCount swap_total; + ByteCount swap_free; #endif #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \ BUILDFLAG(IS_AIX) || BUILDFLAG(IS_FUCHSIA) - int buffers = 0; - int cached = 0; - int active_anon = 0; - int inactive_anon = 0; - int active_file = 0; - int inactive_file = 0; - int dirty = 0; - int reclaimable = 0; + ByteCount buffers; + ByteCount cached; + ByteCount active_anon; + ByteCount inactive_anon; + ByteCount active_file; + ByteCount inactive_file; + ByteCount dirty; + ByteCount reclaimable; #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_AIX) BUILDFLAG(IS_FUCHSIA) #if BUILDFLAG(IS_CHROMEOS) - int shmem = 0; - int slab = 0; + ByteCount shmem; + ByteCount slab; #endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_APPLE) - int speculative = 0; - int file_backed = 0; - int purgeable = 0; + ByteCount speculative; + ByteCount file_backed; + ByteCount purgeable; #endif // BUILDFLAG(IS_APPLE) }; @@ -387,7 +391,7 @@ // // Fills in the provided |meminfo| structure. Returns true on success. // Exposed for memory debugging widget. -BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo); +BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfo* meminfo); #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || // BUILDFLAG(IS_CHROMEOS) BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_AIX) || @@ -413,13 +417,13 @@ // returns true on success or false for a parsing error // Exposed for testing. BASE_EXPORT bool ParseProcMeminfo(std::string_view input, - SystemMemoryInfoKB* meminfo); + SystemMemoryInfo* meminfo); // Returns the memory committed by the system in KBytes, as from // GetSystemCommitCharge(), using data from `meminfo` instead of /proc/meminfo. // Exposed for testing. BASE_EXPORT size_t -GetSystemCommitChargeFromMeminfo(const SystemMemoryInfoKB& meminfo); +GetSystemCommitChargeFromMeminfo(const SystemMemoryInfo& meminfo); // Data from /proc/vmstat. struct BASE_EXPORT VmStatInfo { @@ -571,7 +575,7 @@ size_t committed_memory_; #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - SystemMemoryInfoKB memory_info_; + SystemMemoryInfo memory_info_; VmStatInfo vmstat_info_; SystemDiskInfo disk_info_; #endif
diff --git a/base/process/process_metrics_apple.mm b/base/process/process_metrics_apple.mm index 9e9f36b..9b3b524 100644 --- a/base/process/process_metrics_apple.mm +++ b/base/process/process_metrics_apple.mm
@@ -16,6 +16,7 @@ #include "base/apple/mach_logging.h" #include "base/apple/scoped_mach_port.h" +#include "base/byte_count.h" #include "base/containers/heap_array.h" #include "base/logging.h" #include "base/mac/mac_util.h" @@ -252,8 +253,8 @@ return (data.active_count * PAGE_SIZE) / 1024; } -bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { - meminfo->total = static_cast<int>(SysInfo::AmountOfPhysicalMemory() / 1024); +bool GetSystemMemoryInfo(SystemMemoryInfo* meminfo) { + meminfo->total = ByteCount::FromUnsigned(SysInfo::AmountOfPhysicalMemory()); base::apple::ScopedMachSendRight host(mach_host_self()); vm_statistics64_data_t vm_info; @@ -298,8 +299,8 @@ #endif // !(defined(IS_IOS) && defined(ARCH_CPU_X86_FAMILY)) if (vm_info.speculative_count <= vm_info.free_count) { - meminfo->free = saturated_cast<int>( - PAGE_SIZE / 1024 * (vm_info.free_count - vm_info.speculative_count)); + meminfo->free = ByteCount::FromUnsigned( + PAGE_SIZE * (vm_info.free_count - vm_info.speculative_count)); } else { // Inside the `host_statistics64` call above, `speculative_count` is // computed later than `free_count`, so these values are snapshots of two @@ -312,15 +313,15 @@ // inexact, but even in the case where `speculative_count` is less than // `free_count`, the computed `meminfo->free` will only be an approximation // given that the two inputs come from different points in time. - meminfo->free = 0; + meminfo->free = ByteCount(); } meminfo->speculative = - saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.speculative_count); + ByteCount::FromUnsigned(PAGE_SIZE * vm_info.speculative_count); meminfo->file_backed = - saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.external_page_count); + ByteCount::FromUnsigned(PAGE_SIZE * vm_info.external_page_count); meminfo->purgeable = - saturated_cast<int>(PAGE_SIZE / 1024 * vm_info.purgeable_count); + ByteCount::FromUnsigned(PAGE_SIZE * vm_info.purgeable_count); return true; }
diff --git a/base/process/process_metrics_fuchsia.cc b/base/process/process_metrics_fuchsia.cc index f14d8c5..58c256e 100644 --- a/base/process/process_metrics_fuchsia.cc +++ b/base/process/process_metrics_fuchsia.cc
@@ -68,8 +68,8 @@ return memory_info; } -bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { - // TODO(crbug.com/42050627). +bool GetSystemMemoryInfo(SystemMemoryInfo* meminfo) { + // TODO(https://crbug.com/42050627). return false; }
diff --git a/base/process/process_metrics_linux.cc b/base/process/process_metrics_linux.cc index c1fe2c2e..64eac2c8 100644 --- a/base/process/process_metrics_linux.cc +++ b/base/process/process_metrics_linux.cc
@@ -20,6 +20,7 @@ #include <string_view> #include <utility> +#include "base/byte_count.h" #include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/cpu.h" @@ -266,20 +267,20 @@ #endif size_t GetSystemCommitCharge() { - SystemMemoryInfoKB meminfo; + SystemMemoryInfo meminfo; if (!GetSystemMemoryInfo(&meminfo)) { return 0; } return GetSystemCommitChargeFromMeminfo(meminfo); } -size_t GetSystemCommitChargeFromMeminfo(const SystemMemoryInfoKB& meminfo) { - // TODO(crbug.com/315988925): This math is incorrect: `cached` can be very +size_t GetSystemCommitChargeFromMeminfo(const SystemMemoryInfo& meminfo) { + // TODO(http://b/315988925): This math is incorrect: `cached` can be very // large so that `free` + `buffers` + `cached` > `total`. Replace this with a // more meaningful metric or remove it. In the meantime, convert underflows to // 0 instead of crashing. - return ClampedNumeric<size_t>(meminfo.total) - meminfo.free - - meminfo.buffers - meminfo.cached; + return ClampedNumeric<size_t>(meminfo.total.InKiB()) - meminfo.free.InKiB() - + meminfo.buffers.InKiB() - meminfo.cached.InKiB(); } int ParseProcStatCPU(std::string_view input) { @@ -380,7 +381,7 @@ } // namespace bool ParseProcMeminfo(std::string_view meminfo_data, - SystemMemoryInfoKB* meminfo) { + SystemMemoryInfo* meminfo) { // The format of /proc/meminfo is: // // MemTotal: 8235324 kB @@ -393,7 +394,7 @@ // As a basic sanity check at the end, make sure the MemTotal value will be at // least non-zero. So start off with a zero total. - meminfo->total = 0; + meminfo->total = ByteCount(0); for (std::string_view line : SplitStringPiece( meminfo_data, "\n", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY)) { @@ -407,7 +408,7 @@ continue; } - int* target = nullptr; + ByteCount* target = nullptr; if (tokens[0] == "MemTotal:") { target = &meminfo->total; } else if (tokens[0] == "MemFree:") { @@ -445,12 +446,15 @@ } #endif if (target) { - StringToInt(tokens[1], target); + int64_t value; + if (StringToInt64(tokens[1], &value)) { + *target = KiB(value); + } } } // Make sure the MemTotal is valid. - return meminfo->total > 0; + return meminfo->total > ByteCount(0); } bool ParseProcVmstat(std::string_view vmstat_data, VmStatInfo* vmstat) { @@ -510,7 +514,7 @@ return has_pswpin && has_pswpout && has_pgmajfault; } -bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { +bool GetSystemMemoryInfo(SystemMemoryInfo* meminfo) { // Used memory is: total - free - buffers - caches // ReadFileToStringNonBlocking doesn't require ScopedAllowIO, and reading // /proc/meminfo is fast. See crbug.com/1160988 for details.
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc index d61a242..a3983d0 100644 --- a/base/process/process_metrics_unittest.cc +++ b/base/process/process_metrics_unittest.cc
@@ -20,6 +20,7 @@ #include <utility> #include <vector> +#include "base/byte_count.h" #include "base/command_line.h" #include "base/files/file.h" #include "base/files/file_path.h" @@ -340,7 +341,7 @@ } TEST_F(SystemMetricsTest, ParseMeminfo) { - SystemMemoryInfoKB meminfo; + SystemMemoryInfo meminfo; const char invalid_input1[] = "abc"; const char invalid_input2[] = "MemTotal:"; // Partial file with no MemTotal @@ -424,39 +425,39 @@ "Hugepagesize: 4096 kB\n"; EXPECT_TRUE(ParseProcMeminfo(valid_input1, &meminfo)); - EXPECT_EQ(meminfo.total, 3981504); - EXPECT_EQ(meminfo.free, 140764); - EXPECT_EQ(meminfo.available, 535413); - EXPECT_EQ(meminfo.buffers, 116480); - EXPECT_EQ(meminfo.cached, 406160); - EXPECT_EQ(meminfo.active_anon, 2972352); - EXPECT_EQ(meminfo.active_file, 179688); - EXPECT_EQ(meminfo.inactive_anon, 270108); - EXPECT_EQ(meminfo.inactive_file, 202748); - EXPECT_EQ(meminfo.swap_total, 5832280); - EXPECT_EQ(meminfo.swap_free, 3672368); - EXPECT_EQ(meminfo.dirty, 184); - EXPECT_EQ(meminfo.reclaimable, 30936); + EXPECT_EQ(meminfo.total.InKiB(), 3981504); + EXPECT_EQ(meminfo.free.InKiB(), 140764); + EXPECT_EQ(meminfo.available.InKiB(), 535413); + EXPECT_EQ(meminfo.buffers.InKiB(), 116480); + EXPECT_EQ(meminfo.cached.InKiB(), 406160); + EXPECT_EQ(meminfo.active_anon.InKiB(), 2972352); + EXPECT_EQ(meminfo.active_file.InKiB(), 179688); + EXPECT_EQ(meminfo.inactive_anon.InKiB(), 270108); + EXPECT_EQ(meminfo.inactive_file.InKiB(), 202748); + EXPECT_EQ(meminfo.swap_total.InKiB(), 5832280); + EXPECT_EQ(meminfo.swap_free.InKiB(), 3672368); + EXPECT_EQ(meminfo.dirty.InKiB(), 184); + EXPECT_EQ(meminfo.reclaimable.InKiB(), 30936); #if BUILDFLAG(IS_CHROMEOS) - EXPECT_EQ(meminfo.shmem, 140204); - EXPECT_EQ(meminfo.slab, 54212); + EXPECT_EQ(meminfo.shmem.InKiB(), 140204); + EXPECT_EQ(meminfo.slab.InKiB(), 54212); #endif EXPECT_EQ(355725u, base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024); // Simulate as if there is no MemAvailable. - meminfo.available = 0; + meminfo.available = ByteCount(0); EXPECT_EQ(374448u, base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024); meminfo = {}; EXPECT_TRUE(ParseProcMeminfo(valid_input2, &meminfo)); - EXPECT_EQ(meminfo.total, 255908); - EXPECT_EQ(meminfo.free, 69936); - EXPECT_EQ(meminfo.available, 0); - EXPECT_EQ(meminfo.buffers, 15812); - EXPECT_EQ(meminfo.cached, 115124); - EXPECT_EQ(meminfo.swap_total, 524280); - EXPECT_EQ(meminfo.swap_free, 524200); - EXPECT_EQ(meminfo.dirty, 4); + EXPECT_EQ(meminfo.total.InKiB(), 255908); + EXPECT_EQ(meminfo.free.InKiB(), 69936); + EXPECT_EQ(meminfo.available.InKiB(), 0); + EXPECT_EQ(meminfo.buffers.InKiB(), 15812); + EXPECT_EQ(meminfo.cached.InKiB(), 115124); + EXPECT_EQ(meminfo.swap_total.InKiB(), 524280); + EXPECT_EQ(meminfo.swap_free.InKiB(), 524200); + EXPECT_EQ(meminfo.dirty.InKiB(), 4); EXPECT_EQ(69936u, base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024); @@ -508,10 +509,10 @@ meminfo = {}; EXPECT_TRUE(ParseProcMeminfo(large_cache_input, &meminfo)); - EXPECT_EQ(meminfo.total, 18025572); - EXPECT_EQ(meminfo.free, 13150176); - EXPECT_EQ(meminfo.buffers, 1524852); - EXPECT_EQ(meminfo.cached, 12645260); + EXPECT_EQ(meminfo.total.InKiB(), 18025572); + EXPECT_EQ(meminfo.free.InKiB(), 13150176); + EXPECT_EQ(meminfo.buffers.InKiB(), 1524852); + EXPECT_EQ(meminfo.cached.InKiB(), 12645260); EXPECT_EQ(GetSystemCommitChargeFromMeminfo(meminfo), 0u); } @@ -801,21 +802,21 @@ #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_LINUX) || \ BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) TEST(SystemMetrics2Test, GetSystemMemoryInfo) { - SystemMemoryInfoKB info; + SystemMemoryInfo info; EXPECT_TRUE(GetSystemMemoryInfo(&info)); // Ensure each field received a value. - EXPECT_GT(info.total, 0); + EXPECT_GT(info.total, ByteCount(0)); #if BUILDFLAG(IS_WIN) - EXPECT_GT(info.avail_phys, 0); + EXPECT_GT(info.avail_phys, ByteCount(0)); #else - EXPECT_GT(info.free, 0); + EXPECT_GT(info.free, ByteCount(0)); #endif #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - EXPECT_GT(info.buffers, 0); - EXPECT_GT(info.cached, 0); - EXPECT_GT(info.active_anon + info.inactive_anon, 0); - EXPECT_GT(info.active_file + info.inactive_file, 0); + EXPECT_GT(info.buffers, ByteCount(0)); + EXPECT_GT(info.cached, ByteCount(0)); + EXPECT_GT(info.active_anon + info.inactive_anon, ByteCount(0)); + EXPECT_GT(info.active_file + info.inactive_file, ByteCount(0)); #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || // BUILDFLAG(IS_ANDROID) @@ -835,12 +836,12 @@ // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_APPLE) - EXPECT_GT(info.file_backed, 0); + EXPECT_GT(info.file_backed, ByteCount(0)); #endif #if BUILDFLAG(IS_CHROMEOS) // Chrome OS exposes shmem. - EXPECT_GT(info.shmem, 0); + EXPECT_GT(info.shmem, ByteCount(0)); EXPECT_LT(info.shmem, info.total); #endif }
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc index 0cf0300..36f1f7d56 100644 --- a/base/process/process_metrics_win.cc +++ b/base/process/process_metrics_win.cc
@@ -13,6 +13,7 @@ #include <algorithm> +#include "base/byte_count.h" #include "base/check.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -247,22 +248,22 @@ } // This function uses the following mapping between MEMORYSTATUSEX and -// SystemMemoryInfoKB: +// SystemMemoryInfo: // ullTotalPhys ==> total // ullAvailPhys ==> avail_phys // ullTotalPageFile ==> swap_total // ullAvailPageFile ==> swap_free -bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { +bool GetSystemMemoryInfo(SystemMemoryInfo* meminfo) { MEMORYSTATUSEX mem_status; mem_status.dwLength = sizeof(mem_status); if (!::GlobalMemoryStatusEx(&mem_status)) { return false; } - meminfo->total = saturated_cast<int>(mem_status.ullTotalPhys / 1024); - meminfo->avail_phys = saturated_cast<int>(mem_status.ullAvailPhys / 1024); - meminfo->swap_total = saturated_cast<int>(mem_status.ullTotalPageFile / 1024); - meminfo->swap_free = saturated_cast<int>(mem_status.ullAvailPageFile / 1024); + meminfo->total = ByteCount::FromUnsigned(mem_status.ullTotalPhys); + meminfo->avail_phys = ByteCount::FromUnsigned(mem_status.ullAvailPhys); + meminfo->swap_total = ByteCount::FromUnsigned(mem_status.ullTotalPageFile); + meminfo->swap_free = ByteCount::FromUnsigned(mem_status.ullAvailPageFile); return true; }
diff --git a/base/system/sys_info.h b/base/system/sys_info.h index 3470b51..0515616b 100644 --- a/base/system/sys_info.h +++ b/base/system/sys_info.h
@@ -50,7 +50,7 @@ } class FilePath; -struct SystemMemoryInfoKB; +struct SystemMemoryInfo; class BASE_EXPORT SysInfo { public: @@ -374,7 +374,7 @@ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \ BUILDFLAG(IS_AIX) static uint64_t AmountOfAvailablePhysicalMemory( - const SystemMemoryInfoKB& meminfo); + const SystemMemoryInfo& meminfo); #endif // Sets the amount of physical memory in MB for testing, thus allowing tests
diff --git a/base/system/sys_info_ios.mm b/base/system/sys_info_ios.mm index 24b48fbf..df4f99ae 100644 --- a/base/system/sys_info_ios.mm +++ b/base/system/sys_info_ios.mm
@@ -107,13 +107,13 @@ // static uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() { - SystemMemoryInfoKB info; + SystemMemoryInfo info; if (!GetSystemMemoryInfo(&info)) { return 0; } // We should add inactive file-backed memory also but there is no such // information from iOS unfortunately. - return checked_cast<uint64_t>(info.free + info.speculative) * 1024; + return (info.free + info.speculative).InBytesUnsigned(); } // static
diff --git a/base/system/sys_info_linux.cc b/base/system/sys_info_linux.cc index a4be9472..b4e226a 100644 --- a/base/system/sys_info_linux.cc +++ b/base/system/sys_info_linux.cc
@@ -17,6 +17,7 @@ #include <sstream> #include <type_traits> +#include "base/byte_count.h" #include "base/check.h" #include "base/files/file_util.h" #include "base/notreached.h" @@ -58,7 +59,7 @@ // static uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() { - SystemMemoryInfoKB info; + SystemMemoryInfo info; if (!GetSystemMemoryInfo(&info)) { return 0; } @@ -67,15 +68,16 @@ // static uint64_t SysInfo::AmountOfAvailablePhysicalMemory( - const SystemMemoryInfoKB& info) { + const SystemMemoryInfo& info) { // See details here: // https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 // The fallback logic (when there is no MemAvailable) would be more precise // if we had info about zones watermarks (/proc/zoneinfo). - int res_kb = info.available != 0 - ? std::max(info.available - info.active_file, 0) - : info.free + info.reclaimable + info.inactive_file; - return checked_cast<uint64_t>(res_kb) * 1024; + ByteCount res = + !info.available.is_zero() + ? std::max(info.available - info.active_file, ByteCount(0)) + : info.free + info.reclaimable + info.inactive_file; + return res.InBytesUnsigned(); } // static
diff --git a/base/system/sys_info_mac.mm b/base/system/sys_info_mac.mm index a00b8d7c..8083648 100644 --- a/base/system/sys_info_mac.mm +++ b/base/system/sys_info_mac.mm
@@ -101,13 +101,13 @@ // static uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() { - SystemMemoryInfoKB info; + SystemMemoryInfo info; if (!GetSystemMemoryInfo(&info)) { return 0; } // We should add inactive file-backed memory also but there is no such // information from Mac OS unfortunately. - return checked_cast<uint64_t>(info.free + info.speculative) * 1024; + return (info.free + info.speculative).InBytesUnsigned(); } // static
diff --git a/base/system/sys_info_unittest.cc b/base/system/sys_info_unittest.cc index 614472a..a897ce0f 100644 --- a/base/system/sys_info_unittest.cc +++ b/base/system/sys_info_unittest.cc
@@ -53,7 +53,7 @@ // Some Android (Cast) test devices have a large portion of physical memory // reserved. During investigation, around 115-150 MB were seen reserved, so we // track this here with a factory of safety of 2. -static constexpr int kReservedPhysicalMemory = 300 * 1024; // In _K_bytes. +static constexpr ByteCount kReservedPhysicalMemory = MiB(300); #endif // BUILDFLAG(IS_ANDROID) using SysInfoTest = PlatformTest; @@ -103,34 +103,35 @@ #define MAYBE_AmountOfAvailablePhysicalMemory AmountOfAvailablePhysicalMemory #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) TEST_F(SysInfoTest, MAYBE_AmountOfAvailablePhysicalMemory) { - // Note: info is in _K_bytes. - SystemMemoryInfoKB info; + SystemMemoryInfo info; ASSERT_TRUE(GetSystemMemoryInfo(&info)); - EXPECT_GT(info.free, 0); - if (info.available != 0) { + EXPECT_GT(info.free, ByteCount(0)); + if (!info.available.is_zero()) { // If there is MemAvailable from kernel. EXPECT_LT(info.available, info.total); - const uint64_t amount = SysInfo::AmountOfAvailablePhysicalMemory(info); + const ByteCount amount = + ByteCount(SysInfo::AmountOfAvailablePhysicalMemory(info)); // We aren't actually testing that it's correct, just that it's sane. // Available memory is |free - reserved + reclaimable (inactive, non-free)|. // On some android platforms, reserved is a substantial portion. - const int available = + const ByteCount available = #if BUILDFLAG(IS_ANDROID) - std::max(info.free - kReservedPhysicalMemory, 0); + std::max(info.free - kReservedPhysicalMemory, ByteCount(0)); #else info.free; #endif // BUILDFLAG(IS_ANDROID) - EXPECT_GT(amount, checked_cast<uint64_t>(available) * 1024); - EXPECT_LT(amount / 1024, checked_cast<uint64_t>(info.available)); + EXPECT_GT(amount, available); + EXPECT_LT(amount, info.available); // Simulate as if there is no MemAvailable. - info.available = 0; + info.available = ByteCount(0); } // There is no MemAvailable. Check the fallback logic. - const uint64_t amount = SysInfo::AmountOfAvailablePhysicalMemory(info); + const ByteCount amount = + ByteCount(SysInfo::AmountOfAvailablePhysicalMemory(info)); // We aren't actually testing that it's correct, just that it's sane. - EXPECT_GT(amount, checked_cast<uint64_t>(info.free) * 1024); - EXPECT_LT(amount / 1024, checked_cast<uint64_t>(info.total)); + EXPECT_GT(amount, info.free); + EXPECT_LT(amount, info.total); } #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || // BUILDFLAG(IS_ANDROID)
diff --git a/base/system/sys_info_win.cc b/base/system/sys_info_win.cc index 9c735e5..cd0fb2a 100644 --- a/base/system/sys_info_win.cc +++ b/base/system/sys_info_win.cc
@@ -195,11 +195,11 @@ // static uint64_t SysInfo::AmountOfAvailablePhysicalMemoryImpl() { - SystemMemoryInfoKB info; + SystemMemoryInfo info; if (!GetSystemMemoryInfo(&info)) { return 0; } - return checked_cast<uint64_t>(info.avail_phys) * 1024; + return info.avail_phys.InBytesUnsigned(); } // static
diff --git a/build/android/gyp/java_cpp_enum.py b/build/android/gyp/java_cpp_enum.py index ffd896d..a9c6ede 100755 --- a/build/android/gyp/java_cpp_enum.py +++ b/build/android/gyp/java_cpp_enum.py
@@ -269,7 +269,8 @@ def _ParseLine(self, line): if HeaderParser.if_buildflag_re.match(line): self._in_preprocessor_block += 1 - self._in_buildflag_android.append('BUILDFLAG(IS_ANDROID)' in line) + self._in_buildflag_android.append('BUILDFLAG(IS_ANDROID)' in line + or 'BUILDFLAG(IS_POSIX)' in line) return if self._in_preprocessor_block and HeaderParser.if_buildflag_end_re.match( line): @@ -336,7 +337,8 @@ self._current_enum_entry += ' ' + line.strip() def _FinalizeCurrentEnumDefinition(self): - if self._current_enum_entry: + # It has a space as a prefix so strip is needed. + if self._current_enum_entry.strip(): self._ParseCurrentEnumEntry() self._ApplyGeneratorDirectives() self._current_definition.Finalize()
diff --git a/build/android/gyp/java_cpp_enum_tests.py b/build/android/gyp/java_cpp_enum_tests.py index c84d3d0c..642d3e2 100755 --- a/build/android/gyp/java_cpp_enum_tests.py +++ b/build/android/gyp/java_cpp_enum_tests.py
@@ -586,6 +586,16 @@ #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) TERMINATION_STATUS_TWELVE = 12, #endif + + TERMINATION_STATUS_THIRTEEN = 13, + +#if BUILDFLAG(IS_POSIX) + TERMINATION_STATUS_FOURTEEN = 14, +#endif + +#if BUILDFLAG(IS_WIN) + TERMINATION_STATUS_LAST = 1000, +#endif }; """.split('\n') definitions = HeaderParser(test_data).ParseDefinitions() @@ -606,6 +616,8 @@ # INTEGRITY_FAILURE value should not appear here. # TEN and ELEVEN should not appear here. ('TWELVE', '12'), + ('THIRTEEN', '13'), + ('FOURTEEN', '14'), ]), definition.entries) self.assertEqual(
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 17ebdbc..5af7954 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -590,8 +590,8 @@ # directory) regardless of whether the libc++ module is used in this # target. public_deps += [ - "//buildtools/third_party/libc++:copy_custom_headers", - "//buildtools/third_party/libc++:copy_libcxx_headers", + "//buildtools/third_party/libc++:copy_custom_headers($default_toolchain)", + "//buildtools/third_party/libc++:copy_libcxx_headers($default_toolchain)", ] } @@ -718,8 +718,8 @@ # directory) regardless of whether the libc++ module is used in this # target. public_deps += [ - "//buildtools/third_party/libc++:copy_custom_headers", - "//buildtools/third_party/libc++:copy_libcxx_headers", + "//buildtools/third_party/libc++:copy_custom_headers($default_toolchain)", + "//buildtools/third_party/libc++:copy_libcxx_headers($default_toolchain)", ] }
diff --git a/build/config/c++/c++.gni b/build/config/c++/c++.gni index 8047a9f..dd1a9b0 100644 --- a/build/config/c++/c++.gni +++ b/build/config/c++/c++.gni
@@ -99,7 +99,7 @@ } if (use_clang_modules) { - libcxx_prefix = "${root_gen_dir}/third_party/libc++/src" + libcxx_prefix = "${root_build_dir}/gen/third_party/libc++/src" libcxx_modulemap_in = read_file("//third_party/libc++/src/include/module.modulemap.in", "string")
diff --git a/buildtools/third_party/libc++/BUILD.gn b/buildtools/third_party/libc++/BUILD.gn index da694e9..863060f 100644 --- a/buildtools/third_party/libc++/BUILD.gn +++ b/buildtools/third_party/libc++/BUILD.gn
@@ -63,10 +63,9 @@ } config("libcxx_modulemap") { - cflags = - [ "-fmodule-map-file=" + rebase_path( - "${root_gen_dir}/third_party/libc++/src/include/module.modulemap", - root_build_dir) ] + cflags = [ "-fmodule-map-file=" + rebase_path( + "${root_build_dir}/gen/third_party/libc++/src/include/module.modulemap", + root_build_dir) ] } if (use_clang_modules) { @@ -89,6 +88,30 @@ } } +if (current_toolchain == default_toolchain) { + # The Clang modules build requires libc++ headers, __assertion_handler, and + # __config_site to be in the same directory. + # + # To avoid redundant work, the copy targets are declared only in the default + # toolchain. This prevents unnecessary copies in multi-toolchain builds and + # allows Siso to use its precomputed tree for the default toolchain's `gen` + # directory. + copy("copy_libcxx_headers") { + sources = libcxx_headers + outputs = [ "{{source_gen_dir}}/{{source_file_part}}" ] + } + + copy("copy_custom_headers") { + sources = [ + "__assertion_handler", + "__config_site", + ] + outputs = [ + "${root_gen_dir}/third_party/libc++/src/include/{{source_file_part}}", + ] + } +} + if (use_clang_modules) { if (is_linux || is_chromeos) { textual_module("sysroot_ctype") { @@ -661,23 +684,6 @@ ] } - # We need to have libc++ headers, __assertion_handler and __config_site in the - # same directory for clang modules build. - copy("copy_libcxx_headers") { - sources = libcxx_headers - outputs = [ "{{source_gen_dir}}/{{source_file_part}}" ] - } - - copy("copy_custom_headers") { - sources = [ - "__assertion_handler", - "__config_site", - ] - outputs = [ - "${root_gen_dir}/third_party/libc++/src/include/{{source_file_part}}", - ] - } - libcxx_module("std") { public_deps = [ ":_Builtin_limits", @@ -983,8 +989,8 @@ use_libcxx_modules = false deps += [ - ":copy_custom_headers", - ":copy_libcxx_headers", + ":copy_custom_headers($default_toolchain)", + ":copy_libcxx_headers($default_toolchain)", ] } if ((is_android || is_apple) && libcxx_is_shared) {
diff --git a/buildtools/third_party/libc++/modules.gni b/buildtools/third_party/libc++/modules.gni index e3183911..1bc5283 100644 --- a/buildtools/third_party/libc++/modules.gni +++ b/buildtools/third_party/libc++/modules.gni
@@ -83,11 +83,10 @@ # This is a template to build libc++'s module file. modulemap(target_name) { forward_variables_from(invoker, "*") - modulemap = - "${root_gen_dir}/third_party/libc++/src/include/module.modulemap" + modulemap = "${root_build_dir}/gen/third_party/libc++/src/include/module.modulemap" deps = [ - "//buildtools/third_party/libc++:copy_custom_headers", - "//buildtools/third_party/libc++:copy_libcxx_headers", + "//buildtools/third_party/libc++:copy_custom_headers($default_toolchain)", + "//buildtools/third_party/libc++:copy_libcxx_headers($default_toolchain)", ] } } @@ -117,8 +116,8 @@ forward_variables_from(invoker, "*") modulemap = sysroot_modulemap deps = [ - ":copy_custom_headers", - ":copy_libcxx_headers", + ":copy_custom_headers($default_toolchain)", + ":copy_libcxx_headers($default_toolchain)", ] } }
diff --git a/buildtools/third_party/libc++abi/BUILD.gn b/buildtools/third_party/libc++abi/BUILD.gn index 25d4b15..bc17e58 100644 --- a/buildtools/third_party/libc++abi/BUILD.gn +++ b/buildtools/third_party/libc++abi/BUILD.gn
@@ -24,8 +24,8 @@ if (use_clang_modules) { deps += [ - "//buildtools/third_party/libc++:copy_custom_headers", - "//buildtools/third_party/libc++:copy_libcxx_headers", + "//buildtools/third_party/libc++:copy_custom_headers($default_toolchain)", + "//buildtools/third_party/libc++:copy_libcxx_headers($default_toolchain)", ] }
diff --git a/cc/base/features.cc b/cc/base/features.cc index 54b1a49..3e1a9c4 100644 --- a/cc/base/features.cc +++ b/cc/base/features.cc
@@ -206,10 +206,6 @@ "FastPathNoRaster", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kExportFrameTimingAfterFrameDone, - "ExportFrameTimingAfterFrameDone", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kInternalBeginFrameSourceOnManyDidNotProduceFrame, "InternalBeginFrameSourceOnManyDidNotProduceFrame", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/cc/base/features.h b/cc/base/features.h index 340827c..ed7ac69e0 100644 --- a/cc/base/features.h +++ b/cc/base/features.h
@@ -200,11 +200,6 @@ // tasks. CC_BASE_EXPORT BASE_DECLARE_FEATURE(kFastPathNoRaster); -// When enabled, moves the layer tree client's metric export call -// for from beginning of the subsequent frame to the end of the subsequent -// frame. -CC_BASE_EXPORT BASE_DECLARE_FEATURE(kExportFrameTimingAfterFrameDone); - // When enabled, internal begin frame source will be used in cc to reduce IPC // between cc and viz when there were many "did not produce frame" recently, // and SetAutoNeedsBeginFrame will be called on CompositorFrameSink.
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink.cc b/cc/mojo_embedder/async_layer_tree_frame_sink.cc index a2511c501..3d663d8a 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink.cc +++ b/cc/mojo_embedder/async_layer_tree_frame_sink.cc
@@ -331,13 +331,10 @@ } void AsyncLayerTreeFrameSink::ExportFrameTiming() { - if (base::FeatureList::IsEnabled( - features::kExportFrameTimingAfterFrameDone)) { - for (const auto& pair : timing_details_) { - client_->DidPresentCompositorFrame(pair.first, pair.second); - } - timing_details_.clear(); + for (const auto& pair : timing_details_) { + client_->DidPresentCompositorFrame(pair.first, pair.second); } + timing_details_.clear(); } std::unique_ptr<LayerContext> AsyncLayerTreeFrameSink::CreateLayerContext( @@ -383,17 +380,9 @@ ReclaimResources(std::move(resources)); } - bool timing_export = - base::FeatureList::IsEnabled(features::kExportFrameTimingAfterFrameDone); - if (timing_export) { - timing_details_.insert(timing_details.begin(), timing_details.end()); - } + timing_details_.insert(timing_details.begin(), timing_details.end()); + for (const auto& pair : timing_details) { - // Cache timing details to be exported in either SubmitCompositorFrame() or - // DidNotProduceFrame(). - if (!timing_export) { - client_->DidPresentCompositorFrame(pair.first, pair.second); - } if (synthetic_begin_frame_source_ && use_begin_frame_presentation_feedback_) { const auto& feedback = pair.second.presentation_feedback;
diff --git a/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc b/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc index 12b57f15a..9203bc0 100644 --- a/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc +++ b/cc/mojo_embedder/async_layer_tree_frame_sink_unittest.cc
@@ -224,24 +224,14 @@ } // namespace -// Mocks DidPresentCompositorFrame class in order to test at what point -// in the frame lifecycle the method gets called. -class MockFakeLayerTreeFrameSinkClient : public FakeLayerTreeFrameSinkClient { - public: - MOCK_METHOD2(DidPresentCompositorFrame, - void(uint32_t frame_token, - const viz::FrameTimingDetails& details)); -}; - // Boilerplate code for simple AsyncLayerTreeFrameSink. Friend of // AsyncLayerTreeFrameSink. -class AsyncLayerTreeFrameSinkSimpleTest : public testing::TestWithParam<bool> { +class AsyncLayerTreeFrameSinkSimpleTest : public testing::Test { public: AsyncLayerTreeFrameSinkSimpleTest() : task_runner_(base::MakeRefCounted<base::TestMockTimeTaskRunner>( base::TestMockTimeTaskRunner::Type::kStandalone)), - display_rect_(1, 1), - layer_tree_frame_sink_client_(MockFakeLayerTreeFrameSinkClient()) { + display_rect_(1, 1) { client_to_bind_ = &layer_tree_frame_sink_client_; } @@ -281,28 +271,6 @@ hit_test_data_changed); } - void OnBeginFrame(const viz::BeginFrameArgs& args, - const viz::FrameTimingDetailsMap& timing_details, - std::vector<viz::ReturnedResource> resources) { - layer_tree_frame_sink_->OnBeginFrame(args, timing_details, - std::move(resources)); - } - - void DidNotProduceFrame(const viz::BeginFrameAck& ack, - FrameSkippedReason reason) { - layer_tree_frame_sink_->DidNotProduceFrame(ack, reason); - } - - void SubmitCompositorFrame(viz::CompositorFrame frame, - bool hit_test_data_changed) { - layer_tree_frame_sink_->SubmitCompositorFrame(std::move(frame), - hit_test_data_changed); - } - - void SetNeedsBeginFrame() { - layer_tree_frame_sink_->OnNeedsBeginFrames(true); - } - const viz::HitTestRegionList& GetHitTestData() const { return layer_tree_frame_sink_->get_last_hit_test_data_for_testing(); } @@ -312,7 +280,7 @@ scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; gfx::Rect display_rect_; std::unique_ptr<AsyncLayerTreeFrameSink> layer_tree_frame_sink_; - MockFakeLayerTreeFrameSinkClient layer_tree_frame_sink_client_; + FakeLayerTreeFrameSinkClient layer_tree_frame_sink_client_; raw_ptr<LayerTreeFrameSinkClient> client_to_bind_; mojo::Remote<viz::mojom::CompositorFrameSinkClient> client_remote_; std::unique_ptr<MockCompositorFrameSink> mock_compositor_frame_sink_; @@ -434,97 +402,6 @@ viz::HitTestRegionList::IsEqual(hit_test_region_list, GetHitTestData())); } -class AsyncLayerTreeFrameSinkMetricsRefactorTest - : public AsyncLayerTreeFrameSinkSimpleTest { - public: - AsyncLayerTreeFrameSinkMetricsRefactorTest() { - if (!GetParam()) { - scoped_feature_list_.InitAndDisableFeature( - features::kExportFrameTimingAfterFrameDone); - } - } - ~AsyncLayerTreeFrameSinkMetricsRefactorTest() override = default; - - viz::BeginFrameArgs CreateAndDispatchNewBeginFrame() { - viz::BeginFrameArgs args = viz::CreateBeginFrameArgsForTesting( - BEGINFRAME_FROM_HERE, viz::BeginFrameArgs::kManualSourceId, 1, - base::TimeTicks() + base::Milliseconds(1)); - viz::FrameTimingDetailsMap timing_details_map; - viz::FrameTimingDetails timing_details; - timing_details.presentation_feedback.timestamp = base::TimeTicks::Now(); - timing_details_map[++frame_token_] = timing_details; - SetNeedsBeginFrame(); - OnBeginFrame(args, timing_details_map, - std::vector<viz::ReturnedResource>()); - return args; - } - - base::test::ScopedFeatureList scoped_feature_list_; - uint32_t frame_token_ = 0; -}; - -INSTANTIATE_TEST_SUITE_P(AsyncLayerTreeFrameSinkRefactorTest, - AsyncLayerTreeFrameSinkMetricsRefactorTest, - testing::Bool(), - [](auto& param) { - return (param.param) ? "MetricExportOnEndFrame" - : "MetricExportOnBeginFrame"; - }); - -TEST_P(AsyncLayerTreeFrameSinkMetricsRefactorTest, DroppedFrameExportsMetrics) { - // Establish that DidPresentCompositorFrame should be called exactly once. - EXPECT_CALL(layer_tree_frame_sink_client_, - DidPresentCompositorFrame(testing::_, testing::_)) - .Times(GetParam() ? 0 : 1); - - // Simulate an OnBeginFrame call from viz. - viz::BeginFrameArgs args = CreateAndDispatchNewBeginFrame(); - testing::Mock::VerifyAndClearExpectations(&layer_tree_frame_sink_client_); - - // Check that that either the OnBeginFrame call or the subsequent - // DidNotProduceFrame call has exported timing metrics to the client, - // depending on test params. - if (GetParam()) { - EXPECT_CALL(layer_tree_frame_sink_client_, - DidPresentCompositorFrame(testing::_, testing::_)) - .Times(1); - DidNotProduceFrame(viz::BeginFrameAck(args, false), - FrameSkippedReason::kDrawThrottled); - testing::Mock::VerifyAndClearExpectations(&layer_tree_frame_sink_client_); - } -} - -TEST_P(AsyncLayerTreeFrameSinkMetricsRefactorTest, SubmitFrameExportsMetrics) { - // Establish that DidPresentCompositorFrame should be called exactly once. - EXPECT_CALL(layer_tree_frame_sink_client_, - DidPresentCompositorFrame(testing::_, testing::_)) - .Times(GetParam() ? 0 : 1); - - // Simulate an OnBeginFrame call from viz. - viz::BeginFrameArgs args = CreateAndDispatchNewBeginFrame(); - testing::Mock::VerifyAndClearExpectations(&layer_tree_frame_sink_client_); - - // Check that that either the OnBeginFrame call or the subsequent - // SubmitCompositorFrame call has exported timing metrics to the client, - // depending on test params. - if (GetParam()) { - EXPECT_CALL(layer_tree_frame_sink_client_, - DidPresentCompositorFrame(testing::_, testing::_)) - .Times(1); - // Valid frame requires a pass list. - viz::CompositorRenderPassList pass_list; - auto pass = viz::CompositorRenderPass::Create(); - pass->id = viz::CompositorRenderPassId{1}; - pass->output_rect = display_rect_; - pass_list.push_back(std::move(pass)); - SubmitCompositorFrame(viz::CompositorFrameBuilder() - .SetRenderPassList(std::move(pass_list)) - .Build(), - false); - testing::Mock::VerifyAndClearExpectations(&layer_tree_frame_sink_client_); - } -} - // Boilerplate code for begin frame test of AsyncLayerTreeFrameSink. class AsyncLayerTreeFrameSinkBeginFrameTest : public AsyncLayerTreeFrameSinkSimpleTest {
diff --git a/cc/mojo_embedder/viz_layer_context.cc b/cc/mojo_embedder/viz_layer_context.cc index 89269a3..599549d 100644 --- a/cc/mojo_embedder/viz_layer_context.cc +++ b/cc/mojo_embedder/viz_layer_context.cc
@@ -17,6 +17,7 @@ #include "base/containers/span.h" #include "base/notreached.h" #include "base/numerics/safe_conversions.h" +#include "base/time/time.h" #include "cc/animation/animation.h" #include "cc/animation/animation_host.h" #include "cc/animation/animation_timeline.h" @@ -1242,7 +1243,7 @@ service_->SetVisible(visible); } -void VizLayerContext::UpdateDisplayTreeFrom( +base::TimeTicks VizLayerContext::UpdateDisplayTreeFrom( LayerTreeImpl& tree, viz::ClientResourceProvider& resource_provider, viz::RasterContextProvider& context_provider, @@ -1377,9 +1378,12 @@ if (base::FeatureList::IsEnabled(features::kTreeAnimationsInViz)) { SerializeAnimationUpdates(tree, *update); } + + base::TimeTicks time_sent_to_service = base::TimeTicks::Now(); service_->UpdateDisplayTree(std::move(update)); needs_full_sync_ = false; + return time_sent_to_service; } // Sends a single-tile update to the Viz service by serializing it as a tiling.
diff --git a/cc/mojo_embedder/viz_layer_context.h b/cc/mojo_embedder/viz_layer_context.h index 185da31..6bf241f 100644 --- a/cc/mojo_embedder/viz_layer_context.h +++ b/cc/mojo_embedder/viz_layer_context.h
@@ -40,7 +40,7 @@ // LayerContext: void SetVisible(bool visible) override; - void UpdateDisplayTreeFrom( + base::TimeTicks UpdateDisplayTreeFrom( LayerTreeImpl& tree, viz::ClientResourceProvider& resource_provider, viz::RasterContextProvider& context_provider,
diff --git a/cc/test/fake_layer_context.cc b/cc/test/fake_layer_context.cc index 27a6c98..85fefba 100644 --- a/cc/test/fake_layer_context.cc +++ b/cc/test/fake_layer_context.cc
@@ -4,16 +4,20 @@ #include "cc/test/fake_layer_context.h" +#include "base/time/time.h" + namespace cc { void FakeLayerContext::SetVisible(bool visible) {} -void FakeLayerContext::UpdateDisplayTreeFrom( +base::TimeTicks FakeLayerContext::UpdateDisplayTreeFrom( LayerTreeImpl& tree, viz::ClientResourceProvider& resource_provider, viz::RasterContextProvider& context_provider, const gfx::Rect& viewport_damage_rect, - const viz::LocalSurfaceId& target_local_surface_id) {} + const viz::LocalSurfaceId& target_local_surface_id) { + return base::TimeTicks::Now(); +} void FakeLayerContext::UpdateDisplayTile( PictureLayerImpl& layer,
diff --git a/cc/test/fake_layer_context.h b/cc/test/fake_layer_context.h index e0ff2dba..0d37fe9 100644 --- a/cc/test/fake_layer_context.h +++ b/cc/test/fake_layer_context.h
@@ -16,7 +16,7 @@ void SetVisible(bool visible) override; - void UpdateDisplayTreeFrom( + base::TimeTicks UpdateDisplayTreeFrom( LayerTreeImpl& tree, viz::ClientResourceProvider& resource_provider, viz::RasterContextProvider& context_provider,
diff --git a/cc/test/test_layer_context.cc b/cc/test/test_layer_context.cc index 490a094..78dcc6d 100644 --- a/cc/test/test_layer_context.cc +++ b/cc/test/test_layer_context.cc
@@ -8,12 +8,14 @@ void TestLayerContext::SetVisible(bool visible) {} -void TestLayerContext::UpdateDisplayTreeFrom( +base::TimeTicks TestLayerContext::UpdateDisplayTreeFrom( LayerTreeImpl& tree, viz::ClientResourceProvider& resource_provider, viz::RasterContextProvider& context_provider, const gfx::Rect& viewport_damage_rect, - const viz::LocalSurfaceId& target_local_surface_id) {} + const viz::LocalSurfaceId& target_local_surface_id) { + return base::TimeTicks::Now(); +} void TestLayerContext::UpdateDisplayTile( PictureLayerImpl& layer,
diff --git a/cc/test/test_layer_context.h b/cc/test/test_layer_context.h index 662b234..6b3a1c6 100644 --- a/cc/test/test_layer_context.h +++ b/cc/test/test_layer_context.h
@@ -16,7 +16,7 @@ void SetVisible(bool visible) override; - void UpdateDisplayTreeFrom( + base::TimeTicks UpdateDisplayTreeFrom( LayerTreeImpl& tree, viz::ClientResourceProvider& resource_provider, viz::RasterContextProvider& context_provider,
diff --git a/cc/trees/layer_context.h b/cc/trees/layer_context.h index b0d9c2c..4df30fb 100644 --- a/cc/trees/layer_context.h +++ b/cc/trees/layer_context.h
@@ -5,6 +5,7 @@ #ifndef CC_TREES_LAYER_CONTEXT_H_ #define CC_TREES_LAYER_CONTEXT_H_ +#include "base/time/time.h" #include "cc/cc_export.h" #include "cc/trees/commit_state.h" #include "components/viz/common/surfaces/local_surface_id.h" @@ -35,7 +36,7 @@ virtual void SetVisible(bool visible) = 0; // Pushes updates from `tree` into the context's display tree. - virtual void UpdateDisplayTreeFrom( + virtual base::TimeTicks UpdateDisplayTreeFrom( LayerTreeImpl& tree, viz::ClientResourceProvider& resource_provider, viz::RasterContextProvider& context_provider,
diff --git a/chrome/VERSION b/chrome/VERSION index 92317ae1..beb2990 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=141 MINOR=0 -BUILD=7340 +BUILD=7341 PATCH=0
diff --git a/chrome/android/expectations/trichrome_chrome_64_32_bundle__dev_ui.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_64_32_bundle__dev_ui.AndroidManifest.expected index 46c3ab4d..c3c6c4a 100644 --- a/chrome/android/expectations/trichrome_chrome_64_32_bundle__dev_ui.AndroidManifest.expected +++ b/chrome/android/expectations/trichrome_chrome_64_32_bundle__dev_ui.AndroidManifest.expected
@@ -8,9 +8,17 @@ platformBuildVersionName="16" android:versionCode="OFFSET=33" android:versionName="#.#.#.#"> - <dist:module dist:onDemand="true" dist:title="@string/dev_ui_module_title"> # DIFF-ANCHOR: 671a5c9f + <dist:module dist:title="@string/dev_ui_module_title"> # DIFF-ANCHOR: ce49604c + <dist:delivery> # DIFF-ANCHOR: 2f6943d1 + <dist:install-time> # DIFF-ANCHOR: 945cd8fb + <dist:conditions> # DIFF-ANCHOR: dab9d630 + <dist:device-feature dist:name="android.hardware.type.pc"/> + </dist:conditions> # DIFF-ANCHOR: dab9d630 + </dist:install-time> # DIFF-ANCHOR: 945cd8fb + <dist:on-demand/> + </dist:delivery> # DIFF-ANCHOR: 2f6943d1 <dist:fusing dist:include="true"/> - </dist:module> # DIFF-ANCHOR: 671a5c9f + </dist:module> # DIFF-ANCHOR: ce49604c <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="36"/> <application/> </manifest> \ No newline at end of file
diff --git a/chrome/android/features/dev_ui/internal/java/AndroidManifest.xml b/chrome/android/features/dev_ui/internal/java/AndroidManifest.xml index 5d1a2aba..332c9ef5 100644 --- a/chrome/android/features/dev_ui/internal/java/AndroidManifest.xml +++ b/chrome/android/features/dev_ui/internal/java/AndroidManifest.xml
@@ -10,8 +10,16 @@ featureSplit="dev_ui"> <dist:module - dist:onDemand="true" dist:title="@string/dev_ui_module_title"> + <dist:delivery> + <dist:on-demand/> + <dist:install-time> + <dist:conditions> + <!-- Install DevUI for desktop devices at install time --> + <dist:device-feature dist:name="android.hardware.type.pc"/> + </dist:conditions> + </dist:install-time> + </dist:delivery> <dist:fusing dist:include="true" /> </dist:module>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java index 00f86d8..dec4930 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -416,17 +416,7 @@ } @Override - public void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) { - if (!isVisible()) return; - - // TODO(b/338447134): This shouldn't show a snackbar if the tab isn't in - // this group. However, background closures are currently not-undoable so - // this is fine for now... - showSingleTabClosureSnackbar(tab); - } - - @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> closedTabs, boolean isAllTabs, @TabClosingSource int closingSource) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java index 51b688d..541093f 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallback.java
@@ -277,9 +277,10 @@ int newIndex = distance >= 0 ? TabGroupUtils.getLastTabModelIndexForList( - tabModel, destinationTabGroup) + tabModel, destinationTabGroup) : TabGroupUtils.getFirstTabModelIndexForList( tabModel, destinationTabGroup); + newIndex = adjustIndexBasedOnPinning(tabModel, currentTabId, newIndex); filter.moveRelatedTabs(currentTabId, newIndex); } RecordUserAction.record("TabGrid.Drag.Reordered." + mComponentName); @@ -287,6 +288,30 @@ return true; } + private int adjustIndexBasedOnPinning(TabModel tabModel, int fromTabId, int newIndex) { + // Get the tab being moved. + Tab fromTab = tabModel.getTabById(fromTabId); + if (fromTab != null) { + + // Determine the index of the last pinned tab. + int lastPinnedIndex = tabModel.findFirstNonPinnedTabIndex() - 1; + + if (fromTab.getIsPinned()) { + // If the moved tab is pinned, ensure it doesn't move beyond the last pinned index. + if (newIndex > lastPinnedIndex) { + newIndex = lastPinnedIndex; + } + } else { + // If the moved tab is not pinned, ensure it doesn't move before the first + // non-pinned index. + if (newIndex <= lastPinnedIndex) { + newIndex = lastPinnedIndex + 1; + } + } + } + return newIndex; + } + @Override public void onMoved( final RecyclerView recyclerView,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabModelNotificationDotManagerUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabModelNotificationDotManagerUnitTest.java index cc7c770..03be725 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabModelNotificationDotManagerUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabModelNotificationDotManagerUnitTest.java
@@ -63,7 +63,6 @@ private static final int EXISTING_TAB_ID = 5; private static final int ROOT_ID = 6; private static final int NON_EXISTANT_TAB_ID = 7; - private static final int TAB_COUNT = 3; private static final Token TAB_GROUP_ID = new Token(378L, 4378L); private static final String TITLE = "Vacation"; @@ -105,7 +104,7 @@ when(mTabGroupModelFilterProvider.getTabGroupModelFilter(false)) .thenReturn(mTabGroupModelFilter); when(mTabGroupModelFilter.getTabModel()).thenReturn(mTabModel); - when(mTabGroupModelFilter.getTabCountForGroup(TAB_GROUP_ID)).thenReturn(TAB_COUNT); + when(mTabGroupModelFilter.getTabsInGroup(TAB_GROUP_ID)).thenReturn(List.of(mTab)); when(mTabGroupModelFilter.getTabGroupTitle(TAB_GROUP_ID)).thenReturn(TITLE); when(mTabGroupModelFilter.tabGroupExists(TAB_GROUP_ID)).thenReturn(true); when(mTabModel.getProfile()).thenReturn(mProfile); @@ -292,7 +291,7 @@ // Set to visible. mPersistentMessageObserverCaptor.getValue().displayPersistentMessage(mDirtyTabMessage); - verifyShown("3 tabs"); + verifyShown("1 tab"); } private void initializeBothBackends() {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPane.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPane.java index c3a69565..7a76638 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPane.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPane.java
@@ -4,7 +4,7 @@ package org.chromium.chrome.browser.tasks.tab_management; -import static org.chromium.chrome.browser.tab_ui.VersionUpdateIphHandler.maybeShowTabGroupPaneButtonIph; +import static org.chromium.chrome.browser.tab_ui.VersionUpdateIphHandler.maybeShowVersioningIph; import android.content.Context; import android.content.SharedPreferences; @@ -359,8 +359,11 @@ if (getIsAnimatingSupplier().get()) return; if (mProfileProvider != null) { - maybeShowTabGroupPaneButtonIph( - mUserEducationHelper, mTabGroupModelFilterSupplier.get(), anchorView); + maybeShowVersioningIph( + mUserEducationHelper, + anchorView, + mTabGroupModelFilterSupplier.get(), + /* expectsAutoOpen= */ true); } IphCommand command =
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneMediator.java index 814fe4a..c6098d5 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneMediator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneMediator.java
@@ -81,14 +81,9 @@ } @Override - public void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) { - notifyBackPressStateChangedInternal(); - } - - @Override public void onFinishingTabClosure(Tab tab, @TabClosingSource int closingSource) { // If tab is closed by the site itself rather than user's input, - // tabPendingClosure & tabClosureCommitted won't be called. + // onTabClosePending & tabClosureCommitted won't be called. notifyBackPressStateChangedInternal(); } @@ -98,7 +93,7 @@ } @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) { notifyBackPressStateChangedInternal(); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneMediatorUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneMediatorUnitTest.java index b581a67..ce48d28e 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneMediatorUnitTest.java
@@ -230,20 +230,16 @@ assertTrue(dialogVisibilitySupplier.get()); when(mTabListEditorController.isVisible()).thenReturn(false); - observer.tabPendingClosure(null, TabClosingSource.UNKNOWN); + observer.onFinishingTabClosure(null, TabClosingSource.UNKNOWN); assertFalse(dialogVisibilitySupplier.get()); when(mTabListEditorController.isVisible()).thenReturn(true); - observer.onFinishingTabClosure(null, TabClosingSource.UNKNOWN); + observer.tabRemoved(null); assertTrue(dialogVisibilitySupplier.get()); when(mTabListEditorController.isVisible()).thenReturn(false); - observer.tabRemoved(null); + observer.onTabClosePending(null, false, TabClosingSource.UNKNOWN); assertFalse(dialogVisibilitySupplier.get()); - - when(mTabListEditorController.isVisible()).thenReturn(true); - observer.multipleTabsPendingClosure(null, false, TabClosingSource.UNKNOWN); - assertTrue(dialogVisibilitySupplier.get()); } @Test
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneUnitTest.java index b0f2981..843ee2e 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherPaneUnitTest.java
@@ -307,6 +307,7 @@ when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); when(mPrefService.getBoolean(Pref.AUTO_OPEN_SYNCED_TAB_GROUPS)).thenReturn(true); + when(mTabGroupSyncService.getVersioningMessageController()).thenReturn(mock()); UserPrefsJni.setInstanceForTesting(mUserPrefsJniMock); }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchRenderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchRenderTest.java index 620973f..023c616 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchRenderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchRenderTest.java
@@ -106,8 +106,7 @@ @Before public void setUp() throws ExecutionException { mTestServer = - TabSwitcherSearchTestUtils.setServerPortAndGetTestServer( - mCtaTestRule.getActivityTestRule(), SERVER_PORT); + mCtaTestRule.getEmbeddedTestServerRule().setServerPort(SERVER_PORT).getServer(); mInitialPage = mCtaTestRule.startOnBlankPage(); }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchTest.java index b8921a5..27cbfc8 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchTest.java
@@ -85,8 +85,7 @@ @Before public void setUp() { mTestServer = - TabSwitcherSearchTestUtils.setServerPortAndGetTestServer( - mCtaTestRule.getActivityTestRule(), SERVER_PORT); + mCtaTestRule.getEmbeddedTestServerRule().setServerPort(SERVER_PORT).getServer(); mPage = mCtaTestRule.startOnBlankPage(); mUserActionTester = new UserActionTester();
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchTestUtils.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchTestUtils.java deleted file mode 100644 index 6319a327..0000000 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchTestUtils.java +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.tasks.tab_management; - -import static androidx.test.espresso.Espresso.closeSoftKeyboard; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.matcher.ViewMatchers.withId; - -import android.content.Context; - -import androidx.test.platform.app.InstrumentationRegistry; - -import org.chromium.chrome.browser.searchwidget.SearchActivity; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.chrome.test.R; -import org.chromium.chrome.test.util.ActivityTestUtils; -import org.chromium.chrome.test.util.OmniboxTestUtils; -import org.chromium.net.test.EmbeddedTestServer; -import org.chromium.ui.base.DeviceFormFactor; - -/** Test utils for hub search. */ -public class TabSwitcherSearchTestUtils { - /** Launch the SearchActivity and wait for ZPS to load. */ - public static SearchActivity launchSearchActivityFromTabSwitcherAndWaitForLoad( - Context context) { - SearchActivity searchActivity = - ActivityTestUtils.waitForActivity( - InstrumentationRegistry.getInstrumentation(), - SearchActivity.class, - () -> { - if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(context)) { - onView(withId(R.id.search_loupe)).perform(click()); - } else { - onView(withId(R.id.search_box_text)).perform(click()); - } - }); - - OmniboxTestUtils omniboxTestUtils = new OmniboxTestUtils(searchActivity); - omniboxTestUtils.waitAnimationsComplete(); - // On Android P devices, the omnibox needs to be focused for the suggestions to show. - omniboxTestUtils.requestFocus(); - closeSoftKeyboard(); - - return searchActivity; - } - - /** Sets the given server port, and returns the EmbeddedTestServer. */ - public static EmbeddedTestServer setServerPortAndGetTestServer( - ChromeTabbedActivityTestRule activityTestRule, int serverPort) { - activityTestRule.getEmbeddedTestServerRule().setServerPort(serverPort); - return activityTestRule.getTestServer(); - } -}
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java index adb7da64..efa53365 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -882,54 +882,34 @@ } @Test - public void tabPendingClosure_DialogVisible() { - mModel.set(TabGridDialogProperties.IS_DIALOG_VISIBLE, true); - - mTabModelObserverCaptor.getValue().tabPendingClosure(mTab1, TabClosingSource.UNKNOWN); - - verify(mSnackbarManager).showSnackbar(any(Snackbar.class)); - } - - @Test - public void tabPendingClosure_DialogInvisible() { - mModel.set(TabGridDialogProperties.IS_DIALOG_VISIBLE, false); - - mTabModelObserverCaptor.getValue().tabPendingClosure(mTab1, TabClosingSource.UNKNOWN); - - verify(mSnackbarManager, never()).showSnackbar(any(Snackbar.class)); - } - - @Test - public void multipleTabsPendingClosure_DialogVisible() { + public void onTabClosePending_DialogVisible() { mModel.set(TabGridDialogProperties.IS_DIALOG_VISIBLE, true); mTabModelObserverCaptor .getValue() - .multipleTabsPendingClosure( - Arrays.asList(mTab1, mTab2), false, TabClosingSource.UNKNOWN); + .onTabClosePending(Arrays.asList(mTab1, mTab2), false, TabClosingSource.UNKNOWN); verify(mSnackbarManager).showSnackbar(any(Snackbar.class)); } @Test - public void multipleTabsPendingClosure_singleTab_DialogVisible() { + public void onTabClosePending_singleTab_DialogVisible() { mModel.set(TabGridDialogProperties.IS_DIALOG_VISIBLE, true); mTabModelObserverCaptor .getValue() - .multipleTabsPendingClosure(Arrays.asList(mTab1), false, TabClosingSource.UNKNOWN); + .onTabClosePending(Arrays.asList(mTab1), false, TabClosingSource.UNKNOWN); verify(mSnackbarManager).showSnackbar(any(Snackbar.class)); } @Test - public void multipleTabsPendingClosure_DialogInvisible() { + public void onTabClosePending_DialogInvisible() { mModel.set(TabGridDialogProperties.IS_DIALOG_VISIBLE, false); mTabModelObserverCaptor .getValue() - .multipleTabsPendingClosure( - Arrays.asList(mTab1, mTab2), false, TabClosingSource.UNKNOWN); + .onTabClosePending(Arrays.asList(mTab1, mTab2), false, TabClosingSource.UNKNOWN); verify(mSnackbarManager, never()).showSnackbar(any(Snackbar.class)); }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallbackUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallbackUnitTest.java index 12550bb..bcb9a71 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallbackUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridItemTouchHelperCallbackUnitTest.java
@@ -42,6 +42,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.annotation.Config; @@ -109,7 +110,7 @@ @Mock private Canvas mCanvas; @Mock private RecyclerView mRecyclerView; @Mock private RecyclerView.Adapter mAdapter; - @Mock private TabModel mTabModel; + @Spy private TabModel mTabModel; @Mock private TabListMediator.TabActionListener mTabClosedListener; @Mock private TabGroupModelFilter mTabGroupModelFilter; @Mock private TabUngrouper mTabUngrouper; @@ -1186,6 +1187,147 @@ mRecyclerView, 100, 10, 1000, 100)); } + @Test + public void testOnMove_PinnedTab_WithinPinnedTabs() { + // Setup: 2 pinned tabs and 2 unpinned tabs. + when(mTab1.getIsPinned()).thenReturn(true); + when(mTab2.getIsPinned()).thenReturn(true); + when(mTab3.getIsPinned()).thenReturn(false); + when(mTab4.getIsPinned()).thenReturn(false); + when(mTabGroupModelFilter.getRelatedTabList(TAB1_ID)).thenReturn(List.of(mTab1)); + when(mTabGroupModelFilter.getRelatedTabList(TAB2_ID)).thenReturn(List.of(mTab2)); + when(mTabModel.indexOf(mTab1)).thenReturn(0); + when(mTabModel.indexOf(mTab2)).thenReturn(1); + when(mTabModel.findFirstNonPinnedTabIndex()).thenReturn(2); + + // Drag pinned tab1 to pinned tab2's position. + mItemTouchHelperCallback.onMove(mRecyclerView, mMockViewHolder1, mMockViewHolder2); + // Verify that tab1 is moved to index 1. + verify(mTabGroupModelFilter).moveRelatedTabs(TAB1_ID, 1); + } + + @Test + public void testOnMove_UnpinnedTab_WithinUnpinnedTabs() { + // Setup: 2 pinned tabs and 2 unpinned tabs. + when(mTab1.getIsPinned()).thenReturn(true); + when(mTab2.getIsPinned()).thenReturn(true); + when(mTab3.getIsPinned()).thenReturn(false); + when(mTab4.getIsPinned()).thenReturn(false); + when(mTabGroupModelFilter.getRelatedTabList(TAB3_ID)).thenReturn(List.of(mTab3)); + when(mTabGroupModelFilter.getRelatedTabList(TAB4_ID)).thenReturn(List.of(mTab4)); + when(mTabModel.indexOf(mTab1)).thenReturn(0); + when(mTabModel.indexOf(mTab2)).thenReturn(1); + when(mTabModel.indexOf(mTab3)).thenReturn(2); + when(mTabModel.indexOf(mTab4)).thenReturn(3); + when(mTabModel.findFirstNonPinnedTabIndex()).thenReturn(2); + + // Drag unpinned tab3 to unpinned tab4's position. + mItemTouchHelperCallback.onMove(mRecyclerView, mMockViewHolder3, mMockViewHolder4); + + // Verify that tab3 is moved to index 3. + verify(mTabGroupModelFilter).moveRelatedTabs(TAB3_ID, 3); + } + + @Test + public void testOnMove_GroupedTab_pinnedTabTriedToMoveBeyondLimit() { + // Setup: 2 pinned tabs, 2 grouped tabs. + when(mTab1.getIsPinned()).thenReturn(true); + when(mTab2.getIsPinned()).thenReturn(true); + when(mTab3.getIsPinned()).thenReturn(false); + when(mTab4.getIsPinned()).thenReturn(false); + Token groupId = Token.createRandom(); + when(mTab3.getTabGroupId()).thenReturn(groupId); + when(mTab4.getTabGroupId()).thenReturn(groupId); + + when(mTabGroupModelFilter.getRelatedTabList(TAB1_ID)).thenReturn(List.of(mTab1)); + when(mTabGroupModelFilter.getRelatedTabList(TAB2_ID)).thenReturn(List.of(mTab2)); + when(mTabGroupModelFilter.getRelatedTabList(TAB3_ID)).thenReturn(List.of(mTab3, mTab4)); + when(mTabGroupModelFilter.getRelatedTabList(TAB4_ID)).thenReturn(List.of(mTab3, mTab4)); + + when(mTabModel.indexOf(mTab1)).thenReturn(0); + when(mTabModel.indexOf(mTab2)).thenReturn(1); + when(mTabModel.indexOf(mTab3)).thenReturn(2); + when(mTabModel.indexOf(mTab4)).thenReturn(3); + when(mTabModel.findFirstNonPinnedTabIndex()).thenReturn(2); + + // Try drag a pinned tab to an unpinned tab's position. + mItemTouchHelperCallback.onMove(mRecyclerView, mMockViewHolder1, mMockViewHolder4); + + // Verify that the tab is moved to index 1, the last possible position for a pinned tab. + verify(mTabGroupModelFilter).moveRelatedTabs(TAB1_ID, 1); + } + + @Test + public void testOnMove_GroupedTab_unpinnedTabTriedToMoveIntoPinnedArea() { + // Setup: 2 pinned tabs, 2 grouped tabs. + when(mTab1.getIsPinned()).thenReturn(true); + when(mTab2.getIsPinned()).thenReturn(true); + when(mTab3.getIsPinned()).thenReturn(false); + when(mTab4.getIsPinned()).thenReturn(false); + Token groupId = Token.createRandom(); + when(mTab3.getTabGroupId()).thenReturn(groupId); + when(mTab4.getTabGroupId()).thenReturn(groupId); + + when(mTabGroupModelFilter.getRelatedTabList(TAB1_ID)).thenReturn(List.of(mTab1)); + when(mTabGroupModelFilter.getRelatedTabList(TAB2_ID)).thenReturn(List.of(mTab2)); + when(mTabGroupModelFilter.getRelatedTabList(TAB3_ID)).thenReturn(List.of(mTab3, mTab4)); + when(mTabGroupModelFilter.getRelatedTabList(TAB4_ID)).thenReturn(List.of(mTab3, mTab4)); + + when(mTabModel.indexOf(mTab1)).thenReturn(0); + when(mTabModel.indexOf(mTab2)).thenReturn(1); + when(mTabModel.indexOf(mTab3)).thenReturn(2); + when(mTabModel.indexOf(mTab4)).thenReturn(3); + when(mTabModel.findFirstNonPinnedTabIndex()).thenReturn(2); + + // Try drag an unpinned tab to a pinned tab's position. + mItemTouchHelperCallback.onMove(mRecyclerView, mMockViewHolder3, mMockViewHolder1); + + // Verify that the tab is moved to index 2, the first possible position for an unpinned + // tab. + verify(mTabGroupModelFilter).moveRelatedTabs(TAB3_ID, 2); + } + + @Test + public void testOnMove_AllUnpinnedTabs_MovedAround() { + // Setup: all tabs are unpinned. + when(mTab1.getIsPinned()).thenReturn(false); + when(mTab2.getIsPinned()).thenReturn(false); + when(mTab3.getIsPinned()).thenReturn(false); + when(mTab4.getIsPinned()).thenReturn(false); + when(mTabGroupModelFilter.getRelatedTabList(TAB1_ID)).thenReturn(List.of(mTab1)); + when(mTabGroupModelFilter.getRelatedTabList(TAB4_ID)).thenReturn(List.of(mTab4)); + when(mTabModel.indexOf(mTab1)).thenReturn(0); + when(mTabModel.indexOf(mTab4)).thenReturn(3); + when(mTabModel.findFirstNonPinnedTabIndex()).thenReturn(0); + + // Drag tab1 to tab4's position. + mItemTouchHelperCallback.onMove(mRecyclerView, mMockViewHolder1, mMockViewHolder4); + + // Verify that tab1 is moved to index 3. + verify(mTabGroupModelFilter).moveRelatedTabs(TAB1_ID, 3); + } + + @Test + public void testOnMove_AllPinnedTabs_MovedAround() { + // Setup: all tabs are pinned. + when(mTab1.getIsPinned()).thenReturn(true); + when(mTab2.getIsPinned()).thenReturn(true); + when(mTab3.getIsPinned()).thenReturn(true); + when(mTab4.getIsPinned()).thenReturn(true); + when(mTabGroupModelFilter.getRelatedTabList(TAB1_ID)).thenReturn(List.of(mTab1)); + when(mTabGroupModelFilter.getRelatedTabList(TAB4_ID)).thenReturn(List.of(mTab4)); + when(mTabModel.indexOf(mTab1)).thenReturn(0); + when(mTabModel.indexOf(mTab4)).thenReturn(3); + // All tabs are pinned, so the first non-pinned tab is at the end of the list. + when(mTabModel.findFirstNonPinnedTabIndex()).thenReturn(4); + + // Drag tab1 to tab4's position. + mItemTouchHelperCallback.onMove(mRecyclerView, mMockViewHolder1, mMockViewHolder4); + + // Verify that tab1 is moved to index 3. + verify(mTabGroupModelFilter).moveRelatedTabs(TAB1_ID, 3); + } + private void verifyDrag( RecyclerView.ViewHolder viewHolder, float dX, float dY, int targetIndex, int status) { // Simulate the process of dragging one card to a position.
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java index c33ea8f..f7f7efd 100644 --- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java +++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -1899,6 +1899,7 @@ when(mTabGroupModelFilter.getTabCountForGroup(TAB_GROUP_ID)).thenReturn(1); when(mTabGroupModelFilter.getRelatedTabList(TAB1_ID)).thenReturn(List.of(mTab1)); when(mTabGroupModelFilter.getRelatedTabList(TAB2_ID)).thenReturn(List.of(mTab2)); + when(mTabGroupModelFilter.getTabsInGroup(TAB_GROUP_ID)).thenReturn(List.of(mTab2)); mTabGroupModelFilterObserverCaptor.getValue().didMoveTabOutOfGroup(mTab1, POSITION1);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 574cd3e..8995fc23 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -815,16 +815,7 @@ } @Override - public void tabPendingClosure( - Tab tab, @TabClosingSource int closingSource) { - closeIfNoTabsAndHomepageEnabled( - true, - /* shouldRemoveWindowWithZeroTabs= */ closingSource - == TabClosingSource.TABLET_TAB_STRIP); - } - - @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/metrics/LaunchCauseMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/app/metrics/LaunchCauseMetrics.java index 952d5df..1858a6cf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/metrics/LaunchCauseMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/metrics/LaunchCauseMetrics.java
@@ -19,6 +19,8 @@ import org.chromium.base.TraceEvent; import org.chromium.base.metrics.RecordHistogram; import org.chromium.build.annotations.CheckDiscard; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.ui.display.DisplayAndroidManager; @@ -26,6 +28,7 @@ import java.lang.annotation.RetentionPolicy; /** Computes and records metrics for what caused Chrome to be launched. */ +@NullMarked public abstract class LaunchCauseMetrics implements ApplicationStatus.ApplicationStateListener, ApplicationStatus.ActivityStateListener { @@ -45,9 +48,9 @@ private long mActivityId; @SuppressLint("StaticFieldLeak") - private static Activity sLastResumedActivity; + private static @Nullable Activity sLastResumedActivity; - private static ApplicationStatus.ActivityStateListener sAppActivityListener; + private static ApplicationStatus.@Nullable ActivityStateListener sAppActivityListener; static { doStaticInit();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetrics.java index a2c4fa5c..0db9d03 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetrics.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetrics.java
@@ -10,6 +10,7 @@ import android.speech.RecognizerResultsIntent; import org.chromium.base.IntentUtils; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.ServiceTabLauncher; import org.chromium.chrome.browser.browserservices.intents.WebappConstants; @@ -19,6 +20,7 @@ import org.chromium.components.webapps.ShortcutSource; /** LaunchCauseMetrics for ChromeTabbedActivity. */ +@NullMarked public class TabbedActivityLaunchCauseMetrics extends LaunchCauseMetrics { private final Activity mActivity;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/notifications/ContextualNotificationPermissionRequesterImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/notifications/ContextualNotificationPermissionRequesterImpl.java index e97da38..467046e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/notifications/ContextualNotificationPermissionRequesterImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/notifications/ContextualNotificationPermissionRequesterImpl.java
@@ -4,9 +4,13 @@ package org.chromium.chrome.browser.app.notifications; +import static org.chromium.build.NullUtil.assertNonNull; + import android.app.Activity; import org.chromium.base.ApplicationStatus; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.notifications.permissions.NotificationPermissionController; @@ -16,6 +20,7 @@ * Implementation of {@link ContextualNotificationPermissionRequester}. Contains the necessary * hookups to request permission using the last focused chrome activity. */ +@NullMarked public class ContextualNotificationPermissionRequesterImpl extends ContextualNotificationPermissionRequester { private static final String FIELD_TRIAL_ENABLE_CONTEXTUAL_PERMISSION_REQUESTS = @@ -53,13 +58,14 @@ return permissionController.doesAppLevelSettingsAllowSiteNotifications(); } - private NotificationPermissionController getNotificationPermissionController() { + private @Nullable NotificationPermissionController getNotificationPermissionController() { Activity activity = ApplicationStatus.getLastTrackedFocusedActivity(); if (!(activity instanceof ChromeTabbedActivity)) return null; // TODO(shaktisahu): Maybe split out the contextual permission logic out of // NotificationPermissionController entirely to serve non-chrome activities. ChromeTabbedActivity chromeTabbedActivity = (ChromeTabbedActivity) activity; - return NotificationPermissionController.from(chromeTabbedActivity.getWindowAndroid()); + return NotificationPermissionController.from( + assertNonNull(chromeTabbedActivity.getWindowAndroid())); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/reengagement/ReengagementActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/reengagement/ReengagementActivity.java index 63541c9..dbc4b5a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/reengagement/ReengagementActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/reengagement/ReengagementActivity.java
@@ -8,13 +8,16 @@ import android.content.Intent; import android.os.Bundle; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.reengagement.ReengagementNotificationController; /** Trampoline activity to start the NTP from the reengagement notification. */ +@NullMarked public class ReengagementActivity extends Activity { @Override - protected void onCreate(Bundle savedInstanceState) { + protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); String action = getIntent().getAction(); if (ReengagementNotificationController.LAUNCH_NTP_ACTION.equals(action)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/send_tab_to_self/SendTabToSelfNotificationReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/app/send_tab_to_self/SendTabToSelfNotificationReceiver.java index 2016c9e..9d41c06 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/send_tab_to_self/SendTabToSelfNotificationReceiver.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/send_tab_to_self/SendTabToSelfNotificationReceiver.java
@@ -10,12 +10,14 @@ import org.jni_zero.CalledByNative; +import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.init.BrowserParts; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.init.EmptyBrowserParts; import org.chromium.chrome.browser.share.send_tab_to_self.NotificationManager; /** Handles changes to notifications based on user action or timeout. */ +@NullMarked public class SendTabToSelfNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/serial/SerialNotificationServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/serial/SerialNotificationServiceImpl.java index ca41b0b7..c1194b7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/serial/SerialNotificationServiceImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/serial/SerialNotificationServiceImpl.java
@@ -7,12 +7,15 @@ import android.content.Intent; import android.os.IBinder; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.serial.SerialNotificationManager; import org.chromium.chrome.browser.serial.SerialNotificationManagerDelegate; import org.chromium.components.browser_ui.notifications.BaseNotificationManagerProxyFactory; /** Service that manages the WebSerial notification when a website is connected to a serial port. */ +@NullMarked public class SerialNotificationServiceImpl extends SerialNotificationService.Impl { private final SerialNotificationManagerDelegate mManagerDelegate = new SerialNotificationManagerDelegate() { @@ -44,7 +47,7 @@ } @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(@Nullable Intent intent, int flags, int startId) { mManager.onStartCommand(intent, flags, startId); return super.onStartCommand(intent, flags, startId); } @@ -62,7 +65,7 @@ } @Override - public IBinder onBind(Intent intent) { + public @Nullable IBinder onBind(Intent intent) { return null; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/usb/UsbNotificationServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/usb/UsbNotificationServiceImpl.java index 99d1297..a1952e3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/usb/UsbNotificationServiceImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/usb/UsbNotificationServiceImpl.java
@@ -7,6 +7,9 @@ import android.content.Intent; import android.os.IBinder; +import org.chromium.build.annotations.Initializer; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.usb.UsbNotificationManager; import org.chromium.chrome.browser.usb.UsbNotificationManagerDelegate; @@ -16,6 +19,7 @@ * Service that manages the WebUSB notification when a website is connected * to a USB device. */ +@NullMarked public class UsbNotificationServiceImpl extends UsbNotificationService.Impl { private final UsbNotificationManagerDelegate mManagerDelegate = new UsbNotificationManagerDelegate() { @@ -38,6 +42,7 @@ private UsbNotificationManager mManager; + @Initializer @Override public void onCreate() { mManager = @@ -47,7 +52,7 @@ } @Override - public int onStartCommand(Intent intent, int flags, int startId) { + public int onStartCommand(@Nullable Intent intent, int flags, int startId) { mManager.onStartCommand(intent, flags, startId); return super.onStartCommand(intent, flags, startId); } @@ -65,7 +70,7 @@ } @Override - public IBinder onBind(Intent intent) { + public @Nullable IBinder onBind(Intent intent) { return null; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java index 9fd55db..f7f6d68 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatService.java
@@ -114,6 +114,7 @@ return mService; } + @Initializer public void onCreate() {} public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java index 63ea2fd..7ca7d24 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
@@ -274,12 +274,7 @@ } @Override - public void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) { - tabClosed(tab.getId(), tab.isIncognito(), false); - } - - @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) { // Handled by willCloseAllTabs; if (isAllTabs) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStacker.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStacker.java index e4b2135..f5a812e92 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStacker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStacker.java
@@ -17,15 +17,12 @@ @Override public void pushDrawPropertiesToViews( - StripLayoutView[] indexOrderedViews, - float xOffset, - float visibleWidth, - boolean tabClosing, - float cachedTabWidth) { + StripLayoutView[] indexOrderedViews, float xOffset, float visibleWidth) { for (int i = 0; i < indexOrderedViews.length; i++) { StripLayoutView view = indexOrderedViews[i]; - setDrawXAndY(view, tabClosing, cachedTabWidth); + view.setDrawX(view.getIdealX() + view.getOffsetX()); + view.setDrawY(view.getOffsetY()); // visibility is based drawX - call this after setting drawX / Y. setVisible(view, xOffset, visibleWidth); } @@ -60,16 +57,4 @@ (drawXAccountingPadding + width) >= xOffset && drawXAccountingPadding <= xOffset + visibleWidth); } - - private static void setDrawXAndY( - StripLayoutView view, boolean tabClosing, float cachedTabWidth) { - float newDrawX = view.getIdealX() + view.getOffsetX(); - // Adjust the newDrawX to correctly animate container slide-out in RTL. - // TODO(crbug.com/375029950): Investigate if this is still needed. - if (view instanceof StripLayoutTab tab && LocalizationUtils.isLayoutRtl() && !tabClosing) { - newDrawX += (cachedTabWidth - tab.getWidth()); - } - view.setDrawX(newDrawX); - view.setDrawY(view.getOffsetY()); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutGroupTitle.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutGroupTitle.java index 5d0005b..9063104 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutGroupTitle.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutGroupTitle.java
@@ -122,9 +122,6 @@ @ColorInt private final int mBubbleTint; private @Nullable TabBubbler mTabBubbler; - // Reorder state - @ColorInt private final int mReorderBackgroundTint; - /** * Create a {@link StripLayoutGroupTitle} that represents the TabGroup for the {@code * tabGroupId}. @@ -145,7 +142,6 @@ mDelegate = delegate; mTabGroupId = tabGroupId; mBubbleTint = TabUiThemeUtil.getGroupTitleBubbleColor(mContext); - mReorderBackgroundTint = TabUiThemeUtil.getReorderBackgroundColor(mContext, incognito); } @Override @@ -314,7 +310,9 @@ /** Returns the {@link ColorInt} for the reorder background. */ public @ColorInt int getReorderBackgroundTint() { - return mReorderBackgroundTint; + return getIsNonDragReordering() + ? TabUiThemeUtil.getTabStripBackgroundColor(mContext, isIncognito()) + : TabUiThemeUtil.getReorderBackgroundColor(mContext, isIncognito()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index 4242d8e..31b5ec3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -244,6 +244,18 @@ public void didMoveTabGroup( Tab movedTab, int tabModelOldIndex, int tabModelNewIndex) { mMovingGroup = false; + // The sequencing of #didMoveTabGroup and #didMoveTab is different with and + // without Tab Collections. With Tab Collections enabled, the final event is + // #didMoveTabGroup, meaning we need to trigger a rebuild here. With it + // disabled, we instead need to trigger a rebuild after the final #didMoveTab + // event, which is handled in #tabMoved. + if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_COLLECTION_ANDROID)) { + // Additionally rebuild the StripLayoutTabs here as well. This was + // previously maintained by #tabMoved, but the old/new indices that are + // provided are different with Tab Collections enabled. + rebuildStripTabs(/* deferAnimations= */ true); + rebuildStripViewsAfterMove(); + } } @Override @@ -1519,20 +1531,7 @@ // 2. Swap the tabs. StripLayoutUtils.moveElement(mStripTabs, index, newIndex); - if (!mMovingGroup) { - if (mReorderDelegate.isReorderingTab()) { - // Update strip start and end margins to create more space for first tab or last tab - // to drag out of group. - mReorderDelegate.setEdgeMarginsForReorder(mStripTabs); - } - // When tab groups are moved, each tab is moved one-by-one. During this process, the - // invariant that tab groups must be contiguous is temporarily broken, so we suppress - // rebuilding until the entire group is moved. See https://crbug.com/329318567. - // TODO(crbug.com/329335086): Investigate reordering (with #moveElement) instead of - // rebuilding here. - rebuildStripViews(); - computeIdealViewPositions(); - } + if (!mMovingGroup) rebuildStripViewsAfterMove(); } /** @@ -1572,6 +1571,7 @@ */ public void multipleTabsClosed(List<Tab> tabs) { rebuildStripTabs(/* deferAnimations= */ false); + clearPendingMouseTabClosureState(); } /** Called when all tabs are closed at once. */ @@ -1901,14 +1901,6 @@ } } - private void setTabContainerVisible(StripLayoutTab tab) { - // The container will be visible if the tab is selected, - // is a placeholder tab or is multi-selected. - boolean isVisible = - tab.getIsSelected() || tab.getIsPlaceholder() || tab.getIsMultiSelected(); - StripLayoutTabDelegate.setTabVisibility(tab, isVisible); - } - private void updateTabContainersAndDividers() { int hoveredId = mLastHoveredTab != null ? mLastHoveredTab.getTabId() : Tab.INVALID_TAB_ID; @@ -1918,7 +1910,7 @@ // 1. Set container visibility. Handled in a separate animation for hovered tabs. if (hoveredId != currTab.getTabId()) { - setTabContainerVisible(currTab); + StripLayoutTabDelegate.updateTabVisibility(currTab); } boolean currContainerHidden = StripLayoutTabDelegate.isTabHidden(currTab); @@ -3954,6 +3946,21 @@ mUpdateHost.requestUpdate(); } + private void rebuildStripViewsAfterMove() { + if (mReorderDelegate.isReorderingTab()) { + // Update strip start and end margins to create more space for first tab or last tab + // to drag out of group. + mReorderDelegate.setEdgeMarginsForReorder(mStripTabs); + } + // When tab groups are moved, each tab is moved one-by-one. During this process, the + // invariant that tab groups must be contiguous is temporarily broken, so we suppress + // rebuilding until the entire group is moved. See https://crbug.com/329318567. + // TODO(crbug.com/329335086): Investigate reordering (with #moveElement) instead of + // rebuilding here. + rebuildStripViews(); + computeIdealViewPositions(); + } + private int getTabGroupCount() { if (mTabGroupModelFilter == null) return 0; @@ -4474,12 +4481,7 @@ // 3. Calculate view stacking - update view draw properties and visibility. float stripWidth = getVisibleRightBound() - getVisibleLeftBound(); - mStripStacker.pushDrawPropertiesToViews( - mStripViews, - getVisibleLeftBound(), - stripWidth, - mMultiStepTabCloseAnimRunning, - getCachedTabWidth()); + mStripStacker.pushDrawPropertiesToViews(mStripViews, getVisibleLeftBound(), stripWidth); // 4. Create render list. createRenderList(); @@ -4514,7 +4516,7 @@ + mScrollDelegate.getReorderStartMargin(); } else { return mWidth - - getCachedTabWidth() + - TAB_OVERLAP_WIDTH_DP - mScrollDelegate.getScrollOffset() - mRightMargin - mScrollDelegate.getReorderStartMargin(); @@ -4530,23 +4532,25 @@ if (view instanceof StripLayoutTab tab) { if (tab.isClosed()) continue; // idealX represents where a tab should be placed in the tab strip. - view.setIdealX(startX); + setTabIdealX(tab, startX); + if (ChromeFeatureList.sTabletTabStripAnimation.isEnabled() || !tab.isDying()) { delta = (tab.getWidth() - TAB_OVERLAP_WIDTH_DP) * tab.getWidthWeight(); } else { delta = getEffectiveTabWidth(); } - } else { + } else if (view instanceof StripLayoutGroupTitle groupTitle) { // Offset to "undo" the tab overlap width as that doesn't apply to non-tab views. // Also applies the desired overlap with the previous tab. - float drawXOffset = mGroupTitleDrawXOffset; - // Adjust for RTL. - if (LocalizationUtils.isLayoutRtl()) { - drawXOffset = getCachedTabWidth() - view.getWidth() - drawXOffset; - } + float drawXOffset = + MathUtils.flipSignIf( + mGroupTitleDrawXOffset, LocalizationUtils.isLayoutRtl()); + setGroupTitleIdealX(groupTitle, startX + drawXOffset); - view.setIdealX(startX + drawXOffset); delta = (view.getWidth() - mGroupTitleOverlapWidth) * view.getWidthWeight(); + } else { + assert false : "Unexpected view type in tab strip views."; + delta = 0; } // Trailing margins will only be nonzero during reorder mode. delta += view.getTrailingMargin(); @@ -4555,6 +4559,36 @@ } } + /** + * Sets the idealX for the given {@link StripLayoutTab}. For LTR, this is the same as the + * startX. For RTL, however, draw coordinates are still always anchored at the top-left of the + * screen. This means we need to set the idealX to the left-side of the tab. This is the startX + * minus the effective width of the tab. + * + * @param stripTab The {@link StripLayoutTab} to set the idealX for. + * @param startX The idealX of the tab's starting side. This is the left side in LTR and the + * right side in RTL. + */ + private void setTabIdealX(StripLayoutTab stripTab, float startX) { + if (LocalizationUtils.isLayoutRtl()) { + stripTab.setIdealX(startX - (stripTab.getWidth() - TAB_OVERLAP_WIDTH_DP)); + } else { + stripTab.setIdealX(startX); + } + } + + /** See {@link #setTabIdealX}. Same concept, but for group titles. */ + private void setGroupTitleIdealX(StripLayoutGroupTitle groupTitle, float startX) { + if (LocalizationUtils.isLayoutRtl()) { + // Use the tab overlap width here. The group title's true width accounts for how much it + // overlaps previous tab (i.e. the tab overlap width). Note that this is different from + // the visual size, which can be found through StripLayoutGroupTitle#getPaddedWidth. + groupTitle.setIdealX(startX - (groupTitle.getWidth() - TAB_OVERLAP_WIDTH_DP)); + } else { + groupTitle.setIdealX(startX); + } + } + private boolean shouldRenderView(StripLayoutView view) { return view.isVisible() && !view.isDraggedOffStrip(); } @@ -4608,12 +4642,14 @@ float viewsWidth = (getNumLiveTabs() * getEffectiveTabWidth()) + TAB_OVERLAP_WIDTH_DP; for (int i = 0; i < mStripViews.length; ++i) { final StripLayoutView view = mStripViews[i]; - if (!(view instanceof StripLayoutTab)) viewsWidth += view.getWidth(); + if (view instanceof StripLayoutGroupTitle) { + viewsWidth += (view.getWidth() - mGroupTitleOverlapWidth); + } } boolean rtl = LocalizationUtils.isLayoutRtl(); float offset = getStartPositionForStripViews() + MathUtils.flipSignIf(viewsWidth, rtl); - if (rtl) offset += getCachedTabWidth() - mNewTabButtonWidth; + if (rtl) offset += TAB_OVERLAP_WIDTH_DP - mNewTabButtonWidth; offset = adjustNewTabButtonOffsetIfNotFull(offset); CompositorAnimator animator =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java index a624883..2974bb6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -1405,14 +1405,7 @@ } @Override - public void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) { - getStripLayoutHelper(tab.isIncognitoBranded()) - .tabClosed(time(), tab.getId()); - updateModelSwitcherButton(); - } - - @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java index 1d0f4858..bdce451a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java
@@ -466,6 +466,8 @@ return TabUiThemeUtil.getTabStripSelectedTabColor(mContext, isIncognito()); case VisualState.SELECTED: return TabUiThemeUtil.getTabStripSelectedTabColor(mContext, isIncognito()); + case VisualState.NON_DRAG_REORDERING: + return TabUiThemeUtil.getTabStripBackgroundColor(mContext, isIncognito()); case VisualState.MULTISELECT_HOVERED: return TabUiThemeUtil.getTabStripMultiSelectedHoveredTabColor( mContext, isIncognito()); @@ -616,6 +618,11 @@ mLoadTracker.loadingFinished(); } + /** Returns {@code true} if the tab should be visible. */ + public boolean shouldBeVisible() { + return mIsSelected || mIsPlaceholder || mIsMultiSelected || getIsNonDragReordering(); + } + /** * @param opacity The fraction (from 0.f to 1.f) of how opaque the tab container should be. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTabDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTabDelegate.java index 4634c5de3..9d2d321 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTabDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTabDelegate.java
@@ -43,7 +43,8 @@ VisualState.MULTISELECT, VisualState.MULTISELECT_HOVERED, VisualState.SELECTED, - VisualState.SELECTED_HOVERED + VisualState.SELECTED_HOVERED, + VisualState.NON_DRAG_REORDERING }) @Retention(RetentionPolicy.SOURCE) public @interface VisualState { @@ -69,6 +70,9 @@ /** The state when a pointer is hovering over the currently active tab. */ int SELECTED_HOVERED = 6; + + /** The state when the tab is reordering for a non-drag operation. */ + int NON_DRAG_REORDERING = 7; } /** @@ -185,6 +189,17 @@ } /** + * Sets the non-drag reordering state for a given tab. + * + * @param tab The {@link StripLayoutTab} to modify. + * @param isNonDragReordering Whether the tab is reordering for a non-drag operation. + */ + public void setIsTabNonDragReordering(StripLayoutTab tab, boolean isNonDragReordering) { + tab.setIsNonDragReordering(isNonDragReordering); + updateTabVisualState(tab, /* animate= */ false); + } + + /** * Checks if the tab's background container is fully transparent. * * @param tab The {@link StripLayoutTab} to check. @@ -204,6 +219,13 @@ return tab.getContainerOpacity() == TAB_OPACITY_VISIBLE; } + /** Updates a tab's visibility based on its internal state. */ + public static void updateTabVisibility(StripLayoutTab tab) { + // TODO(crbug.com/436663313): Stop exposing this method, and handle solely in + // #updateTabVisualState. + setTabVisibility(tab, tab.shouldBeVisible()); + } + /** * Sets the visibility of the tab's background container directly. * @@ -211,6 +233,8 @@ * @param isVisible Whether the container should be visible. */ public static void setTabVisibility(StripLayoutTab tab, boolean isVisible) { + // TODO(crbug.com/436663313): Stop exposing this method, and handle solely in + // #updateTabVisualState. float containerOpacity = isVisible ? TAB_OPACITY_VISIBLE : TAB_OPACITY_HIDDEN; tab.setContainerOpacity(containerOpacity); } @@ -255,15 +279,11 @@ // 2. Update the "folio" lifted effect. // It should only apply to non-selected tabs. if (!tab.getIsSelected()) { - boolean shouldBeDetached = tab.getIsHovered() || tab.getIsMultiSelected(); - tab.setFolioAttached(!shouldBeDetached); - tab.setBottomMargin( - shouldBeDetached - ? FOLIO_DETACHED_BOTTOM_MARGIN_DP - : FOLIO_ATTACHED_BOTTOM_MARGIN_DP); + tab.setFolioAttached(/* folioAttached= */ false); + tab.setBottomMargin(FOLIO_DETACHED_BOTTOM_MARGIN_DP); } else { // Ensure selected tabs are "attached". - tab.setFolioAttached(true); + tab.setFolioAttached(/* folioAttached= */ true); tab.setBottomMargin(FOLIO_ATTACHED_BOTTOM_MARGIN_DP); } } @@ -315,12 +335,17 @@ return !tabStartHidden && !tabEndHidden; } - /** Determines the visual state of a tab based on its selected and hovered properties. */ + /** + * Determines the visual state of a tab based on several properties (e.g. selected, hovered, + * multi-selected, placeholder, non-drag-reordering, etc.). + */ private static @VisualState int calculateVisualState(StripLayoutTab tab) { if (tab.getIsSelected() && tab.getIsHovered()) { return VisualState.SELECTED_HOVERED; } else if (tab.getIsSelected()) { return VisualState.SELECTED; + } else if (tab.getIsNonDragReordering()) { + return VisualState.NON_DRAG_REORDERING; } else if (tab.getIsMultiSelected() && tab.getIsHovered()) { return VisualState.MULTISELECT_HOVERED; } else if (tab.getIsMultiSelected()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutView.java index 327a2a4..e2ec1111 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutView.java
@@ -119,6 +119,7 @@ private boolean mIsIncognito; private boolean mIsForegrounded; private boolean mIsDraggedOffStrip; + private boolean mIsNonDragReordering; private boolean mWillClose; // A11y variables. @@ -359,6 +360,16 @@ return mIsDraggedOffStrip; } + /** Sets if the view is reordering for a non-drag operation. */ + public void setIsNonDragReordering(boolean isNonDragReordering) { + mIsNonDragReordering = isNonDragReordering; + } + + /** Gets whether or not the view is reordering for a non-drag operation. */ + public boolean getIsNonDragReordering() { + return mIsNonDragReordering; + } + /** Marks that the view will be closed due to an incoming TabModel update. */ public void setWillClose() { mWillClose = true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStacker.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStacker.java index a69b680..534ee61 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStacker.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStacker.java
@@ -90,13 +90,7 @@ * @param indexOrderedViews A list of views ordered by index. * @param xOffset The xOffset for the start of the strip. * @param visibleWidth The width of the visible space on the tab strip. - * @param tabClosing Whether a tab is being closed. - * @param cachedTabWidth Whether The ideal tab width. */ public abstract void pushDrawPropertiesToViews( - StripLayoutView[] indexOrderedViews, - float xOffset, - float visibleWidth, - boolean tabClosing, - float cachedTabWidth); + StripLayoutView[] indexOrderedViews, float xOffset, float visibleWidth); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/GroupReorderStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/GroupReorderStrategy.java index ef7b6f5..75dd9500 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/GroupReorderStrategy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/GroupReorderStrategy.java
@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.tabmodel.TabGroupModelFilter; import org.chromium.chrome.browser.tabmodel.TabGroupUtils; import org.chromium.chrome.browser.tabmodel.TabModel; +import org.chromium.ui.base.LocalizationUtils; import java.util.ArrayList; import java.util.List; @@ -133,8 +134,12 @@ int firstTabIndex = StripLayoutUtils.findIndexForTab(stripTabs, mFirstTabInGroup.getTabId()); int lastTabIndex = StripLayoutUtils.findIndexForTab(stripTabs, mLastTabInGroup.getTabId()); - if (firstTabIndex == 0) offset = Math.max(0, offset); - if (lastTabIndex == stripTabs.length - 1) offset = Math.min(0, offset); + if (firstTabIndex == 0) { + offset = LocalizationUtils.isLayoutRtl() ? Math.min(0, offset) : Math.max(0, offset); + } + if (lastTabIndex == stripTabs.length - 1) { + offset = LocalizationUtils.isLayoutRtl() ? Math.max(0, offset) : Math.min(0, offset); + } for (StripLayoutView view : mInteractingViews) { view.setOffsetX(offset); } @@ -209,8 +214,10 @@ // Animate the reordering view. Ensure all the views are foregrounded. reorderingView.setIsForegrounded(/* isForegrounded= */ true); + reorderingView.setIsNonDragReordering(/* isNonDragReordering= */ true); for (StripLayoutTab tab : groupedTabs) { tab.setIsForegrounded(/* isForegrounded= */ true); + tabDelegate.setIsTabNonDragReordering(tab, /* isNonDragReordering= */ true); animateViewSliding(tab); } animateViewSliding( @@ -219,8 +226,11 @@ @Override public void onAnimationEnd(Animator animation) { reorderingView.setIsForegrounded(/* isForegrounded= */ false); + reorderingView.setIsNonDragReordering(/* isNonDragReordering= */ false); for (StripLayoutTab tab : groupedTabs) { tab.setIsForegrounded(/* isForegrounded= */ false); + tabDelegate.setIsTabNonDragReordering( + tab, /* isNonDragReordering= */ false); } } }); @@ -323,10 +333,10 @@ List<Animator> animators = new ArrayList<>(); if (!adjTitle.isCollapsed()) { // Only need to animate tabs when expanded. - int start = TabGroupUtils.getFirstTabModelIndexForList(mModel, adjTabs); - int end = start + adjTabs.size(); - for (int i = start; i < end; i++) { - animators.add(getViewSlidingAnimator(stripTabs[i])); + for (Tab tab : adjTabs) { + // Find using the IDs, since the provided stripTabs may be stale. + StripLayoutTab stripTab = StripLayoutUtils.findTabById(stripTabs, tab.getId()); + if (stripTab != null) animators.add(getViewSlidingAnimator(stripTab)); } } animators.add(getViewSlidingAnimator(adjTitle));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabReorderStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabReorderStrategy.java index 9122315..9e9db0576 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabReorderStrategy.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabReorderStrategy.java
@@ -212,17 +212,15 @@ curIndex); // Animate the reordering view and ensure it's foregrounded. - // TODO(crbug.com/402775002): Replace the temporary multi-selected visuals once the reorder - // specs are finalized. - tabDelegate.setIsTabMultiSelected(tab, /* isMultiSelected= */ true, /* animate= */ false); + tabDelegate.setIsTabNonDragReordering(tab, /* isNonDragReordering= */ true); reorderingView.setIsForegrounded(/* isForegrounded= */ true); animateViewSliding( reorderingView, new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - tabDelegate.setIsTabMultiSelected( - tab, /* isMultiSelected= */ false, /* animate= */ false); + tabDelegate.setIsTabNonDragReordering( + tab, /* isNonDragReordering= */ false); reorderingView.setIsForegrounded(/* isForegrounded= */ false); } });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerUiUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerUiUtils.java index 12dd0a2..8804b2a7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerUiUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/DomDistillerUiUtils.java
@@ -13,9 +13,15 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.R; import org.chromium.chrome.browser.ActivityUtils; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tab.TabUtils; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider; +import org.chromium.components.dom_distiller.core.DomDistillerFeatures; import org.chromium.content_public.browser.WebContents; /** Java implementation of dom_distiller::android::DistillerUIHandleAndroid. */ @@ -28,9 +34,39 @@ * @param webContents The WebContents containing the distilled content. */ @CalledByNative - public static void openSettings(WebContents webContents) { + public static void openSettings(@Nullable WebContents webContents) { if (webContents == null) return; + if (DomDistillerFeatures.sReaderModeDistillInApp.isEnabled()) { + openSettingsInBottomSheet( + TabUtils.fromWebContents(webContents), /* showFullSheet= */ true); + } else { + openSettingsInDialog(webContents); + } + } + + /** + * Opens the settings in a bottom-sheet. + * + * @param tab The tab in which the bottomsheet is shown. + * @param showFullSheet Whether the bottomsheet should be shown fully, if false it's shown in a + * peeked state. + */ + public static void openSettingsInBottomSheet(@Nullable Tab tab, boolean showFullSheet) { + assert DomDistillerFeatures.sReaderModeDistillInApp.isEnabled(); + if (tab == null || tab.getWindowAndroid() == null) return; + + BottomSheetController bottomSheetController = + BottomSheetControllerProvider.from(tab.getWindowAndroid()); + if (bottomSheetController == null) return; + + ReaderModeBottomSheetCoordinator readerModeBottomSheetCoordinator = + new ReaderModeBottomSheetCoordinator( + tab.getContext(), tab.getProfile(), bottomSheetController); + readerModeBottomSheetCoordinator.show(showFullSheet); + } + + static void openSettingsInDialog(WebContents webContents) { Activity activity = ActivityUtils.getActivityFromWebContents(webContents); if (activity == null) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeBottomSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeBottomSheetCoordinator.java index f89b651..2a50c5d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeBottomSheetCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeBottomSheetCoordinator.java
@@ -67,10 +67,19 @@ mBottomSheetContent = new ReaderModeBottomSheetContent(mReaderModeBottomSheetView); } - /** Shows the reader mode bottom sheet. */ - public void show() { + /** + * Shows the reader mode bottom sheet. + * + * @param showFullSheet Whether the bottomsheet should be shown fully, if false it's shown in a + * peeked state. + */ + public void show(boolean showFullSheet) { mDestroyChecker.checkNotDestroyed(); - mBottomSheetController.requestShowContent(mBottomSheetContent, /* animate= */ true); + boolean success = + mBottomSheetController.requestShowContent(mBottomSheetContent, /* animate= */ true); + if (success && showFullSheet) { + mBottomSheetController.expandSheet(); + } } /** Destroys the coordinator. */ @@ -79,7 +88,7 @@ mChangeProcessor.destroy(); } - private static class ReaderModeBottomSheetContent implements BottomSheetContent { + private class ReaderModeBottomSheetContent implements BottomSheetContent { private final View mContentView; ReaderModeBottomSheetContent(View contentView) { @@ -103,7 +112,7 @@ @Override public void destroy() { - // Note: This bottom sheet can be hidden/shown multiple times without re-creation. + ReaderModeBottomSheetCoordinator.this.destroy(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java index 3b3e13ef..f98f2c4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -54,6 +54,9 @@ import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tab.TabUtils; import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant; +import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManagerProvider; import org.chromium.components.dom_distiller.core.DistilledPagePrefs; import org.chromium.components.dom_distiller.core.DomDistillerFeatures; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; @@ -666,7 +669,8 @@ } /** Navigate the current tab to a Reader Mode URL. */ - private void navigateToReaderMode() { + @VisibleForTesting + void navigateToReaderMode() { WebContents webContents = mTab.getWebContents(); if (webContents == null) return; @@ -688,7 +692,33 @@ browserControlsVisibilityManager.getBrowserVisibilityDelegate().showControlsTransient(); } - DomDistillerTabUtils.distillCurrentPageAndView(webContents); + DomDistillerTabUtils.distillCurrentPageAndViewIfSuccessful( + webContents, + (success) -> { + // If successful, or any of the dependencies needed to show a bottom sheet + // aren't available then return early. + if (success || mTab == null || mTab.getWindowAndroid() == null) { + return; + } + SnackbarManager snackbarManager = + SnackbarManagerProvider.from(mTab.getWindowAndroid()); + if (snackbarManager == null) { + return; + } + + snackbarManager.showSnackbar( + Snackbar.make( + mTab.getContext() + .getString( + R.string + .reader_mode_unavailable_snackbar_message), + new SnackbarManager.SnackbarController() {}, + Snackbar.TYPE_NOTIFICATION, + Snackbar.UMA_UNKNOWN) + .setAction( + mTab.getContext().getString(R.string.chrome_dismiss), + null)); + }); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonController.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonController.java index af2b420..7d13ab63 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonController.java
@@ -26,7 +26,6 @@ import org.chromium.chrome.browser.toolbar.optional_button.ButtonData; import org.chromium.chrome.browser.toolbar.optional_button.ButtonData.ButtonSpec; import org.chromium.chrome.browser.user_education.IphCommandBuilder; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.styles.SemanticColorUtils; import org.chromium.components.dom_distiller.core.DomDistillerFeatures; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; @@ -40,12 +39,10 @@ @NullMarked public class ReaderModeToolbarButtonController extends BaseButtonDataProvider { private final Context mContext; - private final ObservableSupplier<Profile> mProfileSupplier; private final ActivityTabProvider mActivityTabProvider; private final TabSupplierObserver mActivityTabObserver; private final ButtonSpec mEntryPointSpec; private final ButtonSpec mExitPointSpec; - private final BottomSheetController mBottomSheetController; // Created as needed. private @Nullable ReaderModeBottomSheetCoordinator mReaderModeBottomSheetCoordinator; // Only populated when the TabSupplierObserver events fire. @@ -66,8 +63,7 @@ Context context, ObservableSupplier<Profile> profileSupplier, ActivityTabProvider activityTabProvider, - ModalDialogManager modalDialogManager, - BottomSheetController bottomSheetController) { + ModalDialogManager modalDialogManager) { super( activityTabProvider, modalDialogManager, @@ -80,9 +76,7 @@ /* tooltipTextResId= */ Resources.ID_NULL); mContext = context; - mProfileSupplier = profileSupplier; mActivityTabProvider = activityTabProvider; - mBottomSheetController = bottomSheetController; mActivityTabObserver = new TabSupplierObserver(mActivityTabProvider) { @Override @@ -178,12 +172,7 @@ if (!DomDistillerFeatures.sReaderModeDistillInApp.isEnabled()) return; if (tab == null || !DomDistillerUrlUtils.isDistilledPage(tab.getUrl())) return; - if (mReaderModeBottomSheetCoordinator == null) { - mReaderModeBottomSheetCoordinator = - new ReaderModeBottomSheetCoordinator( - mContext, mProfileSupplier.get(), mBottomSheetController); - } - mReaderModeBottomSheetCoordinator.show(); + DomDistillerUiUtils.openSettingsInBottomSheet(tab, /* showFullSheet= */ false); } // Testing-specific functions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java index d12aa50c..22cd1109 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
@@ -89,6 +89,8 @@ // not in search mode when app filter is in effect. private boolean mShowSourceApp; + private boolean mIsLargeScreenWithKeyboard; + public HistoryAdapter( HistoryContentManager manager, HistoryProvider provider, @@ -102,6 +104,7 @@ mShowAppFilter = mManager.showAppFilter(); mShowSourceApp = mShowAppFilter; // defaults to BrApp full history mHistorySyncPromoCoordinator = historySyncPromoCoordinator; + mIsLargeScreenWithKeyboard = false; } /** Called when the activity/native page is destroyed. */ @@ -281,6 +284,11 @@ clear(true); mClearOnNextQueryComplete = false; } + + removeFooter(); + + loadItems(items); + boolean isEmpty = items.size() > 0 || mHistorySyncPromoVisible; if ((!mAreHeadersInitialized && isEmpty && !mIsSearching) || (mIsSearching && mShowAppFilter)) { @@ -288,10 +296,6 @@ mAreHeadersInitialized = true; } - removeFooter(); - - loadItems(items); - mIsLoadingItems = false; mHasMorePotentialItems = hasMorePotentialMatches; @@ -527,6 +531,10 @@ /** Pass header items to {@link #setHeaders(HeaderItem...)} as parameters. */ private void setHeaders() { + if (mIsLargeScreenWithKeyboard) { + setLFFHeaders(); + return; + } ArrayList<HeaderItem> args = new ArrayList<>(); if (mIsSearching) { // Query for apps could be still pending. |setHeaders()| will be invoked @@ -549,6 +557,27 @@ setHeaders(args.toArray(new HeaderItem[args.size()])); } + /** For LFF devices w/ physical keyboard attached, there's only search mode. */ + private void setLFFHeaders() { + ArrayList<HeaderItem> args = new ArrayList<>(); + if (mShowAppFilter && mManager.hasFilterList()) args.add(mAppFilterHeaderItem); + if (isNormalContentAvailable()) { + if (mPrivacyDisclaimersVisible) { + args.add(mPrivacyDisclaimerHeaderItem); + } + if (mClearBrowsingDataButtonVisible) { + args.add(mClearBrowsingDataButtonHeaderItem); + } + } + if (mManager.launchedForApp()) { + args.add(mHistoryOpenInChromeHeaderItem); + } + if (mHistorySyncPromoVisible) { + args.add(mHistorySyncPromoHeaderItem); + } + setHeaders(args.toArray(new HeaderItem[args.size()])); + } + /** * @return True if any privacy disclaimer should be visible, false otherwise. */ @@ -607,6 +636,10 @@ mAppId = appId; } + public void setIsLargeScreenWithKeyboard(boolean isLargeScreenWithKeyboard) { + mIsLargeScreenWithKeyboard = isLargeScreenWithKeyboard; + } + void updateHistorySyncPromoVisibility() { if (mHistorySyncPromoCoordinator == null) { return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java index 8620d4b..38107b64 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -55,6 +55,8 @@ import org.chromium.components.search_engines.TemplateUrl; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.ui.base.Clipboard; +import org.chromium.ui.base.DeviceFormFactor; +import org.chromium.ui.base.DeviceInput; import java.util.List; import java.util.function.Function; @@ -271,6 +273,15 @@ onBackPressStateChanged(); // Initialize back press State. mContentManager.maybeQueryApps(); + + boolean isLargeScreenWithKeyboard = + DeviceInput.supportsKeyboard() + && DeviceFormFactor.isNonMultiDisplayContextOnTablet(mActivity); + mToolbar.setIsLargeScreenWithKeyboard(isLargeScreenWithKeyboard); + mContentManager.getAdapter().setIsLargeScreenWithKeyboard(isLargeScreenWithKeyboard); + if (isLargeScreenWithKeyboard) { + enterSearchMode(); + } } private void initializeEmptyView() { @@ -352,15 +363,7 @@ return true; } else if (item.getItemId() == R.id.search_menu_id) { - mContentManager.maybeResetAppFilterChip(); - mContentManager.getAdapter().onSearchStart(); - mToolbar.showSearchView(true); - String searchEmptyString = getSearchEmptyString(); - mSelectableListLayout.onStartSearch( - searchEmptyString, - R.string.history_manager_empty_state_view_or_open_more_history); - mUmaRecorder.recordSearchHistory(); - mIsSearching = true; + enterSearchMode(); return true; } else if (item.getItemId() == R.id.info_menu_id) { toggleInfoHeaderVisibility(); @@ -368,6 +371,21 @@ return false; } + private void enterSearchMode() { + assumeNonNull(mContentManager); + assumeNonNull(mToolbar); + assumeNonNull(mSelectableListLayout); + + mContentManager.maybeResetAppFilterChip(); + mContentManager.getAdapter().onSearchStart(); + mToolbar.showSearchView(true); + String searchEmptyString = getSearchEmptyString(); + mSelectableListLayout.onStartSearch( + searchEmptyString, R.string.history_manager_empty_state_view_or_open_more_history); + mUmaRecorder.recordSearchHistory(); + mIsSearching = true; + } + private void toggleInfoHeaderVisibility() { assumeNonNull(mToolbar); assumeNonNull(mContentManager);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorMetricsDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorMetricsDelegate.java index d2b2fa6..5eb34dc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorMetricsDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorMetricsDelegate.java
@@ -276,11 +276,6 @@ private void recordShownDurationHistograms() { RecordHistogram.recordLongTimesHistogram100( OFFLINE_INDICATOR_SHOWN_DURATION_V2, mTimeInForegroundMs + mTimeInBackgroundMs); - - if (!ChromeSharedPreferences.getInstance() - .contains(ChromePreferenceKeys.OFFLINE_INDICATOR_V2_TIME_IN_BACKGROUND_MS)) { - assert mNumTimesBackgrounded == 0; - } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java index 354abdb..e07fb61 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
@@ -403,12 +403,6 @@ } @Override - public boolean shouldShowPrivacySandboxRwsUi() { - return ChromeFeatureList.isEnabled( - ChromeFeatureList.PRIVACY_SANDBOX_RELATED_WEBSITE_SETS_UI); - } - - @Override public void getBrowsingDataModel(Callback<BrowsingDataModel> callback) { BrowsingDataBridge.buildBrowsingDataModelFromDisk( mProfile,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCollectionTabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCollectionTabModelImpl.java index b21754f..4c3b4f0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCollectionTabModelImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabCollectionTabModelImpl.java
@@ -588,6 +588,14 @@ return mMultiSelectedTabs.isEmpty() ? 1 : mMultiSelectedTabs.size(); } + @Override + public int findFirstNonPinnedTabIndex() { + assertOnUiThread(); + if (mNativeTabCollectionTabModelImplPtr == 0) return 0; + return TabCollectionTabModelImplJni.get() + .getIndexOfFirstNonPinnedTab(mNativeTabCollectionTabModelImplPtr); + } + // TabCloser overrides. @Override @@ -1957,5 +1965,7 @@ @JniType("TabAndroid*") Tab getLastShownTabForGroup( long nativeTabCollectionTabModelImpl, @JniType("base::Token") Token tabGroupId); + + int getIndexOfFirstNonPinnedTab(long nativeTabCollectionTabModelImpl); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java index 4214da10..ccbf172 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
@@ -87,7 +87,6 @@ private boolean mActive; private boolean mInitializationComplete; - private final PinnedTabReorderManager mPinnedTabReorderManager = new PinnedTabReorderManager(); // Undo State Tracking ------------------------------------------------------------------------- @@ -160,36 +159,6 @@ } } - /** Manages the order of pinned tabs in the tab model. */ - private class PinnedTabReorderManager { - /** - * Returns the index of the first non-pinned tab in the model. - * - * @return The index of the first non-pinned tab, or {@link TabModel#INVALID_TAB_INDEX} if - * all tabs are pinned or the model is empty. - */ - int findFirstNonPinnedTabIndex() { - int low = 0; - int high = mTabs.size() - 1; - int firstNonPinnedIndex = INVALID_TAB_INDEX; - - while (low <= high) { - int mid = low + (high - low) / 2; - Tab tab = mTabs.get(mid); - if (tab.getIsPinned()) { - // The first non-pinned tab must be after this index. - low = mid + 1; - } else { - // This might be the first non-pinned tab, but there might be an earlier one. - firstNonPinnedIndex = mid; - high = mid - 1; - } - } - - return firstNonPinnedIndex; - } - } - public TabModelImpl( Profile profile, @ActivityType int activityType, @@ -324,7 +293,7 @@ index = mOrderController.determineInsertionIndex(type, index, tab); if (tab.getIsPinned()) { - int firstNonPinnedTabIndex = mPinnedTabReorderManager.findFirstNonPinnedTabIndex(); + int firstNonPinnedTabIndex = findFirstNonPinnedTabIndex(); if (firstNonPinnedTabIndex == INVALID_TAB_INDEX) { // All tabs are pinned or the model is empty, next valid non-pinned index is at // the end of the list. @@ -419,8 +388,8 @@ @Override public void pinTab(int tabId) { - int availableIndex = mPinnedTabReorderManager.findFirstNonPinnedTabIndex(); - if (availableIndex == INVALID_TAB_INDEX) return; + int availableIndex = findFirstNonPinnedTabIndex(); + if (availableIndex == mTabs.size()) return; Tab tab = getTabById(tabId); if (tab == null) return; @@ -434,10 +403,8 @@ @Override public void unpinTab(int tabId) { - int nextAvailableIndex = mPinnedTabReorderManager.findFirstNonPinnedTabIndex(); - if (nextAvailableIndex == INVALID_TAB_INDEX) { - nextAvailableIndex = mTabs.size(); - } + int nextAvailableIndex = findFirstNonPinnedTabIndex(); + Tab tab = getTabById(tabId); if (tab == null) return; @@ -551,18 +518,18 @@ allowUndo &= supportsPendingClosures(); startTabClosure(tabToClose, recommendedNextTab, uponExit, allowUndo, tabCloseType); + List<Tab> tabsToClose = Collections.singletonList(tabToClose); if (notifyPending && allowUndo) { assumeNonNull(mPendingTabClosureManager); - mPendingTabClosureManager.addTabClosureEvent( - Collections.singletonList(tabToClose), undoRunnable); + mPendingTabClosureManager.addTabClosureEvent(tabsToClose, undoRunnable); for (TabModelObserver obs : mObservers) { - obs.tabPendingClosure(tabToClose, tabClosingSource); + obs.onTabClosePending(tabsToClose, /* isAllTabs= */ false, tabClosingSource); } } if (!allowUndo) { if (tabCloseType == TabCloseType.SINGLE) { notifyOnFinishingMultipleTabClosure( - Collections.singletonList(tabToClose), /* saveToTabRestoreService= */ true); + tabsToClose, /* saveToTabRestoreService= */ true); } finalizeTabClosure( tabToClose, /* notifyTabClosureCommitted= */ false, tabClosingSource); @@ -608,7 +575,7 @@ assumeNonNull(mPendingTabClosureManager); mPendingTabClosureManager.addTabClosureEvent(tabs, undoRunnable); for (TabModelObserver obs : mObservers) { - obs.multipleTabsPendingClosure(tabs, false, tabClosingSource); + obs.onTabClosePending(tabs, false, tabClosingSource); } } } @@ -674,7 +641,7 @@ if (supportsPendingClosures()) { mPendingTabClosureManager.addTabClosureEvent(closedTabs, undoRunnable); for (TabModelObserver obs : mObservers) { - obs.multipleTabsPendingClosure(closedTabs, true, tabClosingSource); + obs.onTabClosePending(closedTabs, true, tabClosingSource); } } } @@ -1117,4 +1084,27 @@ // considered selected. return mMultiSelectedTabs.isEmpty() ? 1 : mMultiSelectedTabs.size(); } + + @Override + public int findFirstNonPinnedTabIndex() { + int low = 0; + int high = getCount() - 1; + int firstNonPinnedIndex = getCount(); + + while (low <= high) { + int mid = low + (high - low) / 2; + Tab tab = getTabAt(mid); + assumeNonNull(tab); + if (tab.getIsPinned()) { + // The first non-pinned tab must be after this index. + low = mid + 1; + } else { + // This might be the first non-pinned tab, but there might be an earlier one. + firstNonPinnedIndex = mid; + high = mid - 1; + } + } + + return firstNonPinnedIndex; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java index 9af594a8..95ce611 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.tabmodel; import org.jni_zero.CalledByNative; +import org.jni_zero.JniType; import org.jni_zero.NativeMethods; import org.chromium.build.annotations.NullMarked; @@ -99,14 +100,6 @@ } @Override - public final void tabPendingClosure(Tab tab, @TabClosingSource int source) { - assert mNativeTabModelObserverJniBridge != 0; - assert tab.isInitialized(); - TabModelObserverJniBridgeJni.get() - .tabPendingClosure(mNativeTabModelObserverJniBridge, tab, source); - } - - @Override public final void tabClosureUndone(Tab tab) { assert mNativeTabModelObserverJniBridge != 0; assert tab.isInitialized(); @@ -122,13 +115,13 @@ } @Override - public final void multipleTabsPendingClosure( + public final void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) { // Convert the List to an array of objects. This makes the corresponding C++ code much // easier. assert mNativeTabModelObserverJniBridge != 0; TabModelObserverJniBridgeJni.get() - .allTabsPendingClosure(mNativeTabModelObserverJniBridge, tabs.toArray(new Tab[0])); + .onTabClosePending(mNativeTabModelObserverJniBridge, tabs, closingSource); } @Override @@ -207,16 +200,16 @@ void didMoveTab(long nativeTabModelObserverJniBridge, Tab tab, int newIndex, int curIndex); - void tabPendingClosure( - long nativeTabModelObserverJniBridge, Tab tab, @TabClosingSource int source); - void tabClosureUndone(long nativeTabModelObserverJniBridge, Tab tab); void onTabCloseUndone(long nativeTabModelObserverJniBridge, Tab[] tab); void tabClosureCommitted(long nativeTabModelObserverJniBridge, Tab tab); - void allTabsPendingClosure(long nativeTabModelObserverJniBridge, Tab[] tabs); + void onTabClosePending( + long nativeTabModelObserverJniBridge, + @JniType("std::vector<TabAndroid*>") List<Tab> tabs, + int source); void allTabsClosureCommitted(long nativeTabModelObserverJniBridge);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index a297563c..4b52337 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -1005,8 +1005,7 @@ mActivityTabProvider, mTabModelSelectorSupplier, browsingModeThemeColorProvider, - mIncognitoStateProvider, - profileSupplier); + mIncognitoStateProvider); } NavigationPopup.HistoryDelegate historyDelegate =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/AdaptiveToolbarUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/AdaptiveToolbarUiCoordinator.java index ea2ba70..0b6f846 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/AdaptiveToolbarUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/AdaptiveToolbarUiCoordinator.java
@@ -149,8 +149,7 @@ mContext, mProfileSupplier, mActivityTabProvider, - mModalDialogManagerSupplier.get(), - mBottomSheetController); + mModalDialogManagerSupplier.get()); ReadAloudToolbarButtonController readAloudButtonController = new ReadAloudToolbarButtonController( mContext,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/undo_tab_close_snackbar/TabUndoBarController.java b/chrome/android/java/src/org/chromium/chrome/browser/undo_tab_close_snackbar/TabUndoBarController.java index 2294933..0f570cfc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/undo_tab_close_snackbar/TabUndoBarController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/undo_tab_close_snackbar/TabUndoBarController.java
@@ -36,8 +36,8 @@ /** * A controller that listens to and visually represents cancelable tab closures. * - * <p>Each time a tab is undoably closed via {@link TabModelObserver#tabPendingClosure(Tab)}, this - * controller saves that tab id and title to the stack of SnackbarManager. It will then let + * <p>Each time a tab is undoably closed via {@link TabModelObserver#onTabClosurePending()},' this + * controller saves the tab ids and title to the stack of SnackbarManager. It will then let * SnackbarManager to show a snackbar representing the top entry in of stack. Each added entry * resets the timeout that tracks when to commit the undoable actions. * @@ -88,12 +88,6 @@ } @Override - public void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) { - if (disableUndo(true)) return; - queueUndoBar(new TabClosureEvent(List.of(tab), /* isAllTabs= */ false)); - } - - @Override public void tabClosureUndone(Tab tab) { if (disableUndo(false)) return; dropFromQueue(List.of(tab)); @@ -121,7 +115,7 @@ } @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) {
diff --git a/chrome/android/javatests/BUILD.gn b/chrome/android/javatests/BUILD.gn index 1663224c..2bfb297f 100644 --- a/chrome/android/javatests/BUILD.gn +++ b/chrome/android/javatests/BUILD.gn
@@ -13,7 +13,6 @@ # Contain all source code that is used by tests in a different package. android_library("chrome_test_java_helper") { sources = [ - "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherSearchTestUtils.java", "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedV2TestHelper.java", "//chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/TestFeedServer.java", "src/org/chromium/chrome/browser/MockSafeBrowsingApiHandler.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java index d6f9fe00..6f61276 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
@@ -1070,11 +1070,10 @@ lastHoveredTab = stripLayoutHelperManager.getActiveStripLayoutHelper().getLastHoveredTab(); Assert.assertEquals("The last hovered tab is not set correctly.", tab2, lastHoveredTab); Assert.assertFalse("|mFolioAttached| for tab2 should be false.", tab2.getFolioAttached()); - Assert.assertTrue("|mFolioAttached| for tab1 should be true.", tab1.getFolioAttached()); Assert.assertEquals( - "tab1 container bottom margin should match.", - StripLayoutTabDelegate.FOLIO_ATTACHED_BOTTOM_MARGIN_DP, - tab1.getBottomMargin(), + "tab2 container bottom margin should match.", + StripLayoutTabDelegate.FOLIO_DETACHED_BOTTOM_MARGIN_DP, + tab2.getBottomMargin(), 0.f); // Simulate a subsequent hover outside tab2. @@ -1086,7 +1085,6 @@ MotionEvent.ACTION_HOVER_EXIT, xExit, yExit)); lastHoveredTab = stripLayoutHelperManager.getActiveStripLayoutHelper().getLastHoveredTab(); Assert.assertNull("The last hovered tab is not set correctly.", lastHoveredTab); - Assert.assertTrue("|mFolioAttached| for tab2 should be true.", tab2.getFolioAttached()); } /** Tests hover cards shown in standard as well as incognito tab models. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java index 3cf8b3a5..6d181c6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -325,6 +325,9 @@ @Feature({"Browser"}) @RequiresRestart public void testLongPressOnImage() throws TimeoutException { + doAnswer(sCopyIsAllowedByPolicy) + .when(mDataProtectionBridgeMock) + .verifyGenericCopyImageActionIsAllowedByPolicy(anyString(), any(), any()); checkOpenImageInNewTab("testImage", "/chrome/test/data/android/contextmenu/test_image.png"); } @@ -403,6 +406,9 @@ @MediumTest @Feature({"Browser"}) public void testLongPressOnImageLink() throws TimeoutException { + doAnswer(sCopyIsAllowedByPolicy) + .when(mDataProtectionBridgeMock) + .verifyGenericCopyImageActionIsAllowedByPolicy(anyString(), any(), any()); checkOpenImageInNewTab( "testImageLink", "/chrome/test/data/android/contextmenu/test_image.png"); } @@ -674,6 +680,9 @@ @Test @MediumTest public void testCopyEmailAddress() throws Throwable { + doAnswer(sCopyIsAllowedByPolicy) + .when(mDataProtectionBridgeMock) + .verifyCopyTextIsAllowedByPolicy(anyString(), any(), any()); Tab tab = sDownloadTestRule.getActivityTab(); // Allow all thread policies temporarily in main thread to avoid // DiskWrite and UnBufferedIo violations during copying under @@ -697,6 +706,9 @@ @Test @MediumTest public void testCopyTelNumber() throws Throwable { + doAnswer(sCopyIsAllowedByPolicy) + .when(mDataProtectionBridgeMock) + .verifyCopyTextIsAllowedByPolicy(anyString(), any(), any()); Tab tab = sDownloadTestRule.getActivityTab(); // Allow DiskWrites temporarily in main thread to avoid // violation during copying under emulator environment.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryPaneTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryPaneTest.java index 3a3f283..d530498 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryPaneTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/HistoryPaneTest.java
@@ -6,6 +6,7 @@ import static org.chromium.base.ThreadUtils.runOnUiThreadBlocking; +import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.MediumTest; import org.junit.Before; @@ -31,6 +32,10 @@ import org.chromium.chrome.test.transit.hub.HistoryPaneStation.HistoryWithEntriesFacility; import org.chromium.chrome.test.transit.hub.RegularTabSwitcherStation; import org.chromium.chrome.test.transit.page.WebPageStation; +import org.chromium.ui.base.DeviceFormFactor; +import org.chromium.ui.base.DeviceInput; + +import java.util.concurrent.atomic.AtomicBoolean; /** Public transit tests for the Hub's history pane. */ @RunWith(ChromeJUnit4ClassRunner.class) @@ -43,20 +48,30 @@ ChromeTransitTestRules.autoResetCtaActivityRule(); private WebPageStation mStartingPage; + private boolean mIsLLFDevice; @Before public void setUp() { mStartingPage = mCtaTestRule.startOnBlankPage(); ChromeTabbedActivity cta = mCtaTestRule.getActivity(); + final AtomicBoolean supportsKeyboard = new AtomicBoolean(); + final AtomicBoolean isTablet = new AtomicBoolean(); runOnUiThreadBlocking( - () -> clearHistory(cta.getProfileProviderSupplier().get().getOriginalProfile())); + () -> { + clearHistory(cta.getProfileProviderSupplier().get().getOriginalProfile()); + supportsKeyboard.set(DeviceInput.supportsKeyboard()); + isTablet.set( + DeviceFormFactor.isNonMultiDisplayContextOnTablet( + ApplicationProvider.getApplicationContext())); + }); + mIsLLFDevice = supportsKeyboard.get() && isTablet.get(); } @Test @MediumTest public void testEmptyView() { RegularTabSwitcherStation tabSwitcher = mStartingPage.openRegularTabSwitcher(); - tabSwitcher.selectHistoryPane().expectEmptyState(); + tabSwitcher.selectHistoryPane().expectEmptyState(mIsLLFDevice); } @Test @@ -71,7 +86,8 @@ .loadWebPageProgrammatically(urlOne) .loadWebPageProgrammatically(urlTwo) .openRegularTabSwitcher(); - HistoryWithEntriesFacility history = tabSwitcher.selectHistoryPane().expectEntries(); + HistoryWithEntriesFacility history = + tabSwitcher.selectHistoryPane().expectEntries(mIsLLFDevice); history.expectEntry("One"); history.expectEntry("Two"); } @@ -89,12 +105,12 @@ .loadWebPageProgrammatically(urlTwo) .openRegularTabSwitcher(); HistoryPaneStation historyPaneStation = tabSwitcher.selectHistoryPane(); - HistoryWithEntriesFacility history = historyPaneStation.expectEntries(); + HistoryWithEntriesFacility history = historyPaneStation.expectEntries(mIsLLFDevice); history.expectEntry("One"); history.expectEntry("Two"); // Search for "One" in the history search box. - HistorySearchFacility search = history.openSearch(); + HistorySearchFacility search = history.openSearch(mIsLLFDevice); search.typeSearchTerm("One"); // Verify that "One" is displayed as a match. @@ -114,7 +130,7 @@ .loadWebPageProgrammatically(urlOne) .loadWebPageProgrammatically(urlTwo); HistoryWithEntriesFacility history = - page.openRegularTabSwitcher().selectHistoryPane().expectEntries(); + page.openRegularTabSwitcher().selectHistoryPane().expectEntries(mIsLLFDevice); history.expectEntry("One").selectToOpenWebPage(page, urlOne); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxActionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxActionsTest.java index 2a076f7e..be2ade3a4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxActionsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxActionsTest.java
@@ -37,8 +37,8 @@ import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatchBuilder; import org.chromium.components.omnibox.AutocompleteResult; -import org.chromium.components.omnibox.SuggestTemplateInfoProto.SuggestTemplateInfo.TemplateAction; import org.chromium.components.omnibox.OmniboxSuggestionType; +import org.chromium.components.omnibox.SuggestTemplateInfoProto.SuggestTemplateInfo.TemplateAction; import org.chromium.components.omnibox.action.OmniboxAction; import org.chromium.components.omnibox.action.OmniboxActionJni; @@ -123,7 +123,8 @@ "hint", "accessibility", type.getNumber(), - "https://www.google.com")); + "https://www.google.com", + /* showAsActionButton= */ false)); } return createFakeSuggestion(actions);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/AllSiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/AllSiteSettingsTest.java index b4461c0d..ce5aacb 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/AllSiteSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/AllSiteSettingsTest.java
@@ -30,8 +30,6 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.permissions.PermissionTestRule; import org.chromium.chrome.browser.profiles.ProfileManager; @@ -52,7 +50,6 @@ @RunWith(ChromeJUnit4ClassRunner.class) @Batch(AllSiteSettingsTest.TEST_BATCH_NAME) @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) -@EnableFeatures({ChromeFeatureList.PRIVACY_SANDBOX_RELATED_WEBSITE_SETS_UI}) public class AllSiteSettingsTest { public static final String TEST_BATCH_NAME = "AllSiteSettingsTest"; private static final String A_GITHUB_IO = "a.github.io";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SingleWebsiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SingleWebsiteSettingsTest.java index 28e79dd..95728fa2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SingleWebsiteSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SingleWebsiteSettingsTest.java
@@ -37,8 +37,6 @@ import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.browser.settings.SettingsActivity; @@ -68,7 +66,6 @@ @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) @Batch(SingleWebsiteSettingsTest.TEST_BATCH_NAME) -@EnableFeatures({ChromeFeatureList.PRIVACY_SANDBOX_RELATED_WEBSITE_SETS_UI}) public class SingleWebsiteSettingsTest { private static final String EXAMPLE_ADDRESS = "https://example.com";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java index c0860b81..5e1ac8d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
@@ -11,7 +11,6 @@ import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.matches; import static androidx.test.espresso.matcher.PreferenceMatchers.withKey; -import static androidx.test.espresso.matcher.RootMatchers.isDialog; import static androidx.test.espresso.matcher.RootMatchers.withDecorView; import static androidx.test.espresso.matcher.ViewMatchers.assertThat; import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; @@ -24,7 +23,6 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.emptyIterable; @@ -175,7 +173,6 @@ "ignore-certificate-errors" }) @EnableFeatures({ - ChromeFeatureList.PRIVACY_SANDBOX_RELATED_WEBSITE_SETS_UI, DeviceFeatureList.BLUETOOTH_RFCOMM_ANDROID, ChromeFeatureList.DISPLAY_WILDCARD_CONTENT_SETTINGS }) @@ -469,20 +466,6 @@ return new WebsiteGroup(origin1.getAddress().getOrigin(), Arrays.asList(origin1, origin2)); } - private Website getRwsOwnerSiteForUrls(String url1, String url2) { - Website origin1 = new Website(WebsiteAddress.create(url1), null); - Website origin2 = new Website(WebsiteAddress.create(url2), null); - createAndSetRwsCookieInfo(origin1, List.of(origin1, origin2)); - return origin1; - } - - private WebsiteGroup getRwsSiteGroupForUrls(String url1, String url2) { - Website origin1 = new Website(WebsiteAddress.create(url1), null); - Website origin2 = new Website(WebsiteAddress.create(url2), null); - createAndSetRwsCookieInfo(origin1, List.of(origin1, origin2)); - return new WebsiteGroup(origin1.getAddress().getOrigin(), Arrays.asList(origin1, origin2)); - } - /** Sets Allow Location Enabled to be true and make sure it is set correctly. */ @Test @SmallTest @@ -1054,106 +1037,6 @@ Assert.assertEquals("\"\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); } - /** Tests clearing cookies for the RWS group from SingleWebsiteSettings. */ - @Test - @SmallTest - @Feature({"Preferences"}) - public void clearCookiesForRwsOwner() throws Exception { - final String url1 = - mPermissionRule.getURLWithHostName( - "one.example.com", "/chrome/test/data/android/cookie.html"); - final String url2 = - mPermissionRule.getURLWithHostName( - "two.example.com", "/chrome/test/data/android/cookie.html"); - Website rwsOwner = getRwsOwnerSiteForUrls(url1, url2); - - mPermissionRule.loadUrl(url1); - Assert.assertEquals("\"\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - mPermissionRule.runJavaScriptCodeInCurrentTab("setCookie(\".example.com\")"); - mPermissionRule.runJavaScriptCodeInCurrentTab("setCookie(\".one.example.com\")"); - Assert.assertEquals( - "\"Foo=Bar; Foo=Bar\"", - mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - - mPermissionRule.loadUrl(url2); - Assert.assertEquals( - "\"Foo=Bar\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - mPermissionRule.runJavaScriptCodeInCurrentTab("setCookie(\".two.example.com\")"); - Assert.assertEquals( - "\"Foo=Bar; Foo=Bar\"", - mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - - HistogramWatcher histogramExpectation = - HistogramWatcher.newSingleRecordWatcher( - "Privacy.DeleteBrowsingData.Action", - DeleteBrowsingDataAction.RWS_DELETE_ALL_DATA); - - resetRwsGroupOnSingleWebsiteSettings(rwsOwner); - - // Load the page again and ensure the cookie is gone. - mPermissionRule.loadUrl(url1); - Assert.assertEquals("\"\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - mPermissionRule.loadUrl(url2); - Assert.assertEquals("\"\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - histogramExpectation.assertExpected(); - } - - /** Tests clearing cookies for the RWS group from GroupedWebsiteSettings. */ - @Test - @SmallTest - @Feature({"Preferences"}) - public void clearCookiesForRwsGroup() throws Exception { - final String url1 = - mPermissionRule.getURLWithHostName( - "one.example.com", "/chrome/test/data/android/cookie.html"); - final String url2 = - mPermissionRule.getURLWithHostName( - "two.example.com", "/chrome/test/data/android/cookie.html"); - final String url3 = - mPermissionRule.getURLWithHostName( - "foo.com", "/chrome/test/data/android/cookie.html"); - WebsiteGroup rwsGroup = getRwsSiteGroupForUrls(url1, url2); - - mPermissionRule.loadUrl(url1); - Assert.assertEquals("\"\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - mPermissionRule.runJavaScriptCodeInCurrentTab("setCookie(\".example.com\")"); - mPermissionRule.runJavaScriptCodeInCurrentTab("setCookie(\".one.example.com\")"); - Assert.assertEquals( - "\"Foo=Bar; Foo=Bar\"", - mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - - mPermissionRule.loadUrl(url2); - Assert.assertEquals( - "\"Foo=Bar\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - mPermissionRule.runJavaScriptCodeInCurrentTab("setCookie(\".two.example.com\")"); - Assert.assertEquals( - "\"Foo=Bar; Foo=Bar\"", - mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - - mPermissionRule.loadUrl(url3); - Assert.assertEquals("\"\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - mPermissionRule.runJavaScriptCodeInCurrentTab("setCookie(\".foo.com\")"); - Assert.assertEquals( - "\"Foo=Bar\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - - HistogramWatcher histogramExpectation = - HistogramWatcher.newSingleRecordWatcher( - "Privacy.DeleteBrowsingData.Action", - DeleteBrowsingDataAction.RWS_DELETE_ALL_DATA); - - resetRwsGroupOnGroupedWebsiteSettings(rwsGroup); - - // 1 and 2 got cleared; 3 stays intact. - mPermissionRule.loadUrl(url1); - Assert.assertEquals("\"\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - mPermissionRule.loadUrl(url2); - Assert.assertEquals("\"\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - mPermissionRule.loadUrl(url3); - Assert.assertEquals( - "\"Foo=Bar\"", mPermissionRule.runJavaScriptCodeInCurrentTab("getCookie()")); - histogramExpectation.assertExpected(); - } - /** * Set the cookie content setting to allow through policy and ensure the correct radio buttons * are enabled. @@ -1432,30 +1315,6 @@ settingsActivity.finish(); } - private void resetRwsGroupOnSingleWebsiteSettings(Website website) { - final SettingsActivity settingsActivity = - SiteSettingsTestUtils.startSingleWebsitePreferences(website); - ThreadUtils.runOnUiThreadBlocking( - () -> { - SingleWebsiteSettings websitePreferences = - (SingleWebsiteSettings) settingsActivity.getMainFragment(); - websitePreferences.resetRwsData(); - }); - settingsActivity.finish(); - } - - private void resetRwsGroupOnGroupedWebsiteSettings(WebsiteGroup group) { - final SettingsActivity settingsActivity = - SiteSettingsTestUtils.startGroupedWebsitesPreferences(group); - ThreadUtils.runOnUiThreadBlocking( - () -> { - GroupedWebsitesSettings websitePreferences = - (GroupedWebsitesSettings) settingsActivity.getMainFragment(); - websitePreferences.resetRwsData(); - }); - settingsActivity.finish(); - } - /** Sets Allow Popups Enabled to be false and make sure it is set correctly. */ @Test @SmallTest @@ -4188,24 +4047,6 @@ renderSettingsPage(settingsActivity, name); } - private void renderClearDataDialogView(SettingsActivity settingsActivity, String name) - throws IOException { - onView(withId(R.id.clear_reset_dialog)) - .inRoot(isDialog()) - .check( - (view, noMatchException) -> { - if (noMatchException != null) throw noMatchException; - try { - ChromeRenderTestRule.sanitize(view); - mRenderTestRule.render(view, name); - } catch (IOException e) { - assert false : "Render test failed due to " + e; - } - }); - onView(withText(R.string.cancel)).inRoot(isDialog()).perform(click()); - settingsActivity.finish(); - } - @Test @SmallTest @Feature({"RenderTest"}) @@ -4242,172 +4083,7 @@ createStorageAccessExceptions(); final SettingsActivity settingsActivity = SiteSettingsTestUtils.startGroupedWebsitesPreferences(getRwsSiteGroup()); - renderSettingsPage(settingsActivity, "site_settings_rws_grouped_website_settings"); - } - - @Test - @SmallTest - @Feature({"RenderTest"}) - public void renderRwsSingleWebsiteSettingsDeleteAllDataDialog() throws Exception { - final SettingsActivity settingsActivity = - SiteSettingsTestUtils.startSingleWebsitePreferences(getRwsOwnerSite()); - - onView(withText(R.string.site_settings_rws_delete_button_label)) - .check(matches(isDisplayed())) - .perform(click()); - onView(withText(R.string.site_settings_delete_rws_storage_dialog_title)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - onView(withText(R.string.site_settings_delete_rws_storage_sign_out)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - onView(withText(R.string.webstorage_delete_data_dialog_offline_message)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - onView(withText(R.string.storage_delete_dialog_clear_storage_option)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - - renderClearDataDialogView( - settingsActivity, "site_settings_rws_single_website_delete_dialog"); - } - - @Test - @SmallTest - @Feature({"RenderTest"}) - public void renderRwsGroupedWebsiteSettingsDeleteAllDataDialog() throws Exception { - final SettingsActivity settingsActivity = - SiteSettingsTestUtils.startGroupedWebsitesPreferences(getRwsSiteGroup()); - - onView(withText(R.string.site_settings_rws_delete_button_label)) - .check(matches(isDisplayed())) - .perform(click()); - onView(withText(R.string.site_settings_delete_rws_storage_dialog_title)) - .check(matches(isDisplayed())); - onView(withText(R.string.site_settings_delete_rws_storage_sign_out)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - onView(withText(R.string.webstorage_delete_data_dialog_offline_message)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - onView(withText(R.string.storage_delete_dialog_clear_storage_option)) - .inRoot(isDialog()) - .check(matches(isDisplayed())); - - renderClearDataDialogView( - settingsActivity, "site_settings_rws_grouped_website_settings_delete_dialog"); - } - - @Test - @SmallTest - public void deleteSingleSiteDataRemovesRowSingleWebsiteSettings() throws Exception { - final String currentSiteUrl = "one-test.com"; - final String rwsMemberUrl = "two-test.com"; - SiteSettingsTestUtils.startSingleWebsitePreferences( - getRwsOwnerSiteForUrls(currentSiteUrl, rwsMemberUrl)); - - onView( - allOf( - withText(currentSiteUrl), - isDescendantOfA(withId(SingleWebsiteSettings.RWS_ROW_ID)))) - .check(matches(isDisplayed())); - onView( - allOf( - withText(rwsMemberUrl), - isDescendantOfA(withId(SingleWebsiteSettings.RWS_ROW_ID)))) - .check(matches(isDisplayed())); - - onView( - allOf( - withId(R.id.image_view_widget), - isDescendantOfA(withId(SingleWebsiteSettings.RWS_ROW_ID)), - withContentDescription(containsString(rwsMemberUrl)))) - .check(matches(isDisplayed())) - .perform(click()); - onView(withText(R.string.website_reset_confirmation)).check(matches(isDisplayed())); - onView(withText(R.string.website_reset)) - .inRoot(isDialog()) - .check(matches(isDisplayed())) - .perform(click()); - onView( - allOf( - withText(rwsMemberUrl), - isDescendantOfA(withId(SingleWebsiteSettings.RWS_ROW_ID)))) - .check(doesNotExist()); - onView( - allOf( - withText(currentSiteUrl), - isDescendantOfA(withId(SingleWebsiteSettings.RWS_ROW_ID)))) - .check(matches(isDisplayed())); - } - - @Test - @SmallTest - public void deleteSingleSiteDataRemovesRowGroupedWebsiteSettings() throws Exception { - final String currentSiteUrl = "one-test.com"; - final String rwsMemberUrl = "two-test.com"; - - SiteSettingsTestUtils.startGroupedWebsitesPreferences( - getRwsSiteGroupForUrls(currentSiteUrl, rwsMemberUrl)); - - onView( - allOf( - withText(currentSiteUrl), - isDescendantOfA(withId(GroupedWebsitesSettings.RWS_ROW_ID)))) - .check(matches(isDisplayed())); - onView( - allOf( - withText(rwsMemberUrl), - isDescendantOfA(withId(GroupedWebsitesSettings.RWS_ROW_ID)))) - .check(matches(isDisplayed())); - - onView( - allOf( - withId(R.id.image_view_widget), - isDescendantOfA(withId(GroupedWebsitesSettings.RWS_ROW_ID)), - withContentDescription(containsString(rwsMemberUrl)))) - .check(matches(isDisplayed())) - .perform(click()); - onView(withText(R.string.website_reset_confirmation)).check(matches(isDisplayed())); - onView(withText(R.string.website_reset)) - .inRoot(isDialog()) - .check(matches(isDisplayed())) - .perform(click()); - onView( - allOf( - withText(rwsMemberUrl), - isDescendantOfA(withId(GroupedWebsitesSettings.RWS_ROW_ID)))) - .check(doesNotExist()); - onView( - allOf( - withText(currentSiteUrl), - isDescendantOfA(withId(GroupedWebsitesSettings.RWS_ROW_ID)))) - .check(matches(isDisplayed())); - } - - // TODO(crbug.com/396463421): Remove once RWS UI V2 launched. - @Test - @SmallTest - @Feature({"RenderTest"}) - @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_RELATED_WEBSITE_SETS_UI) - public void renderRwsSingleWebsiteSettingsRwsV2UiDisabled() throws Exception { - createStorageAccessExceptions(); - final SettingsActivity settingsActivity = - SiteSettingsTestUtils.startSingleWebsitePreferences(getRwsOwnerSite()); - renderSettingsPage(settingsActivity, "site_settings_rws_single_website_v2_disabled"); - } - - // TODO(crbug.com/396463421): Remove once RWS UI V2 launched. - @Test - @SmallTest - @Feature({"RenderTest"}) - @DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_RELATED_WEBSITE_SETS_UI) - public void renderRwsGroupedWebsiteSettingsRwsV2UiDisabled() throws Exception { - createStorageAccessExceptions(); - final SettingsActivity settingsActivity = - SiteSettingsTestUtils.startGroupedWebsitesPreferences(getRwsSiteGroup()); - renderSettingsPage( - settingsActivity, "site_settings_rws_grouped_website_settings_v2_disabled"); + renderSettingsPage(settingsActivity, "site_settings_rws_grouped_website"); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java index b5b7dcb..269fc46e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -1576,7 +1576,7 @@ TabModelObserver closeObserver = new TabModelObserver() { @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java index 15cd4d07..e441d48c1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java
@@ -45,6 +45,7 @@ import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.ui.base.DeviceFormFactor; +import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; @@ -134,8 +135,10 @@ model.addObserver( new TabModelObserver() { @Override - public void tabPendingClosure( - Tab tab, @TabClosingSource int closingSource) { + public void onTabClosePending( + List<Tab> tabs, + boolean isAllTabs, + @TabClosingSource int closingSource) { didReceivePendingClosureHelper.notifyCalled(); } }); @@ -149,7 +152,7 @@ boolean didMakePending = undoable && model.supportsPendingClosures(); - // Make sure the TabModel throws a tabPendingClosure callback if necessary. + // Make sure the TabModel throws a onTabClosePending callback if necessary. if (didMakePending) didReceivePendingClosureHelper.waitForCallback(0); // Check post conditions
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStackerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStackerUnitTest.java index 4c30679..004e2e70 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStackerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStackerUnitTest.java
@@ -45,106 +45,73 @@ mInput = new StripLayoutView[] {mView1, mView2, mView3, mView4, mView5}; } - private void setupViews(boolean tabClosing) { + private void setupViews() { // First and last tab out of visible area. Offset_x is 0. - float ideal_x = FIRST_VIEW_IDEAL_X; + float idealX = FIRST_VIEW_IDEAL_X; for (StripLayoutView view : mInput) { - float expected_x = ideal_x; - expected_x += - (view instanceof StripLayoutTab - && LocalizationUtils.isLayoutRtl() - && !tabClosing) - ? CACHED_TAB_WIDTH - WIDTH - : 0; - when(view.getIdealX()).thenReturn(ideal_x); + when(view.getIdealX()).thenReturn(idealX); when(view.getOffsetY()).thenReturn(OFFSET_Y); if (view instanceof StripLayoutTab) { when(view.getWidth()).thenReturn(WIDTH); - when(view.getDrawX()).thenReturn(expected_x); + when(view.getDrawX()).thenReturn(idealX); } else if (view instanceof StripLayoutGroupTitle title) { - when(title.getPaddedX()).thenReturn(expected_x); + when(title.getPaddedX()).thenReturn(idealX); when(title.getPaddedWidth()).thenReturn(WIDTH); } - ideal_x += WIDTH; + idealX += WIDTH; } } - private void verifyViews(boolean tabClosing, List<StripLayoutView> expectedHiddenViews) { + private void verifyViews(List<StripLayoutView> expectedHiddenViews) { // First and last tab out of visible area. - float ideal_x = FIRST_VIEW_IDEAL_X; + float idealX = FIRST_VIEW_IDEAL_X; for (StripLayoutView view : mInput) { - float expected_x = ideal_x; - expected_x += - (view instanceof StripLayoutTab - && LocalizationUtils.isLayoutRtl() - && !tabClosing) - ? CACHED_TAB_WIDTH - WIDTH - : 0; verify(view).setDrawY(OFFSET_Y); - verify(view).setDrawX(expected_x); + verify(view).setDrawX(idealX); if (expectedHiddenViews.contains(view)) { verify(view).setVisible(false); } else { view.setVisible(true); } - ideal_x += WIDTH; + idealX += WIDTH; } } @Test public void testPushDrawPropertiesToViews() { - boolean tabClosing = false; - setupViews(tabClosing); - mTarget.pushDrawPropertiesToViews(mInput, 0, 2 * WIDTH, tabClosing, CACHED_TAB_WIDTH); + setupViews(); + mTarget.pushDrawPropertiesToViews(mInput, 0, 2 * WIDTH); // First and last view hidden based on initial positions. - verifyViews(tabClosing, Arrays.asList(mView1, mView5)); - } - - @Test - public void testSetTabOffsetsWithTabClosing() { - boolean tabClosing = true; - setupViews(tabClosing); - mTarget.pushDrawPropertiesToViews(mInput, 0, 2 * WIDTH, tabClosing, CACHED_TAB_WIDTH); - // First and last view hidden based on initial positions. - verifyViews(tabClosing, Arrays.asList(mView1, mView5)); + verifyViews(Arrays.asList(mView1, mView5)); } @Test public void testPushDrawPropertiesToViewsInRtl() { LocalizationUtils.setRtlForTesting(true); - boolean tabClosing = false; - setupViews(tabClosing); - mTarget.pushDrawPropertiesToViews(mInput, 0, 2 * WIDTH, tabClosing, CACHED_TAB_WIDTH); + setupViews(); + mTarget.pushDrawPropertiesToViews(mInput, 0, 2 * WIDTH); // First and last view hidden based on initial positions. - verifyViews(tabClosing, Arrays.asList(mView1, mView5)); - } - - @Test - public void testPushDrawPropertiesToViewsWithTabClosingInRtl() { - LocalizationUtils.setRtlForTesting(true); - boolean tabClosing = true; - setupViews(tabClosing); - mTarget.pushDrawPropertiesToViews(mInput, 0, 2 * WIDTH, tabClosing, CACHED_TAB_WIDTH); - // First and last view hidden based on initial positions. - verifyViews(tabClosing, Arrays.asList(mView1, mView5)); + verifyViews(Arrays.asList(mView1, mView5)); } @Test public void testPushDrawPropertiesToViewsWithXOffset() { - setupViews(false); - mTarget.pushDrawPropertiesToViews(mInput, WIDTH, 2 * WIDTH, false, CACHED_TAB_WIDTH); + setupViews(); + mTarget.pushDrawPropertiesToViews(mInput, WIDTH, 2 * WIDTH); - // Move the window with xOffset = TAB_WIDTH, will make upto TAB_2 invisible, but rest visible. - verifyViews(false, Arrays.asList(mView1, mView2)); + // Move the window with xOffset = TAB_WIDTH, will make up to TAB_2 invisible, but rest + // visible. + verifyViews(Arrays.asList(mView1, mView2)); } @Test public void testPushDrawPropertiesToViewsWithPartialXOffset() { - setupViews(false); - mTarget.pushDrawPropertiesToViews(mInput, WIDTH / 2, 2 * WIDTH, false, CACHED_TAB_WIDTH); + setupViews(); + mTarget.pushDrawPropertiesToViews(mInput, WIDTH / 2, 2 * WIDTH); - // Move the window with xOffset = TAB_WIDTH / 2, will make both upto TAB_2 and TAB_4 partially + // Move the window with xOffset = TAB_WIDTH / 2, will make both up to TAB_2 and TAB_4 + // partially // invisible. TAB_5 will still be invisible in this case. - verifyViews(false, Arrays.asList(mView1, mView5)); + verifyViews(Arrays.asList(mView1, mView5)); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStackerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStackerUnitTest.java index 6e20d311..2fd058a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStackerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStackerUnitTest.java
@@ -96,10 +96,6 @@ @Override public void pushDrawPropertiesToViews( - StripLayoutView[] indexOrderedViews, - float xOffset, - float visibleWidth, - boolean mMultiStepTabCloseAnimRunning, - float mCachedTabWidth) {} + StripLayoutView[] indexOrderedViews, float xOffset, float visibleWidth) {} } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerTest.java index cacd93e..6dff4b4 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManagerTest.java
@@ -12,6 +12,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -32,6 +33,8 @@ import org.mockito.junit.MockitoRule; import org.robolectric.Shadows; +import org.chromium.base.Callback; +import org.chromium.base.UnownedUserDataHost; import org.chromium.base.UserDataHost; import org.chromium.base.supplier.OneshotSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; @@ -49,6 +52,8 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManagerProvider; import org.chromium.components.dom_distiller.core.DomDistillerFeatures; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtilsJni; @@ -65,6 +70,7 @@ import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContentsObserver; import org.chromium.content_public.browser.test.mock.MockWebContents; +import org.chromium.ui.base.WindowAndroid; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -89,6 +95,8 @@ @Mock private UserPrefs.Natives mUserPrefsJniMock; @Mock private PrefService mPrefService; @Mock private UkmRecorder.Natives mUkmRecorderJniMock; + @Mock private WindowAndroid mWindowAndroid; + @Mock private SnackbarManager mSnackbarManager; @Captor private ArgumentCaptor<TabObserver> mTabObserverCaptor; private TabObserver mTabObserver; @@ -99,7 +107,10 @@ @Captor private ArgumentCaptor<WebContentsObserver> mWebContentsObserverCaptor; private WebContentsObserver mWebContentsObserver; + @Captor private ArgumentCaptor<Callback<Boolean>> mDistillationCallbackCaptor; + private UserDataHost mUserDataHost; + private UnownedUserDataHost mUnownedUserDataHost; private ReaderModeManager mManager; private OneshotSupplierImpl<Boolean> mButtonVisibilitySupplier; @@ -115,6 +126,11 @@ mUserDataHost = new UserDataHost(); mUserDataHost.setUserData(TabDistillabilityProvider.USER_DATA_KEY, mDistillabilityProvider); + mUnownedUserDataHost = new UnownedUserDataHost(); + when(mWindowAndroid.getUnownedUserDataHost()).thenReturn(mUnownedUserDataHost); + SnackbarManagerProvider.attach(mWindowAndroid, mSnackbarManager); + + when(mTab.getWindowAndroid()).thenReturn(mWindowAndroid); when(mTab.getUserDataHost()).thenReturn(mUserDataHost); when(mTab.getWebContents()).thenReturn(mWebContents); when(mTab.getUrl()).thenReturn(MOCK_URL); @@ -603,6 +619,34 @@ assertEquals(1, userActionTester.getActionCount("MobileReaderModeHidden")); } + @Test + @Feature("ReaderMode") + @EnableFeatures({DomDistillerFeatures.READER_MODE_DISTILL_IN_APP}) + public void testDistillationSuccess_noSnackbar() { + when(mTab.getWebContents()).thenReturn(mWebContents); + + mManager.navigateToReaderMode(); + verify(mDistillerTabUtilsJniMock) + .distillCurrentPageAndViewIfSuccessful( + any(), mDistillationCallbackCaptor.capture()); + mDistillationCallbackCaptor.getValue().onResult(true); + verify(mSnackbarManager, times(0)).showSnackbar(any()); + } + + @Test + @Feature("ReaderMode") + @EnableFeatures({DomDistillerFeatures.READER_MODE_DISTILL_IN_APP}) + public void testDistillationFailure_showSnackbar() { + when(mTab.getWebContents()).thenReturn(mWebContents); + + mManager.navigateToReaderMode(); + verify(mDistillerTabUtilsJniMock) + .distillCurrentPageAndViewIfSuccessful( + any(), mDistillationCallbackCaptor.capture()); + mDistillationCallbackCaptor.getValue().onResult(false); + verify(mSnackbarManager).showSnackbar(any()); + } + /** * @param index The index of the entry. * @param url The URL the entry represents.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonControllerTest.java index 04eb6567..bae6758 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/dom_distiller/ReaderModeToolbarButtonControllerTest.java
@@ -24,6 +24,7 @@ import org.chromium.base.ContextUtils; import org.chromium.base.FeatureOverrides; +import org.chromium.base.UnownedUserDataHost; import org.chromium.base.UserDataHost; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; @@ -34,11 +35,13 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.toolbar.optional_button.ButtonData; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerFactory; +import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController; import org.chromium.components.dom_distiller.core.DistilledPagePrefs; import org.chromium.components.dom_distiller.core.DomDistillerFeatures; import org.chromium.components.dom_distiller.core.DomDistillerService; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtilsJni; +import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.url.GURL; @@ -46,28 +49,36 @@ @RunWith(BaseRobolectricTestRunner.class) public class ReaderModeToolbarButtonControllerTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock private Tab mMockTab; + @Mock private WindowAndroid mWindowAndroid; @Mock private ReaderModeManager mMockReaderModeManager; @Mock private ActivityTabProvider mMockActivityTabProvider; @Mock private ModalDialogManager mMockModalDialogManager; @Mock private DomDistillerUrlUtilsJni mDomDistillerUrlUtilsJni; @Mock private Profile mProfile; - @Mock private BottomSheetController mBottomSheetController; @Mock private DomDistillerService mDomDistillerService; @Mock private DomDistillerServiceFactoryJni mDomDistillerServiceFactoryJni; @Mock private DistilledPagePrefs mDistilledPagePrefs; + @Mock private ManagedBottomSheetController mBottomSheetController; private final ObservableSupplierImpl<Profile> mProfileSupplier = new ObservableSupplierImpl<>(); private UserDataHost mUserDataHost; + private UnownedUserDataHost mUnownedUserDataHost; @Before public void setUp() throws Exception { mUserDataHost = new UserDataHost(); + mUnownedUserDataHost = new UnownedUserDataHost(); Context context = new ContextThemeWrapper( ContextUtils.getApplicationContext(), R.style.Theme_BrowserUI_DayNight); + when(mWindowAndroid.getUnownedUserDataHost()).thenReturn(mUnownedUserDataHost); + BottomSheetControllerFactory.attach(mWindowAndroid, mBottomSheetController); + when(mMockTab.getWindowAndroid()).thenReturn(mWindowAndroid); + when(mMockTab.getProfile()).thenReturn(mProfile); when(mProfile.getOriginalProfile()).thenReturn(mProfile); mProfileSupplier.set(mProfile); when(mMockTab.getContext()).thenReturn(context); @@ -88,8 +99,7 @@ mMockTab.getContext(), mProfileSupplier, mMockActivityTabProvider, - mMockModalDialogManager, - mBottomSheetController); + mMockModalDialogManager); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/history/HistoryUiTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/history/HistoryUiTest.java index 01f2f6b..e7f906e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/history/HistoryUiTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/history/HistoryUiTest.java
@@ -94,6 +94,7 @@ import org.chromium.components.sync.SyncService; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.components.user_prefs.UserPrefsJni; +import org.chromium.ui.base.DeviceInput; import org.chromium.ui.base.PageTransition; import org.chromium.ui.base.TestActivity; import org.chromium.url.GURL; @@ -720,6 +721,46 @@ @Test @SmallTest + @Config(qualifiers = "sw600dp") + public void testInfoHeaderInSearchModeOnLFFDevice() { + DeviceInput.setSupportsKeyboardForTesting(true); + mHistoryManager = + new HistoryManager( + mActivity, + true, + mSnackbarManager, + mProfile, + /* bottomSheetController= */ null, + /* Supplier<Tab>= */ null, + mHistoryProvider, + new HistoryUmaRecorder(), + /* clientPackageName= */ null, + /* shouldShowClearData= */ true, + /* launchedForApp= */ false, + /* showAppFilter= */ true, + /* openHistoryItemCallback= */ null, + /* edgeToEdgePadAdjusterGenerator= */ null); + mContentManager = mHistoryManager.getContentManagerForTests(); + mAdapter = mContentManager.getAdapter(); + mRecyclerView = mContentManager.getRecyclerView(); + + final HistoryManagerToolbar toolbar = mHistoryManager.getToolbarForTests(); + final MenuItem searchMenuItem = + toolbar.getItemById(R.id.search_menu_id); // The magnifier button + + // Sign in and set has other forms of browsing data to true. + mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL); + setHasOtherFormsOfBrowsingData(true); + + ShadowLooper.idleMainLooper(); + DateDividedAdapter.ItemGroup firstGroup = mAdapter.getFirstGroupForTests(); + Assert.assertFalse(searchMenuItem.isVisible()); + Assert.assertTrue(mAdapter.hasListHeader()); + Assert.assertEquals(2, firstGroup.size()); + } + + @Test + @SmallTest public void testSearch_NotFound() { final HistoryManagerToolbar toolbar = mHistoryManager.getToolbarForTests();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/UndoTabModelUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/UndoTabModelUnitTest.java index ddf26138..48601d4 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/UndoTabModelUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabmodel/UndoTabModelUnitTest.java
@@ -273,7 +273,8 @@ model.addObserver( new TabModelObserver() { @Override - public void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) { + public void onTabClosePending( + List<Tab> tab, boolean isAllTabs, @TabClosingSource int closingSource) { didReceivePendingClosureHelper.notifyCalled(); } }); @@ -286,7 +287,7 @@ boolean didMakePending = undoable && model.supportsPendingClosures(); - // Make sure the TabModel throws a tabPendingClosure callback if necessary. + // Make sure the TabModel throws a onTabClosePending callback if necessary. if (didMakePending) didReceivePendingClosureHelper.waitForCallback(0); // Check post conditions @@ -303,7 +304,7 @@ model.addObserver( new TabModelObserver() { @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) { @@ -314,7 +315,7 @@ boolean didMakePending = undoable && model.supportsPendingClosures(); - // Make sure the TabModel throws a tabPendingClosure callback if necessary. + // Make sure the TabModel throws a onTabClosePending callback if necessary. if (didMakePending) didReceivePendingClosureHelper.waitForCallback(0); }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index fc463d79..5fe0dff 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -1928,6 +1928,7 @@ "//chrome/browser/ai", "//chrome/browser/ai:impl", "//chrome/browser/autocomplete", + "//chrome/browser/autocomplete:aim_eligibility_service", "//chrome/browser/autofill", "//chrome/browser/background", "//chrome/browser/background:impl", @@ -4404,6 +4405,7 @@ "//chrome/browser/ui/search", "//chrome/browser/ui/tab_sharing", "//chrome/browser/ui/tabs:glic", + "//chrome/browser/ui/tabs/saved_tab_groups", # TODO(crbug.com/418180294): Remove this circular dependency when: # - bookmark_model_factory.h, @@ -4441,6 +4443,7 @@ "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/ui/tabs:tab_strip_impl", "//chrome/browser/ui/tabs/organization:impl", + "//chrome/browser/ui/tabs/saved_tab_groups:impl", "//chrome/browser/ui/tabs/tab_group_home", "//chrome/browser/ui/tabs/tab_strip_api", "//chrome/browser/ui/tabs/tab_strip_api:impl", @@ -4634,6 +4637,7 @@ "//chrome/browser/importer:impl", "//chrome/browser/ui/webui/commerce:impl", "//chrome/browser/ui/webui/customize_buttons", + "//chrome/browser/ui/tabs/saved_tab_groups:impl", "//chrome/browser/ui/webui/settings:impl", "//chrome/browser/ui/webui/new_tab_footer:impl", "//chrome/browser/ui/webui/signin:signin_impl",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 1a6c33f..cb24826 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -11076,11 +11076,6 @@ kAndroidTabHighlightingVariations, "AndroidTabHighlightingVariations")}, - {"tab-group-sync-disable-network-layer", - flag_descriptions::kTabGroupSyncDisableNetworkLayerName, - flag_descriptions::kTabGroupSyncDisableNetworkLayerDescription, kOsAndroid, - FEATURE_VALUE_TYPE(tab_groups::kTabGroupSyncDisableNetworkLayer)}, - {"swap-new-tab-and-new-tab-in-group-android", flag_descriptions::kSwapNewTabAndNewTabInGroupAndroidName, flag_descriptions::kSwapNewTabAndNewTabInGroupAndroidDescription, @@ -11700,9 +11695,6 @@ FEATURE_WITH_PARAMS_VALUE_TYPE(omnibox::kJumpStartOmnibox, kJumpStartOmniboxVariations, "JumpStartOmnibox")}, - {"retain-omnibox-on-focus", flag_descriptions::kRetainOmniboxOnFocusName, - flag_descriptions::kRetainOmniboxOnFocusDescription, kOsAndroid, - FEATURE_VALUE_TYPE(omnibox::kRetainOmniboxOnFocus)}, #endif // BUILDFLAG(IS_ANDROID) {"autofill-enable-log-form-events-to-all-parsed-form-types", @@ -12167,11 +12159,6 @@ FEATURE_VALUE_TYPE( blink::features::kSecurePaymentConfirmationAvailabilityAPI)}, - {"copy-image-filename-to-clipboard", - flag_descriptions::kCopyImageFilenameToClipboardName, - flag_descriptions::kCopyImageFilenameToClipboardDescription, kOsAll, - FEATURE_VALUE_TYPE(download::features::kCopyImageFilenameToClipboard)}, - {"autofill-enable-allowlist-for-bmo-card-category-benefits", flag_descriptions::kAutofillEnableAllowlistForBmoCardCategoryBenefitsName, flag_descriptions:: @@ -13152,6 +13139,14 @@ FEATURE_VALUE_TYPE(chrome::android::kToolbarSnapshotRefactor)}, #endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + {"enforce-management-disclaimer", + flag_descriptions::kEnforceManagementDisclaimerName, + flag_descriptions::kEnforceManagementDisclaimerDescription, kOsDesktop, + FEATURE_VALUE_TYPE(switches::kEnforceManagementDisclaimer)}, + +#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) + // Add new entries above this line. // NOTE: Adding a new flag requires adding a corresponding entry to enum
diff --git a/chrome/browser/actor/tools/attempt_login_tool.cc b/chrome/browser/actor/tools/attempt_login_tool.cc index 88c44b1..5d3fcce0 100644 --- a/chrome/browser/actor/tools/attempt_login_tool.cc +++ b/chrome/browser/actor/tools/attempt_login_tool.cc
@@ -41,7 +41,10 @@ switch (login_result) { case actor_login::LoginStatusResult::kSuccessUsernameAndPasswordFilled: return mojom::ActionResultCode::kOk; + // TODO(crbug.com/427817201):Define ActionResultCode errors specific to + // actor login errors. case actor_login::LoginStatusResult::kErrorNoSigninForm: + case actor_login::LoginStatusResult::kErrorInvalidCredential: return mojom::ActionResultCode::kError; } }
diff --git a/chrome/browser/actor/tools/attempt_login_tool_browsertest.cc b/chrome/browser/actor/tools/attempt_login_tool_browsertest.cc index fc17d56..6137f21 100644 --- a/chrome/browser/actor/tools/attempt_login_tool_browsertest.cc +++ b/chrome/browser/actor/tools/attempt_login_tool_browsertest.cc
@@ -198,6 +198,21 @@ ExpectErrorResult(result, mojom::ActionResultCode::kError); } +IN_PROC_BROWSER_TEST_F(ActorAttemptLoginToolTest, + InvalidCredentialForGivenUrl) { + const GURL url = + embedded_https_test_server().GetURL("example.com", "/actor/blank.html"); + ASSERT_TRUE(content::NavigateToURL(web_contents(), url)); + + mock_login_service().SetLoginStatus( + actor_login::LoginStatusResult::kErrorInvalidCredential); + + std::unique_ptr<ToolRequest> action = MakeAttemptLoginRequest(*active_tab()); + TestFuture<mojom::ActionResultPtr, std::optional<size_t>> result; + actor_task().Act(ToRequestList(action), result.GetCallback()); + ExpectErrorResult(result, mojom::ActionResultCode::kError); +} + IN_PROC_BROWSER_TEST_F(ActorAttemptLoginToolTest, FailedAttemptLogin) { const GURL url = embedded_https_test_server().GetURL("example.com", "/actor/blank.html");
diff --git a/chrome/browser/actor/ui/actor_ui_state_manager.cc b/chrome/browser/actor/ui/actor_ui_state_manager.cc index 98e52ce2..338d3da 100644 --- a/chrome/browser/actor/ui/actor_ui_state_manager.cc +++ b/chrome/browser/actor/ui/actor_ui_state_manager.cc
@@ -305,8 +305,10 @@ }); UiState new_state; - if (!GetCompletedTasks(base::Time::Now()).empty() || has_paused_task) { + if (has_paused_task) { new_state = ActorUiStateManager::UiState::kCheckTasks; + } else if (!GetCompletedTasks(base::Time::Now()).empty()) { + new_state = ActorUiStateManager::UiState::kCompleteTasks; } else if (!active_tasks.empty()) { new_state = ActorUiStateManager::UiState::kActive; } else {
diff --git a/chrome/browser/actor/ui/actor_ui_state_manager_interface.h b/chrome/browser/actor/ui/actor_ui_state_manager_interface.h index 716f23b..812739f 100644 --- a/chrome/browser/actor/ui/actor_ui_state_manager_interface.h +++ b/chrome/browser/actor/ui/actor_ui_state_manager_interface.h
@@ -24,16 +24,21 @@ class ActorUiStateManagerInterface { public: - // TODO(crbug.com/428014205): Once UX is determined for multiple tasks, states - // here may change. + // TODO(crbug.com/424495020): This behavior will need to be revisited once + // multiple tasks come into play. If there are multiple tasks where some tasks + // are complete but some tasks are paused, the current behavior is that + // kCheckTasks takes precedence over kCompleteTasks. For M3 this is not an + // issue since there are not multiple tasks. enum class UiState { // There are no active Actor tasks on this profile. kInactive, // There are active Actor tasks on this profile. kActive, - // There are Actor tasks that need attention, this includes Actor pause & - // completed tasks within the Completed Task Expiry Delay. + // There are Actor tasks that need attention, this includes Actor paused. kCheckTasks, + // There are Actor tasks that are complete within the + // kCompletedTaskExpiryDelay. + kCompleteTasks, }; virtual ~ActorUiStateManagerInterface() = default;
diff --git a/chrome/browser/actor/ui/actor_ui_state_manager_unittest.cc b/chrome/browser/actor/ui/actor_ui_state_manager_unittest.cc index ef2ccf4e..54c9fb4 100644 --- a/chrome/browser/actor/ui/actor_ui_state_manager_unittest.cc +++ b/chrome/browser/actor/ui/actor_ui_state_manager_unittest.cc
@@ -36,7 +36,7 @@ using enum HandoffButtonState::ControlOwnership; -base::TimeDelta CompletedtaskExpiryDelay() { +base::TimeDelta CompletedTaskExpiryDelay() { return base::Seconds( features::kGlicActorUiCompletedTaskExpiryDelaySeconds.Get()); } @@ -242,8 +242,8 @@ StopActorTask(task_id); task_environment().FastForwardBy(kProfileScopedUiUpdateDebounceDelay); EXPECT_EQ(actor_ui_state_manager()->GetUiState(), - ActorUiStateManager::UiState::kCheckTasks); - task_environment().FastForwardBy(CompletedtaskExpiryDelay()); + ActorUiStateManager::UiState::kCompleteTasks); + task_environment().FastForwardBy(CompletedTaskExpiryDelay()); EXPECT_EQ(actor_ui_state_manager()->GetUiState(), ActorUiStateManager::UiState::kInactive); } @@ -291,10 +291,23 @@ EXPECT_EQ(actor_ui_state_manager()->GetUiState(), ActorUiStateManager::UiState::kCheckTasks); - // Resume the first task, the state should now be in kActive. + // Stop the second task, the state should still be in kCheckTasks. + StopActorTask(task_id2); + task_environment().FastForwardBy(kProfileScopedUiUpdateDebounceDelay); + EXPECT_EQ(actor_ui_state_manager()->GetUiState(), + ActorUiStateManager::UiState::kCheckTasks); + + // Resume the first task, the state should now be in kCompleteTasks due to the + // second task. ResumeActorTask(task_id); task_environment().FastForwardBy(kProfileScopedUiUpdateDebounceDelay); EXPECT_EQ(actor_ui_state_manager()->GetUiState(), + ActorUiStateManager::UiState::kCompleteTasks); + + // After the completed task delay, the state should be + // kActive due to the first task still being active. + task_environment().FastForwardBy(CompletedTaskExpiryDelay()); + EXPECT_EQ(actor_ui_state_manager()->GetUiState(), ActorUiStateManager::UiState::kActive); } @@ -310,23 +323,23 @@ StopActorTask(task_id); task_environment().FastForwardBy(kProfileScopedUiUpdateDebounceDelay); EXPECT_EQ(actor_ui_state_manager()->GetUiState(), - ActorUiStateManager::UiState::kCheckTasks); + ActorUiStateManager::UiState::kCompleteTasks); // Create another task. TaskId task_id2 = actor_keyed_service()->CreateTaskForTesting(); StartTask start_task_event2(task_id2); actor_ui_state_manager()->OnUiEvent(start_task_event2); EXPECT_EQ(actor_ui_state_manager()->GetUiState(), - ActorUiStateManager::UiState::kCheckTasks); + ActorUiStateManager::UiState::kCompleteTasks); // The state should still be active due to task2 after the expiry period. - task_environment().FastForwardBy(CompletedtaskExpiryDelay()); + task_environment().FastForwardBy(CompletedTaskExpiryDelay()); EXPECT_EQ(actor_ui_state_manager()->GetUiState(), ActorUiStateManager::UiState::kActive); // When both tasks stop, then the state should be inactive. StopActorTask(task_id2); - task_environment().FastForwardBy(CompletedtaskExpiryDelay()); + task_environment().FastForwardBy(CompletedTaskExpiryDelay()); EXPECT_EQ(actor_ui_state_manager()->GetUiState(), ActorUiStateManager::UiState::kInactive); } @@ -353,16 +366,16 @@ StopActorTask(task_id2); base::TimeDelta delay = - CompletedtaskExpiryDelay() - (base::Time::Now() - task1_finish_time); + CompletedTaskExpiryDelay() - (base::Time::Now() - task1_finish_time); task_environment().FastForwardBy((delay.is_positive()) ? delay : base::TimeDelta()); // Even though the first task expired, we should still be in the correct // state. EXPECT_EQ(actor_ui_state_manager()->GetUiState(), - ActorUiStateManager::UiState::kCheckTasks); + ActorUiStateManager::UiState::kCompleteTasks); // After both tasks expire, the state should be inactive. - task_environment().FastForwardBy(CompletedtaskExpiryDelay()); + task_environment().FastForwardBy(CompletedTaskExpiryDelay()); EXPECT_EQ(actor_ui_state_manager()->GetUiState(), ActorUiStateManager::UiState::kInactive); }
diff --git a/chrome/browser/actor/ui/actor_ui_tab_controller.cc b/chrome/browser/actor/ui/actor_ui_tab_controller.cc index 5dec441..0f16ab6 100644 --- a/chrome/browser/actor/ui/actor_ui_tab_controller.cc +++ b/chrome/browser/actor/ui/actor_ui_tab_controller.cc
@@ -75,14 +75,23 @@ void ActorUiTabController::OnUiTabStateChange(const UiTabState& ui_tab_state, UiResultCallback callback) { - MaybeUpdateState(ui_tab_state, current_tab_active_status_, - std::move(callback)); + MaybeUpdateState(ui_tab_state, std::move(callback)); } void ActorUiTabController::OnTabActiveStatusChanged(bool tab_active_status, tabs::TabInterface* tab) { + if (current_tab_active_status_ == tab_active_status) { + return; + } + VLOG(4) << "Tab scoped UI components updated FROM -> TO:\n" + << " tab_active_status: " << current_tab_active_status_ << " -> " + << tab_active_status << "\n"; + + current_tab_active_status_ = tab_active_status; + // TODO(crbug.com/425952887): decouple the ui tab state changes + tab + // active/visibility changes. MaybeUpdateState( - current_ui_tab_state_, tab_active_status, + current_ui_tab_state_, base::BindOnce(&LogAndIgnoreCallbackError, "OnTabActiveStatusChanged")); } @@ -124,40 +133,34 @@ } void ActorUiTabController::MaybeUpdateState(const UiTabState& ui_tab_state, - bool tab_active_status, UiResultCallback callback) { if (!update_state_debounce_timer_.IsRunning()) { in_progress_updates_int_++; } VLOG(4) << "Tab scoped UI components updated FROM -> TO:\n" << "ui_tab_state: " << current_ui_tab_state_ << " -> " << ui_tab_state - << ", tab_active_status: " << current_tab_active_status_ << " -> " - << tab_active_status << "\n"; + << "\n"; // Update tab state and active status before debouncing to prevent stale data // from being used in UpdateState calls. if (current_ui_tab_state_ != ui_tab_state) { current_ui_tab_state_ = ui_tab_state; } - if (current_tab_active_status_ != tab_active_status) { - current_tab_active_status_ = tab_active_status; - } + update_state_debounce_timer_.Start( FROM_HERE, kUpdateStateDebounceDelay, base::BindOnce(&ActorUiTabController::UpdateState, weak_factory_.GetWeakPtr(), ui_tab_state, - tab_active_status, std::move(callback))); + current_tab_active_status_, std::move(callback))); } void ActorUiTabController::UpdateState(const UiTabState& ui_tab_state, bool tab_active_status, UiResultCallback callback) { - // TODO(crbug.com/428216197): Only notify relevant UI components on change. if (features::kGlicActorUiOverlay.Get()) { actor_overlay_view_controller_->UpdateState( current_ui_tab_state_.actor_overlay, ComputeActorOverlayVisibility()); } - // TODO(crbug.com/428216197): Only notify relevant UI components on change. if (features::kGlicActorUiHandoffButton.Get()) { handoff_button_controller_->UpdateState( current_ui_tab_state_.handoff_button, ComputeHandoffButtonVisibility()); @@ -230,7 +233,7 @@ } is_hovering_overlay_ = is_hovering; MaybeUpdateState( - current_ui_tab_state_, current_tab_active_status_, + current_ui_tab_state_, base::BindOnce(&LogAndIgnoreCallbackError, "SetOverlayHoverStatus")); } @@ -239,7 +242,7 @@ return; } is_hovering_button_ = is_hovering; - MaybeUpdateState(current_ui_tab_state_, current_tab_active_status_, + MaybeUpdateState(current_ui_tab_state_, base::BindOnce(&LogAndIgnoreCallbackError, "SetHandoffButtonHoverStatus")); }
diff --git a/chrome/browser/actor/ui/actor_ui_tab_controller.h b/chrome/browser/actor/ui/actor_ui_tab_controller.h index 07a8bc7d..c2807f3 100644 --- a/chrome/browser/actor/ui/actor_ui_tab_controller.h +++ b/chrome/browser/actor/ui/actor_ui_tab_controller.h
@@ -44,13 +44,13 @@ tabs::TabInterface* tab) override; void SetActiveTaskId(TaskId task_id) override; void ClearActiveTaskId() override; - base::WeakPtr<ActorUiTabControllerInterface> GetWeakPtr() override; void SetActorTaskPaused() override; void SetActorTaskResume() override; void SetOverlayHoverStatus(bool is_hovering) override; void SetHandoffButtonHoverStatus(bool is_hovering) override; void SetCallbackForTesting(base::OnceClosure callback) override; bool ShouldShowActorTabIndicator() override; + base::WeakPtr<ActorUiTabControllerInterface> GetWeakPtr() override; // Binds the Mojo receiver to the tab's ActorOverlayViewController. // Called by ActorOverlayUI when the chrome://actor-overlay page loads. @@ -64,7 +64,6 @@ // Called to propagate a UiTabState and tab status change to UI controllers. // This is passed through a debounce timer to stabilize updates. void MaybeUpdateState(const UiTabState& ui_tab_state, - bool tab_active_status, UiResultCallback callback); void UpdateState(const UiTabState& ui_tab_state, bool tab_active_status, @@ -106,6 +105,8 @@ // How many outstanding callbacks are pending for the debounce timer. int in_progress_updates_int_ = 0; + // TODO(crbug.com/425952887): Look into replacing oneshottimer with + // retainingoneshottimer. base::OneShotTimer update_state_debounce_timer_; base::OnceClosure on_idle_for_testing_;
diff --git a/chrome/browser/apps/app_preload_service/app_preload_service_unittest.cc b/chrome/browser/apps/app_preload_service/app_preload_service_unittest.cc index 10e43d60..659a47f 100644 --- a/chrome/browser/apps/app_preload_service/app_preload_service_unittest.cc +++ b/chrome/browser/apps/app_preload_service/app_preload_service_unittest.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/common/chrome_features.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/settings/cros_settings.h" @@ -87,13 +86,11 @@ // BrowserTaskEnvironment has to be the first member or test will break. content::BrowserTaskEnvironment task_environment_; base::test::ScopedFeatureList scoped_feature_list_; - ScopedTestingLocalState testing_local_state_{ - TestingBrowserProcess::GetGlobal()}; ash::ScopedTestingCrosSettings testing_cros_settings_; user_manager::ScopedUserManager scoped_user_manager_{ std::make_unique<user_manager::UserManagerImpl>( std::make_unique<user_manager::FakeUserManagerDelegate>(), - testing_local_state_.Get(), + TestingBrowserProcess::GetGlobal()->local_state(), ash::CrosSettings::Get())}; std::unique_ptr<TestingProfile> profile_; ash::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
diff --git a/chrome/browser/apps/app_service/BUILD.gn b/chrome/browser/apps/app_service/BUILD.gn index 83cb6d2b..ddc55c4 100644 --- a/chrome/browser/apps/app_service/BUILD.gn +++ b/chrome/browser/apps/app_service/BUILD.gn
@@ -487,6 +487,7 @@ "//chrome/browser/resources:app_icon_resources_grit", "//chrome/browser/web_applications/app_service:unit_tests", "//chrome/test:test_support", + "//chromeos/ash/components/browser_context_helper", "//chromeos/ash/components/dbus/chunneld", "//chromeos/ash/components/dbus/cicerone", "//chromeos/ash/components/dbus/seneschal",
diff --git a/chrome/browser/apps/app_service/app_icon/BUILD.gn b/chrome/browser/apps/app_service/app_icon/BUILD.gn index 7640993..b23dcc5c 100644 --- a/chrome/browser/apps/app_service/app_icon/BUILD.gn +++ b/chrome/browser/apps/app_service/app_icon/BUILD.gn
@@ -145,6 +145,7 @@ "//chrome/browser/ash/app_list/arc:test_support", "//chrome/browser/ash/arc", "//chrome/browser/ash/crostini:test_support", + "//chromeos/ash/components/browser_context_helper", "//chromeos/ash/components/dbus/chunneld", "//chromeos/ash/components/dbus/seneschal", "//chromeos/ash/experiences/arc:arc_app_constants",
diff --git a/chrome/browser/apps/app_service/app_icon/guest_os_apps_icon_unittest.cc b/chrome/browser/apps/app_service/app_icon/guest_os_apps_icon_unittest.cc index 4a89ad8..1698d1e 100644 --- a/chrome/browser/apps/app_service/app_icon/guest_os_apps_icon_unittest.cc +++ b/chrome/browser/apps/app_service/app_icon/guest_os_apps_icon_unittest.cc
@@ -14,15 +14,23 @@ #include "chrome/browser/ash/crostini/fake_crostini_features.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/grit/chrome_unscaled_resources.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" #include "chromeos/ash/components/dbus/vm_applications/apps.pb.h" +#include "components/account_id/account_id.h" +#include "components/prefs/testing_pref_service.h" #include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/features.h" #include "components/services/app_service/public/cpp/icon_types.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h" #include "testing/gtest/include/gtest/gtest.h" @@ -49,7 +57,19 @@ ash::ChunneldClient::InitializeFake(); fake_cicerone_client_ = ash::FakeCiceroneClient::Get(); + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + profile_ = std::make_unique<TestingProfile>(); + ash::AnnotatedAccountId::Set(profile_.get(), account_id); proxy_ = AppServiceProxyFactory::GetForProfile(profile()); web_app::test::AwaitStartWebAppProviderAndSubsystems(profile()); @@ -61,6 +81,7 @@ void TearDown() override { crostini_test_helper_.reset(); profile_.reset(); + user_manager_.Reset(); ash::CiceroneClient::Shutdown(); ash::ConciergeClient::Shutdown(); ash::SeneschalClient::Shutdown(); @@ -123,6 +144,7 @@ private: content::BrowserTaskEnvironment task_environment_; raw_ptr<ash::FakeCiceroneClient, DanglingUntriaged> fake_cicerone_client_; + user_manager::ScopedUserManager user_manager_; std::unique_ptr<TestingProfile> profile_; data_decoder::test::InProcessDataDecoder in_process_data_decoder_; raw_ptr<AppServiceProxy, DanglingUntriaged> proxy_;
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_test_base.h b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_test_base.h index 4a5a4b33..804248e 100644 --- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_test_base.h +++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_service_test_base.h
@@ -13,7 +13,6 @@ #include "chrome/browser/apps/app_service/app_service_test.h" #include "chrome/browser/apps/app_service/metrics/app_platform_metrics_service.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/services/app_service/public/cpp/app_types.h" @@ -143,7 +142,6 @@ content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; private: std::unique_ptr<TestingProfile> testing_profile_;
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc b/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc index a0091a4..6e76871 100644 --- a/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc +++ b/chrome/browser/apps/app_service/publishers/arc_apps_unittest.cc
@@ -37,7 +37,6 @@ #include "chrome/browser/web_applications/policy/web_app_policy_manager.h" #include "chrome/browser/web_applications/test/fake_web_app_provider.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/experiences/arc/app/arc_app_constants.h" @@ -163,9 +162,7 @@ class ArcAppsPublisherTest : public testing::Test { public: - ArcAppsPublisherTest() - : local_state_(std::make_unique<ScopedTestingLocalState>( - TestingBrowserProcess::GetGlobal())) {} + ArcAppsPublisherTest() = default; void SetUp() override { testing::Test::SetUp(); @@ -272,9 +269,6 @@ return result; } - protected: - std::unique_ptr<ScopedTestingLocalState> local_state_; - private: content::BrowserTaskEnvironment task_environment_; ash::SystemWebAppDelegateMap system_apps_; @@ -416,7 +410,8 @@ // Change SystemFeaturesDisableList policy to disable OS Setting. { ScopedListPrefUpdate update( - local_state_->Get(), policy::policy_prefs::kSystemFeaturesDisableList); + TestingBrowserProcess::GetGlobal()->local_state(), + policy::policy_prefs::kSystemFeaturesDisableList); update->Append(static_cast<int>(policy::SystemFeature::kOsSettings)); } @@ -430,7 +425,8 @@ // Clear SystemFeaturesDisableList policy. { ScopedListPrefUpdate update( - local_state_->Get(), policy::policy_prefs::kSystemFeaturesDisableList); + TestingBrowserProcess::GetGlobal()->local_state(), + policy::policy_prefs::kSystemFeaturesDisableList); update->clear(); } @@ -451,7 +447,8 @@ // Change SystemFeaturesDisableList policy to disable OS Setting. { ScopedListPrefUpdate update( - local_state_->Get(), policy::policy_prefs::kSystemFeaturesDisableList); + TestingBrowserProcess::GetGlobal()->local_state(), + policy::policy_prefs::kSystemFeaturesDisableList); update->Append(static_cast<int>(policy::SystemFeature::kOsSettings)); } @@ -473,7 +470,8 @@ // Clear SystemFeaturesDisableList policy. { ScopedListPrefUpdate update( - local_state_->Get(), policy::policy_prefs::kSystemFeaturesDisableList); + TestingBrowserProcess::GetGlobal()->local_state(), + policy::policy_prefs::kSystemFeaturesDisableList); update->clear(); }
diff --git a/chrome/browser/apps/app_service/publishers/crostini_apps_unittest.cc b/chrome/browser/apps/app_service/publishers/crostini_apps_unittest.cc index b12fccc..03096ca 100644 --- a/chrome/browser/apps/app_service/publishers/crostini_apps_unittest.cc +++ b/chrome/browser/apps/app_service/publishers/crostini_apps_unittest.cc
@@ -12,11 +12,19 @@ #include "chrome/browser/ash/crostini/crostini_test_helper.h" #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" +#include "components/account_id/account_id.h" +#include "components/prefs/testing_pref_service.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/app_update.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,7 +43,19 @@ void SetUp() override { ash::CiceroneClient::InitializeFake(); + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + profile_ = std::make_unique<TestingProfile>(); + ash::AnnotatedAccountId::Set(profile_.get(), account_id); + app_service_proxy_ = AppServiceProxyFactory::GetForProfile(profile_.get()); web_app::test::AwaitStartWebAppProviderAndSubsystems(profile_.get()); test_helper_ = @@ -46,6 +66,7 @@ void TearDown() override { test_helper_.reset(); profile_.reset(); + user_manager_.Reset(); ash::CiceroneClient::Shutdown(); } @@ -66,6 +87,7 @@ private: content::BrowserTaskEnvironment task_environment_; + user_manager::ScopedUserManager user_manager_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<crostini::CrostiniTestHelper> test_helper_; raw_ptr<AppServiceProxy, DanglingUntriaged> app_service_proxy_ = nullptr;
diff --git a/chrome/browser/ash/app_list/DEPS b/chrome/browser/ash/app_list/DEPS index ba9d68ea..10d78af 100644 --- a/chrome/browser/ash/app_list/DEPS +++ b/chrome/browser/ash/app_list/DEPS
@@ -20,7 +20,6 @@ "+chrome/browser/ash/arc", "+chrome/browser/ash/borealis", "+chrome/browser/ash/bruschetta", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/crostini", "+chrome/browser/ash/drive", "+chrome/browser/ash/extensions", @@ -37,7 +36,6 @@ "+chrome/browser/autocomplete", "+chrome/browser/bitmap_fetcher", "+chrome/browser/bookmarks", - "+chrome/browser/chromeos/launcher_search", "+chrome/browser/extensions/chrome_app_icon.h", "+chrome/browser/extensions/context_menu_matcher.h", "+chrome/browser/extensions/extension_browsertest.h", @@ -50,11 +48,9 @@ "+chrome/browser/extensions/launch_util.h", "+chrome/browser/extensions/menu_manager_factory.h", "+chrome/browser/extensions/menu_manager.h", - "+chrome/browser/extensions/pending_extension_manager.h", "+chrome/browser/favicon", "+chrome/browser/feature_engagement", "+chrome/browser/history", - "+chrome/browser/metrics", "+chrome/browser/notifications", "+chrome/browser/platform_util.h", "+chrome/browser/policy", @@ -64,7 +60,6 @@ "+chrome/browser/signin", "+chrome/browser/sync", "+chrome/browser/trusted_vault", - "+chrome/browser/ui/app_list", "+chrome/browser/ui/ash", "+chrome/browser/ui/browser_commands.h", "+chrome/browser/ui/browser_finder.h", @@ -74,7 +69,6 @@ "+chrome/browser/ui/browser_navigator_params.h", "+chrome/browser/ui/browser_window.h", "+chrome/browser/ui/chrome_pages.h", - "+chrome/browser/ui/extensions", "+chrome/browser/ui/settings_window_manager_chromeos.h", "+chrome/browser/ui/web_applications", "+chrome/browser/ui/webui/ash/settings/app_management", @@ -83,7 +77,6 @@ "+chrome/browser/ui/webui/ash/settings/search", "+chrome/browser/ui/webui/ash/settings/services/settings_manager", "+chrome/browser/ui/webui/ash/settings/test_support", - "+chrome/browser/ui/webui/chrome_web_ui_controller_factory.h", "+chrome/browser/web_applications/externally_managed_app_manager.h", "+chrome/browser/web_applications/mojom", "+chrome/browser/web_applications/test",
diff --git a/chrome/browser/ash/app_list/app_service/BUILD.gn b/chrome/browser/ash/app_list/app_service/BUILD.gn index 91e2a4f..ee8ccfe 100644 --- a/chrome/browser/ash/app_list/app_service/BUILD.gn +++ b/chrome/browser/ash/app_list/app_service/BUILD.gn
@@ -103,6 +103,7 @@ "//chrome/common:constants", "//chrome/common:non_code_constants", "//chrome/test:test_support", + "//chromeos/ash/components/browser_context_helper", "//chromeos/ash/components/dbus/cicerone", "//chromeos/ash/components/dbus/concierge", "//chromeos/ash/components/dbus/seneschal",
diff --git a/chrome/browser/ash/app_list/app_service/DEPS b/chrome/browser/ash/app_list/app_service/DEPS index bb4afee..1835f36 100644 --- a/chrome/browser/ash/app_list/app_service/DEPS +++ b/chrome/browser/ash/app_list/app_service/DEPS
@@ -19,7 +19,6 @@ "+chrome/browser/ash/app_restore", "+chrome/browser/ash/arc", "+chrome/browser/ash/borealis", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/crostini", "+chrome/browser/ash/guest_os", "+chrome/browser/ash/login/demo_mode", @@ -28,7 +27,6 @@ "+chrome/browser/ash/system_web_apps", "+chrome/browser/extensions/chrome_app_icon.h", "+chrome/browser/extensions/context_menu_matcher.h", - "+chrome/browser/extensions/extension_service.h", "+chrome/browser/extensions/install_tracker_factory.h", "+chrome/browser/extensions/install_tracker.h", "+chrome/browser/extensions/menu_manager.h",
diff --git a/chrome/browser/ash/app_list/app_service/app_service_app_model_builder_unittest.cc b/chrome/browser/ash/app_list/app_service/app_service_app_model_builder_unittest.cc index ae76694..d7d3f9ee 100644 --- a/chrome/browser/ash/app_list/app_service/app_service_app_model_builder_unittest.cc +++ b/chrome/browser/ash/app_list/app_service/app_service_app_model_builder_unittest.cc
@@ -56,13 +56,21 @@ #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" #include "chromeos/ash/components/settings/cros_settings_names.h" +#include "components/account_id/account_id.h" #include "components/policy/core/common/policy_pref_names.h" #include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/test_utils.h" #include "extensions/browser/app_sorting.h" #include "extensions/browser/disable_reason.h" @@ -658,7 +666,17 @@ ash::CiceroneClient::InitializeFake(); ash::ConciergeClient::InitializeFake(); ash::SeneschalClient::InitializeFake(); + + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager::UserManager::Get()) + .AddRegularUser(account_id)); + user_manager::UserManager::Get()->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + AppServiceAppModelBuilderTest::SetUp(); + ash::AnnotatedAccountId::Set(profile(), account_id); + test_helper_ = std::make_unique<CrostiniTestHelper>(profile()); test_helper_->ReInitializeAppServiceIntegration(); CreateBuilder(); @@ -674,6 +692,7 @@ // DBusThreadManager to ensure all keyed services that might rely on DBus // clients are destroyed. profile_.reset(); + ash::SeneschalClient::Shutdown(); ash::ConciergeClient::Shutdown(); ash::CiceroneClient::Shutdown();
diff --git a/chrome/browser/ash/app_list/search/BUILD.gn b/chrome/browser/ash/app_list/search/BUILD.gn index 723577c..841f4d2 100644 --- a/chrome/browser/ash/app_list/search/BUILD.gn +++ b/chrome/browser/ash/app_list/search/BUILD.gn
@@ -197,6 +197,7 @@ "//chrome/common:constants", "//chrome/test:test_support", "//chrome/test:test_support_unit", + "//chromeos/ash/components/browser_context_helper", "//chromeos/ash/components/dbus/chunneld", "//chromeos/ash/components/dbus/cicerone", "//chromeos/ash/components/dbus/concierge",
diff --git a/chrome/browser/ash/app_list/search/DEPS b/chrome/browser/ash/app_list/search/DEPS index 953b6c1..33d8cac 100644 --- a/chrome/browser/ash/app_list/search/DEPS +++ b/chrome/browser/ash/app_list/search/DEPS
@@ -18,7 +18,6 @@ "+chrome/browser/apps/app_service", "+chrome/browser/ash/app_list", "+chrome/browser/ash/arc", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/crostini", "+chrome/browser/ash/drive", "+chrome/browser/ash/extensions", @@ -30,11 +29,9 @@ "+chrome/browser/autocomplete", "+chrome/browser/bitmap_fetcher", "+chrome/browser/bookmarks", - "+chrome/browser/chromeos/launcher_search", "+chrome/browser/extensions/extension_service.h", "+chrome/browser/favicon", "+chrome/browser/history", - "+chrome/browser/metrics", "+chrome/browser/platform_util.h", "+chrome/browser/profiles", "+chrome/browser/screen_ai", @@ -42,7 +39,6 @@ "+chrome/browser/signin", "+chrome/browser/sync", "+chrome/browser/trusted_vault", - "+chrome/browser/ui/app_icon_loader_delegate.h", "+chrome/browser/ui/ash", "+chrome/browser/ui/browser_commands.h", "+chrome/browser/ui/browser_finder.h", @@ -55,7 +51,6 @@ "+chrome/browser/ui/webui/ash/settings/search", "+chrome/browser/ui/webui/ash/settings/services/settings_manager", "+chrome/browser/ui/webui/ash/settings/test_support", - "+chrome/browser/ui/webui/chrome_web_ui_controller_factory.h", "+chrome/browser/web_applications/test", "+chrome/browser/web_applications/web_app_provider.h", "+chrome/common/channel_info.h", @@ -67,7 +62,6 @@ # Dependencies outside of //chrome: "+ash/accelerators", - "+ash/assistant/model", "+ash/assistant/util", "+ash/strings/grit", "+chromeos/ui/vector_icons",
diff --git a/chrome/browser/ash/app_list/search/app_search_provider_unittest.cc b/chrome/browser/ash/app_list/search/app_search_provider_unittest.cc index f774b9f9..816811a 100644 --- a/chrome/browser/ash/app_list/search/app_search_provider_unittest.cc +++ b/chrome/browser/ash/app_list/search/app_search_provider_unittest.cc
@@ -29,6 +29,8 @@ #include "chrome/browser/ash/app_list/search/types.h" #include "chrome/browser/ash/crostini/crostini_test_helper.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" @@ -38,6 +40,10 @@ #include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/icon_types.h" #include "components/services/app_service/public/cpp/stub_icon_loader.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registrar.h" #include "extensions/browser/install_prefs_helper.h" @@ -341,7 +347,20 @@ ash::CiceroneClient::InitializeFake(); ash::ConciergeClient::InitializeFake(); ash::SeneschalClient::InitializeFake(); + + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->local_state())); + + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + AppSearchProviderTest::SetUp(); + ash::AnnotatedAccountId::Set(profile(), account_id); } void TearDown() override { @@ -352,11 +371,15 @@ // DBusThreadManager to ensure all keyed services that might rely on DBus // clients are destroyed. profile_.reset(); + user_manager_.Reset(); ash::SeneschalClient::Shutdown(); ash::ConciergeClient::Shutdown(); ash::CiceroneClient::Shutdown(); ash::ChunneldClient::Shutdown(); } + + private: + user_manager::ScopedUserManager user_manager_; }; TEST_F(AppSearchProviderCrostiniTest, CrostiniApp) {
diff --git a/chrome/browser/ash/app_mode/metrics/periodic_metrics_service.cc b/chrome/browser/ash/app_mode/metrics/periodic_metrics_service.cc index f361daa..10f7ed5 100644 --- a/chrome/browser/ash/app_mode/metrics/periodic_metrics_service.cc +++ b/chrome/browser/ash/app_mode/metrics/periodic_metrics_service.cc
@@ -163,12 +163,12 @@ } void PeriodicMetricsService::RecordSwapUsage() const { - base::SystemMemoryInfoKB memory; + base::SystemMemoryInfo memory; if (!base::GetSystemMemoryInfo(&memory)) { return; } - int64_t swap_free = memory.swap_free; - int64_t swap_total = memory.swap_total; + int64_t swap_free = memory.swap_free.InKiB(); + int64_t swap_total = memory.swap_total.InKiB(); ReportUsedPercentage(kKioskSwapUsagePercentageHistogram, swap_free, swap_total); }
diff --git a/chrome/browser/ash/app_restore/DEPS b/chrome/browser/ash/app_restore/DEPS index 8151088..bf13e1c3 100644 --- a/chrome/browser/ash/app_restore/DEPS +++ b/chrome/browser/ash/app_restore/DEPS
@@ -8,7 +8,6 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/app/vector_icons", "+chrome/browser/app_mode", "+chrome/browser/apps/app_service", "+chrome/browser/apps/platform_apps", @@ -20,7 +19,6 @@ "+chrome/browser/ash/policy/scheduled_task_handler", "+chrome/browser/ash/profiles", "+chrome/browser/ash/system_web_apps", - "+chrome/browser/chromeos/full_restore", "+chrome/browser/first_run", "+chrome/browser/lifetime", "+chrome/browser/notifications",
diff --git a/chrome/browser/ash/arc/DEPS b/chrome/browser/ash/arc/DEPS index d0fae80..a04f418 100644 --- a/chrome/browser/ash/arc/DEPS +++ b/chrome/browser/ash/arc/DEPS
@@ -29,8 +29,6 @@ "+chrome/browser/chromeos/policy/dlp", "+chrome/browser/consent_auditor", "+chrome/browser/extensions/api/settings_private", - "+chrome/browser/extensions/api/tabs", - "+chrome/browser/extensions/extension_tab_util.h", "+chrome/browser/lifetime", "+chrome/browser/media/webrtc", "+chrome/browser/memory", @@ -52,7 +50,6 @@ "+chrome/browser/tab_contents", "+chrome/browser/ui/ash", "+chrome/browser/ui/browser_commands.h", - "+chrome/browser/ui/browser_finder.h", "+chrome/browser/ui/browser.h", "+chrome/browser/ui/browser_list.h", "+chrome/browser/ui/browser_list_observer.h",
diff --git a/chrome/browser/ash/arc/auth/DEPS b/chrome/browser/ash/arc/auth/DEPS index 19cae164..7e894153 100644 --- a/chrome/browser/ash/arc/auth/DEPS +++ b/chrome/browser/ash/arc/auth/DEPS
@@ -18,7 +18,6 @@ "+chrome/browser/ash/app_list/arc", "+chrome/browser/ash/arc", "+chrome/browser/ash/login/demo_mode", - "+chrome/browser/ash/login/users", "+chrome/browser/ash/policy/core", "+chrome/browser/ash/profiles", "+chrome/browser/browser_process.h",
diff --git a/chrome/browser/ash/arc/idle_manager/DEPS b/chrome/browser/ash/arc/idle_manager/DEPS index 779f662..f5f8423 100644 --- a/chrome/browser/ash/arc/idle_manager/DEPS +++ b/chrome/browser/ash/arc/idle_manager/DEPS
@@ -17,7 +17,6 @@ "+chrome/browser/ash/arc/instance_throttle", "+chrome/browser/ash/arc/session", "+chrome/browser/ash/arc/test", - "+chrome/browser/ash/arc/util", "+chrome/browser/ash/arc/vmm", "+chrome/test/base", ]
diff --git a/chrome/browser/ash/arc/nearby_share/DEPS b/chrome/browser/ash/arc/nearby_share/DEPS index ad5151db..94b6f33 100644 --- a/chrome/browser/ash/arc/nearby_share/DEPS +++ b/chrome/browser/ash/arc/nearby_share/DEPS
@@ -19,7 +19,6 @@ "+chrome/browser/ash/arc", "+chrome/browser/ash/fileapi", "+chrome/browser/ash/file_manager", - "+chrome/browser/ash/fusebox", "+chrome/browser/browser_process.h", "+chrome/browser/nearby_sharing", "+chrome/browser/profiles",
diff --git a/chrome/browser/ash/arc/optin/DEPS b/chrome/browser/ash/arc/optin/DEPS index ce6045b3..2406d5cb 100644 --- a/chrome/browser/ash/arc/optin/DEPS +++ b/chrome/browser/ash/arc/optin/DEPS
@@ -17,7 +17,6 @@ "+chrome/browser/ash/arc", "+chrome/browser/ash/login", "+chrome/browser/ash/ownership", - "+chrome/browser/ash/policy/core", "+chrome/browser/ash/settings", "+chrome/browser/browser_process.h", "+chrome/browser/consent_auditor",
diff --git a/chrome/browser/ash/arc/print_spooler/DEPS b/chrome/browser/ash/arc/print_spooler/DEPS index 5d2cdf40..90877bb 100644 --- a/chrome/browser/ash/arc/print_spooler/DEPS +++ b/chrome/browser/ash/arc/print_spooler/DEPS
@@ -18,7 +18,6 @@ "+chrome/browser/pdf", "+chrome/browser/printing", "+chrome/browser/profiles", - "+chrome/browser/ui/ash/arc", "+chrome/services/printing/public/mojom", # Dependencies outside of //chrome:
diff --git a/chrome/browser/ash/arc/session/DEPS b/chrome/browser/ash/arc/session/DEPS index f226000..b8375bfe 100644 --- a/chrome/browser/ash/arc/session/DEPS +++ b/chrome/browser/ash/arc/session/DEPS
@@ -32,8 +32,6 @@ "+chrome/browser/browser_process_platform_part.h", "+chrome/browser/certificate_provider", "+chrome/browser/consent_auditor", - "+chrome/browser/extensions/api/tabs", - "+chrome/browser/extensions/extension_tab_util.h", "+chrome/browser/global_features.h", "+chrome/browser/lifetime", "+chrome/browser/net",
diff --git a/chrome/browser/ash/arc/sharesheet/DEPS b/chrome/browser/ash/arc/sharesheet/DEPS index 991a8e5..96b15c3 100644 --- a/chrome/browser/ash/arc/sharesheet/DEPS +++ b/chrome/browser/ash/arc/sharesheet/DEPS
@@ -15,6 +15,5 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/profiles", - "+chrome/browser/ui/browser.h", "+chrome/test/base", ]
diff --git a/chrome/browser/ash/arc/tracing/DEPS b/chrome/browser/ash/arc/tracing/DEPS index 1343c83..9f3c3a0f 100644 --- a/chrome/browser/ash/arc/tracing/DEPS +++ b/chrome/browser/ash/arc/tracing/DEPS
@@ -25,6 +25,5 @@ "+chrome/test/base", # Dependencies outside of //chrome: - "+third_party/perfetto/include", "+third_party/perfetto/protos", ]
diff --git a/chrome/browser/ash/attestation/DEPS b/chrome/browser/ash/attestation/DEPS index ea56983d..1dc6a1333 100644 --- a/chrome/browser/ash/attestation/DEPS +++ b/chrome/browser/ash/attestation/DEPS
@@ -21,7 +21,6 @@ "+chrome/browser/ash/settings", "+chrome/browser/browser_process.h", "+chrome/browser/browser_process_platform_part_ash.h", - "+chrome/browser/chromeos/platform_keys", "+chrome/browser/extensions/chrome_extension_function_details.h", "+chrome/browser/net", "+chrome/browser/policy",
diff --git a/chrome/browser/ash/boca/DEPS b/chrome/browser/ash/boca/DEPS index 55144b7..d7143bfe 100644 --- a/chrome/browser/ash/boca/DEPS +++ b/chrome/browser/ash/boca/DEPS
@@ -9,7 +9,6 @@ "+chrome/app/chrome_command_ids.h", "+chrome/browser/apps/app_service/launch_result_type.h", "+chrome/browser/ash/system_web_apps/system_web_app_manager.h", - "+chrome/browser/enterprise/util/affiliation.h", "+chrome/browser/extensions/extension_service.h", "+chrome/browser/extensions/test_extension_environment.h", "+chrome/browser/extensions/test_extension_system.h", @@ -28,13 +27,11 @@ "+chrome/browser/ui/exclusive_access/exclusive_access_manager.h", "+chrome/browser/ui/exclusive_access/fullscreen_controller.h", "+chrome/browser/ui/views/frame/browser_view.h", - "+chrome/browser/ui/tabs/tab_enums.h", "+chrome/browser/ui/tabs/tab_strip_model_delegate.h", "+chrome/browser/ui/tabs/tab_strip_model_observer.h", "+chrome/browser/ui/views/frame/immersive_mode_controller.h", "+chrome/test/base/in_process_browser_test.h", "+chrome/test/base/testing_profile.h", - "+chrome/test/base/testing_profile_manager.h", "+chrome/browser/ash/settings/device_settings_service.h", "+components/sessions", # Files needed by babelorca/
diff --git a/chrome/browser/ash/browser_delegate/BUILD.gn b/chrome/browser/ash/browser_delegate/BUILD.gn index e96d8583..af8b94f7 100644 --- a/chrome/browser/ash/browser_delegate/BUILD.gn +++ b/chrome/browser/ash/browser_delegate/BUILD.gn
@@ -42,6 +42,7 @@ deps = [ "//chrome/browser:browser_public_dependencies", + "//chrome/browser/devtools", "//chrome/browser/profiles:profile", "//chrome/browser/ui:browser_navigator_params_headers", "//chrome/browser/ui/autofill",
diff --git a/chrome/browser/ash/browser_delegate/browser_delegate.h b/chrome/browser/ash/browser_delegate/browser_delegate.h index b671e51..bbc52a9 100644 --- a/chrome/browser/ash/browser_delegate/browser_delegate.h +++ b/chrome/browser/ash/browser_delegate/browser_delegate.h
@@ -66,6 +66,11 @@ // be nullptr even if index is in bounds, just like GetActiveWebContents(). virtual content::WebContents* GetWebContentsAt(size_t index) const = 0; + // Returns the inspected web contents if this is a kDevTools type browser. + // Returns nullptr otherwise. + // Can also be nullptr while the browser is initialized/shutdown. + virtual content::WebContents* GetInspectedWebContents() const = 0; + // Returns the native window. Can be nullptr, e.g. when the browser is being // closed. virtual aura::Window* GetNativeWindow() const = 0;
diff --git a/chrome/browser/ash/browser_delegate/browser_delegate_impl.cc b/chrome/browser/ash/browser_delegate/browser_delegate_impl.cc index 1bd01e7..c8cbb24 100644 --- a/chrome/browser/ash/browser_delegate/browser_delegate_impl.cc +++ b/chrome/browser/ash/browser_delegate/browser_delegate_impl.cc
@@ -6,7 +6,9 @@ #include "base/check_deref.h" #include "base/check_is_test.h" +#include "chrome/browser/ash/browser_delegate/browser_type.h" #include "chrome/browser/ash/browser_delegate/browser_type_conversion.h" +#include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_navigator_params.h" @@ -72,6 +74,19 @@ return browser_->tab_strip_model()->GetWebContentsAt(index); } +content::WebContents* BrowserDelegateImpl::GetInspectedWebContents() const { + if (GetType() != BrowserType::kDevTools) { + return nullptr; + } + + content::WebContents* target_tab = nullptr; + if (auto* dev_tools_window = DevToolsWindow::AsDevToolsWindow(&*browser_)) { + target_tab = dev_tools_window->GetInspectedWebContents(); + } + + return target_tab; +} + aura::Window* BrowserDelegateImpl::GetNativeWindow() const { return browser_->window()->GetNativeWindow(); }
diff --git a/chrome/browser/ash/browser_delegate/browser_delegate_impl.h b/chrome/browser/ash/browser_delegate/browser_delegate_impl.h index a8f0f20..f29e1c3b 100644 --- a/chrome/browser/ash/browser_delegate/browser_delegate_impl.h +++ b/chrome/browser/ash/browser_delegate/browser_delegate_impl.h
@@ -27,6 +27,7 @@ content::WebContents* GetActiveWebContents() const override; size_t GetWebContentsCount() const override; content::WebContents* GetWebContentsAt(size_t index) const override; + content::WebContents* GetInspectedWebContents() const override; aura::Window* GetNativeWindow() const override; std::optional<webapps::AppId> GetAppId() const override; bool IsWebApp() const override;
diff --git a/chrome/browser/ash/browser_delegate/browser_type.h b/chrome/browser/ash/browser_delegate/browser_type.h index ed5f633..6348e43 100644 --- a/chrome/browser/ash/browser_delegate/browser_type.h +++ b/chrome/browser/ash/browser_delegate/browser_type.h
@@ -13,6 +13,7 @@ enum class BrowserType { kApp, kAppPopup, + kDevTools, kOther, };
diff --git a/chrome/browser/ash/browser_delegate/browser_type_conversion.cc b/chrome/browser/ash/browser_delegate/browser_type_conversion.cc index 66427c18..03211a5 100644 --- a/chrome/browser/ash/browser_delegate/browser_type_conversion.cc +++ b/chrome/browser/ash/browser_delegate/browser_type_conversion.cc
@@ -12,6 +12,8 @@ return BrowserWindowInterface::TYPE_APP; case BrowserType::kAppPopup: return BrowserWindowInterface::TYPE_APP_POPUP; + case BrowserType::kDevTools: + return BrowserWindowInterface::TYPE_DEVTOOLS; case BrowserType::kOther: NOTREACHED(); } @@ -24,6 +26,8 @@ return BrowserType::kApp; case BrowserWindowInterface::TYPE_APP_POPUP: return BrowserType::kAppPopup; + case BrowserWindowInterface::TYPE_DEVTOOLS: + return BrowserType::kDevTools; default: return BrowserType::kOther; }
diff --git a/chrome/browser/ash/cert_provisioning/DEPS b/chrome/browser/ash/cert_provisioning/DEPS index 1d024766..6c77394 100644 --- a/chrome/browser/ash/cert_provisioning/DEPS +++ b/chrome/browser/ash/cert_provisioning/DEPS
@@ -15,16 +15,12 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/attestation", - "+chrome/browser/ash/crosapi", - "+chrome/browser/ash/login/startup_utils.h", "+chrome/browser/ash/login/users", "+chrome/browser/ash/platform_keys", "+chrome/browser/ash/policy/core", - "+chrome/browser/ash/policy/invalidation", "+chrome/browser/ash/profiles", "+chrome/browser/browser_process.h", "+chrome/browser/browser_process_platform_part.h", - "+chrome/browser/chromeos/platform_keys", "+chrome/browser/invalidation", "+chrome/browser/policy", "+chrome/browser/profiles",
diff --git a/chrome/browser/ash/child_accounts/parent_access_code/DEPS b/chrome/browser/ash/child_accounts/parent_access_code/DEPS index ca08cdba..b4d42cfd 100644 --- a/chrome/browser/ash/child_accounts/parent_access_code/DEPS +++ b/chrome/browser/ash/child_accounts/parent_access_code/DEPS
@@ -15,7 +15,6 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/login/test", - "+chrome/browser/ash/login/users", "+chrome/browser/ash/policy/core", "+chrome/browser/ash/profiles", "+chrome/browser/browser_process.h",
diff --git a/chrome/browser/ash/child_accounts/time_limits/DEPS b/chrome/browser/ash/child_accounts/time_limits/DEPS index 3b625e4..a80ae1f 100644 --- a/chrome/browser/ash/child_accounts/time_limits/DEPS +++ b/chrome/browser/ash/child_accounts/time_limits/DEPS
@@ -30,7 +30,6 @@ "+chrome/browser/web_applications/web_app_helpers.h", "+chrome/browser/web_applications/web_app_install_finalizer.h", "+chrome/browser/web_applications/web_app_provider.h", - "+chrome/browser/web_applications/web_app_sync_bridge.h", "+chrome/common/chrome_features.h", "+chrome/common/chrome_switches.h", "+chrome/common/extensions",
diff --git a/chrome/browser/ash/chromebox_for_meetings/DEPS b/chrome/browser/ash/chromebox_for_meetings/DEPS index a00aa1d..d65b5e8 100644 --- a/chrome/browser/ash/chromebox_for_meetings/DEPS +++ b/chrome/browser/ash/chromebox_for_meetings/DEPS
@@ -14,7 +14,6 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/browser/ash/policy/core", "+chrome/browser/ash/settings", "+chrome/browser/media/webrtc", "+chrome/browser/memory_details.h",
diff --git a/chrome/browser/ash/chromebox_for_meetings/artemis/DEPS b/chrome/browser/ash/chromebox_for_meetings/artemis/DEPS index 1f854a5c..b9bbaac 100644 --- a/chrome/browser/ash/chromebox_for_meetings/artemis/DEPS +++ b/chrome/browser/ash/chromebox_for_meetings/artemis/DEPS
@@ -15,5 +15,4 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/chromebox_for_meetings", - "+chrome/browser/ash/crosapi", ]
diff --git a/chrome/browser/ash/chromebox_for_meetings/device_info/DEPS b/chrome/browser/ash/chromebox_for_meetings/device_info/DEPS index 2bfdf07..b00f640 100644 --- a/chrome/browser/ash/chromebox_for_meetings/device_info/DEPS +++ b/chrome/browser/ash/chromebox_for_meetings/device_info/DEPS
@@ -15,7 +15,6 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/chromebox_for_meetings", - "+chrome/browser/ash/policy/core", "+chrome/browser/ash/settings", "+chrome/common/channel_info.h", ]
diff --git a/chrome/browser/ash/crosapi/DEPS b/chrome/browser/ash/crosapi/DEPS index c8fd54bf..00339985 100644 --- a/chrome/browser/ash/crosapi/DEPS +++ b/chrome/browser/ash/crosapi/DEPS
@@ -21,12 +21,10 @@ "+chrome/browser/ash/app_list", "+chrome/browser/ash/app_mode", "+chrome/browser/ash/app_restore", - "+chrome/browser/ash/apps", "+chrome/browser/ash/arc", "+chrome/browser/ash/attestation", "+chrome/browser/ash/cert_provisioning", "+chrome/browser/ash/fileapi", - "+chrome/browser/ash/file_manager", "+chrome/browser/ash/file_system_provider", "+chrome/browser/ash/floating_workspace", "+chrome/browser/ash/guest_os", @@ -77,8 +75,6 @@ "+chrome/browser/signin", "+chrome/browser/speech", "+chrome/browser/ui/ash", - "+chrome/browser/ui/browser_commands.h", - "+chrome/browser/ui/browser.h", "+chrome/browser/ui/browser_list.h", "+chrome/browser/ui/browser_window.h", "+chrome/browser/ui/chrome_pages.h",
diff --git a/chrome/browser/ash/crostini/BUILD.gn b/chrome/browser/ash/crostini/BUILD.gn index 242f375f..548ddac 100644 --- a/chrome/browser/ash/crostini/BUILD.gn +++ b/chrome/browser/ash/crostini/BUILD.gn
@@ -289,6 +289,7 @@ "//chrome/common", "//chrome/common:chrome_features", "//chrome/test:test_support", + "//chromeos/ash/components/browser_context_helper", "//chromeos/ash/components/dbus/anomaly_detector", "//chromeos/ash/components/dbus/chunneld", "//chromeos/ash/components/dbus/cicerone",
diff --git a/chrome/browser/ash/crostini/crostini_disk_unittest.cc b/chrome/browser/ash/crostini/crostini_disk_unittest.cc index a61a080..3b900d2 100644 --- a/chrome/browser/ash/crostini/crostini_disk_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_disk_unittest.cc
@@ -13,13 +13,21 @@ #include "chrome/browser/ash/crostini/crostini_manager.h" #include "chrome/browser/ash/crostini/crostini_test_helper.h" #include "chrome/browser/ash/crostini/crostini_types.mojom.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" #include "chromeos/ash/components/dbus/concierge/fake_concierge_client.h" #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" #include "chromeos/ash/components/dbus/vm_concierge/concierge_service.pb.h" +#include "components/account_id/account_id.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h" @@ -54,16 +62,26 @@ class CrostiniDiskTestDbus : public CrostiniDiskTest { public: - CrostiniDiskTestDbus() { + void SetUp() override { ash::ChunneldClient::InitializeFake(); ash::CiceroneClient::InitializeFake(); ash::ConciergeClient::InitializeFake(); ash::SeneschalClient::InitializeFake(); fake_concierge_client_ = ash::FakeConciergeClient::Get(); - } - void SetUp() override { + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + profile_ = std::make_unique<TestingProfile>(); + ash::AnnotatedAccountId::Set(profile_.get(), account_id); + test_helper_ = std::make_unique<CrostiniTestHelper>(profile_.get()); CrostiniManager::GetForProfile(profile_.get()) ->set_skip_restart_for_testing(); @@ -72,6 +90,9 @@ void TearDown() override { test_helper_.reset(); profile_.reset(); + user_manager_.Reset(); + + fake_concierge_client_ = nullptr; ash::SeneschalClient::Shutdown(); ash::ConciergeClient::Shutdown(); ash::CiceroneClient::Shutdown(); @@ -92,8 +113,8 @@ Profile* profile() { return profile_.get(); } content::BrowserTaskEnvironment task_environment_; - raw_ptr<ash::FakeConciergeClient, DanglingUntriaged> fake_concierge_client_; - + raw_ptr<ash::FakeConciergeClient> fake_concierge_client_; + user_manager::ScopedUserManager user_manager_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<CrostiniTestHelper> test_helper_; };
diff --git a/chrome/browser/ash/crostini/crostini_export_import_unittest.cc b/chrome/browser/ash/crostini/crostini_export_import_unittest.cc index 4e29171..c41b0998 100644 --- a/chrome/browser/ash/crostini/crostini_export_import_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_export_import_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h" @@ -30,7 +31,13 @@ #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" #include "chromeos/ash/components/dbus/seneschal/seneschal_service.pb.h" #include "chromeos/ash/components/dbus/vm_concierge/concierge_service.pb.h" +#include "components/account_id/account_id.h" #include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "storage/browser/file_system/external_mount_points.h" #include "testing/gtest/include/gtest/gtest.h" @@ -165,7 +172,19 @@ } void SetUp() override { + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + profile_ = std::make_unique<TestingProfile>(); + ash::AnnotatedAccountId::Set(profile_.get(), account_id); + crostini_export_import_ = std::make_unique<CrostiniExportImport>(profile()); test_helper_ = std::make_unique<CrostiniTestHelper>(profile_.get()); notification_display_service_tester_ = @@ -202,11 +221,13 @@ base::DeleteFile(tarball_); test_helper_.reset(); profile_.reset(); + user_manager_.Reset(); } protected: Profile* profile() { return profile_.get(); } + user_manager::ScopedUserManager user_manager_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<CrostiniExportImport> crostini_export_import_; std::unique_ptr<CrostiniTestHelper> test_helper_;
diff --git a/chrome/browser/ash/crostini/crostini_installer_unittest.cc b/chrome/browser/ash/crostini/crostini_installer_unittest.cc index f072fe8..368c052 100644 --- a/chrome/browser/ash/crostini/crostini_installer_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_installer_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h" @@ -33,7 +34,13 @@ #include "chromeos/ash/components/dbus/vm_concierge/concierge_service.pb.h" #include "chromeos/ash/components/disks/disk_mount_manager.h" #include "chromeos/ash/components/disks/mock_disk_mount_manager.h" +#include "components/account_id/account_id.h" #include "components/component_updater/ash/fake_component_manager_ash.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -127,7 +134,19 @@ ash::disks::DiskMountManager::InitializeForTesting( disk_mount_manager_mock_); + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + profile_ = std::make_unique<TestingProfile>(); + ash::AnnotatedAccountId::Set(profile_.get(), account_id); + // Needed at least for passing IsCrostiniUIAllowedForProfile() test in // CrostiniManager. crostini_test_helper_ = @@ -148,7 +167,7 @@ crostini_installer_.reset(); crostini_test_helper_.reset(); profile_.reset(); - + user_manager_.Reset(); ash::disks::MockDiskMountManager::Shutdown(); ash::SeneschalClient::Shutdown(); ash::DebugDaemonClient::Shutdown(); @@ -192,6 +211,7 @@ raw_ptr<WaitingFakeConciergeClient, DanglingUntriaged> waiting_fake_concierge_client_ = nullptr; + user_manager::ScopedUserManager user_manager_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<CrostiniTestHelper> crostini_test_helper_; std::unique_ptr<CrostiniInstaller> crostini_installer_;
diff --git a/chrome/browser/ash/crostini/crostini_package_service_unittest.cc b/chrome/browser/ash/crostini/crostini_package_service_unittest.cc index 5704c42..01eb715d 100644 --- a/chrome/browser/ash/crostini/crostini_package_service_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_package_service_unittest.cc
@@ -20,7 +20,9 @@ #include "chrome/browser/notifications/notification_display_service_factory.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/grit/generated_resources.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/cicerone/fake_cicerone_client.h" @@ -29,6 +31,12 @@ #include "chromeos/ash/components/dbus/seneschal/fake_seneschal_client.h" #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" #include "chromeos/ash/components/dbus/vm_applications/apps.pb.h" +#include "components/account_id/account_id.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "storage/browser/file_system/external_mount_points.h" #include "testing/gmock/include/gmock/gmock.h" @@ -159,8 +167,21 @@ base::test::TaskEnvironment::MainThreadType::UI, base::test::TaskEnvironment::ThreadPoolExecutionMode::ASYNC, content::BrowserTaskEnvironment::REAL_IO_THREAD); + + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + profile_ = std::make_unique<TestingProfile>( base::FilePath("/home/chronos/u-0123456789abcdef")); + ash::AnnotatedAccountId::Set(profile_.get(), account_id); + crostini_test_helper_ = std::make_unique<CrostiniTestHelper>(profile_.get()); notification_display_service_tester_ = @@ -202,6 +223,7 @@ notification_display_service_tester_.reset(); crostini_test_helper_.reset(); profile_.reset(); + user_manager_.Reset(); task_environment_.reset(); ash::SeneschalClient::Shutdown(); ash::ConciergeClient::Shutdown(); @@ -349,6 +371,8 @@ nullptr; std::unique_ptr<content::BrowserTaskEnvironment> task_environment_; + + user_manager::ScopedUserManager user_manager_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<CrostiniTestHelper> crostini_test_helper_; std::unique_ptr<NotificationDisplayServiceTester>
diff --git a/chrome/browser/ash/crostini/crostini_test_helper.cc b/chrome/browser/ash/crostini/crostini_test_helper.cc index 70dc0b47..65d1fc7 100644 --- a/chrome/browser/ash/crostini/crostini_test_helper.cc +++ b/chrome/browser/ash/crostini/crostini_test_helper.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ash/crostini/crostini_test_helper.h" +#include "base/check_deref.h" #include "base/feature_list.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" @@ -13,12 +14,10 @@ #include "chrome/browser/ash/guest_os/guest_os_registry_service.h" #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h" #include "chrome/browser/ash/guest_os/public/guest_os_service.h" -#include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "components/prefs/pref_service.h" -#include "components/user_manager/scoped_user_manager.h" #include "google_apis/gaia/gaia_id.h" #include "third_party/skia/include/core/SkColor.h" @@ -30,17 +29,8 @@ constexpr SkColor kTestContainerBadgeColor = SK_ColorBLUE; CrostiniTestHelper::CrostiniTestHelper(Profile* profile, bool enable_crostini) - : fake_user_manager_(std::make_unique<ash::FakeChromeUserManager>()), - profile_(profile) { + : profile_(CHECK_DEREF(profile)) { scoped_feature_list_.InitAndEnableFeature(features::kCrostini); - - ash::ProfileHelper::SetAlwaysReturnPrimaryUserForTesting(true); - auto account = - AccountId::FromUserEmailGaiaId("test@example.com", GaiaId("12345")); - fake_user_manager_->AddUserWithAffiliationAndTypeAndProfile( - account, false, user_manager::UserType::kRegular, profile); - fake_user_manager_->LoginUser(account); - if (enable_crostini) { EnableCrostini(profile); } @@ -48,14 +38,13 @@ current_apps_.set_vm_name(kCrostiniDefaultVmName); current_apps_.set_container_name(kCrostiniDefaultContainerName); - guest_os::AddContainerToPrefs(profile_, DefaultContainerId(), {}); - SetContainerBadgeColor(profile_, DefaultContainerId(), + guest_os::AddContainerToPrefs(profile, DefaultContainerId(), {}); + SetContainerBadgeColor(profile, DefaultContainerId(), kTestContainerBadgeColor); } CrostiniTestHelper::~CrostiniTestHelper() { - ash::ProfileHelper::SetAlwaysReturnPrimaryUserForTesting(false); - DisableCrostini(profile_); + DisableCrostini(&*profile_); } void CrostiniTestHelper::SetupDummyApps() { @@ -113,7 +102,7 @@ // // We therefore manually have the App Service re-examine whether Crostini // is enabled for this profile. - auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile_); + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(&*profile_); proxy->ReInitializeCrostiniForTesting(); } @@ -173,7 +162,7 @@ } void CrostiniTestHelper::UpdateRegistry() { - guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile_) + guest_os::GuestOsRegistryServiceFactory::GetForProfile(&*profile_) ->UpdateApplicationList(current_apps_); }
diff --git a/chrome/browser/ash/crostini/crostini_test_helper.h b/chrome/browser/ash/crostini/crostini_test_helper.h index 9e2c8de..ca4b3b8 100644 --- a/chrome/browser/ash/crostini/crostini_test_helper.h +++ b/chrome/browser/ash/crostini/crostini_test_helper.h
@@ -8,10 +8,9 @@ #include <map> #include <string> -#include "base/memory/raw_ptr.h" +#include "base/memory/raw_ref.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/ash/crostini/crostini_util.h" -#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chromeos/ash/components/dbus/vm_applications/apps.pb.h" #include "components/user_manager/scoped_user_manager.h" @@ -25,6 +24,7 @@ public: // For convenience, instantiating this allows Crostini, and enables it // unless enable_crostini is false. The destructor resets these. + // `profile` must outlive this instance. explicit CrostiniTestHelper(Profile* profile, bool enable_crostini = true); ~CrostiniTestHelper(); @@ -73,9 +73,7 @@ private: void UpdateRegistry(); - user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> - fake_user_manager_; - raw_ptr<Profile> profile_; + const raw_ref<Profile> profile_; vm_tools::apps::ApplicationList current_apps_; // This are used to allow Crostini.
diff --git a/chrome/browser/ash/crostini/crostini_util_unittest.cc b/chrome/browser/ash/crostini/crostini_util_unittest.cc index 0c9e128..f4607eb 100644 --- a/chrome/browser/ash/crostini/crostini_util_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_util_unittest.cc
@@ -15,6 +15,7 @@ #include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" @@ -22,8 +23,14 @@ #include "chromeos/ash/components/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/ash/components/dbus/dlcservice/dlcservice_client.h" #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" +#include "components/account_id/account_id.h" #include "components/component_updater/ash/fake_component_manager_ash.h" #include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -71,7 +78,18 @@ base::FilePath("/install/path"), base::FilePath("/mount/path"))); browser_part_.InitializeComponentManager(component_manager_); + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + profile_ = std::make_unique<TestingProfile>(); + ash::AnnotatedAccountId::Set(profile_.get(), account_id); test_helper_ = std::make_unique<CrostiniTestHelper>(profile_.get()); test_helper_->SetupDummyApps(); g_browser_process->platform_part() @@ -82,6 +100,7 @@ g_browser_process->platform_part()->ShutdownSchedulerConfigurationManager(); test_helper_.reset(); profile_.reset(); + user_manager_.Reset(); browser_part_.ShutdownComponentManager(); component_manager_.reset(); ash::DlcserviceClient::Shutdown(); @@ -90,6 +109,7 @@ protected: raw_ptr<ash::FakeConciergeClient, DanglingUntriaged> fake_concierge_client_; + user_manager::ScopedUserManager user_manager_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<CrostiniTestHelper> test_helper_; std::string app_id_;
diff --git a/chrome/browser/ash/data_migration/DEPS b/chrome/browser/ash/data_migration/DEPS index 86f93739..a586416 100644 --- a/chrome/browser/ash/data_migration/DEPS +++ b/chrome/browser/ash/data_migration/DEPS
@@ -15,6 +15,5 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/nearby", - "+chrome/browser/nearby_sharing", "+chrome/browser/profiles", ]
diff --git a/chrome/browser/ash/dbus/DEPS b/chrome/browser/ash/dbus/DEPS index 094938e..e56dcb08 100644 --- a/chrome/browser/ash/dbus/DEPS +++ b/chrome/browser/ash/dbus/DEPS
@@ -44,7 +44,6 @@ "+chrome/browser/enterprise/browser_management", "+chrome/browser/policy", "+chrome/browser/profiles", - "+chrome/browser/resource_coordinator", "+chrome/browser/ui/browser.h", "+chrome/browser/ui/chrome_pages.h", "+chrome/browser/ui/chrome_select_file_policy.h",
diff --git a/chrome/browser/ash/exo/BUILD.gn b/chrome/browser/ash/exo/BUILD.gn index a15ea3e..626b160 100644 --- a/chrome/browser/ash/exo/BUILD.gn +++ b/chrome/browser/ash/exo/BUILD.gn
@@ -52,6 +52,7 @@ "//chrome/browser/ash/guest_os", "//chrome/browser/ash/plugin_vm", "//chrome/test:test_support", + "//chromeos/ash/components/browser_context_helper", "//chromeos/ash/components/dbus", "//chromeos/ash/components/dbus/chunneld", "//chromeos/ash/components/dbus/seneschal",
diff --git a/chrome/browser/ash/exo/DEPS b/chrome/browser/ash/exo/DEPS index f51a226..9276ef0 100644 --- a/chrome/browser/ash/exo/DEPS +++ b/chrome/browser/ash/exo/DEPS
@@ -25,3 +25,9 @@ "+chrome/browser/profiles", "+chrome/test/base", ] + +specific_include_rules = { + ".*test\\.cc": [ + "+chrome/browser/ash/login/users/scoped_account_id_annotator.h", + ] +}
diff --git a/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc b/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc index a74754f9..00939499 100644 --- a/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc +++ b/chrome/browser/ash/exo/chrome_data_exchange_delegate_unittest.cc
@@ -10,11 +10,21 @@ #include "chrome/browser/ash/crostini/crostini_test_helper.h" #include "chrome/browser/ash/crostini/crostini_util.h" #include "chrome/browser/ash/file_manager/path_util.h" +#include "chrome/browser/ash/login/users/scoped_account_id_annotator.h" #include "chrome/browser/ash/plugin_vm/plugin_vm_util.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ui/base/app_types.h" #include "chromeos/ui/base/window_properties.h" +#include "components/account_id/account_id.h" #include "components/exo/shell_surface_util.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/common/drop_data.h" #include "content/public/test/browser_task_environment.h" #include "storage/browser/file_system/external_mount_points.h" @@ -36,7 +46,27 @@ class ChromeDataExchangeDelegateTest : public testing::Test { public: void SetUp() override { - profile_ = std::make_unique<TestingProfile>(); + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(profile_manager_->SetUp()); + + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + + { + ash::ScopedAccountIdAnnotator annotator( + profile_manager_->profile_manager(), account_id); + profile_ = + profile_manager_->CreateTestingProfile(account_id.GetUserEmail()); + } + test_helper_ = std::make_unique<crostini::CrostiniTestHelper>(profile_.get()); @@ -56,14 +86,18 @@ void TearDown() override { mount_points_->RevokeAllFileSystems(); test_helper_.reset(); - profile_.reset(); + profile_ = nullptr; + profile_manager_.reset(); + user_manager_.Reset(); } protected: Profile* profile() { return profile_.get(); } content::BrowserTaskEnvironment task_environment_; - std::unique_ptr<TestingProfile> profile_; + user_manager::ScopedUserManager user_manager_; + std::unique_ptr<TestingProfileManager> profile_manager_; + raw_ptr<TestingProfile> profile_; std::unique_ptr<crostini::CrostiniTestHelper> test_helper_; aura::test::TestWindowDelegate delegate_; raw_ptr<storage::ExternalMountPoints> mount_points_;
diff --git a/chrome/browser/ash/exo/chrome_security_delegate_unittest.cc b/chrome/browser/ash/exo/chrome_security_delegate_unittest.cc index a2a67f8..f37fc58 100644 --- a/chrome/browser/ash/exo/chrome_security_delegate_unittest.cc +++ b/chrome/browser/ash/exo/chrome_security_delegate_unittest.cc
@@ -21,9 +21,12 @@ #include "chrome/browser/ash/guest_os/guest_os_security_delegate.h" #include "chrome/browser/ash/guest_os/guest_os_share_path.h" #include "chrome/browser/ash/guest_os/guest_os_share_path_factory.h" +#include "chrome/browser/ash/login/users/scoped_account_id_annotator.h" #include "chrome/browser/ash/plugin_vm/plugin_vm_util.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" @@ -31,6 +34,12 @@ #include "chromeos/ash/components/dbus/seneschal/seneschal_client.h" #include "chromeos/ui/base/app_types.h" #include "chromeos/ui/base/window_properties.h" +#include "components/account_id/account_id.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "storage/browser/file_system/external_mount_points.h" #include "testing/gtest/include/gtest/gtest.h" @@ -75,7 +84,27 @@ ConciergeClient::InitializeFake(); SeneschalClient::InitializeFake(); - profile_ = std::make_unique<TestingProfile>(); + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(profile_manager_->SetUp()); + + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); + + { + ash::ScopedAccountIdAnnotator annotator( + profile_manager_->profile_manager(), account_id); + profile_ = + profile_manager_->CreateTestingProfile(account_id.GetUserEmail()); + } + test_helper_ = std::make_unique<crostini::CrostiniTestHelper>(profile_.get()); @@ -114,7 +143,9 @@ void TearDown() override { mount_points_->RevokeAllFileSystems(); test_helper_.reset(); - profile_.reset(); + profile_ = nullptr; + profile_manager_.reset(); + user_manager_.Reset(); SeneschalClient::Shutdown(); ConciergeClient::Shutdown(); CiceroneClient::Shutdown(); @@ -125,8 +156,9 @@ Profile* profile() { return profile_.get(); } content::BrowserTaskEnvironment task_environment_; - - std::unique_ptr<TestingProfile> profile_; + user_manager::ScopedUserManager user_manager_; + std::unique_ptr<TestingProfileManager> profile_manager_; + raw_ptr<TestingProfile> profile_ = nullptr; std::unique_ptr<crostini::CrostiniTestHelper> test_helper_; raw_ptr<storage::ExternalMountPoints> mount_points_;
diff --git a/chrome/browser/ash/extensions/DEPS b/chrome/browser/ash/extensions/DEPS index cb3edd8..8595f14 100644 --- a/chrome/browser/ash/extensions/DEPS +++ b/chrome/browser/ash/extensions/DEPS
@@ -13,7 +13,6 @@ "+chrome/browser/apps/platform_apps/api/media_galleries", "+chrome/browser/ash/accessibility", "+chrome/browser/ash/app_list/arc", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/file_manager", "+chrome/browser/ash/guest_os", "+chrome/browser/ash/input_method", @@ -34,7 +33,6 @@ "+chrome/browser/download", "+chrome/browser/extensions/api/file_system", "+chrome/browser/extensions/api/input_ime", - "+chrome/browser/extensions/api/messaging", "+chrome/browser/extensions/api/settings_private", "+chrome/browser/extensions/chrome_app_icon.h", "+chrome/browser/extensions/chrome_extension_function_details.h", @@ -50,10 +48,8 @@ "+chrome/browser/extensions/install_observer.h", "+chrome/browser/extensions/install_tracker.h", "+chrome/browser/extensions/mock_crx_installer.h", - "+chrome/browser/extensions/pending_extension_manager.h", "+chrome/browser/extensions/updater", "+chrome/browser/lifetime", - "+chrome/browser/metrics", "+chrome/browser/net", "+chrome/browser/notifications", "+chrome/browser/pdf",
diff --git a/chrome/browser/ash/extensions/autotest_private/DEPS b/chrome/browser/ash/extensions/autotest_private/DEPS index 13049e1..394757ee 100644 --- a/chrome/browser/ash/extensions/autotest_private/DEPS +++ b/chrome/browser/ash/extensions/autotest_private/DEPS
@@ -11,10 +11,8 @@ "+chrome/browser/ash/app_list/arc", "+chrome/browser/ash/app_list/search", "+chrome/browser/ash/arc", - "+chrome/browser/ash/assistant", "+chrome/browser/ash/borealis", "+chrome/browser/ash/bruschetta", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/crostini", "+chrome/browser/ash/file_manager", "+chrome/browser/ash/fusebox", @@ -36,7 +34,6 @@ "+chrome/browser/component_updater", "+chrome/browser/extensions/component_loader.h", "+chrome/browser/extensions/extension_apitest.h", - "+chrome/browser/extensions/extension_service.h", "+chrome/browser/lifetime", "+chrome/browser/platform_util.h", "+chrome/browser/policy",
diff --git a/chrome/browser/ash/extensions/file_manager/DEPS b/chrome/browser/ash/extensions/file_manager/DEPS index 678331b5..c9e97cc 100644 --- a/chrome/browser/ash/extensions/file_manager/DEPS +++ b/chrome/browser/ash/extensions/file_manager/DEPS
@@ -6,7 +6,6 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/app/vector_icons", "+chrome/browser/app_mode", "+chrome/browser/apps/app_service", "+chrome/browser/apps/platform_apps/api/media_galleries", @@ -39,7 +38,6 @@ "+chrome/browser/extensions/extension_util.h", "+chrome/browser/feedback/show_feedback_page.h", "+chrome/browser/lifetime", - "+chrome/browser/metrics", "+chrome/browser/net", "+chrome/browser/notifications", "+chrome/browser/pdf", @@ -52,7 +50,6 @@ "+chrome/browser/ui/ash/multi_user", "+chrome/browser/ui/ash/system_web_apps", "+chrome/browser/ui/browser.h", - "+chrome/browser/ui/browser_list.h", "+chrome/browser/ui/browser_window.h", "+chrome/browser/ui/chrome_pages.h", "+chrome/browser/ui/settings_window_manager_chromeos.h",
diff --git a/chrome/browser/ash/extensions/users_private/DEPS b/chrome/browser/ash/extensions/users_private/DEPS index c633ad6e..0e2cb34c 100644 --- a/chrome/browser/ash/extensions/users_private/DEPS +++ b/chrome/browser/ash/extensions/users_private/DEPS
@@ -19,7 +19,6 @@ "+chrome/browser/ash/ownership", "+chrome/browser/ash/policy/core", "+chrome/browser/ash/profiles", - "+chrome/browser/ash/settings", "+chrome/browser/browser_process.h", "+chrome/browser/browser_process_platform_part.h", "+chrome/browser/extensions/api/settings_private",
diff --git a/chrome/browser/ash/file_manager/DEPS b/chrome/browser/ash/file_manager/DEPS index 59580e3..f1dc8df 100644 --- a/chrome/browser/ash/file_manager/DEPS +++ b/chrome/browser/ash/file_manager/DEPS
@@ -20,7 +20,6 @@ "+chrome/browser/ash/arc", "+chrome/browser/ash/base", "+chrome/browser/ash/bruschetta", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/crostini", "+chrome/browser/ash/drive", "+chrome/browser/ash/extensions/file_manager", @@ -65,7 +64,6 @@ "+chrome/browser/ui/webui/extensions", "+chrome/browser/web_applications/isolated_web_apps", "+chrome/browser/web_applications/os_integration", - "+chrome/browser/web_applications/web_app_helpers.h", "+chrome/browser/web_applications/web_app_provider.h", "+chrome/browser/web_applications/web_app_registry_update.h", "+chrome/browser/web_applications/web_app_sync_bridge.h",
diff --git a/chrome/browser/ash/input_method/DEPS b/chrome/browser/ash/input_method/DEPS index 5d0368e..fc03652c 100644 --- a/chrome/browser/ash/input_method/DEPS +++ b/chrome/browser/ash/input_method/DEPS
@@ -14,8 +14,6 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/browser/ash/crosapi", - "+chrome/browser/ash/file_manager", "+chrome/browser/ash/lobster/lobster_event_sink.h", "+chrome/browser/ash/lobster/lobster_service_provider.h", "+chrome/browser/ash/magic_boost/magic_boost_controller_ash.h", @@ -23,7 +21,6 @@ "+chrome/browser/browser_process.h", "+chrome/browser/browser_process_platform_part_ash.h", "+chrome/browser/extensions/component_loader.h", - "+chrome/browser/extensions/extension_service.h", "+chrome/browser/feedback", "+chrome/browser/lifetime", "+chrome/browser/manta",
diff --git a/chrome/browser/ash/lobster/DEPS b/chrome/browser/ash/lobster/DEPS index d13c40d3..e4732a8 100644 --- a/chrome/browser/ash/lobster/DEPS +++ b/chrome/browser/ash/lobster/DEPS
@@ -10,7 +10,6 @@ # Existing dependencies within //chrome. There is an active effort to # refactor //chrome/browser/ash to break these dependencies; see b/332804822. # Whenever possible, avoid adding new //chrome dependencies to this list. - "+chrome/browser/ash/login/demo_mode/demo_session.h", "+chrome/browser/ash/login/users/fake_chrome_user_manager.h", "+chrome/browser/ash/magic_boost", "+chrome/browser/browser_process.h",
diff --git a/chrome/browser/ash/login/DEPS b/chrome/browser/ash/login/DEPS index a2f883c..6c0d516 100644 --- a/chrome/browser/ash/login/DEPS +++ b/chrome/browser/ash/login/DEPS
@@ -36,9 +36,6 @@ "+chrome/browser/certificate_provider", "+chrome/browser/chrome_browser_main_extra_parts.h", "+chrome/browser/chrome_browser_main.h", - "+chrome/browser/chromeos/app_mode", - "+chrome/browser/command_updater_delegate.h", - "+chrome/browser/command_updater_impl.h", "+chrome/browser/component_updater", "+chrome/browser/consent_auditor", "+chrome/browser/content_settings", @@ -69,7 +66,6 @@ "+chrome/browser/renderer_preferences_util.h", "+chrome/browser/rlz", "+chrome/browser/safe_browsing", - "+chrome/browser/ash/scalable_iph", "+chrome/browser/screen_ai", "+chrome/browser/sessions", "+chrome/browser/signin",
diff --git a/chrome/browser/ash/login/app_mode/DEPS b/chrome/browser/ash/login/app_mode/DEPS index 4ee4d75..d79adf8 100644 --- a/chrome/browser/ash/login/app_mode/DEPS +++ b/chrome/browser/ash/login/app_mode/DEPS
@@ -15,21 +15,16 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/app_mode/test", - "+chrome/browser/ash/accessibility", "+chrome/browser/ash/app_mode", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/login", "+chrome/browser/ash/ownership", "+chrome/browser/ash/policy/core", "+chrome/browser/ash/policy/remote_commands", "+chrome/browser/ash/policy/test_support", - "+chrome/browser/ash/profiles/profile_helper.h", "+chrome/browser/ash/settings", "+chrome/browser/browser_process.h", "+chrome/browser/browser_process_platform_part.h", "+chrome/browser/browser_process_platform_part_ash.h", - "+chrome/browser/chromeos/app_mode", - "+chrome/browser/device_identity", "+chrome/browser/extensions/browsertest_util.h", "+chrome/browser/extensions/extension_service.h", "+chrome/browser/extensions/extension_service_test_base.h", @@ -38,27 +33,13 @@ "+chrome/browser/lifetime", "+chrome/browser/policy", "+chrome/browser/profiles", - "+chrome/browser/signin", - "+chrome/browser/speech/extension_api", "+chrome/browser/ui/ash/keyboard", "+chrome/browser/ui/ash/login", "+chrome/browser/ui/browser.h", "+chrome/browser/ui/browser_list.h", - "+chrome/browser/ui/browser_navigator.h", - "+chrome/browser/ui/browser_navigator_params.h", - "+chrome/browser/ui/browser_window.h", "+chrome/browser/ui/test", "+chrome/browser/ui/webui/ash/login", - "+chrome/browser/web_applications/external_install_options.h", - "+chrome/browser/web_applications/externally_managed_app_manager.h", - "+chrome/browser/web_applications/mojom", - "+chrome/browser/web_applications/web_app_constants.h", - "+chrome/browser/web_applications/web_app_install_info.h", - "+chrome/browser/web_applications/web_app_provider.h", - "+chrome/common/chrome_constants.h", - "+chrome/common/chrome_features.h", "+chrome/common/chrome_paths.h", "+chrome/common/pref_names.h", - "+chrome/grit", "+chrome/test/base", ]
diff --git a/chrome/browser/ash/login/demo_mode/DEPS b/chrome/browser/ash/login/demo_mode/DEPS index 46c8039..016de35 100644 --- a/chrome/browser/ash/login/demo_mode/DEPS +++ b/chrome/browser/ash/login/demo_mode/DEPS
@@ -17,9 +17,7 @@ "+chrome/browser/apps/app_service", "+chrome/browser/apps/platform_apps", "+chrome/browser/ash/browser_delegate/browser_controller.h", - "+chrome/browser/ash/browser_delegate/browser_delegate.h", "+chrome/browser/ash/drive", - "+chrome/browser/ash/extensions", "+chrome/browser/ash/file_manager", "+chrome/browser/ash/login", "+chrome/browser/ash/policy/core", @@ -34,16 +32,12 @@ "+chrome/browser/chrome_browser_main.h", "+chrome/browser/chromeos/extensions/login_screen/login/cleanup", "+chrome/browser/component_updater", - "+chrome/browser/extensions/external_loader.h", - "+chrome/browser/extensions/external_provider_impl.h", "+chrome/browser/metrics", "+chrome/browser/prefs", "+chrome/browser/profiles", "+chrome/browser/lifetime", - "+chrome/browser/ui/apps", "+chrome/browser/ui/ash", "+chrome/browser/ui/webui/ash/login", - "+chrome/common/chrome_paths.h", "+chrome/common/extensions", "+chrome/grit",
diff --git a/chrome/browser/ash/login/lock/DEPS b/chrome/browser/ash/login/lock/DEPS index af23fb09..4fd1a26 100644 --- a/chrome/browser/ash/login/lock/DEPS +++ b/chrome/browser/ash/login/lock/DEPS
@@ -14,14 +14,12 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/browser/ash/lock_screen_apps", "+chrome/browser/ash/login", "+chrome/browser/ash/policy/core", "+chrome/browser/ash/profiles", "+chrome/browser/ash/settings", "+chrome/browser/ash/system", "+chrome/browser/browser_process.h", - "+chrome/browser/browser_process_platform_part.h", "+chrome/browser/certificate_provider", "+chrome/browser/lifetime", "+chrome/browser/profiles",
diff --git a/chrome/browser/ash/login/oobe_apps_service/DEPS b/chrome/browser/ash/login/oobe_apps_service/DEPS index a50617e..5457391 100644 --- a/chrome/browser/ash/login/oobe_apps_service/DEPS +++ b/chrome/browser/ash/login/oobe_apps_service/DEPS
@@ -6,8 +6,6 @@ # This directory is in //chrome, which violates the rule above. Allow this # directory to #include its own files. "+chrome/browser/ash/login/oobe_apps_service", - "+chrome/browser/profiles/profile.h", - "+chrome/browser/profiles/profile_keyed_service_factory.h" # Existing dependencies within //chrome. There is an active effort to # refactor //chrome/browser/ash to break these dependencies; see b/332804822. @@ -19,8 +17,7 @@ "+chrome/browser/apps/almanac_api_client", "+chrome/browser/apps/almanac_api_client/almanac_api_util.h", "+chrome/browser/apps/almanac_api_client/device_info_manager.h", - "+chrome/browser/profiles/profile_keyed_service_factory.h", - "+chrome/browser/apps/almanac_api_client/proto/client_context.proto", - "+chrome/browser/apps/app_service/app_install/app_install_types.h", "+chrome/browser/apps/app_service/app_service_proxy_factory.h", + "+chrome/browser/profiles/profile.h", + "+chrome/browser/profiles/profile_keyed_service_factory.h" ]
diff --git a/chrome/browser/ash/login/oobe_quick_start/DEPS b/chrome/browser/ash/login/oobe_quick_start/DEPS index 69a4fa6..8013665 100644 --- a/chrome/browser/ash/login/oobe_quick_start/DEPS +++ b/chrome/browser/ash/login/oobe_quick_start/DEPS
@@ -17,7 +17,6 @@ "+chrome/browser/ash/accessibility", "+chrome/browser/ash/nearby", "+chrome/browser/browser_process.h", - "+chrome/browser/nearby_sharing", "+chrome/common/channel_info.h", "+chrome/test/base",
diff --git a/chrome/browser/ash/login/quick_unlock/DEPS b/chrome/browser/ash/login/quick_unlock/DEPS index 9450571..56840e2 100644 --- a/chrome/browser/ash/login/quick_unlock/DEPS +++ b/chrome/browser/ash/login/quick_unlock/DEPS
@@ -18,7 +18,6 @@ "+chrome/browser/ash/profiles", "+chrome/browser/browser_process.h", "+chrome/browser/profiles", - "+chrome/browser/ui/ash/auth", "+chrome/common/pref_names.h", "+chrome/grit", "+chrome/test/base",
diff --git a/chrome/browser/ash/login/reporting/DEPS b/chrome/browser/ash/login/reporting/DEPS index 027380ba..a5e2c80 100644 --- a/chrome/browser/ash/login/reporting/DEPS +++ b/chrome/browser/ash/login/reporting/DEPS
@@ -20,7 +20,6 @@ "+chrome/browser/ash/policy/reporting", "+chrome/browser/ash/policy/status_collector", "+chrome/browser/ash/profiles", - "+chrome/browser/ash/settings", "+chrome/browser/browser_process.h", "+chrome/browser/extensions/browsertest_util.h", "+chrome/browser/policy/messaging_layer/proto/synced",
diff --git a/chrome/browser/ash/login/saml/DEPS b/chrome/browser/ash/login/saml/DEPS index ee80aa0c..9c293335 100644 --- a/chrome/browser/ash/login/saml/DEPS +++ b/chrome/browser/ash/login/saml/DEPS
@@ -30,7 +30,6 @@ "+chrome/browser/content_settings", "+chrome/browser/enterprise/connectors/device_trust/common", "+chrome/browser/extensions/extension_browsertest.h", - "+chrome/browser/media/webrtc", "+chrome/browser/net", "+chrome/browser/notifications", "+chrome/browser/policy", @@ -42,7 +41,6 @@ "+chrome/browser/ui/webui/ash/lock_screen_reauth", "+chrome/browser/ui/webui/ash/login", "+chrome/browser/ui/webui/signin", - "+chrome/common/chrome_features.h", "+chrome/common/chrome_paths.h", "+chrome/grit", "+chrome/test/base",
diff --git a/chrome/browser/ash/login/screens/DEPS b/chrome/browser/ash/login/screens/DEPS index 2a7a4a4..71ed2034 100644 --- a/chrome/browser/ash/login/screens/DEPS +++ b/chrome/browser/ash/login/screens/DEPS
@@ -25,8 +25,6 @@ "+chrome/browser/ash/assistant", "+chrome/browser/ash/auth", "+chrome/browser/ash/base", - "+chrome/browser/ash/child_accounts", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/customization", "+chrome/browser/ash/device_sync", "+chrome/browser/ash/drive", @@ -68,7 +66,6 @@ "+chrome/browser/ui/webui/ash/system_web_dialog/system_web_dialog_delegate.h", "+chrome/browser/ui/chrome_pages.h", "+chrome/browser/ui/managed_ui.h", - "+chrome/browser/ui/settings_window_manager_chromeos.h", "+chrome/browser/ui/webui/ash", "+chrome/browser/ui/webui/signin/ash", "+chrome/browser/unified_consent",
diff --git a/chrome/browser/ash/login/session/DEPS b/chrome/browser/ash/login/session/DEPS index ccb622f..7edf9ca 100644 --- a/chrome/browser/ash/login/session/DEPS +++ b/chrome/browser/ash/login/session/DEPS
@@ -28,7 +28,6 @@ "+chrome/browser/ash/calendar", "+chrome/browser/ash/camera_mic", "+chrome/browser/ash/child_accounts", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/crostini", "+chrome/browser/ash/drive", "+chrome/browser/ash/eche_app", @@ -37,7 +36,6 @@ "+chrome/browser/ash/floating_workspace", "+chrome/browser/ash/guest_os", "+chrome/browser/ash/hats", - "+chrome/browser/ash/lock_screen_apps", "+chrome/browser/ash/logging", "+chrome/browser/ash/login", "+chrome/browser/ash/net", @@ -48,7 +46,6 @@ "+chrome/browser/ash/policy/reporting", "+chrome/browser/ash/profiles", "+chrome/browser/ash/release_notes", - "+chrome/browser/ash/session_length_limiter.h", "+chrome/browser/ash/settings", "+chrome/browser/ash/system_web_apps/apps/help_app", "+chrome/browser/ash/tether", @@ -62,7 +59,6 @@ "+chrome/browser/lifetime", "+chrome/browser/manta/manta_service_factory.h", "+chrome/browser/net", - "+chrome/browser/password_manager", "+chrome/browser/policy", "+chrome/browser/prefs", "+chrome/browser/profiles",
diff --git a/chrome/browser/ash/login/users/DEPS b/chrome/browser/ash/login/users/DEPS index 51b07af1..beeaa6c3 100644 --- a/chrome/browser/ash/login/users/DEPS +++ b/chrome/browser/ash/login/users/DEPS
@@ -14,7 +14,6 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/browser/ash/app_mode", "+chrome/browser/ash/image_downloader", "+chrome/browser/ash/login", "+chrome/browser/ash/ownership", @@ -23,12 +22,8 @@ "+chrome/browser/ash/policy/handlers", "+chrome/browser/ash/profiles", "+chrome/browser/ash/settings", - "+chrome/browser/ash/system", - "+chrome/browser/ash/wallpaper_handlers", "+chrome/browser/browser_process.h", "+chrome/browser/browser_process_platform_part.h", - "+chrome/browser/extensions/extension_tab_util.h", - "+chrome/browser/extensions/permissions", "+chrome/browser/policy/networking", "+chrome/browser/prefs", "+chrome/browser/profiles", @@ -38,10 +33,7 @@ "+chrome/browser/ui/browser_window.h", "+chrome/browser/ui/chrome_select_file_policy.h", "+chrome/browser/ui/webui/ash/login", - "+chrome/common/chrome_constants.h", - "+chrome/common/chrome_features.h", "+chrome/common/chrome_paths.h", - "+chrome/common/chrome_switches.h", "+chrome/common/pref_names.h", "+chrome/common/webui_url_constants.h", "+chrome/grit",
diff --git a/chrome/browser/ash/mahi/DEPS b/chrome/browser/ash/mahi/DEPS index a10cfc5..6133d65 100644 --- a/chrome/browser/ash/mahi/DEPS +++ b/chrome/browser/ash/mahi/DEPS
@@ -14,7 +14,6 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/magic_boost", "+chrome/browser/feedback/show_feedback_page.h", "+chrome/browser/history/history_service_factory.h", @@ -22,7 +21,6 @@ "+chrome/browser/policy/profile_policy_connector.h", "+chrome/browser/profiles", "+chrome/browser/ui/browser_finder.h", - "+chrome/browser/ui/chrome_pages.h", "+chrome/browser/ui/settings_window_manager_chromeos.h", "+chrome/test/base", ]
diff --git a/chrome/browser/ash/mahi/web_contents/DEPS b/chrome/browser/ash/mahi/web_contents/DEPS index 23b7797..9debde3 100644 --- a/chrome/browser/ash/mahi/web_contents/DEPS +++ b/chrome/browser/ash/mahi/web_contents/DEPS
@@ -7,7 +7,6 @@ # refactor chromeos codes in //chrome to break these dependencies; see # b/332804822. Whenever possible, avoid adding new //chrome dependencies to # this list. - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/mahi", "+chrome/browser/download", "+chrome/browser/favicon",
diff --git a/chrome/browser/ash/multidevice_setup/DEPS b/chrome/browser/ash/multidevice_setup/DEPS index dae7995..f240afa 100644 --- a/chrome/browser/ash/multidevice_setup/DEPS +++ b/chrome/browser/ash/multidevice_setup/DEPS
@@ -15,7 +15,6 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/android_sms", - "+chrome/browser/ash/cryptauth", "+chrome/browser/ash/device_sync", "+chrome/browser/ash/login/quick_unlock", "+chrome/browser/ash/profiles",
diff --git a/chrome/browser/ash/net/DEPS b/chrome/browser/ash/net/DEPS index c692ab6..c6b86c8 100644 --- a/chrome/browser/ash/net/DEPS +++ b/chrome/browser/ash/net/DEPS
@@ -33,13 +33,11 @@ "+chrome/browser/profiles", "+chrome/browser/sync", "+chrome/browser/ui/ash/login", - "+chrome/browser/ui/ash/network", "+chrome/browser/ui/browser_finder.h", "+chrome/browser/ui/browser.h", "+chrome/browser/ui/browser_window.h", "+chrome/browser/ui/login", "+chrome/common/pref_names.h", - "+chrome/grit", "+chrome/test/base", ]
diff --git a/chrome/browser/ash/note_taking/DEPS b/chrome/browser/ash/note_taking/DEPS index 36efb22cb..319260e 100644 --- a/chrome/browser/ash/note_taking/DEPS +++ b/chrome/browser/ash/note_taking/DEPS
@@ -18,7 +18,6 @@ "+chrome/browser/ash/app_list/arc", "+chrome/browser/ash/arc", "+chrome/browser/ash/arc/fileapi", - "+chrome/browser/ash/lock_screen_apps", "+chrome/browser/ash/login/users", "+chrome/browser/ash/profiles", "+chrome/browser/browser_process.h",
diff --git a/chrome/browser/ash/notifications/DEPS b/chrome/browser/ash/notifications/DEPS index 35ead895..7c74d5b 100644 --- a/chrome/browser/ash/notifications/DEPS +++ b/chrome/browser/ash/notifications/DEPS
@@ -24,7 +24,6 @@ "+chrome/browser/media/webrtc", "+chrome/browser/notifications", "+chrome/browser/profiles", - "+chrome/browser/ui/ash", "+chrome/browser/ui/browser_dialogs.h", "+chrome/browser/ui/browser.h", "+chrome/browser/ui/screen_capture_notification_ui.h",
diff --git a/chrome/browser/ash/os_feedback/DEPS b/chrome/browser/ash/os_feedback/DEPS index c4c6a5f..79aacc40 100644 --- a/chrome/browser/ash/os_feedback/DEPS +++ b/chrome/browser/ash/os_feedback/DEPS
@@ -15,13 +15,17 @@ "+chrome/browser/signin", "+chrome/browser/ui/ash/system_web_apps", "+chrome/browser/ui/browser_dialogs.h", - "+chrome/browser/ui/browser_finder.h", - "+chrome/browser/ui/browser.h", - "+chrome/browser/ui/browser_list.h", - "+chrome/browser/ui/browser_window.h", "+chrome/browser/ui/chrome_pages.h", "+chrome/browser/ui/webui/ash", "+chrome/browser/ui/webui/ash/os_feedback_dialog", "+chrome/common/webui_url_constants.h", "+chrome/test/base", ] + +specific_include_rules = { + "chrome_os_feedback_delegate_browsertest\\.cc": [ + "+chrome/browser/ui/browser_finder.h", + "+chrome/browser/ui/browser.h", + "+chrome/browser/ui/browser_window.h", + ], +}
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc index 6faaf966..a2fdfd5 100644 --- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc +++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
@@ -29,20 +29,17 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/values.h" +#include "chrome/browser/ash/browser_delegate/browser_controller.h" #include "chrome/browser/ash/browser_delegate/browser_delegate.h" #include "chrome/browser/ash/multidevice_setup/multidevice_setup_client_factory.h" #include "chrome/browser/ash/os_feedback/os_feedback_screenshot_manager.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/feedback/feedback_dialog_utils.h" #include "chrome/browser/feedback/feedback_uploader_chrome.h" #include "chrome/browser/feedback/feedback_uploader_factory_chrome.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" -#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" -#include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/webui/ash/diagnostics_dialog/diagnostics_dialog.h" #include "chrome/browser/ui/webui/ash/os_feedback_dialog/os_feedback_dialog.h" #include "chrome/common/webui_url_constants.h" @@ -146,12 +143,18 @@ Profile* profile, scoped_refptr<extensions::FeedbackService> feedback_service) : profile_(profile), feedback_service_(feedback_service) { - Browser* browser = BrowserList::GetInstance()->GetLastActive(); - if (browser) { - // Save the last active page url before opening the feedback tool. - page_url_ = chrome::GetTargetTabUrl( - browser->session_id(), browser->tab_strip_model()->active_index()); + ash::BrowserDelegate* browser = + ash::BrowserController::GetInstance()->GetLastUsedBrowser(); + if (!browser) { + return; } + + auto* web_contents = (browser->GetType() == BrowserType::kDevTools) + ? browser->GetInspectedWebContents() + : browser->GetActiveWebContents(); + + // Save the last active page url before opening the feedback tool. + page_url_ = web_contents->GetLastCommittedURL(); } // Static.
diff --git a/chrome/browser/ash/phonehub/DEPS b/chrome/browser/ash/phonehub/DEPS index ee1c27b..818207c 100644 --- a/chrome/browser/ash/phonehub/DEPS +++ b/chrome/browser/ash/phonehub/DEPS
@@ -15,13 +15,11 @@ # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/attestation", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/device_sync", "+chrome/browser/ash/login/users", "+chrome/browser/ash/multidevice_setup", "+chrome/browser/ash/profiles", "+chrome/browser/ash/secure_channel", - "+chrome/browser/ash/sync", "+chrome/browser/download", "+chrome/browser/favicon", "+chrome/browser/profiles",
diff --git a/chrome/browser/ash/platform_keys/DEPS b/chrome/browser/ash/platform_keys/DEPS index 8ae4e32..9bfaa33 100644 --- a/chrome/browser/ash/platform_keys/DEPS +++ b/chrome/browser/ash/platform_keys/DEPS
@@ -20,7 +20,6 @@ "+chrome/browser/ash/profiles", "+chrome/browser/certificate_provider", "+chrome/browser/chromeos/platform_keys", - "+chrome/browser/extensions/api/enterprise_platform_keys", "+chrome/browser/net", "+chrome/browser/policy", "+chrome/browser/profiles",
diff --git a/chrome/browser/ash/policy/DEPS b/chrome/browser/ash/policy/DEPS index ed926ff..ce2ec9c5 100644 --- a/chrome/browser/ash/policy/DEPS +++ b/chrome/browser/ash/policy/DEPS
@@ -16,7 +16,6 @@ # to test. # Allow includes for shell-encryption and private_membership third_party libs. "+third_party/private_membership", - "+third_party/shell-encryption", # Allow includes for remoting events reporting. "+remoting/host/chromeos",
diff --git a/chrome/browser/ash/policy/core/DEPS b/chrome/browser/ash/policy/core/DEPS index c5a36ab..a8bb5b98 100644 --- a/chrome/browser/ash/policy/core/DEPS +++ b/chrome/browser/ash/policy/core/DEPS
@@ -25,7 +25,6 @@ "+chrome/browser/ash/policy/enrollment", "+chrome/browser/ash/policy/external_data", "+chrome/browser/ash/policy/handlers", - "+chrome/browser/ash/policy/invalidation", "+chrome/browser/ash/policy/skyvault", "+chrome/browser/ash/policy/login", "+chrome/browser/ash/policy/networking", @@ -40,7 +39,6 @@ "+chrome/browser/ash/policy/value_validation", "+chrome/browser/ash/printing", "+chrome/browser/ash/profiles", - "+chrome/browser/ash/session_length_limiter.h", "+chrome/browser/ash/settings", "+chrome/browser/ash/system", "+chrome/browser/ash/tpm",
diff --git a/chrome/browser/ash/policy/external_data/DEPS b/chrome/browser/ash/policy/external_data/DEPS index ecc3d83..b90076d 100644 --- a/chrome/browser/ash/policy/external_data/DEPS +++ b/chrome/browser/ash/policy/external_data/DEPS
@@ -14,11 +14,9 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/browser/ash/crostini", "+chrome/browser/ash/login/users/avatar", "+chrome/browser/ash/policy/core", "+chrome/browser/ash/policy/handlers", - "+chrome/browser/ash/policy/invalidation", "+chrome/browser/ash/policy/login", "+chrome/browser/ash/printing", "+chrome/browser/ash/profiles",
diff --git a/chrome/browser/ash/policy/login/DEPS b/chrome/browser/ash/policy/login/DEPS index 87932c6..669bb08 100644 --- a/chrome/browser/ash/policy/login/DEPS +++ b/chrome/browser/ash/policy/login/DEPS
@@ -21,7 +21,6 @@ "+chrome/browser/ash/profiles", "+chrome/browser/browser_process.h", "+chrome/browser/extensions/crx_installer.h", - "+chrome/browser/extensions/extension_service.h", "+chrome/browser/extensions/install_observer.h", "+chrome/browser/extensions/install_tracker.h", "+chrome/browser/extensions/policy_test_utils.h",
diff --git a/chrome/browser/ash/policy/remote_commands/DEPS b/chrome/browser/ash/policy/remote_commands/DEPS index d0d30da..f4982cf 100644 --- a/chrome/browser/ash/policy/remote_commands/DEPS +++ b/chrome/browser/ash/policy/remote_commands/DEPS
@@ -21,7 +21,6 @@ "+chrome/browser/ash/attestation", "+chrome/browser/ash/login", "+chrome/browser/ash/policy/core", - "+chrome/browser/ash/policy/invalidation", "+chrome/browser/ash/policy/scheduled_task_handler", "+chrome/browser/ash/policy/test_support", "+chrome/browser/ash/policy/uploading", @@ -29,7 +28,6 @@ "+chrome/browser/ash/settings", "+chrome/browser/ash/system", "+chrome/browser/browser_process.h", - "+chrome/browser/browser_process_platform_part_ash.h", "+chrome/browser/browser_process_platform_part.h", "+chrome/browser/device_identity", "+chrome/browser/notifications",
diff --git a/chrome/browser/ash/policy/skyvault/DEPS b/chrome/browser/ash/policy/skyvault/DEPS index 6c3f14b..74e7578c 100644 --- a/chrome/browser/ash/policy/skyvault/DEPS +++ b/chrome/browser/ash/policy/skyvault/DEPS
@@ -16,7 +16,6 @@ # directory basis. See //tools/chromeos/gen_deps.sh for details. "+chrome/browser/ash/drive", "+chrome/browser/ash/file_manager", - "+chrome/browser/ash/file_system_provider", "+chrome/browser/ash/policy/handlers", "+chrome/browser/browser_process.h", "+chrome/browser/chromeos/extensions/login_screen/login/cleanup", @@ -26,13 +25,11 @@ "+chrome/browser/ui/browser.h", "+chrome/browser/ui/webui/ash/cloud_upload", "+chrome/common/chrome_features.h", - "+chrome/common/extensions", "+chrome/common/pref_names.h", "+chrome/common/webui_url_constants.h", "+chrome/test/base", "+chrome/browser/download/download_dir_util.h", "+chrome/browser/notifications", - "+chrome/browser/platform_util.h", "+chrome/browser/ui/webui/ash/skyvault/local_files_migration_dialog.h", "+chromeos/ash/components/system/statistics_provider.h", "+chromeos/ash/components/system/fake_statistics_provider.h",
diff --git a/chrome/browser/ash/policy/skyvault/signin_notification_helper_unittest.cc b/chrome/browser/ash/policy/skyvault/signin_notification_helper_unittest.cc index 8c8d77ef..3bcef798 100644 --- a/chrome/browser/ash/policy/skyvault/signin_notification_helper_unittest.cc +++ b/chrome/browser/ash/policy/skyvault/signin_notification_helper_unittest.cc
@@ -12,6 +12,7 @@ #include "chrome/test/base/testing_profile.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" namespace policy::skyvault_ui_utils {
diff --git a/chrome/browser/ash/policy/status_collector/DEPS b/chrome/browser/ash/policy/status_collector/DEPS index 2d85b71..58ed149 100644 --- a/chrome/browser/ash/policy/status_collector/DEPS +++ b/chrome/browser/ash/policy/status_collector/DEPS
@@ -38,7 +38,6 @@ "+chrome/browser/web_applications/web_app_registrar.h", "+chrome/common/channel_info.h", "+chrome/common/chrome_content_client.h", - "+chrome/common/chrome_features.h", "+chrome/common/chrome_paths.h", "+chrome/common/pref_names.h", "+chrome/test/base",
diff --git a/chrome/browser/ash/policy/test_support/DEPS b/chrome/browser/ash/policy/test_support/DEPS index 2421dbe..41d0dfb 100644 --- a/chrome/browser/ash/policy/test_support/DEPS +++ b/chrome/browser/ash/policy/test_support/DEPS
@@ -20,6 +20,5 @@ "+chrome/browser/ash/policy/server_backed_state", "+chrome/browser/browser_process.h", "+chrome/browser/browser_process_platform_part_ash.h", - "+chrome/browser/browser_process_platform_part.h", "+chrome/test/base", ]
diff --git a/chrome/browser/ash/power/DEPS b/chrome/browser/ash/power/DEPS index bee7002..746eb85 100644 --- a/chrome/browser/ash/power/DEPS +++ b/chrome/browser/ash/power/DEPS
@@ -14,14 +14,12 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/browser/ash/login/demo_mode", "+chrome/browser/ash/login/users", "+chrome/browser/ash/settings", "+chrome/browser/browser_process.h", "+chrome/browser/extensions/extension_service.h", "+chrome/browser/extensions/test_extension_system.h", "+chrome/browser/profiles", - "+chrome/common/extensions/api", "+chrome/common/pref_names.h", "+chrome/grit", "+chrome/test/base",
diff --git a/chrome/browser/ash/preferences/DEPS b/chrome/browser/ash/preferences/DEPS index 8a82e718..38c2114 100644 --- a/chrome/browser/ash/preferences/DEPS +++ b/chrome/browser/ash/preferences/DEPS
@@ -6,7 +6,6 @@ "+chrome/browser/ash/accessibility", "+chrome/browser/ash/base", "+chrome/browser/ash/child_accounts/parent_access_code", - "+chrome/browser/ash/crosapi", "+chrome/browser/ash/drive", "+chrome/browser/ash/input_method", "+chrome/browser/ash/login",
diff --git a/chrome/browser/ash/privacy_hub/DEPS b/chrome/browser/ash/privacy_hub/DEPS index 56351e0b..074b731 100644 --- a/chrome/browser/ash/privacy_hub/DEPS +++ b/chrome/browser/ash/privacy_hub/DEPS
@@ -14,13 +14,9 @@ # Files residing in certain directories (e.g., //chrome/browser) are listed # individually. Other dependencies within //chrome are listed on a per- # directory basis. See //tools/chromeos/gen_deps.sh for details. - "+chrome/browser/notifications", "+chrome/browser/profiles", "+chrome/browser/ui/ash", - "+chrome/browser/ui/browser.h", "+chrome/browser/ui/settings_window_manager_chromeos.h", - "+chrome/common/chrome_features.h", - "+chrome/test/base", ] specific_include_rules = {
diff --git a/chrome/browser/ash/remote_apps/DEPS b/chrome/browser/ash/remote_apps/DEPS index bbb361d..a0bd70c 100644 --- a/chrome/browser/ash/remote_apps/DEPS +++ b/chrome/browser/ash/remote_apps/DEPS
@@ -22,7 +22,6 @@ "+chrome/browser/ash/profiles", "+chrome/browser/extensions/chrome_test_extension_loader.h", "+chrome/browser/profiles", - "+chrome/browser/ui/app_list", "+chrome/browser/ui/ash/shelf", "+chrome/common/apps/platform_apps/api", "+chrome/common/chrome_paths.h",
diff --git a/chrome/browser/ash/scalable_iph/DEPS b/chrome/browser/ash/scalable_iph/DEPS index 73fd74e8..b5c37f0 100644 --- a/chrome/browser/ash/scalable_iph/DEPS +++ b/chrome/browser/ash/scalable_iph/DEPS
@@ -22,7 +22,6 @@ "+chrome/browser/ash/policy/core", "+chrome/browser/ash/printing", "+chrome/browser/ash/profiles", - "+chrome/browser/ash/settings", "+chrome/browser/ash/system_web_apps", "+chrome/browser/browser_process.h", "+chrome/browser/browser_process_platform_part_ash.h", @@ -35,8 +34,6 @@ "+chrome/browser/ui/ash/multi_user", "+chrome/browser/ui/ash/system_web_apps", "+chrome/browser/ui/browser.h", - "+chrome/browser/ui/browser_navigator.h", - "+chrome/browser/ui/browser_navigator_params.h", "+chrome/browser/ui/settings_window_manager_chromeos.h", "+chrome/common/chrome_switches.h", "+chrome/common/pref_names.h",
diff --git a/chrome/browser/ash/system_logs/DEPS b/chrome/browser/ash/system_logs/DEPS index ff6322e..65e8d6a 100644 --- a/chrome/browser/ash/system_logs/DEPS +++ b/chrome/browser/ash/system_logs/DEPS
@@ -21,7 +21,6 @@ "+chrome/browser/ash/profiles", "+chrome/browser/feedback/system_logs", "+chrome/browser/profiles", - "+chrome/browser/ui/browser.h", "+chrome/common/chrome_switches.h", "+chrome/common/logging_chrome.h", "+chrome/grit",
diff --git a/chrome/browser/ash/system_web_apps/DEPS b/chrome/browser/ash/system_web_apps/DEPS index d0f14fe..42be9a4 100644 --- a/chrome/browser/ash/system_web_apps/DEPS +++ b/chrome/browser/ash/system_web_apps/DEPS
@@ -15,7 +15,6 @@ "+chrome/browser/ash/extensions", "+chrome/browser/ash/file_manager", "+chrome/browser/ash/profiles", - "+chrome/browser/ash/boca/boca_role_util.h", "+chrome/browser/browser_process.h", "+chrome/browser/chromeos/upload_office_to_cloud", "+chrome/browser/devtools", @@ -46,10 +45,8 @@ "+chrome/browser/ui/tabs", "+chrome/browser/ui/web_applications", "+chrome/browser/ui/webui/ash", - "+chrome/browser/ui/webui/chrome_web_ui_controller_factory.h", "+chrome/browser/ui/webui/plural_string_handler.h", "+chrome/browser/ui/webui/sanitized_image_source.h", - "+chrome/browser/ui/webui/webui_util.h", "+chrome/browser/web_applications/extension_status_utils.h", "+chrome/browser/web_applications/external_install_options.h", "+chrome/browser/web_applications/externally_managed_app_manager.h",
diff --git a/chrome/browser/ash/system_web_apps/apps/DEPS b/chrome/browser/ash/system_web_apps/apps/DEPS index ee3dc6d..40b78ef 100644 --- a/chrome/browser/ash/system_web_apps/apps/DEPS +++ b/chrome/browser/ash/system_web_apps/apps/DEPS
@@ -85,7 +85,6 @@ "+chrome/browser/ui/tabs", "+chrome/browser/ui/web_applications", "+chrome/browser/ui/webui/ash", - "+chrome/browser/ui/webui/chrome_web_ui_controller_factory.h", "+chrome/browser/ui/webui/plural_string_handler.h", "+chrome/browser/ui/webui/sanitized_image_source.h", "+chrome/browser/web_applications/extension_status_utils.h",
diff --git a/chrome/browser/ash/system_web_apps/test_support/DEPS b/chrome/browser/ash/system_web_apps/test_support/DEPS index 2128f756..80b924a 100644 --- a/chrome/browser/ash/system_web_apps/test_support/DEPS +++ b/chrome/browser/ash/system_web_apps/test_support/DEPS
@@ -24,7 +24,6 @@ "+chrome/browser/ui/browser_window.h", "+chrome/browser/ui/tabs", "+chrome/browser/ui/web_applications", - "+chrome/browser/ui/webui/webui_util.h", "+chrome/browser/web_applications/mojom", "+chrome/browser/web_applications/os_integration", "+chrome/browser/web_applications/test",
diff --git a/chrome/browser/autocomplete/BUILD.gn b/chrome/browser/autocomplete/BUILD.gn index c54337ae..32299799 100644 --- a/chrome/browser/autocomplete/BUILD.gn +++ b/chrome/browser/autocomplete/BUILD.gn
@@ -13,3 +13,25 @@ "//components/omnibox/browser:location_bar", ] } + +source_set("aim_eligibility_service") { + sources = [ + "aim_eligibility_service.cc", + "aim_eligibility_service.h", + "aim_eligibility_service_factory.cc", + "aim_eligibility_service_factory.h", + ] + deps = [ + "//base", + "//chrome/browser:browser_process", + "//chrome/browser/profiles:profile", + "//chrome/browser/search_engines", + "//components/keyed_service/core", + "//components/omnibox/browser", + "//components/prefs", + "//components/search", + "//components/search_engines", + "//components/variations/service", + "//content/public/browser", + ] +}
diff --git a/chrome/browser/autocomplete/aim_eligibility_service.cc b/chrome/browser/autocomplete/aim_eligibility_service.cc new file mode 100644 index 0000000..8efbf30 --- /dev/null +++ b/chrome/browser/autocomplete/aim_eligibility_service.cc
@@ -0,0 +1,54 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autocomplete/aim_eligibility_service.h" + +#include <string> + +#include "chrome/browser/browser_process.h" +#include "components/omnibox/browser/omnibox_prefs.h" +#include "components/prefs/pref_service.h" +#include "components/search/search.h" +#include "components/search_engines/template_url_service.h" +#include "components/variations/service/variations_service.h" + +namespace { + +// Returns the country code from the variations service. +std::string GetCountryCode() { + std::string country_code; + // The variations service may be nullptr in unit tests. + variations::VariationsService* variations_service = + g_browser_process ? g_browser_process->variations_service() : nullptr; + if (variations_service) { + country_code = variations_service->GetStoredPermanentCountry(); + if (country_code.empty()) { + country_code = variations_service->GetLatestCountry(); + } + } + return country_code; +} + +} // namespace + +AimEligibilityService::AimEligibilityService( + PrefService* pref_service, + TemplateURLService* template_url_service) + : pref_service_(pref_service), + template_url_service_(template_url_service) {} + +AimEligibilityService::~AimEligibilityService() = default; + +bool AimEligibilityService::IsCountryAndLocale(const std::string& country, + const std::string& locale) { + return g_browser_process && + g_browser_process->GetApplicationLocale() == locale && + GetCountryCode() == country; +} + +bool AimEligibilityService::IsAimEligible() const { + return search::DefaultSearchProviderIsGoogle(template_url_service_) && + IsCountryAndLocale("us", "en-US") && + omnibox::IsAimAllowedByPolicy(pref_service_); +}
diff --git a/chrome/browser/autocomplete/aim_eligibility_service.h b/chrome/browser/autocomplete/aim_eligibility_service.h new file mode 100644 index 0000000..4fbe83f --- /dev/null +++ b/chrome/browser/autocomplete/aim_eligibility_service.h
@@ -0,0 +1,39 @@ +// 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 CHROME_BROWSER_AUTOCOMPLETE_AIM_ELIGIBILITY_SERVICE_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_AIM_ELIGIBILITY_SERVICE_H_ + +#include <string> + +#include "base/memory/raw_ptr.h" +#include "components/keyed_service/core/keyed_service.h" + +class PrefService; +class TemplateURLService; + +// Utility service to check if the user is eligible for certain features based +// on e.g. locale. Does not check feature states. +class AimEligibilityService : public KeyedService { + public: + AimEligibilityService(PrefService* pref_service, + TemplateURLService* template_url_service); + ~AimEligibilityService() override; + AimEligibilityService(const AimEligibilityService&) = delete; + AimEligibilityService& operator=(const AimEligibilityService&) = delete; + + // Verifies country and locale. + static bool IsCountryAndLocale(const std::string& country, + const std::string& locale); + + // Checks if user is eligible for AI mode e.g. in the omnibox or + // chrome://settings/searchEngines. + bool IsAimEligible() const; + + private: + const raw_ptr<PrefService> pref_service_; + const raw_ptr<TemplateURLService> template_url_service_; +}; + +#endif // CHROME_BROWSER_AUTOCOMPLETE_AIM_ELIGIBILITY_SERVICE_H_
diff --git a/chrome/browser/autocomplete/aim_eligibility_service_factory.cc b/chrome/browser/autocomplete/aim_eligibility_service_factory.cc new file mode 100644 index 0000000..86fe986 --- /dev/null +++ b/chrome/browser/autocomplete/aim_eligibility_service_factory.cc
@@ -0,0 +1,50 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autocomplete/aim_eligibility_service_factory.h" + +#include <memory> + +#include "base/no_destructor.h" +#include "chrome/browser/autocomplete/aim_eligibility_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_selections.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" +#include "content/public/browser/browser_context.h" + +// static +AimEligibilityService* AimEligibilityServiceFactory::GetForProfile( + Profile* profile) { + return static_cast<AimEligibilityService*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +// static +AimEligibilityServiceFactory* AimEligibilityServiceFactory::GetInstance() { + static base::NoDestructor<AimEligibilityServiceFactory> instance; + return instance.get(); +} + +AimEligibilityServiceFactory::AimEligibilityServiceFactory() + : ProfileKeyedServiceFactory( + "AimEligibilityService", + ProfileSelections::Builder() + .WithRegular(ProfileSelection::kRedirectedToOriginal) + .WithGuest(ProfileSelection::kRedirectedToOriginal) + // TODO(crbug.com/41488885): Check if this service is needed for + // Ash Internals. + .WithAshInternals(ProfileSelection::kRedirectedToOriginal) + .Build()) { + DependsOn(TemplateURLServiceFactory::GetInstance()); +} + +AimEligibilityServiceFactory::~AimEligibilityServiceFactory() = default; + +std::unique_ptr<KeyedService> +AimEligibilityServiceFactory::BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const { + Profile* profile = Profile::FromBrowserContext(context); + return std::make_unique<AimEligibilityService>( + profile->GetPrefs(), TemplateURLServiceFactory::GetForProfile(profile)); +}
diff --git a/chrome/browser/autocomplete/aim_eligibility_service_factory.h b/chrome/browser/autocomplete/aim_eligibility_service_factory.h new file mode 100644 index 0000000..17e2cbda --- /dev/null +++ b/chrome/browser/autocomplete/aim_eligibility_service_factory.h
@@ -0,0 +1,39 @@ +// 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 CHROME_BROWSER_AUTOCOMPLETE_AIM_ELIGIBILITY_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_AIM_ELIGIBILITY_SERVICE_FACTORY_H_ + +#include "base/no_destructor.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" + +class AimEligibilityService; +class KeyedService; +class Profile; + +namespace content { +class BrowserContext; +} + +class AimEligibilityServiceFactory : public ProfileKeyedServiceFactory { + public: + static AimEligibilityService* GetForProfile(Profile* profile); + static AimEligibilityServiceFactory* GetInstance(); + + AimEligibilityServiceFactory(const AimEligibilityServiceFactory&) = delete; + AimEligibilityServiceFactory& operator=(const AimEligibilityServiceFactory&) = + delete; + + private: + friend base::NoDestructor<AimEligibilityServiceFactory>; + + AimEligibilityServiceFactory(); + ~AimEligibilityServiceFactory() override; + + // Overrides from BrowserContextKeyedServiceFactory: + std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const override; +}; + +#endif // CHROME_BROWSER_AUTOCOMPLETE_AIM_ELIGIBILITY_SERVICE_FACTORY_H_
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc index f68f8f70..f8ef1c1 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -7,12 +7,16 @@ #include <stddef.h> #include <algorithm> +#include <string> +#include <vector> #include "base/functional/callback_helpers.h" #include "base/strings/cstring_view.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/autocomplete/aim_eligibility_service.h" +#include "chrome/browser/autocomplete/aim_eligibility_service_factory.h" #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" #include "chrome/browser/autocomplete/document_suggestions_service_factory.h" #include "chrome/browser/autocomplete/in_memory_url_index_factory.h" @@ -418,6 +422,11 @@ return tab_groups::TabGroupSyncServiceFactory::GetForProfile(profile_); } +AimEligibilityService* +ChromeAutocompleteProviderClient::GetAimEligibilityService() const { + return AimEligibilityServiceFactory::GetForProfile(profile_); +} + bool ChromeAutocompleteProviderClient::IsOffTheRecord() const { return profile_->IsOffTheRecord(); } @@ -572,31 +581,30 @@ } bool ChromeAutocompleteProviderClient::AreLensEntrypointsVisible() const { - #if !BUILDFLAG(IS_ANDROID) - if (auto* lens_search_controller = - GetLensSearchController(GetWebContents(web_contents_getter_))) { - // Guaranteed to exist if lens_search_controller is not null. - return lens_search_controller->GetTabInterface() - ->GetBrowserWindowInterface() - ->GetFeatures() - .lens_overlay_entry_point_controller() - ->AreVisible(); - } - #endif - return false; - } - - std::optional<bool> ChromeAutocompleteProviderClient::IsPagePaywalled() - const { #if !BUILDFLAG(IS_ANDROID) - if (auto* web_contents = GetWebContents(web_contents_getter_)) { - if (auto* tab_helper = OmniboxTabHelper::FromWebContents(web_contents)) { - return tab_helper->IsPagePaywalled(); - } - } -#endif - return false; + if (auto* lens_search_controller = + GetLensSearchController(GetWebContents(web_contents_getter_))) { + // Guaranteed to exist if lens_search_controller is not null. + return lens_search_controller->GetTabInterface() + ->GetBrowserWindowInterface() + ->GetFeatures() + .lens_overlay_entry_point_controller() + ->AreVisible(); } +#endif // !BUILDFLAG(IS_ANDROID) + return false; +} + +std::optional<bool> ChromeAutocompleteProviderClient::IsPagePaywalled() const { +#if !BUILDFLAG(IS_ANDROID) + if (auto* web_contents = GetWebContents(web_contents_getter_)) { + if (auto* tab_helper = OmniboxTabHelper::FromWebContents(web_contents)) { + return tab_helper->IsPagePaywalled(); + } + } +#endif // !BUILDFLAG(IS_ANDROID) + return false; +} base::CallbackListSubscription ChromeAutocompleteProviderClient::GetLensSuggestInputsWhenReady( @@ -612,6 +620,10 @@ return {}; } +bool ChromeAutocompleteProviderClient::IsAimEligible() const { + return GetAimEligibilityService()->IsAimEligible(); +} + base::WeakPtr<AutocompleteProviderClient> ChromeAutocompleteProviderClient::GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr();
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h index 4771b80..5b38f85 100644 --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
@@ -26,11 +26,12 @@ class TabMatcher; class AutocompleteScoringModelService; class OnDeviceTailModelService; +class AimEligibilityService; namespace content { class StoragePartition; class WebContents; -} +} // namespace content namespace unified_consent { class UrlKeyedDataCollectionConsentHelper; @@ -95,6 +96,8 @@ OnDeviceTailModelService* GetOnDeviceTailModelService() const override; ProviderStateService* GetProviderStateService() const override; tab_groups::TabGroupSyncService* GetTabGroupSyncService() const override; + AimEligibilityService* GetAimEligibilityService() const override; + bool IsOffTheRecord() const override; bool IsIncognitoProfile() const override; bool IsGuestSession() const override; @@ -127,6 +130,7 @@ std::optional<bool> IsPagePaywalled() const override; base::CallbackListSubscription GetLensSuggestInputsWhenReady( LensOverlaySuggestInputsCallback callback) const override; + bool IsAimEligible() const override; base::WeakPtr<AutocompleteProviderClient> GetWeakPtr() override; // OmniboxAction::Client: @@ -137,10 +141,9 @@ void PromptPageTranslation() override; bool OpenJourneys(const std::string& query) override; void OpenLensOverlay(bool show) override; - void IssueContextualSearchRequest( - const GURL& destination_url, - AutocompleteMatchType::Type match_type, - bool is_zero_prefix_suggestion) override; + void IssueContextualSearchRequest(const GURL& destination_url, + AutocompleteMatchType::Type match_type, + bool is_zero_prefix_suggestion) override; // For testing. void set_storage_partition(content::StoragePartition* storage_partition) {
diff --git a/chrome/browser/background/glic/glic_launcher_configuration_unittest.cc b/chrome/browser/background/glic/glic_launcher_configuration_unittest.cc index 86186cb1..54496f09 100644 --- a/chrome/browser/background/glic/glic_launcher_configuration_unittest.cc +++ b/chrome/browser/background/glic/glic_launcher_configuration_unittest.cc
@@ -7,7 +7,6 @@ #include "base/test/task_environment.h" #include "chrome/browser/glic/glic_pref_names.h" #include "chrome/common/chrome_features.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/prefs/testing_pref_service.h" #include "content/public/test/browser_task_environment.h" @@ -34,13 +33,13 @@ GlicLauncherConfigurationTest() = default; ~GlicLauncherConfigurationTest() override = default; - PrefService* local_state() { return scoped_testing_local_state_.Get(); } + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } private: content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::MainThreadType::UI}; - ScopedTestingLocalState scoped_testing_local_state_{ - TestingBrowserProcess::GetGlobal()}; }; TEST_F(GlicLauncherConfigurationTest, IsEnabled) {
diff --git a/chrome/browser/background/glic/glic_status_icon_unittest.cc b/chrome/browser/background/glic/glic_status_icon_unittest.cc index 782ecbda..c292ccb6 100644 --- a/chrome/browser/background/glic/glic_status_icon_unittest.cc +++ b/chrome/browser/background/glic/glic_status_icon_unittest.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/ui/webui/whats_new/whats_new_ui.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/fake_profile_manager.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/prefs/testing_pref_service.h" #include "content/public/test/browser_task_environment.h" @@ -110,8 +109,6 @@ private: content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::MainThreadType::UI}; - ScopedTestingLocalState scoped_testing_local_state_{ - TestingBrowserProcess::GetGlobal()}; std::unique_ptr<GlicStatusIcon> glic_status_icon_; MockStatusTray status_tray_; MockGlicController glic_controller_;
diff --git a/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc b/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc index 3a03b68..7b710a4b 100644 --- a/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc +++ b/chrome/browser/banners/app_banner_manager_desktop_browsertest.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/banners/app_banner_manager_browsertest_base.h" #include "chrome/browser/banners/test_app_banner_manager_desktop.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/actions/chrome_action_id.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_window.h" @@ -258,8 +259,13 @@ } // Install the app via the menu instead of the banner. - browser()->window()->ExecutePageActionIconForTesting( - PageActionIconType::kPwaInstall); + if (IsPageActionMigrated(PageActionIconType::kPwaInstall)) { + actions::ActionManager::Get().FindAction(kActionInstallPwa)->InvokeAction(); + } else { + browser()->window()->ExecutePageActionIconForTesting( + PageActionIconType::kPwaInstall); + } + manager->AwaitAppInstall(); EXPECT_FALSE(manager->IsPromptAvailableForTesting());
diff --git a/chrome/browser/bookmarks/android/BUILD.gn b/chrome/browser/bookmarks/android/BUILD.gn index eef6a1ba..67755f6 100644 --- a/chrome/browser/bookmarks/android/BUILD.gn +++ b/chrome/browser/bookmarks/android/BUILD.gn
@@ -38,6 +38,10 @@ ] } +android_resources("java_resources") { + sources = [ "java/res/values/dimens.xml" ] +} + android_library("java") { sources = [ "java/src/org/chromium/chrome/browser/bookmarks/BookmarkAddNewFolderCoordinator.java", @@ -94,6 +98,7 @@ ] deps = [ + ":java_resources", "//base:base_java", "//base:base_shared_preferences_java", "//base:callback_java", @@ -206,6 +211,7 @@ "junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarCoordinatorTest.java", "junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarItemsLayoutManagerTest.java", "junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarItemsProviderTest.java", + "junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediatorTest.java", "junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarUtilsTest.java", "junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarVisibilityProviderTest.java", ]
diff --git a/chrome/browser/bookmarks/android/java/res/values/dimens.xml b/chrome/browser/bookmarks/android/java/res/values/dimens.xml new file mode 100644 index 0000000..a538cf9 --- /dev/null +++ b/chrome/browser/bookmarks/android/java/res/values/dimens.xml
@@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- +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. +--> + +<resources> + <dimen name="bookmark_bar_popup_elevation">2dp</dimen> +</resources> \ No newline at end of file
diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarCoordinator.java b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarCoordinator.java index 926ef6a..753c398 100644 --- a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarCoordinator.java +++ b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarCoordinator.java
@@ -125,7 +125,9 @@ profileSupplier, currentTab, bookmarkOpener, - bookmarkManagerOpenerSupplier); + bookmarkManagerOpenerSupplier, + itemsContainer, + mView); PropertyModelChangeProcessor.create(model, mView, BookmarkBarViewBinder::bind); mTopControlsStacker = topControlsStacker;
diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediator.java b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediator.java index 30d25ed..b5bd968 100644 --- a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediator.java +++ b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediator.java
@@ -5,10 +5,15 @@ package org.chromium.chrome.browser.bookmarks.bar; import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; import android.view.KeyEvent; import android.view.View; +import androidx.annotation.VisibleForTesting; import androidx.appcompat.content.res.AppCompatResources; +import androidx.recyclerview.widget.RecyclerView; import org.chromium.base.Callback; import org.chromium.base.supplier.LazyOneshotSupplier; @@ -20,19 +25,29 @@ import org.chromium.chrome.browser.bookmarks.BookmarkManagerOpener; import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.bookmarks.BookmarkOpener; +import org.chromium.chrome.browser.bookmarks.BookmarkUiPrefs.BookmarkRowDisplayPref; +import org.chromium.chrome.browser.bookmarks.BookmarkViewUtils; import org.chromium.chrome.browser.bookmarks.R; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.ui.favicon.FaviconUtils; +import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.bookmarks.BookmarkItem; import org.chromium.components.browser_ui.util.GlobalDiscardableReferencePool; +import org.chromium.components.browser_ui.widget.BrowserUiListMenuUtils; import org.chromium.components.image_fetcher.ImageFetcherConfig; import org.chromium.components.image_fetcher.ImageFetcherFactory; +import org.chromium.ui.listmenu.BasicListMenu; +import org.chromium.ui.listmenu.ListItemType; +import org.chromium.ui.listmenu.ListMenuItemProperties; +import org.chromium.ui.listmenu.ListMenuSubmenuItemProperties; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.widget.AnchoredPopupWindow; +import org.chromium.ui.widget.ViewRectProvider; import java.util.ArrayList; import java.util.List; @@ -45,6 +60,8 @@ class BookmarkBarMediator implements BookmarkBarItemsProvider.Observer, BrowserControlsStateProvider.Observer { + private static final int INVALID_INDEX = -1; + @VisibleForTesting static @Nullable Bitmap sFolderIconBitmap; private final Activity mActivity; private final PropertyModel mAllBookmarksButtonModel; private final BrowserControlsStateProvider mBrowserControlsStateProvider; @@ -58,7 +75,12 @@ private @Nullable final Tab mCurrentTab; private final BookmarkOpener mBookmarkOpener; private final ObservableSupplier<BookmarkManagerOpener> mBookmarkManagerOpenerSupplier; + private final RecyclerView mItemsRecyclerView; + private final BookmarkBar mBookmarkBarView; + // The popup window that displays the contents of a bookmark folder. Instantiated in {@code + // showPopupMenu} when a folder is tapped. + private @Nullable AnchoredPopupWindow mAnchoredPopupWindow; private @Nullable BookmarkImageFetcher mImageFetcher; private @Nullable BookmarkBarItemsProvider mItemsProvider; @@ -76,6 +98,9 @@ * @param currentTab The current tab if it exists. * @param bookmarkOpener Used to open bookmarks. * @param bookmarkManagerOpenerSupplier Used to open the bookmark manager. + * @param itemsRecyclerView The bookmark_bar_items_container recycler view that is inside the + * bookmark_bar view. + * @param bookmarkBarView The bookmark_bar view that contains the entire bookmarks bar. */ public BookmarkBarMediator( Activity activity, @@ -88,7 +113,9 @@ ObservableSupplier<Profile> profileSupplier, @Nullable Tab currentTab, BookmarkOpener bookmarkOpener, - ObservableSupplier<BookmarkManagerOpener> bookmarkManagerOpenerSupplier) { + ObservableSupplier<BookmarkManagerOpener> bookmarkManagerOpenerSupplier, + RecyclerView itemsRecyclerView, + BookmarkBar bookmarkBarView) { mActivity = activity; mAllBookmarksButtonModel = allBookmarksButtonModel; @@ -129,6 +156,8 @@ mCurrentTab = currentTab; mBookmarkOpener = bookmarkOpener; mBookmarkManagerOpenerSupplier = bookmarkManagerOpenerSupplier; + mItemsRecyclerView = itemsRecyclerView; + mBookmarkBarView = bookmarkBarView; updateTopMargin(); updateVisibility(); @@ -140,6 +169,9 @@ mBrowserControlsStateProvider.removeObserver(this); mItemsOverflowSupplier.removeObserver(mItemsOverflowSupplierObserver); + // TODO(crbug.com/430044890): Change it to a member variable. + sFolderIconBitmap = null; + if (mImageFetcher != null) { mImageFetcher.destroy(); mImageFetcher = null; @@ -255,11 +287,11 @@ private void onBookmarkItemClick(BookmarkItem item, int metaState) { final Profile profile = mProfileSupplier.get(); - // TODO(crbug.com/394614779): Open in popup window instead of bookmark manager. if (item.isFolder()) { - mBookmarkManagerOpenerSupplier - .get() - .showBookmarkManager(mActivity, mCurrentTab, profile, item.getId()); + // Get the view of the folder that was clicked. + View anchorView = getAnchorViewForBookmark(item); + if (anchorView == null) return; + showPopupMenu(item.getId(), anchorView); return; } @@ -380,4 +412,181 @@ public void setVisibility(boolean isVisible) { mModel.set(BookmarkBarProperties.VISIBILITY, isVisible ? View.VISIBLE : View.GONE); } + + private void showPopupMenu(BookmarkId folderId, View anchorView) { + // Dismiss any existing popup windows. + if (mAnchoredPopupWindow != null) mAnchoredPopupWindow.dismiss(); + + // Build the entire model list for this folder. The grandchildren are stored in + // SUBMENU_ITEMS. + ModelList bookmarkItems = buildMenuModelListForFolder(folderId); + + BasicListMenu popupListMenu = + BrowserUiListMenuUtils.getBasicListMenu( + mActivity, + bookmarkItems, + (model) -> model.get(ListMenuItemProperties.CLICK_LISTENER).onClick(null)); + + // Go through the entire model list and add the click listeners. + popupListMenu.setupCallbacksRecursively( + () -> { + if (mAnchoredPopupWindow != null) { + mAnchoredPopupWindow.dismiss(); + } + }); + + View popupContentView = popupListMenu.getContentView(); + // This is needed because list_menu_layout.xml already sets a background, and we want to + // avoid double backgrounds. If we were to create a new BasicListMenu and pass 0 as the + // background drawable, the BasicListMenu would just use the pre-defined background. + popupContentView.setBackground(null); + + mAnchoredPopupWindow = + new AnchoredPopupWindow( + mActivity, + mBookmarkBarView, + AppCompatResources.getDrawable(mActivity, R.drawable.default_popup_menu_bg), + popupListMenu.getContentView(), + new ViewRectProvider(anchorView)); + + mAnchoredPopupWindow.setFocusable(true); + mAnchoredPopupWindow.setPreferredVerticalOrientation( + AnchoredPopupWindow.VerticalOrientation.BELOW); + mAnchoredPopupWindow.setHorizontalOverlapAnchor(true); + mAnchoredPopupWindow.setElevation( + mActivity + .getResources() + .getDimensionPixelSize(R.dimen.bookmark_bar_popup_elevation)); + + // TODO(crbug.com/430044890): Address the fixed width and height of the anchored popup. + mAnchoredPopupWindow.setDesiredContentSize(800, 600); + mAnchoredPopupWindow.show(); + } + + private int getIndexInBookmarksBar(BookmarkItem item) { + // Get the main data model for all bookmarks for the user. + BookmarkModel bookmarkModel = BookmarkModel.getForProfile(mProfileSupplier.get()); + if (bookmarkModel == null) return INVALID_INDEX; + + // Get the id of the entire bookmarks bar. + BookmarkId bookmarkBarFolderId = bookmarkModel.getDesktopFolderId(); + if (bookmarkBarFolderId == null) return INVALID_INDEX; + + // Get an ordered list of all the children (both folders and web pages) of the bookmarks + // bar. + List<BookmarkId> childrenOfBookmarkBar = bookmarkModel.getChildIds(bookmarkBarFolderId); + + return childrenOfBookmarkBar.indexOf(item.getId()); + } + + private @Nullable View getAnchorViewForBookmark(BookmarkItem item) { + // Find the pos of the specific folder we selected. + int index = getIndexInBookmarksBar(item); + if (index == INVALID_INDEX) return null; + + // Get the view holder of that pos. + RecyclerView.ViewHolder holder = mItemsRecyclerView.findViewHolderForAdapterPosition(index); + return (holder != null) ? holder.itemView : null; + } + + // Recursive method that builds the entire model list for a clicked bookmark in the bookmarks + // bar. The size of the returned model list will just be the number of the direct children + // because each folder's SUBMENU_ITEMS contains the children list as a separate model list. + @VisibleForTesting + ModelList buildMenuModelListForFolder(BookmarkId folderId) { + ModelList modelList = new ModelList(); + // Get the main data model for all bookmarks for the user. + BookmarkModel bookmarkModel = BookmarkModel.getForProfile(mProfileSupplier.get()); + if (bookmarkModel == null) { + return modelList; + } + // Iterate through the ordered list of all the children (both folders and links) of this + // folder. + for (BookmarkId childId : bookmarkModel.getChildIds(folderId)) { + BookmarkItem childBookmarkItem = bookmarkModel.getBookmarkById(childId); + if (childBookmarkItem == null) continue; + if (childBookmarkItem.isFolder()) { + modelList.add( + createListItemForBookmarkFolder( + childBookmarkItem, + buildMenuModelListForFolder(childBookmarkItem.getId()))); + } else { + modelList.add(createListItemForBookmarkLeaf(childBookmarkItem)); + } + } + return modelList; + } + + // Folders do not have urls. + private ListItem createListItemForBookmarkFolder( + BookmarkItem bookmarkItem, ModelList children) { + + if (sFolderIconBitmap == null) { + BookmarkModel bookmarkModel = BookmarkModel.getForProfile(mProfileSupplier.get()); + Drawable folderIcon = + BookmarkViewUtils.getFolderIcon( + mActivity, + bookmarkItem.getId(), + bookmarkModel, + BookmarkRowDisplayPref.VISUAL); + // Utilize lazy static caching and call this only once for the entire time the app is + // running. + sFolderIconBitmap = drawableToBitmap(folderIcon); + } + + // Convert ModelList to ArrayList. + List<ListItem> childrenList = new ArrayList<>(); + for (ListItem item : children) { + childrenList.add(item); + } + + final PropertyModel model = + new PropertyModel.Builder(ListMenuSubmenuItemProperties.ALL_KEYS) + .with(ListMenuItemProperties.TITLE, bookmarkItem.getTitle()) + .with(ListMenuSubmenuItemProperties.SUBMENU_ITEMS, childrenList) + .with(ListMenuItemProperties.START_ICON_BITMAP, sFolderIconBitmap) + .with(ListMenuItemProperties.ENABLED, true) + .build(); + return new ListItem(ListItemType.MENU_ITEM_WITH_SUBMENU, model); + } + + // Bookmark leaves are web pages and not folders. They do not have any children (sub menu + // items). + private ListItem createListItemForBookmarkLeaf(BookmarkItem bookmarkItem) { + PropertyModel model = + new PropertyModel.Builder(ListMenuItemProperties.ALL_KEYS) + .with(ListMenuItemProperties.TITLE, bookmarkItem.getTitle()) + .with(ListMenuItemProperties.ENABLED, true) + .with( + ListMenuItemProperties.CLICK_LISTENER, + (v) -> { + // Open url. + mBookmarkOpener.openBookmarkInCurrentTab( + bookmarkItem.getId(), + mProfileSupplier.get().isOffTheRecord()); + }) + .build(); + if (mImageFetcher != null) { + mImageFetcher.fetchFaviconForBookmark( + bookmarkItem, + (iconDrawable) -> { + // Update property model once we fetch the icon. + model.set(ListMenuItemProperties.START_ICON_DRAWABLE, iconDrawable); + }); + } + + return new ListItem(ListItemType.MENU_ITEM, model); + } + + private static Bitmap drawableToBitmap(Drawable drawable) { + Bitmap bitmap = + Bitmap.createBitmap( + drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } }
diff --git a/chrome/browser/bookmarks/android/javatests/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarTest.java b/chrome/browser/bookmarks/android/javatests/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarTest.java index dc2bc6a..6c95c60 100644 --- a/chrome/browser/bookmarks/android/javatests/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarTest.java +++ b/chrome/browser/bookmarks/android/javatests/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarTest.java
@@ -9,8 +9,11 @@ import static android.view.KeyEvent.META_CTRL_ON; import static android.view.KeyEvent.META_SHIFT_ON; +import static androidx.test.espresso.Espresso.onView; import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.RootMatchers.isPlatformPopup; import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; @@ -161,7 +164,13 @@ final String title = "Folder"; mItemIds = List.of(addFolder(title)); onViewWaiting(bookmarkBarItemWithText(title)).perform(click()); - onViewWaiting(bookmarkManagerToolbarWithText(title)).check(matches(isDisplayed())); + + // Check that the Bookmark Manager toolbar does not appear anymore when the folder is + // clicked. + onView(withClassName(endsWith("BookmarkToolbar"))).check(doesNotExist()); + + // Check that the new popup window is displayed. + onView(withId(R.id.menu_list)).inRoot(isPlatformPopup()).check(matches(isDisplayed())); } @Test
diff --git a/chrome/browser/bookmarks/android/junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediatorTest.java b/chrome/browser/bookmarks/android/junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediatorTest.java new file mode 100644 index 0000000..d45e64a --- /dev/null +++ b/chrome/browser/bookmarks/android/junit/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediatorTest.java
@@ -0,0 +1,162 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.bookmarks.bar; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import android.app.Activity; +import android.view.View; + +import androidx.recyclerview.widget.RecyclerView; +import androidx.test.ext.junit.rules.ActivityScenarioRule; +import androidx.test.filters.SmallTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +import org.chromium.base.supplier.ObservableSupplierImpl; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.bookmarks.BookmarkManagerOpener; +import org.chromium.chrome.browser.bookmarks.BookmarkModel; +import org.chromium.chrome.browser.bookmarks.BookmarkOpener; +import org.chromium.chrome.browser.bookmarks.FakeBookmarkModel; +import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.components.bookmarks.BookmarkId; +import org.chromium.ui.base.TestActivity; +import org.chromium.ui.listmenu.ListItemType; +import org.chromium.ui.listmenu.ListMenuItemProperties; +import org.chromium.ui.listmenu.ListMenuSubmenuItemProperties; +import org.chromium.ui.modelutil.MVCListAdapter.ListItem; +import org.chromium.ui.modelutil.MVCListAdapter.ModelList; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.url.JUnitTestGURLs; + +import java.util.List; + +/** Unit tests for the {@link BookmarkBarMediator}. */ +@RunWith(BaseRobolectricTestRunner.class) +public class BookmarkBarMediatorTest { + @Rule + public ActivityScenarioRule<TestActivity> mActivityScenarioRule = + new ActivityScenarioRule<>(TestActivity.class); + + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock private PropertyModel mPropertyModel; + @Mock private ModelList mItemsModel; + @Mock private PropertyModel mAllBookmarksButtonModel; + @Mock private BrowserControlsStateProvider mBrowserControlsStateProvider; + @Mock private ObservableSupplierImpl<Boolean> mItemsOverflowSupplier; + @Mock private Profile mProfile; + @Mock private BookmarkOpener mBookmarkOpener; + @Mock private RecyclerView mItemsRecyclerView; + @Mock private BookmarkBar mBookmarkBarView; + @Mock private View mAnchorView; + @Mock private RecyclerView.ViewHolder mViewHolder; + @Mock private BookmarkManagerOpener mBookmarkManagerOpener; + + private Activity mActivity; + private BookmarkBarMediator mMediator; + private FakeBookmarkModel mBookmarkModel; + private ObservableSupplierImpl<Profile> mProfileSupplier; + + @Before + public void setUp() { + mActivityScenarioRule.getScenario().onActivity((activity) -> mActivity = activity); + + mBookmarkModel = FakeBookmarkModel.createModel(); + BookmarkModel.setInstanceForTesting(mBookmarkModel); + mProfileSupplier = new ObservableSupplierImpl<>(mProfile); + + mMediator = + new BookmarkBarMediator( + mActivity, + mAllBookmarksButtonModel, + mBrowserControlsStateProvider, + () -> 0, // heightSupplier + mItemsModel, + mItemsOverflowSupplier, + mPropertyModel, + mProfileSupplier, + /* currentTab= */ null, + mBookmarkOpener, + new ObservableSupplierImpl<>(mBookmarkManagerOpener), + mItemsRecyclerView, + mBookmarkBarView); + } + + @After + public void tearDown() throws Exception { + mMediator.destroy(); + assertNull(BookmarkBarMediator.sFolderIconBitmap); + } + + // Tests the behavior of sFolderIconBitmap. + @Test + @SmallTest + public void testStaticFolderIconBitmap() throws Exception { + // Create a new folder inside the bookmarks bar. + BookmarkId desktopFolderId = mBookmarkModel.getDesktopFolderId(); + BookmarkId rootFolderId = mBookmarkModel.addFolder(desktopFolderId, 0, "Root Folder"); + + // Add a child folder to the root folder to ensure the caching logic is triggered. + mBookmarkModel.addFolder(rootFolderId, 0, "Child Folder"); + + assertNull("Cache should be empty initially.", BookmarkBarMediator.sFolderIconBitmap); + + // Trigger #createListItemForBookmarkFolder, which populates the sFolderIconBitmap cache. + mMediator.buildMenuModelListForFolder(rootFolderId); + + assertNotNull("Cache should be populated.", BookmarkBarMediator.sFolderIconBitmap); + + // Destroy behavior is tested in #tearDown. + } + + @Test + @SmallTest + public void testBuildMenuModelListForFolder_createsCorrectStructure() { + // Setup a nested folder structure: F1 -> (L1, F2 -> L2) + BookmarkId f1 = mBookmarkModel.addFolder(mBookmarkModel.getDesktopFolderId(), 0, "F1"); + mBookmarkModel.addBookmark(f1, 0, "L1", JUnitTestGURLs.URL_1); + BookmarkId f2 = mBookmarkModel.addFolder(f1, 1, "F2"); + mBookmarkModel.addBookmark(f2, 0, "L2", JUnitTestGURLs.URL_2); + + // Build the model list for the top-level folder F1. + ModelList modelList = mMediator.buildMenuModelListForFolder(f1); + + // Verify the structure of the top-level menu. + assertEquals("Top-level menu should have two items (L1, F2).", 2, modelList.size()); + + // Verify the first item (L1). + ListItem l1ListItem = modelList.get(0); + assertEquals(ListItemType.MENU_ITEM, l1ListItem.type); + assertEquals("L1", l1ListItem.model.get(ListMenuItemProperties.TITLE)); + + // Verify the second item (F2), which should be a submenu. + ListItem f2ListItem = modelList.get(1); + assertEquals(ListItemType.MENU_ITEM_WITH_SUBMENU, f2ListItem.type); + assertEquals("F2", f2ListItem.model.get(ListMenuItemProperties.TITLE)); + + // Verify the structure of the submenu. + List<ListItem> submenuItems = + f2ListItem.model.get(ListMenuSubmenuItemProperties.SUBMENU_ITEMS); + assertNotNull("Submenu items list should not be null.", submenuItems); + assertEquals("Submenu should have one item (L2).", 1, submenuItems.size()); + + // Verify the item in the submenu (L2). + ListItem l2ListItem = submenuItems.get(0); + assertEquals(ListItemType.MENU_ITEM, l2ListItem.type); + assertEquals("L2", l2ListItem.model.get(ListMenuItemProperties.TITLE)); + } +}
diff --git a/chrome/browser/browser_about_handler_unittest.cc b/chrome/browser/browser_about_handler_unittest.cc index 00a9c683..0c59b0d 100644 --- a/chrome/browser/browser_about_handler_unittest.cc +++ b/chrome/browser/browser_about_handler_unittest.cc
@@ -16,7 +16,6 @@ #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/policy/content/policy_blocklist_service.h" @@ -81,7 +80,9 @@ return &task_environment_; } - TestingPrefServiceSimple* local_state() { return local_state_.Get(); } + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } // Reverts the effects of a browser quit or restart attempt, // specifically for testing environments to prevent test failures. @@ -100,7 +101,6 @@ private: content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; std::unique_ptr<TestingProfile> profile_; };
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc index 63b9df8..e57de23 100644 --- a/chrome/browser/browser_features.cc +++ b/chrome/browser/browser_features.cc
@@ -34,11 +34,11 @@ "BookmarksTreeView", base::FEATURE_DISABLED_BY_DEFAULT); -// This flag is used for enabling Bookmark triggered prerendering. See -// crbug.com/1422819 for more details of Bookmark triggered prerendering. -BASE_FEATURE(kBookmarkTriggerForPrerender2, - "BookmarkTriggerForPrerender2", - base::FEATURE_ENABLED_BY_DEFAULT); +// This is used as a kill switch for Bookmark triggered prerendering. See +// crbug.com/40259793 for more details of Bookmark triggered prerendering. +BASE_FEATURE(kBookmarkTriggerForPrerender2KillSwitch, + "BookmarkTriggerForPrerender2KillSwitch", + base::FEATURE_DISABLED_BY_DEFAULT); // This flag is used for enabling BookmarkBar triggered preconnect. BASE_FEATURE(kBookmarkTriggerForPreconnect,
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h index 922b7fbd..64ce044f 100644 --- a/chrome/browser/browser_features.h +++ b/chrome/browser/browser_features.h
@@ -33,7 +33,7 @@ #endif // BUILDFLAG(IS_ANDROID) BASE_DECLARE_FEATURE(kAutocompleteActionPredictorConfidenceCutoff); BASE_DECLARE_FEATURE(kBookmarksTreeView); -BASE_DECLARE_FEATURE(kBookmarkTriggerForPrerender2); +BASE_DECLARE_FEATURE(kBookmarkTriggerForPrerender2KillSwitch); BASE_DECLARE_FEATURE(kBookmarkTriggerForPreconnect); BASE_DECLARE_FEATURE(kCertificateTransparencyAskBeforeEnabling); BASE_DECLARE_FEATURE(kCertVerificationNetworkTime);
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc index b67e29e..8edaadcb 100644 --- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc +++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -812,169 +812,6 @@ EXPECT_FALSE(HasDataForType(kType)); } -// ChromeOS users cannot sign out, their account preferences can never be -// cleared. -#if !BUILDFLAG(IS_CHROMEOS) - -IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, - ClearingCookiesAlsoClearsPasswordAccountStorageOptIn) { - const char kTestEmail[] = "foo@gmail.com"; - syncer::SyncService* sync_service = - SyncServiceFactory::GetForProfile(GetProfile()); - signin::IdentityManager* identity_manager = - IdentityManagerFactory::GetForProfile(GetProfile()); - signin::MakePrimaryAccountAvailable(identity_manager, kTestEmail, - signin::ConsentLevel::kSignin); - - // TODO(crbug.com/375024026): Revisit. - sync_service->GetUserSettings()->SetSelectedType( - syncer::UserSelectableType::kPasswords, false); - ASSERT_FALSE( - password_manager::features_util::IsAccountStorageEnabled(sync_service)); - - signin::ClearPrimaryAccount(identity_manager); - RemoveAndWait(chrome_browsing_data_remover::DATA_TYPE_SITE_DATA); - signin::MakePrimaryAccountAvailable(identity_manager, kTestEmail, - signin::ConsentLevel::kSignin); - - EXPECT_TRUE( - password_manager::features_util::IsAccountStorageEnabled(sync_service)); -} - -IN_PROC_BROWSER_TEST_F( - BrowsingDataRemoverBrowserTest, - ClearingCookiesWithFilterAlsoClearsPasswordAccountStorageSetting) { - const char kTestEmail[] = "foo@gmail.com"; - syncer::SyncService* sync_service = - SyncServiceFactory::GetForProfile(GetProfile()); - signin::IdentityManager* identity_manager = - IdentityManagerFactory::GetForProfile(GetProfile()); - signin::MakePrimaryAccountAvailable(identity_manager, kTestEmail, - signin::ConsentLevel::kSignin); - - sync_service->GetUserSettings()->SetSelectedType( - syncer::UserSelectableType::kPasswords, false); - ASSERT_FALSE( - password_manager::features_util::IsAccountStorageEnabled(sync_service)); - - // Clearing cookies for some random domain should have no effect on the - // setting. - signin::ClearPrimaryAccount(identity_manager); - { - std::unique_ptr<BrowsingDataFilterBuilder> filter_builder = - BrowsingDataFilterBuilder::Create( - BrowsingDataFilterBuilder::Mode::kDelete); - filter_builder->AddRegisterableDomain("example.com"); - RemoveWithFilterAndWait(chrome_browsing_data_remover::DATA_TYPE_SITE_DATA, - std::move(filter_builder)); - } - signin::MakePrimaryAccountAvailable(identity_manager, kTestEmail, - signin::ConsentLevel::kSignin); - EXPECT_FALSE( - password_manager::features_util::IsAccountStorageEnabled(sync_service)); - - // Clearing cookies for google.com should clear the setting. - signin::ClearPrimaryAccount(identity_manager); - { - std::unique_ptr<BrowsingDataFilterBuilder> filter_builder = - BrowsingDataFilterBuilder::Create( - BrowsingDataFilterBuilder::Mode::kDelete); - filter_builder->AddRegisterableDomain("google.com"); - RemoveWithFilterAndWait(chrome_browsing_data_remover::DATA_TYPE_SITE_DATA, - std::move(filter_builder)); - } - signin::MakePrimaryAccountAvailable(identity_manager, kTestEmail, - signin::ConsentLevel::kSignin); - EXPECT_TRUE( - password_manager::features_util::IsAccountStorageEnabled(sync_service)); -} - -IN_PROC_BROWSER_TEST_F(BrowsingDataRemoverBrowserTest, ClearSiteData) { - const char kTestEmail[] = "foo@gmail.com"; - syncer::SyncService* sync_service = - SyncServiceFactory::GetForProfile(GetProfile()); - signin::IdentityManager* identity_manager = - IdentityManagerFactory::GetForProfile(GetProfile()); - signin::MakePrimaryAccountAvailable(identity_manager, kTestEmail, - signin::ConsentLevel::kSignin); - - const GURL kFirstPartyURL("https://google.com"); - const GURL kCrossSiteURL("https://example.com"); - - struct TestCases { - const url::Origin origin; - const std::optional<net::CookiePartitionKey> cookie_partition_key; - const std::optional<blink::StorageKey> storage_key; - bool expects_keep_optin_pref; - }; - const auto test_cases = std::to_array<TestCases>({ - { - url::Origin::Create(kFirstPartyURL), - std::nullopt, - std::nullopt, - false, - }, - { - url::Origin::Create(kCrossSiteURL), - std::nullopt, - std::nullopt, - true, - }, - { - url::Origin::Create(kFirstPartyURL), - net::CookiePartitionKey::FromURLForTesting(kFirstPartyURL), - std::nullopt, - false, - }, - { - url::Origin::Create(kFirstPartyURL), - net::CookiePartitionKey::FromURLForTesting(kFirstPartyURL), - blink::StorageKey::CreateFirstParty( - url::Origin::Create(kFirstPartyURL)), - false, - }, - { - url::Origin::Create(kFirstPartyURL), - net::CookiePartitionKey::FromURLForTesting(kCrossSiteURL), - std::nullopt, - true, - }, - { - url::Origin::Create(kFirstPartyURL), - net::CookiePartitionKey::FromURLForTesting(kCrossSiteURL), - blink::StorageKey::Create( - url::Origin::Create(kCrossSiteURL), - net::SchemefulSite(url::Origin::Create(kFirstPartyURL)), - blink::mojom::AncestorChainBit::kCrossSite), - true, - }, - }); - for (size_t i = 0; i < std::size(test_cases); i++) { - SCOPED_TRACE(base::StringPrintf("Test case %zu", i)); - const auto& test_case = test_cases[i]; - - sync_service->GetUserSettings()->SetSelectedType( - syncer::UserSelectableType::kPasswords, false); - ASSERT_FALSE( - password_manager::features_util::IsAccountStorageEnabled(sync_service)); - signin::ClearPrimaryAccount(identity_manager); - ClearSiteDataAndWait(test_case.origin, test_case.cookie_partition_key, - test_case.storage_key, {}); - signin::MakePrimaryAccountAvailable(identity_manager, kTestEmail, - signin::ConsentLevel::kSignin); - - if (test_case.expects_keep_optin_pref) { - EXPECT_FALSE(password_manager::features_util::IsAccountStorageEnabled( - sync_service)); - } else { - EXPECT_TRUE(password_manager::features_util::IsAccountStorageEnabled( - sync_service)); - } - } -} - -#endif // !BUILDFLAG(IS_CHROMEOS) - // Storage Buckets class BrowsingDataRemoverStorageBucketsBrowserTest
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc index 292130d..e736ecd 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -353,10 +353,6 @@ ~content::BrowsingDataRemover::DATA_TYPE_AVOID_CLOSING_CONNECTIONS & ~constants::FILTERABLE_DATA_TYPES) == 0) || filter_builder->MatchesAllOriginsAndDomains()); -#if !BUILDFLAG(IS_ANDROID) - DCHECK(!should_clear_sync_account_settings_); -#endif - TRACE_EVENT0("browsing_data", "ChromeBrowsingDataRemoverDelegate::RemoveEmbedderData"); @@ -696,16 +692,6 @@ #endif } -#if !BUILDFLAG(IS_ANDROID) - if (nullable_filter.is_null() || - (!filter_builder->PartitionedCookiesOnly() && - nullable_filter.Run(GaiaUrls::GetInstance()->google_url()))) { - // Set a flag to clear account storage settings later instead of clearing - // it now as we can not reset this setting before passwords are deleted. - should_clear_sync_account_settings_ = true; - } -#endif - // Persistent Origin Trial tokens are only saved until the next page // load from the same origin. For that reason, they are not saved with // last-modified information, so deletion will clear all stored information. @@ -1591,32 +1577,6 @@ } } -#if !BUILDFLAG(IS_ANDROID) - // Explicitly clear any per account sync settings when cookies are being - // cleared. This needs to happen after the corresponding data has been - // deleted, so it is performed when all other tasks are completed. - // Note: These usually get cleared automatically when the Google cookies are - // deleted, but there is one edge case where that doesn't work: If the user - // clears cookies via CBD while they are already signed out (but their - // account is still present in the account chooser). In that case, without the - // code below, the settings-clearing would only happen when the Google cookies - // are refreshed the next time, typically on the next browser restart. - if (should_clear_sync_account_settings_) { - should_clear_sync_account_settings_ = false; - signin::IdentityManager* identity_manager = - IdentityManagerFactory::GetForProfile(profile_); - base::flat_set<GaiaId> gaia_ids = signin::GetAllGaiaIdsForKeyedPreferences( - identity_manager, - signin::AccountsInCookieJarInfo() /* empty_cookies */); - if (syncer::SyncService* sync_service = - SyncServiceFactory::GetForProfile(profile_); - sync_service) { - sync_service->GetUserSettings()->KeepAccountSettingsPrefsOnlyForUsers( - base::ToVector(gaia_ids)); - } - } -#endif // !BUILDFLAG(IS_ANDROID) - slow_pending_tasks_closure_.Cancel(); DCHECK(!callback_.is_null());
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h index 4f676b0a..bb86d66 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h +++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h
@@ -243,13 +243,6 @@ std::unique_ptr<WebappRegistry> webapp_registry_; #endif -#if !BUILDFLAG(IS_ANDROID) - // On desktop, some per-account sync settings must be cleared when cookies are - // deleted. This flag is used to defer the process until after sync uploads - // deletions of any other data. - bool should_clear_sync_account_settings_ = false; -#endif - // PasswordStore::DisableAutoSignInForOrigins() is required when wiping // DATA_TYPE_COOKIES, but that must be deferred until any password deletions // have completed, to avoid resurrecting passwords (c.f. crbug.com/325323180). @@ -257,8 +250,7 @@ // other tasks are done. Executing it adds to `pending_sub_tasks_` again. // OnBrowsingDataRemoverDone() is only called after the (async) auto-signin // disabling has completed. - // This field is similar to `should_clear_sync_account_settings_` above, - // except that clearing settings is synchronous, disabling auto sign-in isn't. + // Note disabling auto sign-in is asynchronous. base::OnceClosure deferred_disable_passwords_auto_signin_cb_; std::unique_ptr<device::fido::PlatformCredentialStore> credential_store_;
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 fe0bb19d..1400cda 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
@@ -14,6 +14,7 @@ #include <utility> #include <vector> +#include "base/check_deref.h" #include "base/containers/contains.h" #include "base/containers/flat_set.h" #include "base/files/file_util.h" @@ -90,7 +91,6 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/fake_profile_manager.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" @@ -727,22 +727,22 @@ class TestTpcdManagerDelegate : public tpcd::metadata::Manager::Delegate { public: - explicit TestTpcdManagerDelegate(ScopedTestingLocalState& local_state) - : local_state_(local_state) {} + explicit TestTpcdManagerDelegate(PrefService* local_state) + : local_state_(CHECK_DEREF(local_state)) {} void SetTpcdMetadataGrants(const ContentSettingsForOneType& grants) override { } - PrefService& GetLocalState() override { return *local_state_->Get(); } + PrefService& GetLocalState() override { return local_state_.get(); } private: - const raw_ref<ScopedTestingLocalState> local_state_; + const raw_ref<PrefService> local_state_; }; } // namespace class RemoveTpcdMetadataCohortsTester { public: - explicit RemoveTpcdMetadataCohortsTester(ScopedTestingLocalState& local_state, + explicit RemoveTpcdMetadataCohortsTester(PrefService* local_state, TestingProfile* profile) : test_delegate_(local_state) { det_generator_ = new tpcd::metadata::DeterministicGenerator(); @@ -1353,7 +1353,9 @@ return &task_environment_; } - ScopedTestingLocalState& local_state() { return local_state_; } + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } protected: // |feature_list_| needs to be destroyed after |task_environment_|, to avoid @@ -1372,7 +1374,6 @@ content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; base::ScopedTempDir temp_dir_; - ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; std::unique_ptr<network::NetworkContext> network_context_; std::unique_ptr<TestingProfileManager> profile_manager_; raw_ptr<TestingProfile> profile_; // Owned by `profile_manager_`.
diff --git a/chrome/browser/chrome_content_browser_client_browsertest.cc b/chrome/browser/chrome_content_browser_client_browsertest.cc index 410b620..76b6fc3 100644 --- a/chrome/browser/chrome_content_browser_client_browsertest.cc +++ b/chrome/browser/chrome_content_browser_client_browsertest.cc
@@ -1100,8 +1100,9 @@ } // namespace // URLs which are explicitly allowlisted by policy can bypass security checks. +// TODO: https://crbug.com/434758587 - Re-enable this test. IN_PROC_BROWSER_TEST_F(ProtocolHandlerTest, - SecurityCheckExceptionForAllowlistedUrls) { + DISABLED_SecurityCheckExceptionForAllowlistedUrls) { ProtocolHandlerRegistryFactory::GetInstance() ->GetForBrowserContext(browser()->profile()) ->OnAcceptRegisterProtocolHandler(
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc index 2f39f7636..70bd457 100644 --- a/chrome/browser/chrome_content_browser_client_unittest.cc +++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -46,7 +46,6 @@ #include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/browsing_data/content/browsing_data_helper.h" @@ -58,6 +57,7 @@ #include "components/file_access/test/mock_scoped_file_access_delegate.h" #include "components/network_session_configurator/common/network_switches.h" #include "components/policy/core/common/policy_pref_names.h" +#include "components/prefs/testing_pref_service.h" #include "components/privacy_sandbox/privacy_sandbox_features.h" #include "components/privacy_sandbox/tracking_protection_prefs.h" #include "components/search_engines/template_url_service.h" @@ -595,8 +595,7 @@ static const char kFakeGroupName[]; BlinkSettingsFieldTrialTest() - : command_line_(base::CommandLine::NO_PROGRAM), - testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + : command_line_(base::CommandLine::NO_PROGRAM) {} void SetUp() override { command_line_.AppendSwitchASCII(switches::kProcessType, @@ -639,7 +638,6 @@ base::CommandLine command_line_; content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState testing_local_state_; }; const char BlinkSettingsFieldTrialTest::kDisallowFetchFieldTrialName[] = @@ -913,21 +911,13 @@ #endif // BUILDFLAG(CHROME_ROOT_STORE_CERT_MANAGEMENT_UI) -class ChromeContentSettingsRedirectTest - : public ChromeContentBrowserClientTest { - public: - ChromeContentSettingsRedirectTest() - : testing_local_state_(TestingBrowserProcess::GetGlobal()) {} - - protected: - ScopedTestingLocalState testing_local_state_; -}; +using ChromeContentSettingsRedirectTest = ChromeContentBrowserClientTest; TEST_F(ChromeContentSettingsRedirectTest, RedirectDebugURL) { TestChromeContentBrowserClient test_content_browser_client; // Disable the internal only uis pref. - testing_local_state_.Get()->SetBoolean(chrome_urls::kInternalOnlyUisEnabled, - false); + TestingBrowserProcess::GetGlobal()->local_state()->SetBoolean( + chrome_urls::kInternalOnlyUisEnabled, false); // chrome://local-state is an internal debugging page available on all // platforms. @@ -940,8 +930,8 @@ dest_url.query()); // Enable the internal only uis pref. - testing_local_state_.Get()->SetBoolean(chrome_urls::kInternalOnlyUisEnabled, - true); + TestingBrowserProcess::GetGlobal()->local_state()->SetBoolean( + chrome_urls::kInternalOnlyUisEnabled, true); dest_url = debug_url; test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(debug_url, dest_url); @@ -957,7 +947,7 @@ base::Value::List list; list.Append(static_cast<int>(policy::SystemFeature::kBrowserSettings)); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, std::move(list)); dest_url = settings_url; @@ -972,7 +962,7 @@ test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(help_url, dest_url); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, base::Value::List().Append( static_cast<int>(policy::SystemFeature::kExplore))); @@ -992,7 +982,7 @@ test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(help_url, dest_url); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, base::Value::List().Append( static_cast<int>(policy::SystemFeature::kExplore))); @@ -1009,7 +999,7 @@ test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(gallery_url, dest_url); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, base::Value::List().Append( static_cast<int>(policy::SystemFeature::kGallery))); @@ -1028,7 +1018,7 @@ test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(gallery_url, dest_url); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, base::Value::List().Append( static_cast<int>(policy::SystemFeature::kGallery))); @@ -1048,7 +1038,7 @@ test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(terminal_url, dest_url); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, base::Value::List().Append( static_cast<int>(policy::SystemFeature::kTerminal))); @@ -1066,7 +1056,7 @@ test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(print_jobs_url, dest_url); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, base::Value::List().Append( static_cast<int>(policy::SystemFeature::kPrintJobs))); @@ -1084,7 +1074,7 @@ test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(key_shortcuts_url, dest_url); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, base::Value::List().Append( static_cast<int>(policy::SystemFeature::kKeyShortcuts))); @@ -1103,7 +1093,7 @@ base::Value::List list; list.Append(static_cast<int>(policy::SystemFeature::kOsSettings)); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, std::move(list)); dest_url = os_settings_url; @@ -1127,7 +1117,7 @@ test_content_browser_client.HandleWebUI(&dest_url, &profile_); EXPECT_EQ(recorder_url, dest_url); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, base::Value::List().Append( static_cast<int>(policy::SystemFeature::kRecorder))); @@ -1146,7 +1136,7 @@ base::Value::List list; list.Append(static_cast<int>(policy::SystemFeature::kScanning)); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, std::move(list)); dest_url = scanning_app_url; @@ -1165,7 +1155,7 @@ base::Value::List list; list.Append(static_cast<int>(policy::SystemFeature::kCamera)); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, std::move(list)); dest_url = camera_app_url; @@ -1182,7 +1172,7 @@ base::Value::List list; list.Append(static_cast<int>(policy::SystemFeature::kBrowserSettings)); - testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( policy::policy_prefs::kSystemFeaturesDisableList, std::move(list)); dest_url = help_url; @@ -1515,8 +1505,7 @@ class ChromeContentBrowserClientSwitchTest : public ChromeRenderViewHostTestHarness { public: - ChromeContentBrowserClientSwitchTest() - : testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + ChromeContentBrowserClientSwitchTest() = default; protected: void AppendSwitchInCurrentProcess(std::string_view switch_string) { @@ -1534,7 +1523,6 @@ } private: - ScopedTestingLocalState testing_local_state_; ChromeContentBrowserClient client_; }; @@ -1840,8 +1828,6 @@ ChromeContentBrowserClient& client() { return client_; } private: - ScopedTestingLocalState testing_local_state_{ - TestingBrowserProcess::GetGlobal()}; ScopedMetricsServiceForSyntheticTrials metrics_service_{ TestingBrowserProcess::GetGlobal()}; ChromeContentBrowserClient client_;
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 23336bd..010ce01 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc
@@ -52,7 +52,6 @@ #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -60,6 +59,7 @@ #include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/experiences/system_web_apps/types/system_web_app_delegate_map.h" #include "chromeos/dbus/power/fake_power_manager_client.h" +#include "components/prefs/pref_service.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h" #include "content/public/common/webplugininfo.h" @@ -272,9 +272,7 @@ : public ::testing::TestWithParam<KioskBrowserSessionParamType> { public: KioskBrowserSessionBaseTest() - : local_state_(std::make_unique<ScopedTestingLocalState>( - TestingBrowserProcess::GetGlobal())), - testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {} + : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) {} KioskBrowserSessionBaseTest(const KioskBrowserSessionBaseTest&) = delete; KioskBrowserSessionBaseTest& operator=(const KioskBrowserSessionBaseTest&) = @@ -293,7 +291,9 @@ static void TearDownTestSuite() { chromeos::PowerManagerClient::Shutdown(); } - TestingPrefServiceSimple* local_state() { return local_state_->Get(); } + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } TestingProfile* profile() { return profile_; } @@ -415,7 +415,6 @@ content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; base::ScopedTempDir temp_dir_; - std::unique_ptr<ScopedTestingLocalState> local_state_; ash::AshTestHelper ash_test_helper_; // `RenderViewHostTestEnabled` is required to make the navigation work that
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc index 66030c6c..6651a7e 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
@@ -20,13 +20,13 @@ #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" #include "chrome/browser/chromeos/policy/dlp/test/dlp_rules_manager_test_utils.h" #include "chrome/common/chrome_features.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/dlp/dlp_client.h" #include "components/enterprise/data_controls/core/browser/component.h" #include "components/enterprise/data_controls/core/browser/dlp_histogram_helper.h" #include "components/policy/core/common/policy_pref_names.h" +#include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -79,15 +79,14 @@ class DlpRulesManagerImplTest : public testing::Test { protected: - DlpRulesManagerImplTest() - : testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + DlpRulesManagerImplTest() = default; void SetUp() override { TestingProfile::Builder builder; profile_ = builder.Build(); dlp_rules_manager_ = std::make_unique<MockDlpRulesManager>( - testing_local_state_.Get(), profile_.get()); + TestingBrowserProcess::GetGlobal()->local_state(), profile_.get()); // THe histogram tester should be created after the rules manager, since the // rules manager constructor call OnPolicyUpdate, and we would then record @@ -100,8 +99,8 @@ for (const auto& rule : rules) { policy_rules.Append(rule.Create()); } - testing_local_state_.Get()->SetList(policy_prefs::kDlpRulesList, - std::move(policy_rules)); + TestingBrowserProcess::GetGlobal()->local_state()->SetList( + policy_prefs::kDlpRulesList, std::move(policy_rules)); } void CheckIsRestrictedComponent( @@ -176,7 +175,6 @@ } content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState testing_local_state_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<MockDlpRulesManager> dlp_rules_manager_; std::unique_ptr<base::HistogramTester> histogram_tester_;
diff --git a/chrome/browser/chromeos/reporting/local_state_reporting_settings_unittest.cc b/chrome/browser/chromeos/reporting/local_state_reporting_settings_unittest.cc index 01b7bb4..1d2f576 100644 --- a/chrome/browser/chromeos/reporting/local_state_reporting_settings_unittest.cc +++ b/chrome/browser/chromeos/reporting/local_state_reporting_settings_unittest.cc
@@ -9,7 +9,6 @@ #include "base/callback_list.h" #include "base/functional/callback_helpers.h" #include "base/test/bind.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/browser_task_environment.h" @@ -27,11 +26,12 @@ class LocalStateReportingSettingsTest : public ::testing::Test { protected: - TestingPrefServiceSimple* local_state() { return local_state_.Get(); } + TestingPrefServiceSimple* local_state() { + return TestingBrowserProcess::GetGlobal()->GetTestingLocalState(); + } private: ::content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; protected: LocalStateReportingSettings local_state_reporting_settings_;
diff --git a/chrome/browser/component_updater/origin_trials_component_installer_unittest.cc b/chrome/browser/component_updater/origin_trials_component_installer_unittest.cc index a30fc82..c131ef9c 100644 --- a/chrome/browser/component_updater/origin_trials_component_installer_unittest.cc +++ b/chrome/browser/component_updater/origin_trials_component_installer_unittest.cc
@@ -9,7 +9,6 @@ #include "base/version.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/component_updater/chrome_origin_trials_component_installer.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/embedder_support/origin_trials/pref_names.h" #include "components/prefs/scoped_user_pref_update.h" @@ -32,8 +31,7 @@ class OriginTrialsComponentInstallerTest : public PlatformTest { public: - OriginTrialsComponentInstallerTest() - : testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + OriginTrialsComponentInstallerTest() = default; OriginTrialsComponentInstallerTest( const OriginTrialsComponentInstallerTest&) = delete; @@ -62,7 +60,6 @@ protected: base::ScopedTempDir temp_dir_; - ScopedTestingLocalState testing_local_state_; std::unique_ptr<ComponentInstallerPolicy> policy_; };
diff --git a/chrome/browser/compose/compose_session.cc b/chrome/browser/compose/compose_session.cc index c21ac26..dd687b1 100644 --- a/chrome/browser/compose/compose_session.cc +++ b/chrome/browser/compose/compose_session.cc
@@ -83,6 +83,9 @@ const char kOnDeviceComposeBugReportURL[] = "https://goto.google.com/ccbrfdod"; const char kComposeLearnMorePageURL[] = "https://support.google.com/chrome?p=help_me_write"; +// TODO(crbug.com/40500621): Replace with p-link +const char kEnterpriseComposeLearnMorePageURL[] = + "https://support.google.com/chrome/a/answer/14443058"; const char kComposeFeedbackSurveyURL[] = "https://goto.google.com/ccfsfd"; const char kSignInPageURL[] = "https://accounts.google.com"; const char kOnDeviceComposeFeedbackSurveyURL[] = @@ -952,6 +955,15 @@ /*navigation_handle_callback=*/{}); } +void ComposeSession::OpenEnterpriseComposeLearnMorePage() { + web_contents_->OpenURL( + content::OpenURLParams( + GURL(kEnterpriseComposeLearnMorePageURL), content::Referrer(), + WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, + /* is_renderer_initiated= */ false), + /*navigation_handle_callback=*/{}); +} + void ComposeSession::OpenFeedbackSurveyLink() { const char* url = kComposeFeedbackSurveyURL; if (auto last_response_state = LastResponseState();
diff --git a/chrome/browser/compose/compose_session.h b/chrome/browser/compose/compose_session.h index ac86b6a..1738654 100644 --- a/chrome/browser/compose/compose_session.h +++ b/chrome/browser/compose/compose_session.h
@@ -156,6 +156,10 @@ // is clicked in the FRE or Compose dialog. void OpenComposeLearnMorePage() override; + // Opens the Chrome Generative AI features and policies page in a new tab when + // the "Learn more" link is clicked in the FRE or Compose dialog. + void OpenEnterpriseComposeLearnMorePage() override; + // Opens the Compose feedback survey page in a new tab. This implementation is // designed for Dogfood only. void OpenFeedbackSurveyLink() override;
diff --git a/chrome/browser/controlled_frame/controlled_frame_apitest.cc b/chrome/browser/controlled_frame/controlled_frame_apitest.cc index 821ae67..4150073 100644 --- a/chrome/browser/controlled_frame/controlled_frame_apitest.cc +++ b/chrome/browser/controlled_frame/controlled_frame_apitest.cc
@@ -1080,30 +1080,7 @@ // via defaults but instead by overrides. As a result, any feature that's // enabled or disabled by ScopedFeatureList will appear as an override. bool DetermineExpectedState() { - if (feature_setting() == FeatureSetting::DISABLED) { - return false; - } - - if (feature_setting() == FeatureSetting::NONE && - flag_setting() == FlagSetting::NONE) { - return false; - } - - if (feature_setting() == FeatureSetting::ENABLED && - (flag_setting() == FlagSetting::EXPERIMENTAL || - flag_setting() == FlagSetting::CONTROLLED_FRAME)) { - return true; - } - - // In Blink's runtime flags, if the base::Feature is overridden and that - // feature is enabled via the override, then the corresponding Blink - // runtime flag is also enabled. - if (feature_setting() == FeatureSetting::ENABLED && - flag_setting() == FlagSetting::NONE) { - return true; - } - - return false; + return feature_setting() != FeatureSetting::DISABLED; } };
diff --git a/chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc b/chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc index 511cbca..6ea928d6 100644 --- a/chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc +++ b/chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/device_identity/chromeos/token_encryptor.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/ash/components/cryptohome/system_salt_getter.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" @@ -26,6 +25,7 @@ #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" #include "chromeos/ash/components/policy/device_policy/device_policy_builder.h" #include "components/ownership/mock_owner_key_util.h" +#include "components/prefs/testing_pref_service.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" @@ -46,8 +46,7 @@ class DeviceOAuth2TokenStoreChromeOSTest : public testing::Test { public: - DeviceOAuth2TokenStoreChromeOSTest() - : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + DeviceOAuth2TokenStoreChromeOSTest() = default; void SetUp() override { ash::CryptohomeMiscClient::InitializeFake(); @@ -124,7 +123,7 @@ void StoreV1TokenInLocalState(const std::string& token) { ash::CryptohomeTokenEncryptor encryptor(GetStubSaltAsString()); - scoped_testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( prefs::kDeviceRobotAnyApiRefreshTokenV1, std::make_unique<base::Value>( encryptor.WeakEncryptWithSystemSalt(token))); @@ -132,7 +131,7 @@ void StoreV2TokenInLocalState(const std::string& token) { ash::CryptohomeTokenEncryptor encryptor(GetStubSaltAsString()); - scoped_testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( prefs::kDeviceRobotAnyApiRefreshTokenV2, std::make_unique<base::Value>(encryptor.EncryptWithSystemSalt(token))); } @@ -143,17 +142,17 @@ chrome::FILE_CHROME_OS_DEVICE_REFRESH_TOKEN, GetTempPath(), true, false)); ASSERT_TRUE(base::WriteFile(GetTempPath(), token)); - scoped_testing_local_state_.Get()->SetUserPref( + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetUserPref( prefs::kDeviceRefreshTokenAnyApiIsV3Used, std::make_unique<base::Value>(true)); } content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState scoped_testing_local_state_; ash::ScopedStubInstallAttributes scoped_stub_install_attributes_; ash::ScopedTestDeviceSettingsService scoped_device_settings_service_; ash::CrosSettingsHolder cros_settings_holder_{ - ash::DeviceSettingsService::Get(), scoped_testing_local_state_.Get()}; + ash::DeviceSettingsService::Get(), + TestingBrowserProcess::GetGlobal()->local_state()}; ash::FakeSessionManagerClient session_manager_client_; policy::DevicePolicyBuilder device_policy_; base::ScopedTempDir temp_dir_; @@ -164,7 +163,7 @@ ash::FakeCryptohomeMiscClient::Get()->SetServiceIsAvailable(false); chromeos::DeviceOAuth2TokenStoreChromeOS store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); EXPECT_TRUE(store.GetAccountId().empty()); EXPECT_TRUE(store.GetRefreshToken().empty()); @@ -187,7 +186,7 @@ TEST_F(DeviceOAuth2TokenStoreChromeOSTest, LoadV1Token) { chromeos::DeviceOAuth2TokenStoreChromeOS store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); StoreV1TokenInLocalState("test-token"); InitStore(&store); @@ -197,7 +196,7 @@ TEST_F(DeviceOAuth2TokenStoreChromeOSTest, LoadV2Token) { chromeos::DeviceOAuth2TokenStoreChromeOS store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); StoreV2TokenInLocalState("test-token"); InitStore(&store); @@ -207,7 +206,7 @@ TEST_F(DeviceOAuth2TokenStoreChromeOSTest, LoadV3Token) { chromeos::DeviceOAuth2TokenStoreChromeOS store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(chromeos::kRefreshTokenV3Feature); StoreV3Token("test-token"); @@ -220,7 +219,7 @@ base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndDisableFeature(chromeos::kRefreshTokenV3Feature); chromeos::DeviceOAuth2TokenStoreChromeOS store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); StoreV1TokenInLocalState("test-token-v1"); StoreV2TokenInLocalState("test-token-v2"); @@ -232,7 +231,7 @@ TEST_F(DeviceOAuth2TokenStoreChromeOSTest, SaveToken) { chromeos::DeviceOAuth2TokenStoreChromeOS store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); InitStore(&store); @@ -243,7 +242,7 @@ TEST_F(DeviceOAuth2TokenStoreChromeOSTest, SaveEncryptedTokenEarly) { chromeos::DeviceOAuth2TokenStoreChromeOS store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); // Set a new refresh token without the system salt available. InitWithPendingSalt(&store); @@ -263,7 +262,7 @@ // Reloading shouldn't change the token either. chromeos::DeviceOAuth2TokenStoreChromeOS other_store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); InitStore(&other_store); EXPECT_EQ("test-token", other_store.GetRefreshToken()); @@ -271,7 +270,7 @@ TEST_F(DeviceOAuth2TokenStoreChromeOSTest, DoNotAnnounceTokenWithoutAccountID) { chromeos::DeviceOAuth2TokenStoreChromeOS store( - scoped_testing_local_state_.Get()); + TestingBrowserProcess::GetGlobal()->local_state()); InitStore(&store); class StoreObserver : public DeviceOAuth2TokenStore::Observer {
diff --git a/chrome/browser/device_identity/device_oauth2_token_service_unittest.cc b/chrome/browser/device_identity/device_oauth2_token_service_unittest.cc index fdac4a50..4230d21 100644 --- a/chrome/browser/device_identity/device_oauth2_token_service_unittest.cc +++ b/chrome/browser/device_identity/device_oauth2_token_service_unittest.cc
@@ -15,7 +15,6 @@ #include "base/task/thread_pool/thread_pool_instance.h" #include "build/build_config.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/prefs/testing_pref_service.h" #include "content/public/browser/browser_thread.h" @@ -98,8 +97,7 @@ class DeviceOAuth2TokenServiceTest : public testing::Test { public: - DeviceOAuth2TokenServiceTest() - : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + DeviceOAuth2TokenServiceTest() = default; // Most tests just want a noop crypto impl with a dummy refresh token value in // Local State (if the value is an empty string, it will be ignored). @@ -206,7 +204,6 @@ }; content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState scoped_testing_local_state_; network::TestURLLoaderFactory test_url_loader_factory_; std::unique_ptr<DeviceOAuth2TokenService, TokenServiceDeleter> oauth2_service_;
diff --git a/chrome/browser/device_identity/device_oauth2_token_store_desktop_unittest.cc b/chrome/browser/device_identity/device_oauth2_token_store_desktop_unittest.cc index 754081a..88f942dd 100644 --- a/chrome/browser/device_identity/device_oauth2_token_store_desktop_unittest.cc +++ b/chrome/browser/device_identity/device_oauth2_token_store_desktop_unittest.cc
@@ -7,11 +7,11 @@ #include "base/base64.h" #include "base/test/bind.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/os_crypt/sync/os_crypt.h" #include "components/os_crypt/sync/os_crypt_mocker.h" #include "components/policy/core/common/policy_pref_names.h" +#include "components/prefs/pref_service.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -32,12 +32,11 @@ class DeviceOAuth2TokenStoreDesktopTest : public testing::Test { public: - DeviceOAuth2TokenStoreDesktopTest() - : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + DeviceOAuth2TokenStoreDesktopTest() = default; ~DeviceOAuth2TokenStoreDesktopTest() override = default; - ScopedTestingLocalState* scoped_testing_local_state() { - return &scoped_testing_local_state_; + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); } void SetUp() override { @@ -49,13 +48,10 @@ OSCryptMocker::TearDown(); testing::Test::TearDown(); } - - private: - ScopedTestingLocalState scoped_testing_local_state_; }; TEST_F(DeviceOAuth2TokenStoreDesktopTest, InitWithoutSavedToken) { - DeviceOAuth2TokenStoreDesktop store(scoped_testing_local_state()->Get()); + DeviceOAuth2TokenStoreDesktop store(local_state()); EXPECT_TRUE(store.GetAccountId().empty()); EXPECT_TRUE(store.GetRefreshToken().empty()); @@ -73,8 +69,7 @@ } TEST_F(DeviceOAuth2TokenStoreDesktopTest, InitWithSavedToken) { - scoped_testing_local_state()->Get()->SetString(kCBCMServiceAccountEmail, - kTestRobotEmail); + local_state()->SetString(kCBCMServiceAccountEmail, kTestRobotEmail); std::string token = "test_token"; std::string encrypted_token; @@ -82,10 +77,9 @@ std::string encoded = base::Base64Encode(encrypted_token); - scoped_testing_local_state()->Get()->SetString( - kCBCMServiceAccountRefreshToken, encoded); + local_state()->SetString(kCBCMServiceAccountRefreshToken, encoded); - DeviceOAuth2TokenStoreDesktop store(scoped_testing_local_state()->Get()); + DeviceOAuth2TokenStoreDesktop store(local_state()); EXPECT_TRUE(store.GetRefreshToken().empty()); @@ -101,8 +95,7 @@ } TEST_F(DeviceOAuth2TokenStoreDesktopTest, ObserverNotifiedWhenAccountChanges) { - scoped_testing_local_state()->Get()->SetString(kCBCMServiceAccountEmail, - kTestRobotEmail); + local_state()->SetString(kCBCMServiceAccountEmail, kTestRobotEmail); std::string token = "test_token"; std::string encrypted_token; @@ -110,10 +103,9 @@ std::string encoded = base::Base64Encode(encrypted_token); - scoped_testing_local_state()->Get()->SetString( - kCBCMServiceAccountRefreshToken, encoded); + local_state()->SetString(kCBCMServiceAccountRefreshToken, encoded); - DeviceOAuth2TokenStoreDesktop store(scoped_testing_local_state()->Get()); + DeviceOAuth2TokenStoreDesktop store(local_state()); TestObserver test_observer; store.SetObserver(&test_observer); @@ -136,7 +128,7 @@ TEST_F(DeviceOAuth2TokenStoreDesktopTest, SaveToken) { std::string token = "test_token"; - DeviceOAuth2TokenStoreDesktop store(scoped_testing_local_state()->Get()); + DeviceOAuth2TokenStoreDesktop store(local_state()); store.Init(base::BindOnce([](bool, bool) {})); EXPECT_TRUE(store.GetRefreshToken().empty()); @@ -149,8 +141,8 @@ EXPECT_TRUE(callback_success); - std::string persisted_token = scoped_testing_local_state()->Get()->GetString( - kCBCMServiceAccountRefreshToken); + std::string persisted_token = + local_state()->GetString(kCBCMServiceAccountRefreshToken); std::string decoded; base::Base64Decode(persisted_token, &decoded);
diff --git a/chrome/browser/device_reauth/chromeos/device_authenticator_chromeos_unittest.cc b/chrome/browser/device_reauth/chromeos/device_authenticator_chromeos_unittest.cc index 59e1eed..a9d6aea 100644 --- a/chrome/browser/device_reauth/chromeos/device_authenticator_chromeos_unittest.cc +++ b/chrome/browser/device_reauth/chromeos/device_authenticator_chromeos_unittest.cc
@@ -13,10 +13,10 @@ #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/time/time.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/device_reauth/device_reauth_metrics_util.h" #include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -49,8 +49,7 @@ : device_authenticator_params_( kAuthValidityPeriod, device_reauth::DeviceAuthSource::kPasswordManager, - kHistogramName), - testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + kHistogramName) {} void SetUp() override { std::unique_ptr<MockSystemAuthenticator> system_authenticator = std::make_unique<MockSystemAuthenticator>(); @@ -65,7 +64,9 @@ return *system_authenticator_; } - ScopedTestingLocalState& local_state() { return testing_local_state_; } + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } base::test::TaskEnvironment& task_environment() { return task_environment_; } @@ -86,7 +87,6 @@ base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; std::unique_ptr<DeviceAuthenticatorChromeOS> authenticator_; - ScopedTestingLocalState testing_local_state_; base::HistogramTester histogram_tester_; // This is owned by the authenticator. @@ -214,7 +214,7 @@ EXPECT_EQ(test_case.expected_result, authenticator()->CanAuthenticateWithBiometrics()); EXPECT_EQ(test_case.expected_result, - local_state().Get()->GetBoolean( + local_state()->GetBoolean( password_manager::prefs::kHadBiometricsAvailable)); histogram_tester().ExpectUniqueSample( "PasswordManager.BiometricAvailabilityChromeOS",
diff --git a/chrome/browser/device_reauth/mac/device_authenticator_mac_unittest.mm b/chrome/browser/device_reauth/mac/device_authenticator_mac_unittest.mm index 7e5772d..b10d0f8 100644 --- a/chrome/browser/device_reauth/mac/device_authenticator_mac_unittest.mm +++ b/chrome/browser/device_reauth/mac/device_authenticator_mac_unittest.mm
@@ -12,10 +12,10 @@ #include "base/time/time.h" #include "chrome/browser/device_reauth/chrome_device_authenticator_factory.h" #include "chrome/browser/device_reauth/mac/authenticator_mac.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/device_reauth/device_reauth_metrics_util.h" #include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_service.h" #include "device/fido/mac/scoped_touch_id_test_environment.h" #include "device/fido/mac/touch_id_context.h" #include "testing/gtest/include/gtest/gtest.h" @@ -48,8 +48,7 @@ : public ::testing::TestWithParam<std::tuple<bool, bool>> { public: DeviceAuthenticatorMacTest() - : testing_local_state_(TestingBrowserProcess::GetGlobal()), - device_authenticator_params_( + : device_authenticator_params_( kAuthValidityPeriod, device_reauth::DeviceAuthSource::kPasswordManager, kHistogramName) { @@ -94,7 +93,9 @@ return *system_authenticator_; } - ScopedTestingLocalState& local_state() { return testing_local_state_; } + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } base::test::TaskEnvironment& task_environment() { return task_environment_; } @@ -110,7 +111,6 @@ DeviceAuthenticatorProxy proxy_; base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - ScopedTestingLocalState testing_local_state_; device_reauth::DeviceAuthParams device_authenticator_params_; std::unique_ptr<device_reauth::DeviceAuthenticator> authenticator_; device::fido::mac::AuthenticatorConfig config_{ @@ -217,7 +217,7 @@ EXPECT_EQ(authenticator()->CanAuthenticateWithBiometrics(), is_biometric_available()); EXPECT_EQ(is_biometric_available(), - local_state().Get()->GetBoolean( + local_state()->GetBoolean( password_manager::prefs::kHadBiometricsAvailable)); } @@ -232,7 +232,7 @@ EXPECT_EQ(authenticator()->CanAuthenticateWithBiometricOrScreenLock(), is_biometric_available() || is_screen_lock_available()); EXPECT_EQ(is_biometric_available(), - local_state().Get()->GetBoolean( + local_state()->GetBoolean( password_manager::prefs::kHadBiometricsAvailable)); }
diff --git a/chrome/browser/device_reauth/win/device_authenticator_win_unittest.cc b/chrome/browser/device_reauth/win/device_authenticator_win_unittest.cc index 84822bb..e1c8b4d 100644 --- a/chrome/browser/device_reauth/win/device_authenticator_win_unittest.cc +++ b/chrome/browser/device_reauth/win/device_authenticator_win_unittest.cc
@@ -16,11 +16,11 @@ #include "base/test/task_environment.h" #include "base/time/time.h" #include "chrome/browser/device_reauth/chrome_device_authenticator_factory.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/device_reauth/device_authenticator.h" #include "components/device_reauth/device_reauth_metrics_util.h" #include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/prefs/pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -52,8 +52,7 @@ class DeviceAuthenticatorWinTest : public testing::Test { public: DeviceAuthenticatorWinTest() - : testing_local_state_(TestingBrowserProcess::GetGlobal()), - device_authenticator_params_( + : device_authenticator_params_( kAuthValidityPeriod, device_reauth::DeviceAuthSource::kPasswordManager, kHistogramName) {} @@ -73,7 +72,9 @@ base::test::TaskEnvironment& task_environment() { return task_environment_; } - ScopedTestingLocalState& local_state() { return testing_local_state_; } + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } base::HistogramTester& histogram_tester() { return histogram_tester_; } @@ -91,7 +92,6 @@ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; DeviceAuthenticatorProxy proxy_; std::unique_ptr<DeviceAuthenticatorWin> authenticator_; - ScopedTestingLocalState testing_local_state_; device_reauth::DeviceAuthParams device_authenticator_params_; base::HistogramTester histogram_tester_; @@ -163,24 +163,24 @@ // Checks if CanAuthenticateWithBiometrics returns a valid pref value. TEST_F(DeviceAuthenticatorWinTest, CanAuthenticateWithBiometrics) { - local_state().Get()->SetBoolean( - password_manager::prefs::kIsBiometricAvailable, true); + local_state()->SetBoolean(password_manager::prefs::kIsBiometricAvailable, + true); EXPECT_TRUE(authenticator()->CanAuthenticateWithBiometrics()); - local_state().Get()->SetBoolean( - password_manager::prefs::kIsBiometricAvailable, false); + local_state()->SetBoolean(password_manager::prefs::kIsBiometricAvailable, + false); EXPECT_FALSE(authenticator()->CanAuthenticateWithBiometrics()); } // Checks if CanAuthenticateWithBiometricOrScreenLock returns the correct // response based on whether biometric or screen lock is available. TEST_F(DeviceAuthenticatorWinTest, CanAuthenticateWithBiometricOrScreenLock) { - local_state().Get()->SetBoolean( - password_manager::prefs::kIsBiometricAvailable, true); + local_state()->SetBoolean(password_manager::prefs::kIsBiometricAvailable, + true); EXPECT_TRUE(authenticator()->CanAuthenticateWithBiometricOrScreenLock()); - local_state().Get()->SetBoolean( - password_manager::prefs::kIsBiometricAvailable, false); + local_state()->SetBoolean(password_manager::prefs::kIsBiometricAvailable, + false); ON_CALL(system_authenticator(), CanAuthenticateWithScreenLock) .WillByDefault(testing::Return(true)); EXPECT_TRUE(authenticator()->CanAuthenticateWithBiometricOrScreenLock()); @@ -253,7 +253,7 @@ EXPECT_EQ(test_case.expected_result, authenticator()->CanAuthenticateWithBiometrics()); EXPECT_EQ(test_case.expected_result, - local_state().Get()->GetBoolean( + local_state()->GetBoolean( password_manager::prefs::kHadBiometricsAvailable)); histogram_tester().ExpectUniqueSample( "PasswordManager.BiometricAvailabilityWin", test_case.expected_bucket, 1);
diff --git a/chrome/browser/devtools/devtools_contents_resizing_strategy.cc b/chrome/browser/devtools/devtools_contents_resizing_strategy.cc index 758c73c..4f38ea06 100644 --- a/chrome/browser/devtools/devtools_contents_resizing_strategy.cc +++ b/chrome/browser/devtools/devtools_contents_resizing_strategy.cc
@@ -49,11 +49,10 @@ return; } - int left = - std::min(bounds.x() + container_bounds.x(), container_bounds.width()); - int top = - std::min(bounds.y() + container_bounds.y(), container_bounds.height()); - int width = std::min(bounds.width(), container_bounds.width() - left); - int height = std::min(bounds.height(), container_bounds.height() - top); - new_contents_bounds->SetRect(left, top, width, height); + int left = std::min(bounds.x(), container_bounds.width()); + int top = std::min(bounds.y(), container_bounds.height()); + int width = std::min(bounds.width(), container_bounds.width()); + int height = std::min(bounds.height(), container_bounds.height()); + new_contents_bounds->SetRect(left + container_bounds.x(), + top + container_bounds.y(), width, height); }
diff --git a/chrome/browser/devtools/devtools_select_file_dialog_unittest.cc b/chrome/browser/devtools/devtools_select_file_dialog_unittest.cc index 0811328..8b80430 100644 --- a/chrome/browser/devtools/devtools_select_file_dialog_unittest.cc +++ b/chrome/browser/devtools/devtools_select_file_dialog_unittest.cc
@@ -7,7 +7,6 @@ #include "base/files/file_path.h" #include "base/run_loop.h" #include "base/test/mock_callback.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "content/public/test/file_system_chooser_test_helpers.h" @@ -31,10 +30,6 @@ ui::SelectFileDialog::SetFactory(nullptr); content::RenderViewHostTestHarness::TearDown(); } - - private: - ScopedTestingLocalState testing_local_state_{ - TestingBrowserProcess::GetGlobal()}; }; TEST_F(DevToolsSelectFileDialogTest, SelectFileCanceledCallback) {
diff --git a/chrome/browser/devtools/protocol/autofill_handler.cc b/chrome/browser/devtools/protocol/autofill_handler.cc index 4b37e41..c72512b 100644 --- a/chrome/browser/devtools/protocol/autofill_handler.cc +++ b/chrome/browser/devtools/protocol/autofill_handler.cc
@@ -21,6 +21,7 @@ #include "components/autofill/core/browser/data_model/addresses/autofill_profile.h" #include "components/autofill/core/browser/data_model/payments/credit_card.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/filling/addresses/field_filling_address_util.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/foundations/autofill_manager.h" #include "components/autofill/core/browser/foundations/browser_autofill_manager.h" @@ -244,6 +245,9 @@ return ids; }(); + // Devtools is already in English, so we can default the locale to en-US. + const std::string locale = "en-US"; + auto filled_fields_to_be_sent_to_devtools = std::make_unique<protocol::Array<protocol::Autofill::FilledField>>(); filled_fields_to_be_sent_to_devtools->reserve(filled_field_ids.size()); @@ -268,14 +272,23 @@ std::vector<std::string_view> field_type_strings = base::ToVector( field_types, &autofill::FieldTypeToDeveloperRepresentationString); std::erase(field_type_strings, ""); - + // TODO(crbug.com/436489442): Reading the filled value from the profile is + // brittle because it could diverge from the values that are actually sent + // to the renderer. A more robust solution should be found. + std::u16string filled_value = u""; + if (filled_field_ids.contains(field->global_id())) { + std::string failure_to_fill; + filled_value = + autofill::GetFillingValueAndTypeForProfile( + *profile_used_to_fill_form, locale, field->Type(), *field, + manager.client().GetAddressNormalizer(), &failure_to_fill) + .first; + } filled_fields_to_be_sent_to_devtools->push_back( protocol::Autofill::FilledField::Create() .SetId(base::UTF16ToUTF8(field->id_attribute())) .SetName(base::UTF16ToUTF8(field->name_attribute())) - .SetValue(base::UTF16ToUTF8( - filled_field_ids.contains(field->global_id()) ? field->value() - : u"")) + .SetValue(base::UTF16ToUTF8(filled_value)) .SetHtmlType(std::string( autofill::FormControlTypeToString(field->form_control_type()))) .SetAutofillType(base::JoinString(field_type_strings, ", ")) @@ -295,8 +308,6 @@ // Send profile information to devtools so that it can build the UI. // We use the same format we see in the settings page. std::vector<std::vector<autofill::AutofillAddressUIComponent>> components; - // Devtools is already in english, so we can default the local to en-US. - const std::string locale = "en-US"; autofill::GetAddressComponents( base::UTF16ToUTF8(profile_used_to_fill_form->GetInfo( autofill::FieldType::ADDRESS_HOME_COUNTRY, locale)),
diff --git a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc index 74004e7..ff18129 100644 --- a/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc +++ b/chrome/browser/devtools/protocol/devtools_autofill_browsertest.cc
@@ -493,11 +493,6 @@ form_structure->field(1)->SetHtmlType(HtmlFieldType::kUnspecified, HtmlFieldMode::kShipping); - // Fake a that the fields were filled. - form_structure->field(0)->set_value(u"value_1"); - form_structure->field(1)->set_value(u"value_2"); - test_api(form).field(0).set_value(u"value_1"); - test_api(form).field(1).set_value(u"value_2"); const std::vector<FormFieldData> filled_fields_by_autofill = { {form.fields()[0], form.fields()[1]}}; @@ -558,7 +553,8 @@ EXPECT_THAT( ff, FilledFieldHasAttributeWithValue( "autofillType", base::JoinString(field_type_strings, ", "))); - EXPECT_THAT(ff, FilledFieldHasAttributeWithValue16("value", af->value())); + EXPECT_THAT(ff, FilledFieldHasAttributeWithValue16( + "value", profile.GetInfo(af->Type(), "en-us"))); EXPECT_THAT(ff, FilledFieldHasAttributeWithValue16( "frameId", base::UTF8ToUTF16(
diff --git a/chrome/browser/devtools/protocol/user_reidentification_issues_browsertest.cc b/chrome/browser/devtools/protocol/user_reidentification_issues_browsertest.cc index f498d1f..593a97d 100644 --- a/chrome/browser/devtools/protocol/user_reidentification_issues_browsertest.cc +++ b/chrome/browser/devtools/protocol/user_reidentification_issues_browsertest.cc
@@ -6,23 +6,18 @@ #include <tuple> #include "base/test/scoped_feature_list.h" -#include "base/test/values_test_util.h" #include "chrome/browser/fingerprinting_protection/fingerprinting_protection_filter_browser_test_harness.h" #include "chrome/browser/ui/browser.h" -#include "chrome/test/base/ui_test_utils.h" #include "components/fingerprinting_protection_filter/common/fingerprinting_protection_filter_features.h" +#include "components/fingerprinting_protection_filter/interventions/common/interventions_features.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" -#include "content/public/test/content_browser_test_utils.h" #include "content/public/test/test_devtools_protocol_client.h" #include "url/gurl.h" namespace fingerprinting_protection_filter { namespace { -using testing::Eq; -using testing::Pointee; - class UserReideintificationDevtoolsProtocolTest : public content::TestDevToolsProtocolClient, public FingerprintingProtectionFilterBrowserTest { @@ -61,6 +56,28 @@ affected_url.possibly_invalid_spec()); } + void WaitForCanvasNoiseIssueAdded() { + auto matcher = [](const base::Value::Dict& params) { + const std::string* maybe_issue_code = + params.FindStringByDottedPath("issue.code"); + return maybe_issue_code && + *maybe_issue_code == "UserReidentificationIssue"; + }; + + base::Value::Dict notification = WaitForMatchingNotification( + "Audits.issueAdded", base::BindRepeating(matcher)); + + EXPECT_EQ(*notification.FindStringByDottedPath( + "issue.details.userReidentificationIssueDetails.type"), + "NoisedCanvasReadback"); + // The canvas noise issue does not have a request. + EXPECT_FALSE(notification.FindDictByDottedPath( + "issue.details.userReidentificationIssueDetails.request")); + // But it should have a source code location. + EXPECT_TRUE(notification.FindDictByDottedPath( + "issue.details.userReidentificationIssueDetails.sourceCodeLocation")); + } + protected: void Attach() { AttachToWebContents(web_contents()); } @@ -90,6 +107,16 @@ ~IncognitoUserReideintificationDevtoolsProtocolTest() override = default; }; +class CanvasNoiseDevtoolsProtocolTest + : public UserReideintificationDevtoolsProtocolTest { + public: + CanvasNoiseDevtoolsProtocolTest() { + scoped_feature_list_.InitAndEnableFeatureWithParameters( + fingerprinting_protection_interventions::features::kCanvasNoise, + {{"enable_in_regular_mode", "true"}}); + } +}; + } // namespace IN_PROC_BROWSER_TEST_F(UserReideintificationDevtoolsProtocolTest, @@ -164,4 +191,19 @@ /*affected_url=*/GetCrossSiteTestUrl("/frame_with_included_script.html")); } +IN_PROC_BROWSER_TEST_F(CanvasNoiseDevtoolsProtocolTest, + CanvasNoiseApplied_IssueReported) { + ASSERT_TRUE(embedded_test_server()->Start()); + EnableAudits(); + + ASSERT_TRUE(content::ExecJs( + web_contents(), + "const canvas = document.createElement('canvas');" + "document.body.appendChild(canvas);" + "const ctx = canvas.getContext('2d');" + "ctx.fillText('CanvasNoiseTest', 0, 10); canvas.toDataURL();")); + + WaitForCanvasNoiseIssueAdded(); +} + } // namespace fingerprinting_protection_filter
diff --git a/chrome/browser/dom_distiller/tab_utils_android.cc b/chrome/browser/dom_distiller/tab_utils_android.cc index fc19873..b7ba35f 100644 --- a/chrome/browser/dom_distiller/tab_utils_android.cc +++ b/chrome/browser/dom_distiller/tab_utils_android.cc
@@ -39,7 +39,9 @@ base::BindOnce( [](const jni_zero::ScopedJavaGlobalRef<jobject>& callback, bool success) { - base::android::RunBooleanCallbackAndroid(callback, success); + if (callback) { + base::android::RunBooleanCallbackAndroid(callback, success); + } }, jni_zero::ScopedJavaGlobalRef<jobject>(j_callback))); }
diff --git a/chrome/browser/download/download_commands.cc b/chrome/browser/download/download_commands.cc index d4f31ba..88661fa 100644 --- a/chrome/browser/download/download_commands.cc +++ b/chrome/browser/download/download_commands.cc
@@ -102,11 +102,8 @@ scw.Reset(); if (!decoded_image.empty() && !decoded_image.isNull()) { - if (base::FeatureList::IsEnabled( - download::features::kCopyImageFilenameToClipboard)) { - scw.WriteFilenames(ui::FileInfosToURIList( - {ui::FileInfo(file_path_, file_name_to_report_user_)})); - } + scw.WriteFilenames(ui::FileInfosToURIList( + {ui::FileInfo(file_path_, file_name_to_report_user_)})); scw.WriteImage(decoded_image); }
diff --git a/chrome/browser/download/download_prefs_unittest.cc b/chrome/browser/download/download_prefs_unittest.cc index 9fb69f4..46b42455 100644 --- a/chrome/browser/download/download_prefs_unittest.cc +++ b/chrome/browser/download/download_prefs_unittest.cc
@@ -33,7 +33,6 @@ #include "chrome/browser/ash/file_manager/volume_manager.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/profiles/profile_helper.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h" #include "chromeos/ash/components/disks/disk_mount_manager.h" @@ -524,9 +523,6 @@ TEST(DownloadPrefsTest, DownloadDirSanitization) { content::BrowserTaskEnvironment task_environment; - // Needed for `DriveIntegrationService`. - ScopedTestingLocalState local_state{TestingBrowserProcess::GetGlobal()}; - TestingProfile profile(base::FilePath("/home/chronos/u-0123456789abcdef")); DownloadPrefs prefs(&profile); const base::FilePath default_dir =
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/ash/ash_attestation_cleanup_manager_unittest.cc b/chrome/browser/enterprise/connectors/device_trust/attestation/ash/ash_attestation_cleanup_manager_unittest.cc index a418f0f..731e25a 100644 --- a/chrome/browser/enterprise/connectors/device_trust/attestation/ash/ash_attestation_cleanup_manager_unittest.cc +++ b/chrome/browser/enterprise/connectors/device_trust/attestation/ash/ash_attestation_cleanup_manager_unittest.cc
@@ -7,7 +7,6 @@ #include <memory> #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/dbus/attestation/attestation_client.h" @@ -16,10 +15,12 @@ #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" #include "components/account_id/account_id.h" #include "components/account_id/account_id_literal.h" +#include "components/prefs/pref_service.h" #include "components/user_manager/fake_user_manager_delegate.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/test_helper.h" #include "components/user_manager/user_manager.h" +#include "components/user_manager/user_manager_impl.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -47,7 +48,7 @@ user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( std::make_unique<user_manager::FakeUserManagerDelegate>(), - TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); + TestingBrowserProcess::GetGlobal()->local_state())); // To make user removable, two (or more) users are needed. user_manager::TestHelper test_helper(user_manager_.Get()); @@ -78,7 +79,6 @@ ash::ScopedStubInstallAttributes stub_install_attributes_; ash::ScopedTestingCrosSettings cros_settings_; - ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; user_manager::ScopedUserManager user_manager_; content::BrowserTaskEnvironment task_environment_{
diff --git a/chrome/browser/enterprise/data_controls/dlp_reporting_manager_unittest.cc b/chrome/browser/enterprise/data_controls/dlp_reporting_manager_unittest.cc index af975731..61b0208 100644 --- a/chrome/browser/enterprise/data_controls/dlp_reporting_manager_unittest.cc +++ b/chrome/browser/enterprise/data_controls/dlp_reporting_manager_unittest.cc
@@ -32,7 +32,6 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/test_helper.h" @@ -211,7 +210,6 @@ #if BUILDFLAG(IS_CHROMEOS) TEST_F(DlpReportingManagerTest, UserType) { - ScopedTestingLocalState local_state{TestingBrowserProcess::GetGlobal()}; auto* user_manager = new ash::FakeChromeUserManager(); user_manager::ScopedUserManager enabler(base::WrapUnique(user_manager));
diff --git a/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc b/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc index f1eded4..04fec78 100644 --- a/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc +++ b/chrome/browser/enterprise/reporting/report_scheduler_unittest.cc
@@ -15,6 +15,7 @@ #include "base/test/mock_callback.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h" +#include "base/values.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/enterprise/reporting/prefs.h" @@ -22,7 +23,6 @@ #include "chrome/browser/upgrade_detector/build_state.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "components/device_signals/core/common/signals_features.h" @@ -33,6 +33,8 @@ #include "components/enterprise/browser/reporting/report_generator.h" #include "components/enterprise/browser/reporting/report_request.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" #include "components/reporting/client/report_queue_provider.h" #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/sync_preferences/testing_pref_service_syncable.h" @@ -150,7 +152,6 @@ protected: ReportSchedulerTest() : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME), - local_state_(TestingBrowserProcess::GetGlobal()), profile_manager_(TestingBrowserProcess::GetGlobal()) {} ReportSchedulerTest(const ReportSchedulerTest&) = delete; @@ -222,27 +223,33 @@ void SetLastUploadInHour(base::TimeDelta gap, Profile* profile = nullptr) { previous_set_last_upload_timestamp_ = base::Time::Now() - gap; - auto* pref_service = profile ? profile->GetPrefs() : local_state_.Get(); + auto* pref_service = + profile ? profile->GetPrefs() + : TestingBrowserProcess::GetGlobal()->local_state(); pref_service->SetTime(kLastUploadTimestamp, previous_set_last_upload_timestamp_); } void SetReportFrequency(base::TimeDelta frequency) { - local_state_.Get()->SetTimeDelta(kCloudReportingUploadFrequency, frequency); + TestingBrowserProcess::GetGlobal()->local_state()->SetTimeDelta( + kCloudReportingUploadFrequency, frequency); } void ToggleCloudReport(bool enabled) { - local_state_.Get()->SetManagedPref(kCloudReportingEnabled, - std::make_unique<base::Value>(enabled)); + TestingBrowserProcess::GetGlobal()->GetTestingLocalState()->SetManagedPref( + kCloudReportingEnabled, std::make_unique<base::Value>(enabled)); } #if !BUILDFLAG(IS_CHROMEOS) void SetLastUploadVersion(const std::string& version) { - local_state_.Get()->SetString(kLastUploadVersion, version); + TestingBrowserProcess::GetGlobal()->local_state()->SetString( + kLastUploadVersion, version); } void ExpectLastUploadVersion(const std::string& version) { - EXPECT_EQ(local_state_.Get()->GetString(kLastUploadVersion), version); + EXPECT_EQ(TestingBrowserProcess::GetGlobal()->local_state()->GetString( + kLastUploadVersion), + version); } #endif // !BUILDFLAG(IS_CHROMEOS) @@ -250,7 +257,8 @@ // Otherwise, it should be same as previous set timestamp. void ExpectLastUploadTimestampUpdated(bool is_updated) { auto current_last_upload_timestamp = - local_state_.Get()->GetTime(kLastUploadTimestamp); + TestingBrowserProcess::GetGlobal()->local_state()->GetTime( + kLastUploadTimestamp); if (is_updated) { EXPECT_EQ(base::Time::Now(), current_last_upload_timestamp); } else { @@ -282,7 +290,6 @@ virtual bool profile_security_signals_enabled() { return false; } content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState local_state_; TestingProfileManager profile_manager_; #if BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/extensions/alert_apitest.cc b/chrome/browser/extensions/alert_apitest.cc index 8f0dd08..54c18f6 100644 --- a/chrome/browser/extensions/alert_apitest.cc +++ b/chrome/browser/extensions/alert_apitest.cc
@@ -183,8 +183,7 @@ const GURL extension_url = extension->GetResourceURL("popup.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), extension_url)); - content::WebContents* tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* tab = GetActiveWebContents(); // Verify the title that would be used for a dialog spawned by extension. javascript_dialogs::AppModalDialogManager* dialog_manager =
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc index 9187435..bfc1664 100644 --- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc +++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
@@ -54,7 +54,6 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" -#include "crypto/rsa_private_key.h" #include "extensions/browser/api/test/test_api_observer.h" #include "extensions/browser/api/test/test_api_observer_registry.h" #include "extensions/browser/disable_reason.h"
diff --git a/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc b/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc index d95147e0..bbc75b5 100644 --- a/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc +++ b/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc
@@ -13,7 +13,6 @@ #include "base/run_loop.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/extensions/api/file_system/consent_provider_impl.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/prefs/testing_pref_service.h" #include "components/user_manager/scoped_user_manager.h" @@ -124,8 +123,6 @@ } protected: - ScopedTestingLocalState scoped_testing_local_state_{ - TestingBrowserProcess::GetGlobal()}; raw_ptr<ash::FakeChromeUserManager, DanglingUntriaged> user_manager_; // Owned by the scope enabler. std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_enabler_;
diff --git a/chrome/browser/extensions/api/pdf_viewer_private/BUILD.gn b/chrome/browser/extensions/api/pdf_viewer_private/BUILD.gn index 9b69299..21e1307 100644 --- a/chrome/browser/extensions/api/pdf_viewer_private/BUILD.gn +++ b/chrome/browser/extensions/api/pdf_viewer_private/BUILD.gn
@@ -28,4 +28,7 @@ "//extensions/browser", "//url", ] + if (enable_pdf_save_to_drive) { + deps += [ "//chrome/browser/save_to_drive" ] + } }
diff --git a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc index 85952f78..9404dc4 100644 --- a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc +++ b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/pdf/pdf_pref_names.h" #include "chrome/browser/pdf/pdf_viewer_stream_manager.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/save_to_drive/save_to_drive_flow.h" #include "chrome/common/extensions/api/pdf_viewer_private.h" #include "chrome/common/pref_names.h" #include "components/pdf/common/constants.h" @@ -127,7 +128,15 @@ std::optional<SaveToDrive::Params> params = SaveToDrive::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - // TODO(crbug.com/424208776): Start the save to drive flow. + using SaveToDriveFlow = save_to_drive::SaveToDriveFlow; + + auto* flow = SaveToDriveFlow::GetForCurrentDocument(render_frame_host()); + if (flow) { + return RespondNow(Error("An upload is already in progress")); + } + flow = SaveToDriveFlow::GetOrCreateForCurrentDocument(render_frame_host()); + flow->Run(); + return RespondNow(NoArguments()); #else return RespondNow(Error("Not supported"));
diff --git a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api_unittest.cc b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api_unittest.cc index 33a133a..a0ebb2a 100644 --- a/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api_unittest.cc +++ b/chrome/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api_unittest.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/extensions/extension_service_test_base.h" #include "chrome/browser/pdf/pdf_test_util.h" #include "chrome/browser/pdf/pdf_viewer_stream_manager.h" +#include "chrome/browser/save_to_drive/save_to_drive_flow.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/pdf/common/constants.h" #include "content/public/browser/navigation_entry.h" @@ -324,6 +325,51 @@ EXPECT_TRUE( api_test_utils::RunFunction(function, R"(["ORIGINAL"])", profile())); } + +// Failed in sending a request to save a PDF to Drive if there is already a +// request in progress. +TEST_F(PdfViewerPrivateApiUnitTest, SaveToDriveFailedIfAlreadyInProgress) { + CreateAndClaimStreamContainer(); + { + auto function = base::MakeRefCounted<PdfViewerPrivateSaveToDriveFunction>(); + function->SetRenderFrameHost(extension_host()); + + EXPECT_TRUE(api_test_utils::RunFunction(function.get(), R"(["ORIGINAL"])", + profile())); + } + { + auto function = base::MakeRefCounted<PdfViewerPrivateSaveToDriveFunction>(); + function->SetRenderFrameHost(extension_host()); + + EXPECT_EQ("An upload is already in progress", + api_test_utils::RunFunctionAndReturnError( + function.get(), R"(["ORIGINAL"])", profile())); + } +} + +// Succeed in sending a request to save a PDF to Drive after the previous +// request is canceled. +TEST_F(PdfViewerPrivateApiUnitTest, SaveToDriveCanceledAndStartNew) { + CreateAndClaimStreamContainer(); + { + auto function = base::MakeRefCounted<PdfViewerPrivateSaveToDriveFunction>(); + function->SetRenderFrameHost(extension_host()); + + EXPECT_TRUE(api_test_utils::RunFunction(function.get(), R"(["ORIGINAL"])", + profile())); + auto* flow = + save_to_drive::SaveToDriveFlow::GetForCurrentDocument(extension_host()); + ASSERT_TRUE(flow); + flow->Stop(); + } + { + auto function = base::MakeRefCounted<PdfViewerPrivateSaveToDriveFunction>(); + function->SetRenderFrameHost(extension_host()); + EXPECT_TRUE(api_test_utils::RunFunction(function.get(), R"(["ORIGINAL"])", + profile())); + } +} + #endif // BUILDFLAG(ENABLE_PDF_SAVE_TO_DRIVE) } // namespace extensions
diff --git a/chrome/browser/extensions/api/runtime/runtime_apitest.cc b/chrome/browser/extensions/api/runtime/runtime_apitest.cc index 5cb16cc..c555146 100644 --- a/chrome/browser/extensions/api/runtime/runtime_apitest.cc +++ b/chrome/browser/extensions/api/runtime/runtime_apitest.cc
@@ -17,6 +17,8 @@ #include "chrome/browser/devtools/devtools_window_testing.h" #include "chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h" #include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/extensions/extension_action_test_helper.h" #include "chrome/common/url_constants.h" @@ -41,6 +43,7 @@ #include "extensions/browser/process_manager.h" #include "extensions/browser/script_executor.h" #include "extensions/browser/test_extension_registry_observer.h" +#include "extensions/buildflags/buildflags.h" #include "extensions/common/extension_id.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/result_catcher.h" @@ -49,14 +52,15 @@ #include "url/url_constants.h" #if !BUILDFLAG(IS_ANDROID) -#include "chrome/browser/apps/platform_apps/app_browsertest_util.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/test/base/ui_test_utils.h" #endif +#if BUILDFLAG(ENABLE_PLATFORM_APPS) +#include "chrome/browser/apps/platform_apps/app_browsertest_util.h" +#endif + namespace extensions { using ContextType = extensions::browser_test_util::ContextType; @@ -68,6 +72,10 @@ ~RuntimeApiTest() override = default; RuntimeApiTest(const RuntimeApiTest&) = delete; RuntimeApiTest& operator=(const RuntimeApiTest&) = delete; + + std::string GetActiveUrl() { + return GetActiveWebContents()->GetLastCommittedURL().spec(); + } }; // Android only supports MV3 and later, therefor don't need to test for @@ -100,8 +108,6 @@ EXPECT_TRUE(catcher.GetNextResult()) << message_; } -// TODO (crbug.com/383366125): Enable more tests for desktop android. -#if !BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_P(RuntimeApiTest, ChromeRuntimeUninstallURL) { // Auto-confirm the uninstall dialog. ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::ACCEPT); @@ -119,14 +125,9 @@ namespace { +#if BUILDFLAG(ENABLE_EXTENSIONS) const char kUninstallUrl[] = "https://www.google.com/"; - -std::string GetActiveUrl(Browser* browser) { - return browser->tab_strip_model() - ->GetActiveWebContents() - ->GetLastCommittedURL() - .spec(); -} +#endif class RuntimeAPIUpdateTest : public ExtensionApiTest { public: @@ -164,8 +165,8 @@ bool CrashEnabledExtension(const ExtensionId& extension_id) { ExtensionHost* background_host = - ProcessManager::Get(browser()->profile()) - ->GetBackgroundHostForExtension(extension_id); + ProcessManager::Get(profile())->GetBackgroundHostForExtension( + extension_id); if (!background_host) { return false; } @@ -179,9 +180,13 @@ } // namespace +#if BUILDFLAG(ENABLE_EXTENSIONS) +// TODO(crbug.com/383366125): Enable this test for desktop Android once +// ChromeRuntimeAPIDelegate::OpenOptionsPage() is implemented. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeRuntimeOpenOptionsPage) { ASSERT_TRUE(RunExtensionTest("runtime/open_options_page")); } +#endif // BUILDFLAG(ENABLE_EXTENSIONS) IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeRuntimeOpenOptionsPageError) { ASSERT_TRUE(RunExtensionTest("runtime/open_options_page_error")); @@ -201,6 +206,7 @@ #endif } +#if BUILDFLAG(ENABLE_PLATFORM_APPS) // Tests chrome.runtime.getPackageDirectory with an app. IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, ChromeRuntimeGetPackageDirectoryEntryApp) { @@ -208,6 +214,7 @@ {.launch_as_platform_app = true})) << message_; } +#endif // BUILDFLAG(ENABLE_PLATFORM_APPS) // Tests chrome.runtime.getPackageDirectory with an MV2 extension. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, @@ -524,6 +531,9 @@ } } +#if BUILDFLAG(ENABLE_EXTENSIONS) +// TODO(crbug.com/423725749): Port to desktop Android when a cross-platform +// browser abstraction is available. // Tests that when the last active tab in the window belongs to the extension // with an uninstall URL, uninstalling the extension does not close the current // browser. Regression test for crbug.com/362452856 @@ -552,7 +562,7 @@ TabStripModel* tabs = browser()->tab_strip_model(); ASSERT_EQ(1, tabs->count()); - ASSERT_EQ("about:blank", GetActiveUrl(browser())); + ASSERT_EQ("about:blank", GetActiveUrl()); // Navigate to an extension page. const GURL extension_page_url = extension->GetResourceURL("page.html"); @@ -561,8 +571,7 @@ ASSERT_TRUE(new_host); EXPECT_EQ(1, tabs->count()); - EXPECT_EQ(extension_page_url.spec(), GetActiveUrl(browser())); - + EXPECT_EQ(extension_page_url.spec(), GetActiveUrl()); // Uninstall the extension and expect its uninstall url to open in a new tab. extension_registrar()->UninstallExtension( extension->id(), UNINSTALL_REASON_USER_INITIATED, nullptr); @@ -570,7 +579,7 @@ EXPECT_EQ(2, tabs->count()); // The current tab should be pointing to the uninstall url of the extension. - EXPECT_EQ(kUninstallUrl, GetActiveUrl(browser())); + EXPECT_EQ(kUninstallUrl, GetActiveUrl()); // The tab at index 0 should now be overwritten with the default NTP. EXPECT_EQ(chrome::kChromeUINewTabURL, @@ -600,12 +609,12 @@ EXPECT_EQ(2, tabs->count()); content::WaitForLoadStop(tabs->GetActiveWebContents()); // Verify the uninstall url - EXPECT_EQ(kUninstallUrl, GetActiveUrl(browser())); + EXPECT_EQ(kUninstallUrl, GetActiveUrl()); // Close the tab pointing to the uninstall url. tabs->CloseWebContentsAt(tabs->active_index(), 0); EXPECT_EQ(1, tabs->count()); - EXPECT_EQ("about:blank", GetActiveUrl(browser())); + EXPECT_EQ("about:blank", GetActiveUrl()); // Load the same extension again, except blocklist it after installation. ExtensionTestMessageListener ready_listener_reload("ready"); @@ -630,10 +639,13 @@ EXPECT_EQ(1, tabs->count()); EXPECT_TRUE(content::WaitForLoadStop(tabs->GetActiveWebContents())); - EXPECT_EQ(url::kAboutBlankURL, GetActiveUrl(browser())); + EXPECT_EQ(url::kAboutBlankURL, GetActiveUrl()); } +#endif // BUILDFLAG(ENABLE_EXTENSIONS) -// Used for tests that only make sense with a background page. +#if !BUILDFLAG(IS_ANDROID) +// Used for tests that only make sense with a background page. Unsupported on +// Android because it only supports service workers. using BackgroundPageOnlyRuntimeApiTest = RuntimeApiTest; INSTANTIATE_TEST_SUITE_P(All, BackgroundPageOnlyRuntimeApiTest, @@ -673,8 +685,9 @@ } { - ExtensionHost* host = ProcessManager::Get(browser()->profile()) - ->GetBackgroundHostForExtension(extension->id()); + ExtensionHost* host = + ProcessManager::Get(profile())->GetBackgroundHostForExtension( + extension->id()); ASSERT_TRUE(host); content::DOMMessageQueue message_queue(host->host_contents()); @@ -831,7 +844,6 @@ TestExtensionDir test_dir_; }; -#if !BUILDFLAG(IS_ANDROID) // Tests retrieving the background service worker context using // `chrome.runtime.getContexts()`. @@ -878,9 +890,10 @@ extension().id()); // In order to be able to call the API, we need to open a new tab to an // extension resource. + auto* web_contents = GetActiveWebContents(); const GURL extension_page_url = extension().GetResourceURL("page.html"); - content::RenderFrameHost* new_host = - ui_test_utils::NavigateToURL(browser(), extension_page_url); + ASSERT_TRUE(NavigateToURL(web_contents, extension_page_url)); + content::RenderFrameHost* new_host = web_contents->GetPrimaryMainFrame(); ASSERT_TRUE(new_host); static constexpr char kScript[] = @@ -897,12 +910,11 @@ IN_PROC_BROWSER_TEST_F(RuntimeGetContextsApiTest, FilterMatching) { // Currently, there is only one context: the background service worker. Also // open a tab-based context. + auto* web_contents = GetActiveWebContents(); const GURL extension_page_url = extension().GetResourceURL("page.html"); - content::RenderFrameHost* new_host = - ui_test_utils::NavigateToURL(browser(), extension_page_url); + ASSERT_TRUE(NavigateToURL(web_contents, extension_page_url)); + content::RenderFrameHost* new_host = web_contents->GetPrimaryMainFrame(); ASSERT_TRUE(new_host); - content::WebContents* web_contents = - content::WebContents::FromRenderFrameHost(new_host); int tab_id = ExtensionTabUtil::GetTabId(web_contents); { @@ -965,12 +977,11 @@ // Tests retrieving tab contexts using `chrome.runtime.getContexts()`. IN_PROC_BROWSER_TEST_F(RuntimeGetContextsApiTest, GetTabContext) { // Open a new extension tab. + auto* web_contents = GetActiveWebContents(); const GURL frame_url = extension().GetResourceURL("page.html"); - content::RenderFrameHost* new_host = - ui_test_utils::NavigateToURL(browser(), frame_url); + ASSERT_TRUE(NavigateToURL(web_contents, frame_url)); + content::RenderFrameHost* new_host = web_contents->GetPrimaryMainFrame(); ASSERT_TRUE(new_host); - content::WebContents* web_contents = - content::WebContents::FromRenderFrameHost(new_host); int expected_tab_id = ExtensionTabUtil::GetTabId(web_contents); int expected_window_id = ExtensionTabUtil::GetWindowIdOfTab(web_contents); @@ -1004,7 +1015,6 @@ expected_frame_url.c_str(), expected_origin.c_str()); EXPECT_THAT(background_contexts, base::test::IsJson(expected)); } -#endif // !BUILDFLAG(IS_ANDROID) // Tests retrieving offscreen documents with `runtime.getContexts()`. IN_PROC_BROWSER_TEST_F(RuntimeGetContextsApiTest, GetOffscreenDocumentContext) { @@ -1068,6 +1078,7 @@ } #if !BUILDFLAG(IS_ANDROID) +// TODO(crbug.com/405218955): Support side panel on desktop Android. class RuntimeGetContextsSidePanelTest : public RuntimeGetContextsApiTest { public: void SetUpExtension() override { @@ -1166,6 +1177,7 @@ expected_frame_url.c_str(), expected_origin.c_str()); EXPECT_THAT(side_panel_contexts, base::test::IsJson(expected)); } +#endif // !BUILDFLAG(IS_ANDROID) // Tests the behavior of `runtime.getContexts()` with a split-mode incognito // extension. In split mode, the extension should only be able to access data @@ -1200,34 +1212,37 @@ ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); // Open a tab on-the-record to one of the extension's pages. + auto* web_contents = GetActiveWebContents(); GURL regular_url = extension->GetResourceURL("regular.html"); - content::RenderFrameHost* regular_host = - ui_test_utils::NavigateToURL(browser(), regular_url); - ASSERT_TRUE(regular_host); + ASSERT_TRUE(NavigateToURL(web_contents, regular_url)); + ASSERT_TRUE(web_contents->GetPrimaryMainFrame()); // Open up an incognito tab to another extension page, and wait for the // incognito version of the extension to start up. ready_listener.Reset(); GURL incognito_url = extension->GetResourceURL("incognito.html"); - Browser* incognito_browser = OpenURLOffTheRecord(profile(), incognito_url); + content::WebContents* incognito_web_contents = + PlatformOpenURLOffTheRecord(profile(), incognito_url); + ASSERT_TRUE(incognito_web_contents->GetPrimaryMainFrame()); ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); - // A helper method to retrieve the contexts for the given `profile`. - auto run_get_contexts_in_profile = [extension](Profile* profile) { - static constexpr char kScript[] = - R"((async () => { + // A helper method to retrieve the contexts for the given `browser_context`. + auto run_get_contexts = + [extension](content::BrowserContext* browser_context) { + static constexpr char kScript[] = + R"((async () => { chrome.test.sendScriptResult( await chrome.runtime.getContexts({})); })();)"; - return BackgroundScriptExecutor::ExecuteScript( - profile, extension->id(), kScript, - BackgroundScriptExecutor::ResultCapture::kSendScriptResult); - }; + return BackgroundScriptExecutor::ExecuteScript( + browser_context, extension->id(), kScript, + BackgroundScriptExecutor::ResultCapture::kSendScriptResult); + }; { // Verify the on-the-record contexts. There should be a single background // context and the on-the-record tab. - base::Value regular_results = run_get_contexts_in_profile(profile()); + base::Value regular_results = run_get_contexts(profile()); std::vector<api::runtime::ExtensionContext> contexts = ContextValueToContextStructs(regular_results); EXPECT_THAT(contexts, testing::UnorderedElementsAre( @@ -1239,7 +1254,7 @@ // Now verify the incognito contexts. Here, too, there should be a single // background context and tab, but it should be the incognito tab. base::Value incognito_results = - run_get_contexts_in_profile(incognito_browser->profile()); + run_get_contexts(incognito_web_contents->GetBrowserContext()); std::vector<api::runtime::ExtensionContext> contexts = ContextValueToContextStructs(incognito_results); EXPECT_THAT(contexts, testing::UnorderedElementsAre( @@ -1283,24 +1298,21 @@ ASSERT_TRUE(extension); // Open an on-the-record tab to an extension page. + auto* web_contents = GetActiveWebContents(); GURL regular_url = extension->GetResourceURL("regular.html"); - content::RenderFrameHost* regular_host = - ui_test_utils::NavigateToURL(browser(), regular_url); - ASSERT_TRUE(regular_host); + ASSERT_TRUE(NavigateToURL(web_contents, regular_url)); // Now, the tricky part. Spanning mode extensions aren't, typically, allowed // to open contexts in an incognito profile (which means all contexts just // open in the same profile). There's one exception to this: an embedded web- // accessible iframe in an incognito tab. Make it so. GURL incognito_url = extension->GetResourceURL("incognito.html"); - Browser* incognito_browser = OpenURLOffTheRecord( + auto* incognito_web_contents = PlatformOpenURLOffTheRecord( profile(), embedded_test_server()->GetURL("example.com", "/simple.html")); // Inject a script to add an iframe and navigate it to the extension's // web-accessible resource. content::RenderFrameHost* incognito_main_frame = - incognito_browser->tab_strip_model() - ->GetActiveWebContents() - ->GetPrimaryMainFrame(); + incognito_web_contents->GetPrimaryMainFrame(); static constexpr char kNavigateTemplate[] = R"(let frame = document.createElement('iframe'); frame.src = '%s'; @@ -1353,6 +1365,7 @@ } } +#if !BUILDFLAG(IS_ANDROID) // This is a manifest V2 test meant to ensure test coverage for // chrome.extension.getURL, which is deprecated and unavailable // in MV3. @@ -1385,6 +1398,7 @@ } // Tests retrieving contexts when developer tools are opened. +// TODO(crbug.com/402538127): Improve devtools support on desktop Android. class GetContextsWithDeveloperToolsOpened : public RuntimeGetContextsApiTest, public testing::WithParamInterface<bool> { @@ -1478,6 +1492,6 @@ INSTANTIATE_TEST_SUITE_P(DockedDevTools, GetContextsWithDeveloperToolsOpened, ::testing::Values(true) /* open_docked */); -#endif //! BUILDFLAG(IS_ANDROID) +#endif // !BUILDFLAG(IS_ANDROID) } // namespace extensions
diff --git a/chrome/browser/extensions/api/tab_groups/BUILD.gn b/chrome/browser/extensions/api/tab_groups/BUILD.gn index 34e58f8..6d0cde2 100644 --- a/chrome/browser/extensions/api/tab_groups/BUILD.gn +++ b/chrome/browser/extensions/api/tab_groups/BUILD.gn
@@ -38,6 +38,7 @@ "//chrome/browser/ui/tabs:tab_group", "//chrome/browser/ui/tabs:tab_model", "//chrome/browser/ui/tabs:tab_strip", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/common/extensions", "//content/public/browser", "//extensions/common",
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 5d6dc41..91b9881d 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -57,6 +57,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_destroyer.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/extensions/reload_page_dialog_controller.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" @@ -2011,7 +2012,8 @@ runner->GetBlockedActions(extension->id())); // Grant activeTab permission. - runner->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); runner->RunAction(extension, true); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(content::WaitForLoadStop(web_contents)); @@ -2116,7 +2118,8 @@ // a.com), it should still see the request. This is necessary for extensions // with webRequest to work with runtime host permissions. // https://crbug.com/851722. - runner->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); runner->RunAction(extension, true /* grant tab permissions */); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(content::WaitForLoadStop(web_contents)); @@ -3462,7 +3465,8 @@ // Only records ACCESS_WITHHELD, not ACCESS_DENIED, this is why it matches // BLOCKED_ACTION_NONE. EXPECT_EQ(BLOCKED_ACTION_NONE, runner->GetBlockedActions(extension->id())); - runner->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); runner->RunAction(extension, true); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(content::WaitForLoadStop(web_contents));
diff --git a/chrome/browser/extensions/api_binding_perf_browsertest.cc b/chrome/browser/extensions/api_binding_perf_browsertest.cc index 12143bd..ab1775f 100644 --- a/chrome/browser/extensions/api_binding_perf_browsertest.cc +++ b/chrome/browser/extensions/api_binding_perf_browsertest.cc
@@ -5,7 +5,6 @@ #include "base/time/time.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -43,7 +42,7 @@ base::TimeDelta RunTestAndReportTime() { return base::Milliseconds( content::EvalJs( - browser()->tab_strip_model()->GetActiveWebContents(), + GetActiveWebContents(), "new Promise(resolve => runTest(time => resolve(time)))") .ExtractDouble()); }
diff --git a/chrome/browser/extensions/chrome_test_extension_loader_browsertest.cc b/chrome/browser/extensions/chrome_test_extension_loader_browsertest.cc index 2e73eb6..8e82a98 100644 --- a/chrome/browser/extensions/chrome_test_extension_loader_browsertest.cc +++ b/chrome/browser/extensions/chrome_test_extension_loader_browsertest.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -88,8 +87,7 @@ browser(), embedded_test_server()->GetURL("example.com", "/simple.html"))); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); EXPECT_EQ(true, content::EvalJs(web_contents, "!!document.getElementById('script1');")); EXPECT_EQ(true, content::EvalJs(web_contents,
diff --git a/chrome/browser/extensions/content_capabilities_browsertest.cc b/chrome/browser/extensions/content_capabilities_browsertest.cc index e55d029..ffa1d37 100644 --- a/chrome/browser/extensions/content_capabilities_browsertest.cc +++ b/chrome/browser/extensions/content_capabilities_browsertest.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/base/ui_test_utils.h" #include "components/crx_file/id_util.h" @@ -95,10 +94,6 @@ return "[" + list + "]"; } - content::WebContents* web_contents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - GURL GetTestURLFor(const std::string& host) { std::string port = base::NumberToString(embedded_https_test_server().port()); @@ -111,7 +106,8 @@ } content::RenderFrameHost* GetRenderFrameHost() { - return content::ToRenderFrameHost(web_contents()).render_frame_host(); + return content::ToRenderFrameHost(GetActiveWebContents()) + .render_frame_host(); } void SetPermissionOverrideForAsyncClipboardTests( @@ -145,16 +141,16 @@ void CheckSiteCanRead(bool expected) { content::WebContents::FromRenderFrameHost(GetRenderFrameHost())->Focus(); - EXPECT_EQ(expected, content::ExecJs(web_contents(), + EXPECT_EQ(expected, content::ExecJs(GetActiveWebContents(), "navigator.clipboard.readText()")); } void CheckSiteCanWrite(bool expected) { content::WebContents::FromRenderFrameHost(GetRenderFrameHost())->Focus(); - EXPECT_EQ( - expected, - content::ExecJs(web_contents(), "navigator.clipboard.writeText('Test')", - content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + EXPECT_EQ(expected, + content::ExecJs(GetActiveWebContents(), + "navigator.clipboard.writeText('Test')", + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); } // Run some script in the context of the given origin and in the presence of @@ -165,7 +161,7 @@ const GURL& url, const char* code) { EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - if (!content::EvalJs(web_contents(), code).ExtractBool()) { + if (!content::EvalJs(GetActiveWebContents(), code).ExtractBool()) { return testing::AssertionFailure(); } return testing::AssertionSuccess();
diff --git a/chrome/browser/extensions/content_security_policy_apitest.cc b/chrome/browser/extensions/content_security_policy_apitest.cc index 139c49f..30c4235 100644 --- a/chrome/browser/extensions/content_security_policy_apitest.cc +++ b/chrome/browser/extensions/content_security_policy_apitest.cc
@@ -181,8 +181,7 @@ ASSERT_FALSE(Manifest::IsUnpackedLocation(extension->location())); // Blocking the script load should emit a log. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::WebContentsConsoleObserver console_observer(web_contents); console_observer.SetPattern("Refused to load the script '*");
diff --git a/chrome/browser/extensions/content_verifier_browsertest.cc b/chrome/browser/extensions/content_verifier_browsertest.cc index 258b0f2..7b7cdb47 100644 --- a/chrome/browser/extensions/content_verifier_browsertest.cc +++ b/chrome/browser/extensions/content_verifier_browsertest.cc
@@ -38,6 +38,7 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" +#include "crypto/keypair.h" #include "extensions/browser/background_script_executor.h" #include "extensions/browser/content_verifier/content_verify_job.h" #include "extensions/browser/content_verifier/test_utils.h" @@ -263,13 +264,10 @@ std::string private_key_bytes; EXPECT_TRUE( Extension::ParsePEMKeyBytes(private_key_contents, &private_key_bytes)); - auto signing_key = - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(std::vector<uint8_t>( - private_key_bytes.begin(), private_key_bytes.end())); - std::vector<uint8_t> public_key; - signing_key->ExportPublicKey(&public_key); - const std::string public_key_str(public_key.begin(), public_key.end()); - return crx_file::id_util::GenerateId(public_key_str); + auto signing_key = crypto::keypair::PrivateKey::FromPrivateKeyInfo( + base::as_byte_span(private_key_bytes)); + std::vector<uint8_t> public_key = signing_key->ToSubjectPublicKeyInfo(); + return crx_file::id_util::GenerateId(base::as_string_view(public_key)); } // Creates a random signing key and sets |extension_id| according to it. @@ -277,7 +275,6 @@ std::string& extension_id) { auto signing_key = crypto::keypair::PrivateKey::GenerateRsa2048(); std::vector<uint8_t> public_key = signing_key.ToSubjectPublicKeyInfo(); - const std::string public_key_str(public_key.begin(), public_key.end()); extension_id = crx_file::id_util::GenerateId(base::as_string_view(public_key)); return signing_key;
diff --git a/chrome/browser/extensions/cross_origin_isolation_browsertest.cc b/chrome/browser/extensions/cross_origin_isolation_browsertest.cc index c8ada56..7797cf8 100644 --- a/chrome/browser/extensions/cross_origin_isolation_browsertest.cc +++ b/chrome/browser/extensions/cross_origin_isolation_browsertest.cc
@@ -27,7 +27,6 @@ #if !BUILDFLAG(IS_ANDROID) #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #endif @@ -495,8 +494,7 @@ GURL extension_test_url = coi_extension->GetResourceURL("test.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/iframe_blank.html"))); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE( content::NavigateIframeToURL(web_contents, "test", extension_test_url)); content::RenderFrameHost* extension_iframe = @@ -598,8 +596,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/iframe_blank.html"))); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); GURL extension_test_url = coi_extension->GetResourceURL("test.html"); ASSERT_TRUE(
diff --git a/chrome/browser/extensions/delayed_setting_change_browsertest.cc b/chrome/browser/extensions/delayed_setting_change_browsertest.cc index 87c0281..59fa3a2c 100644 --- a/chrome/browser/extensions/delayed_setting_change_browsertest.cc +++ b/chrome/browser/extensions/delayed_setting_change_browsertest.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -114,8 +113,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), GURL("chrome://extensions?id=" + extension->id()))); - content::WebContents* tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* tab = GetActiveWebContents(); EXPECT_TRUE(content::WaitForLoadStop(tab)); // Initial state after installation. @@ -162,8 +160,7 @@ // Go to the managed extension details page. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), GURL("chrome://extensions?id=" + managed_extension->id()))); - content::WebContents* tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* tab = GetActiveWebContents(); EXPECT_TRUE(content::WaitForLoadStop(tab)); // Initial state after installation. @@ -184,7 +181,7 @@ // Go to the 2nd extension details page. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), GURL("chrome://extensions?id=" + second_extension->id()))); - tab = browser()->tab_strip_model()->GetActiveWebContents(); + tab = GetActiveWebContents(); EXPECT_TRUE(content::WaitForLoadStop(tab)); EXPECT_EQ(true, content::EvalJs(tab, GetScript_WarningMessageIsHidden( @@ -193,7 +190,7 @@ // Return to the managed extension details page. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), GURL("chrome://extensions?id=" + managed_extension->id()))); - tab = browser()->tab_strip_model()->GetActiveWebContents(); + tab = GetActiveWebContents(); EXPECT_TRUE(content::WaitForLoadStop(tab)); // The warning message for the managed extension should be visible.
diff --git a/chrome/browser/extensions/event_metrics_browsertest.cc b/chrome/browser/extensions/event_metrics_browsertest.cc index 99d2ac34..eef054fbb 100644 --- a/chrome/browser/extensions/event_metrics_browsertest.cc +++ b/chrome/browser/extensions/event_metrics_browsertest.cc
@@ -748,10 +748,6 @@ host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(StartEmbeddedTestServer()); } - - content::WebContents* web_contents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } }; // Tests that if there is a listener in the extension renderer process, but that @@ -813,7 +809,7 @@ // Navigate to page.html to get the content_script to load. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("page.html"))); - ASSERT_TRUE(content::WaitForLoadStop(web_contents())); + ASSERT_TRUE(content::WaitForLoadStop(GetActiveWebContents())); ASSERT_TRUE(page_script_loaded.WaitUntilSatisfied()); // Set storage value which should fire chrome.storage.onChanged listener in
diff --git a/chrome/browser/extensions/events_apitest.cc b/chrome/browser/extensions/events_apitest.cc index e0f41a8..7c612e3b 100644 --- a/chrome/browser/extensions/events_apitest.cc +++ b/chrome/browser/extensions/events_apitest.cc
@@ -520,8 +520,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("page.html"))); - content::WebContents* extension_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* extension_contents = GetActiveWebContents(); // So far, no events should have been received. EXPECT_EQ(0, content::EvalJs(extension_contents, "self.receivedEvents;")); @@ -743,10 +742,6 @@ host_resolver()->AddRule("*", "127.0.0.1"); ASSERT_TRUE(StartEmbeddedTestServer()); } - - content::WebContents* web_contents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } }; using PersistentBackgroundPageDispatchEventToSenderEventApiTest = @@ -906,7 +901,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("example.com", "/simple.html"))); - ASSERT_TRUE(content::WaitForLoadStop(web_contents())); + ASSERT_TRUE(content::WaitForLoadStop(GetActiveWebContents())); ASSERT_TRUE(content_script_loaded.WaitUntilSatisfied()); // Set storage value which should fire chrome.storage.onChanged listeners.
diff --git a/chrome/browser/extensions/extension_action_runner.cc b/chrome/browser/extensions/extension_action_runner.cc index 5e25fcf5..5048fd8 100644 --- a/chrome/browser/extensions/extension_action_runner.cc +++ b/chrome/browser/extensions/extension_action_runner.cc
@@ -396,18 +396,6 @@ const std::vector<const Extension*>& extensions) { reload_page_dialog_controller_ = std::make_unique<ReloadPageDialogController>( web_contents(), browser_context_); - - // For testing, simulate the bubble being accepted by directly invoking the - // callback, or rejected by skipping the callback. - // TODO(crbug.com/424012380): move accept_bubble_for_testing_ to - // ReloadPageDialogController. - if (accept_bubble_for_testing_.has_value()) { - if (*accept_bubble_for_testing_) { - reload_page_dialog_controller_->OnAcceptSelected(); - } - return; - } - reload_page_dialog_controller_->TriggerShow(extensions); }
diff --git a/chrome/browser/extensions/extension_action_runner.h b/chrome/browser/extensions/extension_action_runner.h index 7c81904..3dc72bc8 100644 --- a/chrome/browser/extensions/extension_action_runner.h +++ b/chrome/browser/extensions/extension_action_runner.h
@@ -107,10 +107,6 @@ int num_page_requests() const { return num_page_requests_; } - void accept_bubble_for_testing(bool accept_bubble) { - accept_bubble_for_testing_ = accept_bubble; - } - // Handles mojom::LocalFrameHost::RequestScriptInjectionPermission(). It // replies back with `callback`. void OnRequestScriptInjectionPermission( @@ -233,10 +229,6 @@ // each caller. std::unique_ptr<ReloadPageDialogController> reload_page_dialog_controller_; - // If true, immediately accept the reload page dialog by running the - // callback. - std::optional<bool> accept_bubble_for_testing_; - base::ObserverList<TestObserver> test_observers_; base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
diff --git a/chrome/browser/extensions/extension_action_runner_browsertest.cc b/chrome/browser/extensions/extension_action_runner_browsertest.cc index 04d2731..aae7587 100644 --- a/chrome/browser/extensions/extension_action_runner_browsertest.cc +++ b/chrome/browser/extensions/extension_action_runner_browsertest.cc
@@ -470,7 +470,8 @@ const bool kAcceptReload = GetParam(); // Run the action and (accept or dismiss) the reload bubble depending on // `kAcceptReload`. - runner->accept_bubble_for_testing(kAcceptReload); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(kAcceptReload); runner->RunAction(extension, /*grant_tab_permissions=*/true); // Verify extension has granted site interaction (since it's immediately @@ -592,7 +593,8 @@ ExtensionActionRunner::GetForWebContents(web_contents); ASSERT_TRUE(runner); - runner->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); content::NavigationEntry* entry = web_contents->GetController().GetLastCommittedEntry();
diff --git a/chrome/browser/extensions/extension_bookmarklet_browsertest.cc b/chrome/browser/extensions/extension_bookmarklet_browsertest.cc index e6f5529..b0095498 100644 --- a/chrome/browser/extensions/extension_bookmarklet_browsertest.cc +++ b/chrome/browser/extensions/extension_bookmarklet_browsertest.cc
@@ -37,8 +37,7 @@ const GURL extension_file_url(extension->GetResourceURL("file.html")); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), extension_file_url)); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); const std::u16string expected_title = u"foo"; ASSERT_EQ(expected_title, web_contents->GetTitle());
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index a09729a..3b5d0c8 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -713,6 +713,16 @@ return chrome_test_utils::GetActiveWebContents(this); } +content::WebContents* ExtensionBrowserTest::GetWebContentsAt(int index) const { +#if !BUILDFLAG(IS_ANDROID) + // Some tests may not immediately open a browser. Handle this gracefully. + if (!browser()) { + return nullptr; + } +#endif + return chrome_test_utils::GetWebContentsAt(this, index); +} + base::FilePath ExtensionBrowserTest::PackExtension( const base::FilePath& dir_path, int extra_run_flags) {
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h index 997e2956..23c3253 100644 --- a/chrome/browser/extensions/extension_browsertest.h +++ b/chrome/browser/extensions/extension_browsertest.h
@@ -215,6 +215,10 @@ // tab. content::WebContents* GetActiveWebContents() const; + // Returns the WebContents at the specified index, or nullptr if there is + // none. + content::WebContents* GetWebContentsAt(int index) const; + // Pack the extension in `dir_path` into a crx file and return its path. // Return an empty FilePath if there were errors. base::FilePath PackExtension(
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc index d417a8b..97d09b1 100644 --- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc +++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -1035,7 +1035,8 @@ // Change extension to run "on click". Since we are revoking permissions, we // need to automatically accept the reload page bubble. - action_runner->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); PermissionsManagerWaiter waiter(permissions_manager); menu.ExecuteCommand(kOnClick, 0); waiter.WaitForExtensionPermissionsUpdate(); @@ -1422,7 +1423,7 @@ // Navigate to a url that should have "customize by extension" site // permissions by default (which allows us to test the page access submenu). - content::WebContents* web_contents = AddTab(kActiveUrl); + AddTab(kActiveUrl); EXPECT_EQ( permissions_manager->GetUserSiteSetting(url::Origin::Create(kActiveUrl)), PermissionsManager::UserSiteSetting::kCustomizeByExtension); @@ -1446,8 +1447,8 @@ // Change extension to run "on click". Since we are revoking permissions, we // need to automatically accept the reload page bubble. - ExtensionActionRunner::GetForWebContents(web_contents) - ->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); PermissionsManagerWaiter waiter(permissions_manager); menu.ExecuteCommand(kOnClick, 0); waiter.WaitForExtensionPermissionsUpdate(); @@ -1645,8 +1646,8 @@ // Set the extension to run "on click". Since we are revoking b.com // permissions, we need to automatically accept the reload page bubble. - ExtensionActionRunner::GetForWebContents(web_contents) - ->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); PermissionsManagerWaiter waiter(permissions_manager); menu.ExecuteCommand(kOnClick, 0); waiter.WaitForExtensionPermissionsUpdate(); @@ -1683,7 +1684,7 @@ EXPECT_FALSE(permissions_manager->HasWithheldHostPermissions(*extension)); const GURL a_com("https://a.com"); - content::WebContents* web_contents = AddTab(a_com); + AddTab(a_com); ExtensionContextMenuModel menu(extension.get(), GetBrowser(), /*is_pinned=*/true, nullptr, true, @@ -1700,8 +1701,8 @@ // Withhold access on a.com by setting the extension to run "on click". Since // we are revoking permissions, we need to automatically accept the reload // page bubble. - ExtensionActionRunner::GetForWebContents(web_contents) - ->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); PermissionsManagerWaiter waiter(permissions_manager); menu.ExecuteCommand(kOnClick, 0); waiter.WaitForExtensionPermissionsUpdate();
diff --git a/chrome/browser/extensions/extension_cookies_browsertest.cc b/chrome/browser/extensions/extension_cookies_browsertest.cc index 1a4a9ab..5e7fa01 100644 --- a/chrome/browser/extensions/extension_cookies_browsertest.cc +++ b/chrome/browser/extensions/extension_cookies_browsertest.cc
@@ -137,8 +137,8 @@ // RenderFrameHost of the main frame. content::RenderFrameHost* NavigateMainFrameToExtensionPage() { EXPECT_TRUE(content::NavigateToURL( - web_contents(), extension_->GetResourceURL("empty.html"))); - return web_contents()->GetPrimaryMainFrame(); + GetActiveWebContents(), extension_->GetResourceURL("empty.html"))); + return GetActiveWebContents()->GetPrimaryMainFrame(); } // Appends a child iframe via JS and waits for it to load. Returns a pointer @@ -210,7 +210,7 @@ const std::string& host) { GURL cookie_url = test_server()->GetURL(host, kFetchCookiesPath); url::Origin initiator = frame->GetLastCommittedOrigin(); - content::TestNavigationObserver nav_observer(web_contents()); + content::TestNavigationObserver nav_observer(GetActiveWebContents()); // We cache the parent here, and use it to get the RenderFrameHost again // later, in order to allow cross-site navigations. Cross-site navigations // cause `frame` to be freed (and use a new RFHI for the new document), so @@ -299,10 +299,6 @@ // Secure. net::EmbeddedTestServer* test_server() { return &test_server_; } - content::WebContents* web_contents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - net::test_server::ControllableHttpResponse& GetNextCookieResponse() { // If the DCHECK below fails, consider increasing the value of the // kMaxNumberOfCookieRequestsFromSingleTest constant above. @@ -666,7 +662,7 @@ // Do one pass of BrowserAction without granting activeTab permission, // extension still shouldn't have access to `kActiveTabHost`. - ExtensionActionRunner::GetForWebContents(web_contents()) + ExtensionActionRunner::GetForWebContents(GetActiveWebContents()) ->RunAction(extension, false); { SCOPED_TRACE("TEST STEP 2: After BrowserAction without granting access."); @@ -676,7 +672,7 @@ // Granting activeTab permission to the extension should give it access to // `kActiveTabHost`. - ExtensionActionRunner::GetForWebContents(web_contents()) + ExtensionActionRunner::GetForWebContents(GetActiveWebContents()) ->RunAction(extension, true); { // ActiveTab access (just like OOR-CORS access) extends to the background @@ -752,18 +748,19 @@ SetCookies(kActiveTabHost); content::RenderFrameHost* extension_subframe = nullptr; { - content::TestNavigationObserver subframe_nav_observer(web_contents()); + content::TestNavigationObserver subframe_nav_observer( + GetActiveWebContents()); constexpr char kSubframeInjectionScriptTemplate[] = R"( var f = document.createElement('iframe'); f.src = $1; document.body.appendChild(f); )"; ASSERT_TRUE(content::ExecJs( - web_contents(), + GetActiveWebContents(), content::JsReplace(kSubframeInjectionScriptTemplate, extension->GetResourceURL("subframe.html")))); subframe_nav_observer.Wait(); - extension_subframe = ChildFrameAt(web_contents(), 0); + extension_subframe = ChildFrameAt(GetActiveWebContents(), 0); ASSERT_TRUE(extension_subframe); ASSERT_EQ(extension->origin(), extension_subframe->GetLastCommittedOrigin()); @@ -779,7 +776,7 @@ // Do one pass of BrowserAction without granting activeTab permission, // extension still shouldn't have access to `kActiveTabHost`. - ExtensionActionRunner::GetForWebContents(web_contents()) + ExtensionActionRunner::GetForWebContents(GetActiveWebContents()) ->RunAction(extension, false); { SCOPED_TRACE("TEST STEP 2: After BrowserAction without granting access."); @@ -789,7 +786,7 @@ // Granting activeTab permission to the extension should give it access to // `kActiveTabHost`. - ExtensionActionRunner::GetForWebContents(web_contents()) + ExtensionActionRunner::GetForWebContents(GetActiveWebContents()) ->RunAction(extension, true); { // ActiveTab should grant access to SameSite cookies to the @@ -875,9 +872,10 @@ GURL original_document_url = test_server()->GetURL(kActiveTabHost, "/title1.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), original_document_url)); - EXPECT_EQ( - kActiveTabHost, - web_contents()->GetPrimaryMainFrame()->GetLastCommittedURL().host()); + EXPECT_EQ(kActiveTabHost, GetActiveWebContents() + ->GetPrimaryMainFrame() + ->GetLastCommittedURL() + .host()); SetCookies(kActiveTabHost); GURL extension_frame_url = extension->GetResourceURL("frame.html"); ui_test_utils::NavigateToURLWithDisposition( @@ -899,7 +897,7 @@ // Do one pass of BrowserAction without granting activeTab permission, // extension still shouldn't have access to `kActiveTabHost`. - ExtensionActionRunner::GetForWebContents(web_contents()) + ExtensionActionRunner::GetForWebContents(GetActiveWebContents()) ->RunAction(extension, false); { SCOPED_TRACE("TEST STEP 2: After BrowserAction without granting access."); @@ -910,7 +908,7 @@ // Granting activeTab permission to the extension should give it access to // `kActiveTabHost`. - ExtensionActionRunner::GetForWebContents(web_contents()) + ExtensionActionRunner::GetForWebContents(GetActiveWebContents()) ->RunAction(extension, true); { // ActiveTab access (just like OOR-CORS access) extends to the service
diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc index 682b60a..7332efed 100644 --- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc +++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
@@ -193,8 +193,7 @@ SCOPED_TRACE("after reloading"); CheckExtensionConsistency(first_extension_id_); - WebContents* current_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + WebContents* current_tab = GetActiveWebContents(); ASSERT_TRUE(current_tab); // The balloon should automatically hide after the extension is successfully @@ -210,15 +209,13 @@ CrashExtension(first_extension_id_); ASSERT_EQ(count_before, GetEnabledExtensionCount()); - WebContents* original_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + WebContents* original_tab = GetActiveWebContents(); ASSERT_TRUE(original_tab); ASSERT_EQ(1U, CountNotifications()); // Open a new tab, but the balloon will still be there. chrome::NewTab(browser()); - WebContents* new_current_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + WebContents* new_current_tab = GetActiveWebContents(); ASSERT_TRUE(new_current_tab); ASSERT_NE(new_current_tab, original_tab); ASSERT_EQ(1U, CountNotifications()); @@ -241,8 +238,7 @@ CrashExtension(first_extension_id_); ASSERT_EQ(count_before, GetEnabledExtensionCount()); - WebContents* current_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + WebContents* current_tab = GetActiveWebContents(); ASSERT_TRUE(current_tab); ASSERT_EQ(1U, CountNotifications()); @@ -396,8 +392,7 @@ { SCOPED_TRACE("first: reload"); - WebContents* current_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + WebContents* current_tab = GetActiveWebContents(); ASSERT_TRUE(current_tab); // At the beginning we should have one balloon displayed for each extension. ASSERT_EQ(2U, CountNotifications()); @@ -478,8 +473,7 @@ extensions::TestExtensionRegistryObserver observer(GetExtensionRegistry()); { - content::LoadStopObserver notification_observer( - browser()->tab_strip_model()->GetActiveWebContents()); + content::LoadStopObserver notification_observer(GetActiveWebContents()); chrome::Reload(browser(), WindowOpenDisposition::CURRENT_TAB); notification_observer.Wait(); }
diff --git a/chrome/browser/extensions/extension_csp_bypass_browsertest.cc b/chrome/browser/extensions/extension_csp_bypass_browsertest.cc index 8a0998d..5a33afe 100644 --- a/chrome/browser/extensions/extension_csp_bypass_browsertest.cc +++ b/chrome/browser/extensions/extension_csp_bypass_browsertest.cc
@@ -46,10 +46,6 @@ } protected: - content::WebContents* web_contents() const { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - const Extension* AddExtension(bool is_component, bool all_urls_permission) { TestExtensionDir dir; @@ -88,7 +84,7 @@ bool CanLoadScript(const Extension* extension) { content::RenderFrameHost* render_frame_host = - web_contents()->GetPrimaryMainFrame(); + GetActiveWebContents()->GetPrimaryMainFrame(); std::string code = base::StringPrintf( R"( function canLoadScript() { @@ -112,7 +108,7 @@ content::RenderFrameHost* GetFrameByName(const std::string& name) { return content::FrameMatchingPredicate( - web_contents()->GetPrimaryPage(), + GetActiveWebContents()->GetPrimaryPage(), base::BindRepeating(&content::FrameMatchesName, name)); } @@ -165,7 +161,7 @@ // First, verify that adding an iframe to the page from the main world will // fail. Add the frame. Its onload event fires even if it's blocked // (see https://crbug.com/365457), and reports back. - EXPECT_EQ(true, content::EvalJs(web_contents(), "addIframe();")); + EXPECT_EQ(true, content::EvalJs(GetActiveWebContents(), "addIframe();")); // Use WasFrameWithScriptLoaded() to check whether the target frame really // loaded. @@ -178,7 +174,7 @@ // which bypasses CSP, and adds the iframe. content::DOMMessageQueue message_queue; EXPECT_TRUE( - content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(), + content::ExecJs(GetActiveWebContents(), "document.querySelector('#addIframeButton').click();")); std::string ack; EXPECT_TRUE(message_queue.WaitForMessage(&ack)); @@ -219,16 +215,17 @@ const Extension* extension = LoadExtension(test_dir.UnpackedPath()); ASSERT_TRUE(extension); - content::WebContentsConsoleObserver console_observer(web_contents()); + content::WebContentsConsoleObserver console_observer(GetActiveWebContents()); console_observer.SetPattern( "Refused to frame * because an ancestor violates *"); GURL popup_url = extension->GetResourceURL("popup.html"); - ASSERT_TRUE(content::NavigateToURL(web_contents(), popup_url)); + ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), popup_url)); // The iframe must be blocked because of CSP. ASSERT_TRUE(console_observer.Wait()); - content::RenderFrameHost* main_frame = web_contents()->GetPrimaryMainFrame(); + content::RenderFrameHost* main_frame = + GetActiveWebContents()->GetPrimaryMainFrame(); content::RenderFrameHost* child_frame = ChildFrameAt(main_frame, 0); EXPECT_EQ(popup_url, main_frame->GetLastCommittedURL()); EXPECT_EQ(iframe_url, child_frame->GetLastCommittedURL());
diff --git a/chrome/browser/extensions/extension_dom_clipboard_apitest.cc b/chrome/browser/extensions/extension_dom_clipboard_apitest.cc index 3c701b4..a1e61b1 100644 --- a/chrome/browser/extensions/extension_dom_clipboard_apitest.cc +++ b/chrome/browser/extensions/extension_dom_clipboard_apitest.cc
@@ -97,9 +97,7 @@ bool ClipboardApiTest::ExecuteScriptInSelectedTab(const std::string& script, int options) { - return content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), - script, options) - .ExtractBool(); + return content::EvalJs(GetActiveWebContents(), script, options).ExtractBool(); } } // namespace
diff --git a/chrome/browser/extensions/extension_garbage_collector_chromeos_unittest.cc b/chrome/browser/extensions/extension_garbage_collector_chromeos_unittest.cc index 98e0682..262a173 100644 --- a/chrome/browser/extensions/extension_garbage_collector_chromeos_unittest.cc +++ b/chrome/browser/extensions/extension_garbage_collector_chromeos_unittest.cc
@@ -93,7 +93,7 @@ const std::string& users_string, const base::FilePath& path) { ScopedDictPrefUpdate shared_extensions( - testing_local_state_.Get(), + TestingBrowserProcess::GetGlobal()->local_state(), ExtensionAssetsManagerChromeOS::kSharedExtensions); base::Value::Dict* extension_info_weak = shared_extensions->EnsureDict(id); @@ -177,7 +177,7 @@ EXPECT_TRUE(base::PathExists(path_id2_1)); const base::Value::Dict& shared_extensions = - testing_local_state_.Get()->GetDict( + TestingBrowserProcess::GetGlobal()->local_state()->GetDict( ExtensionAssetsManagerChromeOS::kSharedExtensions); EXPECT_FALSE(shared_extensions.Find(kExtensionId1));
diff --git a/chrome/browser/extensions/extension_install_ui_browsertest.cc b/chrome/browser/extensions/extension_install_ui_browsertest.cc index 75751d2..b3e8160 100644 --- a/chrome/browser/extensions/extension_install_ui_browsertest.cc +++ b/chrome/browser/extensions/extension_install_ui_browsertest.cc
@@ -46,8 +46,7 @@ // Checks that a theme info bar is currently visible and issues an undo to // revert to the previous theme. void VerifyThemeInfoBarAndUndoInstall() { - WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(web_contents); infobars::ContentInfoBarManager* infobar_manager = infobars::ContentInfoBarManager::FromWebContents(web_contents);
diff --git a/chrome/browser/extensions/extension_keybinding_apitest.cc b/chrome/browser/extensions/extension_keybinding_apitest.cc index e7fa9d9..5cfbdc4 100644 --- a/chrome/browser/extensions/extension_keybinding_apitest.cc +++ b/chrome/browser/extensions/extension_keybinding_apitest.cc
@@ -285,8 +285,7 @@ EXPECT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("/extensions/test_file.txt"))); - return sessions::SessionTabHelper::FromWebContents( - browser()->tab_strip_model()->GetActiveWebContents()) + return sessions::SessionTabHelper::FromWebContents(GetActiveWebContents()) ->session_id() .id(); } @@ -327,7 +326,7 @@ browser(), embedded_test_server()->GetURL("/extensions/test_file.txt"))); // activeTab shouldn't have been granted yet. - WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents(); + WebContents* tab = GetActiveWebContents(); ASSERT_TRUE(tab); EXPECT_FALSE(IsGrantedForTab(extension, tab)); @@ -1015,8 +1014,7 @@ const Extension* extension = GetSingleLoadedExtension(); ASSERT_TRUE(extension) << message_; ResultCatcher catcher; - EXPECT_TRUE(content::WaitForLoadStop( - browser()->tab_strip_model()->GetActiveWebContents())); + EXPECT_TRUE(content::WaitForLoadStop(GetActiveWebContents())); ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), ui::VKEY_Y, true, true, false, false)); // Ctrl+Shift+Y EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
diff --git a/chrome/browser/extensions/extension_loading_browsertest.cc b/chrome/browser/extensions/extension_loading_browsertest.cc index 54ec1b2..080c4c0 100644 --- a/chrome/browser/extensions/extension_loading_browsertest.cc +++ b/chrome/browser/extensions/extension_loading_browsertest.cc
@@ -88,9 +88,7 @@ embedded_test_server()->GetURL("/README.chromium"); EXPECT_THAT(test_link_from_NTP.spec(), testing::EndsWith("/README.chromium")) << "Check that the test server started."; - EXPECT_TRUE( - NavigateInRenderer(browser()->tab_strip_model()->GetActiveWebContents(), - test_link_from_NTP)); + EXPECT_TRUE(NavigateInRenderer(GetActiveWebContents(), test_link_from_NTP)); // Increase the extension's version. extension_dir.WriteManifest(base::StringPrintf(kManifestTemplate, 2)); @@ -144,9 +142,7 @@ embedded_test_server()->GetURL("/README.chromium"); EXPECT_THAT(test_link_from_ntp.spec(), testing::EndsWith("/README.chromium")) << "Check that the test server started."; - EXPECT_TRUE( - NavigateInRenderer(browser()->tab_strip_model()->GetActiveWebContents(), - test_link_from_ntp)); + EXPECT_TRUE(NavigateInRenderer(GetActiveWebContents(), test_link_from_ntp)); // Increase the extension's version and add the NTP url override which will // add the kNewTabPageOverride permission.
diff --git a/chrome/browser/extensions/extension_security_exploit_browsertest.cc b/chrome/browser/extensions/extension_security_exploit_browsertest.cc index fc4e842a..041ab4f 100644 --- a/chrome/browser/extensions/extension_security_exploit_browsertest.cc +++ b/chrome/browser/extensions/extension_security_exploit_browsertest.cc
@@ -234,10 +234,6 @@ ASSERT_TRUE(embedded_test_server()->Start()); } - content::WebContents* active_web_contents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - // Asks the `extension_id` to inject `content_script` into `web_contents`. // Returns true if the content script execution started successfully. bool ExecuteProgrammaticContentScript(content::WebContents* web_contents, @@ -359,14 +355,14 @@ // RenderProcessHost on all platforms.) GURL test_page_url = embedded_test_server()->GetURL("foo.com", "/title1.html"); - int old_process_id = active_web_contents() + int old_process_id = GetActiveWebContents() ->GetPrimaryMainFrame() ->GetProcess() ->GetDeprecatedID(); EXPECT_TRUE( ui_test_utils::NavigateToURL(browser(), GURL("chrome://version"))); EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url)); - int new_process_id = active_web_contents() + int new_process_id = GetActiveWebContents() ->GetPrimaryMainFrame() ->GetProcess() ->GetDeprecatedID(); @@ -383,14 +379,14 @@ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC // from a content script of an `active_extension_id`. ASSERT_TRUE(ExecuteProgrammaticContentScript( - active_web_contents(), active_extension_id(), + GetActiveWebContents(), active_extension_id(), "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});")); content::RenderProcessHost* main_frame_process = - active_web_contents()->GetPrimaryMainFrame()->GetProcess(); + GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process); auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>( - active_web_contents()->GetPrimaryMainFrame()); + GetActiveWebContents()->GetPrimaryMainFrame()); interceptor->SetOpenChannelToExtensionMutator( base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) { EXPECT_EQ(MessagingEndpoint::Type::kContentScript, @@ -408,14 +404,14 @@ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC // from a content script of an `active_extension_id`. ASSERT_TRUE(ExecuteProgrammaticContentScript( - active_web_contents(), active_extension_id(), + GetActiveWebContents(), active_extension_id(), "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});")); content::RenderProcessHost* main_frame_process = - active_web_contents()->GetPrimaryMainFrame()->GetProcess(); + GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process); auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>( - active_web_contents()->GetPrimaryMainFrame()); + GetActiveWebContents()->GetPrimaryMainFrame()); interceptor->SetOpenChannelToExtensionMutator( base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) { EXPECT_EQ(MessagingEndpoint::Type::kContentScript, @@ -432,14 +428,14 @@ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC // from a content script of an `active_extension_id`. ASSERT_TRUE(ExecuteProgrammaticContentScript( - active_web_contents(), active_extension_id(), + GetActiveWebContents(), active_extension_id(), "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});")); content::RenderProcessHost* main_frame_process = - active_web_contents()->GetPrimaryMainFrame()->GetProcess(); + GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process); auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>( - active_web_contents()->GetPrimaryMainFrame()); + GetActiveWebContents()->GetPrimaryMainFrame()); interceptor->SetOpenChannelToExtensionMutator( base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) { EXPECT_EQ(MessagingEndpoint::Type::kContentScript, @@ -457,14 +453,14 @@ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC // from a content script of an `active_extension_id`. ASSERT_TRUE(ExecuteProgrammaticContentScript( - active_web_contents(), active_extension_id(), + GetActiveWebContents(), active_extension_id(), "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});")); content::RenderProcessHost* main_frame_process = - active_web_contents()->GetPrimaryMainFrame()->GetProcess(); + GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process); auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>( - active_web_contents()->GetPrimaryMainFrame()); + GetActiveWebContents()->GetPrimaryMainFrame()); interceptor->SetOpenChannelToExtensionMutator( base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) { EXPECT_EQ(MessagingEndpoint::Type::kContentScript, @@ -484,14 +480,14 @@ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC // from a content script of an `active_extension_id`. ASSERT_TRUE(ExecuteProgrammaticContentScript( - active_web_contents(), active_extension_id(), + GetActiveWebContents(), active_extension_id(), "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});")); content::RenderProcessHost* main_frame_process = - active_web_contents()->GetPrimaryMainFrame()->GetProcess(); + GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process); auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>( - active_web_contents()->GetPrimaryMainFrame()); + GetActiveWebContents()->GetPrimaryMainFrame()); interceptor->SetOpenChannelToExtensionMutator( base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) { EXPECT_EQ(MessagingEndpoint::Type::kContentScript, @@ -499,8 +495,9 @@ EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id); // Mutate `source_url` in the IPC payload. - GURL actual_url = - active_web_contents()->GetPrimaryMainFrame()->GetLastCommittedURL(); + GURL actual_url = GetActiveWebContents() + ->GetPrimaryMainFrame() + ->GetLastCommittedURL(); ASSERT_EQ(actual_url, info.source_url); GURL spoofed_url = embedded_test_server()->GetURL("spoofed.com", "/title1.html"); @@ -616,7 +613,7 @@ }); )"; ASSERT_EQ("onload", - content::EvalJs(active_web_contents(), + content::EvalJs(GetActiveWebContents(), content::JsReplace(kScriptTemplate, kDataUrl))); ASSERT_TRUE(listener.WaitUntilSatisfied()); @@ -636,13 +633,13 @@ embedded_test_server()->GetURL("foo.com", "/title1.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url)); content::RenderFrameHost* main_frame = - active_web_contents()->GetPrimaryMainFrame(); + GetActiveWebContents()->GetPrimaryMainFrame(); // Verify the test setup by checking if the non-intercepted `chrome.storage` // API call will succeed. { ExtensionTestMessageListener listener("Got chrome.storage response"); - ASSERT_TRUE(ExecuteProgrammaticContentScript(active_web_contents(), + ASSERT_TRUE(ExecuteProgrammaticContentScript(GetActiveWebContents(), active_extension_id(), R"( chrome.storage.local.set( { test_key: 'test value'}, @@ -670,7 +667,7 @@ // verify that the mutated/spoofed extension id is detected and leads to // terminating the misbehaving renderer process. RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame->GetProcess()); - ASSERT_TRUE(ExecuteProgrammaticContentScript(active_web_contents(), + ASSERT_TRUE(ExecuteProgrammaticContentScript(GetActiveWebContents(), active_extension_id(), R"( chrome.storage.local.set({ test_key: 'test value2'}, () => {}); )")); @@ -685,14 +682,14 @@ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC // from a user script of an `active_extension_id`. ExecuteUserScript( - *active_web_contents(), active_extension_id(), + *GetActiveWebContents(), active_extension_id(), "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"); content::RenderProcessHost* main_frame_process = - active_web_contents()->GetPrimaryMainFrame()->GetProcess(); + GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process); auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>( - active_web_contents()->GetPrimaryMainFrame()); + GetActiveWebContents()->GetPrimaryMainFrame()); interceptor->SetOpenChannelToExtensionMutator( base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) { EXPECT_EQ(MessagingEndpoint::Type::kUserScript, @@ -712,14 +709,14 @@ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC // from a user script of an `active_extension_id`. ExecuteUserScript( - *active_web_contents(), active_extension_id(), + *GetActiveWebContents(), active_extension_id(), "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"); content::RenderProcessHost* main_frame_process = - active_web_contents()->GetPrimaryMainFrame()->GetProcess(); + GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process); auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>( - active_web_contents()->GetPrimaryMainFrame()); + GetActiveWebContents()->GetPrimaryMainFrame()); interceptor->SetOpenChannelToExtensionMutator( base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) { EXPECT_EQ(MessagingEndpoint::Type::kUserScript, @@ -739,14 +736,14 @@ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC // from a user script of an `active_extension_id`. ExecuteUserScript( - *active_web_contents(), active_extension_id(), + *GetActiveWebContents(), active_extension_id(), "chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"); content::RenderProcessHost* main_frame_process = - active_web_contents()->GetPrimaryMainFrame()->GetProcess(); + GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process); auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>( - active_web_contents()->GetPrimaryMainFrame()); + GetActiveWebContents()->GetPrimaryMainFrame()); interceptor->SetOpenChannelToExtensionMutator( base::BindLambdaForTesting([this](mojom::ExternalConnectionInfo& info) { EXPECT_EQ(MessagingEndpoint::Type::kUserScript,
diff --git a/chrome/browser/extensions/extension_service_test_base.cc b/chrome/browser/extensions/extension_service_test_base.cc index ea74706..650df94 100644 --- a/chrome/browser/extensions/extension_service_test_base.cc +++ b/chrome/browser/extensions/extension_service_test_base.cc
@@ -45,6 +45,7 @@ #include "components/crx_file/crx_verifier.h" #include "components/policy/core/common/policy_service_impl.h" #include "components/pref_registry/pref_registry_syncable.h" +#include "components/prefs/pref_service.h" #include "components/sync_preferences/pref_service_mock_factory.h" #include "components/sync_preferences/pref_service_syncable.h" #include "content/public/browser/browser_context.h" @@ -59,9 +60,9 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/ash/extensions/install_limiter.h" -#include "chrome/browser/ash/login/users/user_manager_delegate_impl.h" #include "chrome/browser/browser_process.h" #include "chromeos/ash/components/settings/cros_settings.h" +#include "components/user_manager/fake_user_manager_delegate.h" #include "components/user_manager/user_manager_impl.h" #endif @@ -248,13 +249,11 @@ std::unique_ptr<content::BrowserTaskEnvironment> task_environment) : task_environment_(std::move(task_environment)), service_(nullptr), - testing_local_state_(TestingBrowserProcess::GetGlobal()), registry_(nullptr), #if BUILDFLAG(IS_CHROMEOS) user_manager_(std::make_unique<user_manager::UserManagerImpl>( - std::make_unique<ash::UserManagerDelegateImpl>(), - testing_local_state_.Get(), - ash::CrosSettings::Get())), + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->local_state())), #endif verifier_format_override_(crx_file::VerifierFormat::CRX3) { base::FilePath test_data_dir;
diff --git a/chrome/browser/extensions/extension_service_test_base.h b/chrome/browser/extensions/extension_service_test_base.h index 54aa18a..ff59210 100644 --- a/chrome/browser/extensions/extension_service_test_base.h +++ b/chrome/browser/extensions/extension_service_test_base.h
@@ -18,7 +18,6 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/extensions/scoped_test_mv2_enabler.h" #include "chrome/common/chrome_constants.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_profile.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_service.h" @@ -236,7 +235,6 @@ // The ExtensionService, whose lifetime is managed by `profile`'s // ExtensionSystem. raw_ptr<ExtensionService, DanglingUntriaged> service_; - ScopedTestingLocalState testing_local_state_; private: void CreateExtensionService(bool is_first_run,
diff --git a/chrome/browser/extensions/extension_user_script_loader_browsertest.cc b/chrome/browser/extensions/extension_user_script_loader_browsertest.cc index 44dc149..aa1465a0 100644 --- a/chrome/browser/extensions/extension_user_script_loader_browsertest.cc +++ b/chrome/browser/extensions/extension_user_script_loader_browsertest.cc
@@ -107,8 +107,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("example.com", "/simple.html"))); - EXPECT_EQ(u"script injected", - browser()->tab_strip_model()->GetActiveWebContents()->GetTitle()); + EXPECT_EQ(u"script injected", GetActiveWebContents()->GetTitle()); const Extension* extension = nullptr; for (const auto& entry : @@ -183,8 +182,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL("example.com", "/simple.html"))); - EXPECT_EQ(u"script injected", - browser()->tab_strip_model()->GetActiveWebContents()->GetTitle()); + EXPECT_EQ(u"script injected", GetActiveWebContents()->GetTitle()); } } // namespace extensions
diff --git a/chrome/browser/extensions/extension_webui_apitest.cc b/chrome/browser/extensions/extension_webui_apitest.cc index 75db8e1..2f023b20 100644 --- a/chrome/browser/extensions/extension_webui_apitest.cc +++ b/chrome/browser/extensions/extension_webui_apitest.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/ui_test_utils.h" @@ -125,8 +124,7 @@ content::RenderFrameHost* OpenExtensionOptions(const Extension* extension) { EXPECT_TRUE(ui_test_utils::NavigateToURL( browser(), GURL(chrome::kChromeUIExtensionsURL))); - content::WebContents* webui = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* webui = GetActiveWebContents(); EXPECT_EQ(0U, test_guest_view_manager_->num_guests_created()); @@ -438,8 +436,7 @@ GURL test_url("chrome://webui-test/extension_webui_listeners_test.html"); EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url)); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame(); EventRouter* event_router = EventRouter::Get(profile()); EXPECT_FALSE(event_router->HasEventListener("test.onMessage"));
diff --git a/chrome/browser/extensions/fetch_apitest.cc b/chrome/browser/extensions/fetch_apitest.cc index 416e2e0b..1abd513 100644 --- a/chrome/browser/extensions/fetch_apitest.cc +++ b/chrome/browser/extensions/fetch_apitest.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_navigator_params.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" @@ -120,7 +119,7 @@ NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK); params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; ui_test_utils::NavigateToURL(¶ms); - return browser()->tab_strip_model()->GetActiveWebContents(); + return GetActiveWebContents(); } void SetUpOnMainThread() override {
diff --git a/chrome/browser/extensions/isolated_world_csp_browsertest.cc b/chrome/browser/extensions/isolated_world_csp_browsertest.cc index f583406..516d07e 100644 --- a/chrome/browser/extensions/isolated_world_csp_browsertest.cc +++ b/chrome/browser/extensions/isolated_world_csp_browsertest.cc
@@ -60,8 +60,7 @@ // We wait on a console message which will be raised on an unsuccessful // navigation to a javascript url since there isn't any other clean way to // assert that the navigation didn't succeed. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::WebContentsConsoleObserver console_observer(web_contents); console_observer.SetPattern( "Refused to run the JavaScript URL because it violates the following "
diff --git a/chrome/browser/extensions/lazy_background_page_apitest.cc b/chrome/browser/extensions/lazy_background_page_apitest.cc index 0239ba0..98cd86c5 100644 --- a/chrome/browser/extensions/lazy_background_page_apitest.cc +++ b/chrome/browser/extensions/lazy_background_page_apitest.cc
@@ -30,7 +30,6 @@ #include "chrome/browser/ui/extensions/extension_action_test_helper.h" #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/browser/ui/tabs/tab_enums.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/api/tabs.h" @@ -206,8 +205,7 @@ // Background page created a new tab before it closed. EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); EXPECT_EQ(num_tabs_before + 1, browser()->tab_strip_model()->count()); - content::WebContents* active_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* active_tab = GetActiveWebContents(); EXPECT_TRUE(content::WaitForLoadStop(active_tab)); EXPECT_EQ(GURL(chrome::kChromeUIExtensionsURL), active_tab->GetLastCommittedURL()); @@ -244,7 +242,7 @@ // Lazy Background Page doesn't exist yet. EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); EXPECT_EQ(0u, extension_action_test_util::GetActivePageActionCount( - browser()->tab_strip_model()->GetActiveWebContents())); + GetActiveWebContents())); // Open a tab to a URL that will trigger the page action to show. ExtensionHostTestHelper host_helper(profile(), last_loaded_extension_id()); @@ -260,7 +258,7 @@ // Page action is shown. WaitForPageActionVisibilityChangeTo(1); EXPECT_EQ(1u, extension_action_test_util::GetActivePageActionCount( - browser()->tab_strip_model()->GetActiveWebContents())); + GetActiveWebContents())); } IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, Filters) { @@ -388,8 +386,7 @@ ASSERT_TRUE(extension); EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); - content::WebContents* active_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* active_tab = GetActiveWebContents(); EXPECT_TRUE(content::WaitForLoadStop(active_tab)); // The extension should've opened a new tab to an extension page. EXPECT_EQ(extension->GetResourceURL("extension_page.html"), @@ -455,8 +452,7 @@ ASSERT_TRUE(extension); EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); - content::WebContents* active_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* active_tab = GetActiveWebContents(); EXPECT_TRUE(content::WaitForLoadStop(active_tab)); // The extension should've opened a new tab to an extension page. EXPECT_EQ(GURL(chrome::kChromeUINewTabURL),
diff --git a/chrome/browser/extensions/manifest_v3_browsertest.cc b/chrome/browser/extensions/manifest_v3_browsertest.cc index 3ab105b..0f535b70 100644 --- a/chrome/browser/extensions/manifest_v3_browsertest.cc +++ b/chrome/browser/extensions/manifest_v3_browsertest.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/extensions/extension_action_test_helper.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "components/version_info/channel.h" #include "content/public/browser/web_contents.h" @@ -105,8 +104,7 @@ embedded_test_server()->GetURL("example.com", "/simple.html"))); ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); - EXPECT_EQ(u"My New Title", - browser()->tab_strip_model()->GetActiveWebContents()->GetTitle()); + EXPECT_EQ(u"My New Title", GetActiveWebContents()->GetTitle()); } // A simple end-to-end test exercising the new action API in Manifest V3. @@ -176,8 +174,7 @@ ExtensionActionManager::Get(profile())->GetExtensionAction(*extension); ASSERT_TRUE(action); EXPECT_FALSE(action->GetIsVisible(ExtensionAction::kDefaultTabId)); - int tab_id = ExtensionTabUtil::GetTabId( - browser()->tab_strip_model()->GetActiveWebContents()); + int tab_id = ExtensionTabUtil::GetTabId(GetActiveWebContents()); EXPECT_FALSE(action->GetIsVisible(tab_id)); }
diff --git a/chrome/browser/extensions/navigation_extension_enabler_browsertest.cc b/chrome/browser/extensions/navigation_extension_enabler_browsertest.cc index 5a98927..8ec68cb 100644 --- a/chrome/browser/extensions/navigation_extension_enabler_browsertest.cc +++ b/chrome/browser/extensions/navigation_extension_enabler_browsertest.cc
@@ -186,8 +186,7 @@ // Navigate to a page with a subframe. GURL main_url = embedded_test_server()->GetURL("/iframe.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url)); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); EXPECT_EQ(web_contents->GetPrimaryMainFrame()->GetLastCommittedURL(), main_url); @@ -291,8 +290,7 @@ document.body.appendChild(a); a.click(); )"; - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::TestNavigationObserver nav_observer(web_contents, 1); ExecuteScriptAsync(web_contents, content::JsReplace(kScriptTemplate, target_url));
diff --git a/chrome/browser/extensions/offscreen_document_browsertest.cc b/chrome/browser/extensions/offscreen_document_browsertest.cc index 87546e26..e022069 100644 --- a/chrome/browser/extensions/offscreen_document_browsertest.cc +++ b/chrome/browser/extensions/offscreen_document_browsertest.cc
@@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "extensions/browser/offscreen_document_host.h" -#include "extensions/common/mojom/context_type.mojom.h" - #include "base/test/bind.h" #include "base/test/values_test_util.h" #include "chrome/browser/devtools/devtools_window.h" @@ -12,7 +9,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" @@ -21,12 +17,14 @@ #include "content/public/test/test_navigation_observer.h" #include "extensions/browser/background_script_executor.h" #include "extensions/browser/extension_host_registry.h" +#include "extensions/browser/offscreen_document_host.h" #include "extensions/browser/process_manager.h" #include "extensions/browser/process_map.h" #include "extensions/browser/script_result_queue.h" #include "extensions/browser/view_type_utils.h" #include "extensions/common/constants.h" #include "extensions/common/features/feature.h" +#include "extensions/common/mojom/context_type.mojom.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/test/test_extension_dir.h" #include "net/dns/mock_host_resolver.h" @@ -165,8 +163,7 @@ // a tab. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("other.html"))); - content::WebContents* tab_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* tab_contents = GetActiveWebContents(); EXPECT_EQ(tab_contents->GetPrimaryMainFrame()->GetProcess(), contents->GetPrimaryMainFrame()->GetProcess()); }
diff --git a/chrome/browser/extensions/omnibox_focus_interactive_test.cc b/chrome/browser/extensions/omnibox_focus_interactive_test.cc index 72e6bad0..c23e6455 100644 --- a/chrome/browser/extensions/omnibox_focus_interactive_test.cc +++ b/chrome/browser/extensions/omnibox_focus_interactive_test.cc
@@ -67,8 +67,7 @@ void OpenNewTab() { chrome::NewTab(browser()); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); // Wait until chrome://newtab navigation finished. content::TestNavigationObserver nav_observer(web_contents); @@ -107,8 +106,7 @@ // Open the new tab, because of the NTP extension behavior, the focus should // move to the tab contents. OpenNewTab(); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); EXPECT_EQ(final_ntp_url, web_contents->GetLastCommittedURL()); EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); @@ -159,8 +157,7 @@ // Verify that ext_ntp.html is loaded in place of the NTP and that the omnibox // is focused. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); EXPECT_EQ("NTP replacement extension", content::EvalJs(web_contents, "document.body.innerText")); EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); @@ -218,8 +215,7 @@ // Open the new tab, because of the NTP extension behavior, the focus should // move to the tab contents. OpenNewTab(); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); EXPECT_EQ(final_ntp_url, web_contents->GetLastCommittedURL()); EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); @@ -250,8 +246,7 @@ // Verify that ext_ntp.html is loaded in place of the NTP and that the omnibox // is focused. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); EXPECT_EQ("NTP replacement extension", content::EvalJs(web_contents, "document.body.innerText")); EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); @@ -295,8 +290,7 @@ // Verify that ext_ntp.html is loaded in place of the NTP and that the omnibox // is focused. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); EXPECT_EQ("NTP replacement extension", content::EvalJs(web_contents, "document.body.innerText")); EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); @@ -348,8 +342,7 @@ // ShouldFork/OpenURL code path and might have stolen the focus from the // location bar / omnibox. GURL web_url = embedded_test_server()->GetURL("/title1.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::TestFrameNavigationObserver nav_observer( web_contents->GetPrimaryMainFrame()); ASSERT_TRUE(content::ExecJs( @@ -378,8 +371,7 @@ EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); // Focus the tab contents. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); web_contents->Focus(); EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); @@ -467,8 +459,7 @@ EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); // Focus the tab contents. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); web_contents->Focus(); EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); @@ -543,8 +534,7 @@ EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER)); // Focus the tab contents. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); web_contents->Focus(); EXPECT_FALSE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_OMNIBOX)); EXPECT_TRUE(ui_test_utils::IsViewFocused(browser(), VIEW_ID_TAB_CONTAINER));
diff --git a/chrome/browser/extensions/permissions/site_permissions_helper_browsertest.cc b/chrome/browser/extensions/permissions/site_permissions_helper_browsertest.cc index 00b3f1c..ed451e5d 100644 --- a/chrome/browser/extensions/permissions/site_permissions_helper_browsertest.cc +++ b/chrome/browser/extensions/permissions/site_permissions_helper_browsertest.cc
@@ -127,11 +127,9 @@ } bool SitePermissionsHelperBrowserTest::WaitForReloadToFinish() { - // This is needed in the instance where on site -> on-click revokes - // permissions. This is because when testing we run - // `ExtensionActionRunner::accept_bubble_for_testing(true)` which causes - // `ExtensionActionRunner::ShowReloadPageBubble(...)` to run the reload with - // a `base::SingleThreadTaskRunner` so we must wait for that to complete. + // This is needed when changing permissions triggers a page reload with a + // `base::SingleThreadTaskRunner`, so we must wait for that to + // complete. base::RunLoop().RunUntilIdle(); return content::WaitForLoadStop(GetActiveWebContents()); } @@ -160,7 +158,8 @@ // By default, test setup should set site access to be on all sites. ASSERT_EQ(permissions_manager_->GetUserSiteAccess(*extension_, original_url_), UserSiteAccess::kOnAllSites); - active_action_runner()->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); // on all sites -> on site permissions_helper_->UpdateSiteAccess(*extension_, GetActiveWebContents(), @@ -233,7 +232,8 @@ ASSERT_EQ(permissions_manager_->GetUserSiteAccess(*extension_, original_url_), UserSiteAccess::kOnAllSites); // Reload will not happen via the user reload bubble. - active_action_runner()->accept_bubble_for_testing(false); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); // on all sites -> on site permissions_helper_->UpdateSiteAccess(*extension_, GetActiveWebContents(), @@ -347,7 +347,8 @@ UpdateSiteAccess_RevokingSitePermission_AlsoClearsActiveTab) { // We want to control refreshes manually due to timing issues with permissions // being updated across browser/renderer. - active_action_runner()->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); { // on all sites -> on click (revokes access) @@ -415,7 +416,8 @@ IN_PROC_BROWSER_TEST_F( SitePermissionsHelperExecuteSciptBrowserTest, UpdateSiteAccess_RevokingSitePermissionAfterGrantTab_AlsoClearsActiveTab) { - active_action_runner()->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); { // on all sites -> on click (revokes access) @@ -488,7 +490,8 @@ // rest for b/324455951. IN_PROC_BROWSER_TEST_F(SitePermissionsHelperExecuteSciptBrowserTest, CrossOriginRenavigationClearsGrantedTabPermission) { - active_action_runner()->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); // Withheld extension's site access. ScriptingPermissionsModifier(profile(), extension_.get()) @@ -593,7 +596,8 @@ UpdateSiteAccess_RevokingSitePermission_AlsoClearsActiveTab) { // We want to control refreshes manually due to timing issues with permissions // being updated across browser/renderer. - active_action_runner()->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); // on all sites -> on click (revokes access) permissions_helper_->UpdateSiteAccess(*extension_, GetActiveWebContents(), @@ -692,7 +696,8 @@ // By default, test setup should set site access to be on all sites. ASSERT_EQ(permissions_manager_->GetUserSiteAccess(*extension_, original_url_), UserSiteAccess::kOnAllSites); - active_action_runner()->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); { // on all sites -> on site.
diff --git a/chrome/browser/extensions/permissions/site_permissions_helper_unittest.cc b/chrome/browser/extensions/permissions/site_permissions_helper_unittest.cc index 844ac32..06678d2 100644 --- a/chrome/browser/extensions/permissions/site_permissions_helper_unittest.cc +++ b/chrome/browser/extensions/permissions/site_permissions_helper_unittest.cc
@@ -282,10 +282,8 @@ // Open a site requested by both extensions. content::WebContents* site_contents = AddTab(requested_site); - ExtensionActionRunner* action_runner = - ExtensionActionRunner::GetForWebContents(site_contents); - ASSERT_TRUE(action_runner); - action_runner->accept_bubble_for_testing(false); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); // Extension A should have 'on site' access for the site it requested and 'on // click' for a site it didn't request. Extension A should have 'on all sites' @@ -406,12 +404,8 @@ { // Switch the extension from on all sites to on-click. - ExtensionActionRunner* action_runner = - ExtensionActionRunner::GetForWebContents(non_user_permitted_contents); - ASSERT_TRUE(action_runner); - // Permissions for the site are still updated even if the tab is not - // reloaded. - action_runner->accept_bubble_for_testing(false); + auto reload_page_dialog_reset = + ReloadPageDialogController::AcceptDialogForTesting(true); PermissionsManagerWaiter waiter(permissions_manager()); permissions_helper()->UpdateSiteAccess( *extension, non_user_permitted_contents, UserSiteAccess::kOnClick);
diff --git a/chrome/browser/extensions/process_map_browsertest.cc b/chrome/browser/extensions/process_map_browsertest.cc index 61e88ea4..05e0937 100644 --- a/chrome/browser/extensions/process_map_browsertest.cc +++ b/chrome/browser/extensions/process_map_browsertest.cc
@@ -12,7 +12,6 @@ #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -47,13 +46,8 @@ ASSERT_TRUE(embedded_test_server()->Start()); } - // Returns the WebContents of the currently-active tab. - content::WebContents* GetActiveTab() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - content::RenderProcessHost& GetActiveMainFrameProcess() { - return *GetActiveTab()->GetPrimaryMainFrame()->GetProcess(); + return *GetActiveWebContents()->GetPrimaryMainFrame()->GetProcess(); } int GetActiveMainFrameProcessID() { @@ -109,7 +103,7 @@ void ExecuteUserScriptInActiveTab(const ExtensionId& extension_id) { base::RunLoop run_loop; - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); // TODO(crbug.com/40262660): Add a utility method for user script // injection in browser tests. ScriptExecutor script_executor(web_contents); @@ -580,7 +574,7 @@ browser(), embedded_test_server()->GetURL("a.test", "/simple.html"))); ASSERT_TRUE(listener_mainframe.WaitUntilSatisfied()); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame(); content::TestNavigationObserver observer(web_contents, 1); ExtensionTestMessageListener listener_subframe("dynamic import success"); @@ -613,7 +607,7 @@ embedded_test_server()->GetURL("a.test", "/csp-sandbox.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), sandboxed_url)); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* sandboxed_main_frame = web_contents->GetPrimaryMainFrame(); ASSERT_TRUE(sandboxed_main_frame->IsSandboxed( @@ -729,7 +723,7 @@ // Load E1. ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension1->GetResourceURL("main.html"))); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame(); content::RenderFrameHost* sandboxed_a_frame = content::ChildFrameAt(main_frame, 0); @@ -977,7 +971,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("parent.html"))); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame(); content::RenderFrameHost* sandboxed_child_frame = content::ChildFrameAt(main_frame, 0); @@ -1077,7 +1071,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("parent.html"))); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame(); // Use JS to add content to the child frame. content::TestNavigationObserver observer(web_contents); @@ -1172,7 +1166,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension2->GetResourceURL("parent.html"))); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame(); content::RenderFrameHost* sandboxed_child_frame = content::ChildFrameAt(main_frame, 0); @@ -1205,7 +1199,7 @@ frm.src = $1; document.body.appendChild(frm); )"; - content::TestNavigationObserver observer(GetActiveTab(), 1); + content::TestNavigationObserver observer(GetActiveWebContents(), 1); EXPECT_TRUE(ExecJs(sandboxed_child_frame, content::JsReplace(kJsScript, e2_private_page_url))); observer.Wait(); @@ -1231,7 +1225,7 @@ OpenExtensionPageWithSandboxedFrame(*extension); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame(); content::RenderFrameHost* sandboxed_frame = content::ChildFrameAt(main_frame, 0); @@ -1288,7 +1282,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("parent.html"))); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* extension_frame = web_contents->GetPrimaryMainFrame(); content::RenderFrameHost* non_extension_frame = @@ -1368,7 +1362,7 @@ OpenExtensionPageWithSandboxedFrame(*extension); - content::WebContents* web_contents = GetActiveTab(); + content::WebContents* web_contents = GetActiveWebContents(); content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame(); content::RenderFrameHost* sandboxed_frame = content::ChildFrameAt(main_frame, 0);
diff --git a/chrome/browser/extensions/protocol_handler_apitest.cc b/chrome/browser/extensions/protocol_handler_apitest.cc index 6346bfe..69b67283 100644 --- a/chrome/browser/extensions/protocol_handler_apitest.cc +++ b/chrome/browser/extensions/protocol_handler_apitest.cc
@@ -87,8 +87,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); // Bypass permission dialogs for registering new protocol handlers. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); permissions::PermissionRequestManager::FromWebContents(web_contents) ->set_auto_response_for_test( permissions::PermissionRequestManager::ACCEPT_ALL); @@ -159,7 +158,7 @@ << message_; content::WebContentsDelegate* web_contents_delegate = - browser()->tab_strip_model()->GetActiveWebContents()->GetDelegate(); + GetActiveWebContents()->GetDelegate(); content::RenderFrameHost* main_frame = browser() ->tab_strip_model() ->GetActiveWebContents()
diff --git a/chrome/browser/extensions/renderer_initialization_browsertest.cc b/chrome/browser/extensions/renderer_initialization_browsertest.cc index f45a0f3..bde99a9 100644 --- a/chrome/browser/extensions/renderer_initialization_browsertest.cc +++ b/chrome/browser/extensions/renderer_initialization_browsertest.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -34,8 +33,7 @@ // Without waiting for the tab to finish, unload the extension. extension_registrar()->RemoveExtension(extension->id(), UnloadedExtensionReason::TERMINATE); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); // Wait for the web contents to stop loading. content::WaitForLoadStop(web_contents); EXPECT_EQ(url, web_contents->GetLastCommittedURL()); @@ -56,8 +54,7 @@ ASSERT_TRUE(extension->is_theme()); GURL url = extension->GetResourceURL("manifest.json"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); // Wait for the web contents to stop loading. EXPECT_TRUE(content::WaitForLoadStop(web_contents)); EXPECT_EQ(url, web_contents->GetLastCommittedURL());
diff --git a/chrome/browser/extensions/script_executor_browsertest.cc b/chrome/browser/extensions/script_executor_browsertest.cc index 9c3255e7..0efb20f0 100644 --- a/chrome/browser/extensions/script_executor_browsertest.cc +++ b/chrome/browser/extensions/script_executor_browsertest.cc
@@ -13,7 +13,6 @@ #include "base/values.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" @@ -111,8 +110,7 @@ GURL example_com = embedded_test_server()->GetURL("example.com", "/simple.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(web_contents); { @@ -160,8 +158,7 @@ GURL example_com = embedded_test_server()->GetURL("example.com", "/simple.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(web_contents); { @@ -212,8 +209,7 @@ GURL example_com = embedded_test_server()->GetURL("example.com", "/simple.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(web_contents); { @@ -269,8 +265,7 @@ GURL example_com = embedded_test_server()->GetURL("example.com", "/simple.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(web_contents); { @@ -367,8 +362,7 @@ GURL example_com = embedded_test_server()->GetURL( "example.com", "/extensions/iframes/main.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(web_contents); {
diff --git a/chrome/browser/extensions/script_injection_tracker_browsertest.cc b/chrome/browser/extensions/script_injection_tracker_browsertest.cc index 0288bdc..8159b70c 100644 --- a/chrome/browser/extensions/script_injection_tracker_browsertest.cc +++ b/chrome/browser/extensions/script_injection_tracker_browsertest.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/extensions/user_scripts_test_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "components/guest_view/browser/guest_view_base.h" #include "components/guest_view/browser/guest_view_manager_delegate.h" @@ -151,11 +150,6 @@ content::SetupCrossSiteRedirector(embedded_test_server()); } - // Returns the current active web contents. - content::WebContents* GetActiveWebContents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - // Navigates to url for given `hostname` and `relative_url`. Returns whether // the navigation is in a new process compared to the currently active tab. [[nodiscard]] bool NavigateToURLInNewProcess(std::string_view hostname, @@ -1175,10 +1169,8 @@ // Verify that content script has been injected. ASSERT_TRUE(listener.WaitUntilSatisfied()); - content::RenderFrameHost* main_frame = browser() - ->tab_strip_model() - ->GetActiveWebContents() - ->GetPrimaryMainFrame(); + content::RenderFrameHost* main_frame = + GetActiveWebContents()->GetPrimaryMainFrame(); EXPECT_EQ("content script has run", content::EvalJs(main_frame, "document.body.innerText"));
diff --git a/chrome/browser/extensions/service_worker_apitest.cc b/chrome/browser/extensions/service_worker_apitest.cc index db3bb959..550e3f6 100644 --- a/chrome/browser/extensions/service_worker_apitest.cc +++ b/chrome/browser/extensions/service_worker_apitest.cc
@@ -172,8 +172,7 @@ ui_test_utils::NavigateToURLWithDisposition( browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::WaitForLoadStop(web_contents); return web_contents; } @@ -1177,8 +1176,7 @@ GURL page_url = embedded_test_server()->GetURL( "/extensions/api_test/service_worker/" "webrequest/webpage.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), page_url)); EXPECT_TRUE(content::WaitForLoadStop(web_contents)); @@ -1569,8 +1567,7 @@ { SCOPED_TRACE( "waiting for page to load and content script to finish running"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ResultCatcher content_script_catcher; ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), embedded_test_server()->GetURL( @@ -1848,8 +1845,7 @@ ASSERT_TRUE(extension); ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("page.html"))); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); // Have the page script start the service worker and wait for that to // succeed. @@ -1872,8 +1868,7 @@ ASSERT_TRUE(extension); ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("page.html"))); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); // Prevent firing by going offline. content::background_sync_test_util::SetOnline(web_contents, false); @@ -1896,8 +1891,7 @@ GURL page_url = embedded_test_server()->GetURL( "/extensions/api_test/service_worker/content_script_fetch/" "controlled_page/index.html"); - content::WebContents* tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* tab = GetActiveWebContents(); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), page_url)); EXPECT_TRUE(content::WaitForLoadStop(tab)); @@ -1918,8 +1912,7 @@ GURL url = extension->GetResourceURL("page.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); // Start the ServiceWorker. ExtensionTestMessageListener ready_listener("SERVICE_WORKER_READY"); @@ -2498,8 +2491,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL( browser(), extension->GetResourceURL("page.html"))); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); url::Origin extension_origin = url::Origin::Create(extension->url()); const blink::StorageKey extension_key = @@ -2710,8 +2702,7 @@ content::WebContents* web_contents = browsertest_util::AddTab(browser(), GURL("about:blank")); ASSERT_TRUE(web_contents); - ExtensionActionRunner::GetForWebContents( - browser()->tab_strip_model()->GetActiveWebContents()) + ExtensionActionRunner::GetForWebContents(GetActiveWebContents()) ->RunAction(extension, true); } EXPECT_TRUE(catcher.GetNextResult()) << message_; @@ -2767,8 +2758,7 @@ content::WebContents* web_contents = browsertest_util::AddTab(browser(), GURL("about:blank")); ASSERT_TRUE(web_contents); - ExtensionActionRunner::GetForWebContents( - browser()->tab_strip_model()->GetActiveWebContents()) + ExtensionActionRunner::GetForWebContents(GetActiveWebContents()) ->RunAction(extension, true); } EXPECT_TRUE(catcher.GetNextResult()) << message_; @@ -2958,8 +2948,7 @@ } })(); )"; - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); EXPECT_EQ("PASS", content::EvalJs(web_contents, kScript)); // Also ensure that a local scheme subframe in the extension page correctly
diff --git a/chrome/browser/extensions/service_worker_event_dispatching_browsertest.cc b/chrome/browser/extensions/service_worker_event_dispatching_browsertest.cc index 9596a35e..04bac7f 100644 --- a/chrome/browser/extensions/service_worker_event_dispatching_browsertest.cc +++ b/chrome/browser/extensions/service_worker_event_dispatching_browsertest.cc
@@ -113,10 +113,6 @@ sw_context_ = nullptr; } - content::WebContents* web_contents() const { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - DispatchWebNavigationEventCallback CreateDispatchWebNavEventCallback( int num_events_to_dispatch = 1) { return base::BindOnce( @@ -127,7 +123,8 @@ // Broadcasts a webNavigation.onBeforeNavigate events. void DispatchWebNavigationEvent(int num_events_to_dispatch = 1) { EventRouter* router = EventRouter::EventRouter::Get(profile()); - testing::NiceMock<content::MockNavigationHandle> handle(web_contents()); + testing::NiceMock<content::MockNavigationHandle> handle( + GetActiveWebContents()); for (int i = 0; i < num_events_to_dispatch; i++) { auto event = web_navigation_api_helpers::CreateOnBeforeNavigateEvent(&handle);
diff --git a/chrome/browser/extensions/service_worker_registration_apitest.cc b/chrome/browser/extensions/service_worker_registration_apitest.cc index d6d4eda..5e2cac7f 100644 --- a/chrome/browser/extensions/service_worker_registration_apitest.cc +++ b/chrome/browser/extensions/service_worker_registration_apitest.cc
@@ -482,10 +482,8 @@ WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - EXPECT_EQ( - "This is a page", - content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), - "document.body.innerText;")); + EXPECT_EQ("This is a page", content::EvalJs(GetActiveWebContents(), + "document.body.innerText;")); // Verify the service worker is at v1. EXPECT_EQ(base::Value(1), GetVersionFlagFromBackgroundContext(id)); @@ -934,14 +932,13 @@ // Get the NTP javascript's version. content::EvalJsResult GetVersionOfNTPScript() { - return content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), - "self.currentVersion;"); + return content::EvalJs(GetActiveWebContents(), "self.currentVersion;"); } // Request the version of the background context script from the perspective // of the NTP js. content::EvalJsResult GetBackgroundContextVersionFromNTPPage() { - return content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), + return content::EvalJs(GetActiveWebContents(), "getCurrentVersionOfBackgroundContext();"); }
diff --git a/chrome/browser/extensions/service_worker_tracking_browsertest.cc b/chrome/browser/extensions/service_worker_tracking_browsertest.cc index 5cbe8d7b..0c32db2 100644 --- a/chrome/browser/extensions/service_worker_tracking_browsertest.cc +++ b/chrome/browser/extensions/service_worker_tracking_browsertest.cc
@@ -257,8 +257,7 @@ ui_test_utils::NavigateToURLWithDisposition( browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::WaitForLoadStop(web_contents); } @@ -833,8 +832,7 @@ ASSERT_EQ("0.2", new_extension_version->version().GetString()); // Double-confirm that after our wait the renderer hasn't crashed. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(web_contents); EXPECT_FALSE(web_contents->IsCrashed()); }
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc index 21b07e90..c2732aa 100644 --- a/chrome/browser/extensions/updater/extension_updater_unittest.cc +++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -50,10 +50,10 @@ #include "chrome/browser/extensions/test_extension_system.h" #include "chrome/browser/extensions/updater/chrome_extension_downloader_factory.h" #include "chrome/browser/google/google_brand.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/crx_file/id_util.h" +#include "components/prefs/pref_service.h" #include "components/signin/public/identity_manager/identity_test_environment.h" #include "components/sync_preferences/pref_service_syncable.h" #include "components/update_client/update_query_params.h" @@ -482,8 +482,7 @@ class ExtensionUpdaterTest : public testing::Test { public: ExtensionUpdaterTest() - : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP), - testing_local_state_(TestingBrowserProcess::GetGlobal()) {} + : task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {} void SetUp() override { prefs_ = std::make_unique<TestExtensionPrefs>( @@ -2351,14 +2350,12 @@ private: content::InProcessUtilityThreadHelper in_process_utility_thread_helper_; - ScopedTestingLocalState testing_local_state_; - #if BUILDFLAG(IS_CHROMEOS) ash::ScopedCrosSettingsTestHelper cros_settings_test_helper_; user_manager::ScopedUserManager user_manager_{ std::make_unique<user_manager::UserManagerImpl>( std::make_unique<ash::UserManagerDelegateImpl>(), - testing_local_state_.Get(), + TestingBrowserProcess::GetGlobal()->local_state(), ash::CrosSettings::Get())}; #endif
diff --git a/chrome/browser/extensions/user_host_restrictions_browsertest.cc b/chrome/browser/extensions/user_host_restrictions_browsertest.cc index da044d4..cecdc036 100644 --- a/chrome/browser/extensions/user_host_restrictions_browsertest.cc +++ b/chrome/browser/extensions/user_host_restrictions_browsertest.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/extensions/permissions/scripting_permissions_modifier.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "components/sessions/content/session_tab_helper.h" #include "content/public/test/browser_test.h" @@ -47,12 +46,8 @@ host_resolver()->AddRule("*", "127.0.0.1"); } - content::WebContents* GetActiveTab() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - int GetActiveTabId() { - return sessions::SessionTabHelper::IdForTab(GetActiveTab()).id(); + return sessions::SessionTabHelper::IdForTab(GetActiveWebContents()).id(); } // Withholds host permissions from `extension` and waits for the withholding @@ -186,16 +181,16 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), allowed_url)); static constexpr char16_t kInjectedTitle[] = u"Injected"; - EXPECT_EQ(kInjectedTitle, GetActiveTab()->GetTitle()); + EXPECT_EQ(kInjectedTitle, GetActiveWebContents()->GetTitle()); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), restricted_url)); // The extension should not be able to run on the user-restricted site iff // the feature is enabled. if (GetParam()) { - EXPECT_EQ(u"Title Of Awesomeness", GetActiveTab()->GetTitle()); + EXPECT_EQ(u"Title Of Awesomeness", GetActiveWebContents()->GetTitle()); } else { - EXPECT_EQ(kInjectedTitle, GetActiveTab()->GetTitle()); + EXPECT_EQ(kInjectedTitle, GetActiveWebContents()->GetTitle()); } } @@ -447,13 +442,13 @@ // their original (awesome) titles. ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), allowed_url)); static constexpr char16_t kInjectedTitle[] = u"Injected"; - EXPECT_EQ(kInjectedTitle, GetActiveTab()->GetTitle()); + EXPECT_EQ(kInjectedTitle, GetActiveWebContents()->GetTitle()); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), restricted_url)); - EXPECT_EQ(u"Title Of Awesomeness", GetActiveTab()->GetTitle()); + EXPECT_EQ(u"Title Of Awesomeness", GetActiveWebContents()->GetTitle()); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), unrequested_url)); - EXPECT_EQ(u"Title Of More Awesomeness", GetActiveTab()->GetTitle()); + EXPECT_EQ(u"Title Of More Awesomeness", GetActiveWebContents()->GetTitle()); // Finally, remove the user-permitted `allowed_url`. Since the extension // only had access to this URL via it being a user-permitted URL (and not @@ -476,7 +471,7 @@ // sanitized for display (e.g. stripping HTTPS) so to avoid tying this too // closely with the UI, we just check that it's not equal to the injected // title. - EXPECT_NE(kInjectedTitle, GetActiveTab()->GetTitle()); + EXPECT_NE(kInjectedTitle, GetActiveWebContents()->GetTitle()); // TODO(crbug.com/40803363): We could add more checks here to // exercise the network service path, as we do for user restricted sites
diff --git a/chrome/browser/extensions/user_script_extension_browsertest.cc b/chrome/browser/extensions/user_script_extension_browsertest.cc index 6083652..cb8affcc 100644 --- a/chrome/browser/extensions/user_script_extension_browsertest.cc +++ b/chrome/browser/extensions/user_script_extension_browsertest.cc
@@ -8,7 +8,6 @@ #include "chrome/browser/extensions/permissions/permissions_updater.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -82,10 +81,8 @@ const GURL url = embedded_test_server()->GetURL("example.com", "/simple.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - EXPECT_EQ( - "user script injected", - content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), - "document.title")); + EXPECT_EQ("user script injected", + content::EvalJs(GetActiveWebContents(), "document.title")); } } // namespace extensions
diff --git a/chrome/browser/extensions/user_script_listener_browsertest.cc b/chrome/browser/extensions/user_script_listener_browsertest.cc index 528ec788..66a49a7 100644 --- a/chrome/browser/extensions/user_script_listener_browsertest.cc +++ b/chrome/browser/extensions/user_script_listener_browsertest.cc
@@ -27,8 +27,7 @@ ->GetUserScriptListener() ->SetUserScriptsNotReadyForTesting(&profile); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::TestNavigationObserver nav_observer(web_contents, 1); content::DidStartNavigationObserver start_observer(web_contents);
diff --git a/chrome/browser/extensions/user_script_world_browsertest.cc b/chrome/browser/extensions/user_script_world_browsertest.cc index f26166c43..31129e7 100644 --- a/chrome/browser/extensions/user_script_world_browsertest.cc +++ b/chrome/browser/extensions/user_script_world_browsertest.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -171,10 +170,6 @@ RendererStartupHelperFactory::GetForBrowserContext(profile()) ->ClearUserScriptWorldProperties(extension, std::move(world_id)); } - - content::WebContents* GetActiveWebContents() { - return browser()->tab_strip_model()->GetActiveWebContents(); - } }; // Tests that a user script world for an extension executed in an
diff --git a/chrome/browser/extensions/view_extension_source_browsertest.cc b/chrome/browser/extensions/view_extension_source_browsertest.cc index bb5524f..008fae966 100644 --- a/chrome/browser/extensions/view_extension_source_browsertest.cc +++ b/chrome/browser/extensions/view_extension_source_browsertest.cc
@@ -46,8 +46,7 @@ GURL bookmarks_url(chrome::kChromeUIBookmarksURL); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), bookmarks_url)); EXPECT_TRUE(chrome::CanViewSource(browser())); - content::WebContents* bookmarks_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* bookmarks_tab = GetActiveWebContents(); GURL bookmarks_extension_url = bookmarks_tab->GetPrimaryMainFrame()->GetLastCommittedURL(); EXPECT_TRUE(bookmarks_extension_url.SchemeIs(extensions::kExtensionScheme)); @@ -56,8 +55,7 @@ GURL view_source_url(content::kViewSourceScheme + std::string(":") + bookmarks_extension_url.spec()); ASSERT_TRUE(AddTabAtIndex(1, view_source_url, ui::PAGE_TRANSITION_TYPED)); - content::WebContents* view_source_tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* view_source_tab = GetActiveWebContents(); EXPECT_EQ(view_source_url, view_source_tab->GetVisibleURL()); EXPECT_EQ(bookmarks_extension_url, view_source_tab->GetPrimaryMainFrame()->GetLastCommittedURL()); @@ -72,7 +70,7 @@ ui_test_utils::TabAddedWaiter wait_for_new_tab(browser()); chrome::RestoreTab(browser()); wait_for_new_tab.Wait(); - view_source_tab = browser()->tab_strip_model()->GetActiveWebContents(); + view_source_tab = GetActiveWebContents(); EXPECT_TRUE(WaitForLoadStop(view_source_tab)); // Verify the browser-side URLs. Note that without view-source, the
diff --git a/chrome/browser/extensions/web_accessible_resources_browsertest.cc b/chrome/browser/extensions/web_accessible_resources_browsertest.cc index e72a2d1..2fd6f95 100644 --- a/chrome/browser/extensions/web_accessible_resources_browsertest.cc +++ b/chrome/browser/extensions/web_accessible_resources_browsertest.cc
@@ -346,8 +346,7 @@ resource_url.spec()); // Get the first child frame, which should be the only html child [iframe]. - auto* active_web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + auto* active_web_contents = GetActiveWebContents(); content::RenderFrameHost* first_child = content::ChildFrameAt(active_web_contents, 0); @@ -415,8 +414,7 @@ resource_url.spec()); // Get the first child frame, which should be the only html child [iframe]. - auto* active_web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + auto* active_web_contents = GetActiveWebContents(); content::RenderFrameHost* first_child = content::ChildFrameAt(active_web_contents, 0); @@ -456,7 +454,7 @@ extension->GetResourceURL("accessible.html").spec()); GURL gurl(embedded_test_server()->GetURL("an.example.org", url)); - auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + auto* web_contents = GetActiveWebContents(); content::TestNavigationObserver observer(web_contents); EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl)); observer.WaitForNavigationFinished(); @@ -483,8 +481,7 @@ // Navigate to a non-extension web page before beginning the test. This might // not be needed, but it will at the very least put the tab on a known url. { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); GURL gurl = embedded_test_server()->GetURL("example.com", "/simple.html"); content::TestNavigationObserver navigation_observer(web_contents); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl)); @@ -505,8 +502,7 @@ // in manual testing, this would succeed when the url is pasted into the // Omnibox but not when the same url is clicked from a link withing the // page. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); content::TestNavigationObserver navigation_observer(web_contents); ASSERT_TRUE(ExecJs(web_contents->GetPrimaryMainFrame(), base::StringPrintf("window.location.href = '%s';", @@ -683,7 +679,7 @@ base::StringPrintf( "/server-redirect?%s", extension->GetResourceURL(resource).spec().c_str())); - auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + auto* web_contents = GetActiveWebContents(); content::TestNavigationObserver observer(web_contents); EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl)); observer.WaitForNavigationFinished(); @@ -821,7 +817,7 @@ int expect_net_error = net::ERR_BLOCKED_BY_CLIENT; const char* resource = "inaccessible.html"; GURL gurl = embedded_test_server()->GetURL("a.example.com", "/empty.html"); - auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + auto* web_contents = GetActiveWebContents(); content::TestNavigationObserver observer(web_contents); EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), gurl)); observer.WaitForNavigationFinished(); @@ -893,10 +889,6 @@ protected: const Extension* GetExtension() { return extension_; } - content::WebContents* GetActiveWebContents() const { - return browser()->tab_strip_model()->GetActiveWebContents(); - } - content::RenderFrameHost* GetPrimaryMainFrame() const { return GetActiveWebContents()->GetPrimaryMainFrame(); }
diff --git a/chrome/browser/extensions/webstore_domain_browsertest.cc b/chrome/browser/extensions/webstore_domain_browsertest.cc index c1f7d2f..0d2fa98 100644 --- a/chrome/browser/extensions/webstore_domain_browsertest.cc +++ b/chrome/browser/extensions/webstore_domain_browsertest.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" #include "components/network_session_configurator/common/network_switches.h" @@ -83,8 +82,7 @@ const GURL webstore_url = GetParam().Resolve("/webstore/mock_store.html"); const GURL not_webstore_url = GURL(kNonWebstoreURL1).Resolve("/empty.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); auto is_api_available = [web_contents](const std::string& api_name) { constexpr char kScript[] = "chrome.hasOwnProperty($1);"; @@ -115,8 +113,7 @@ IN_PROC_BROWSER_TEST_P(WebstoreDomainBrowserTest, CanReceiveEvents) { const GURL webstore_url = GetParam().Resolve("/webstore/mock_store.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), webstore_url)); EXPECT_EQ(web_contents->GetPrimaryMainFrame()->GetLastCommittedURL(), @@ -129,8 +126,7 @@ )"; ASSERT_EQ("listener added", content::EvalJs(web_contents, kAddListener)); - content::DOMMessageQueue message_queue( - browser()->tab_strip_model()->GetActiveWebContents()); + content::DOMMessageQueue message_queue(GetActiveWebContents()); // Directly broadcast the management.onInstalled event from the EventRouter // and verify it arrived to the page without causing a crash. EventRouter* event_router = EventRouter::Get(profile()); @@ -152,8 +148,7 @@ IN_PROC_BROWSER_TEST_P(WebstoreDomainBrowserTest, FrameWebstorePageBlocked) { GURL outer_frame_url = GURL(kNonWebstoreURL1).Resolve("/empty.html"); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* web_contents = GetActiveWebContents(); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), outer_frame_url)); EXPECT_EQ(outer_frame_url, web_contents->GetLastCommittedURL());
diff --git a/chrome/browser/extensions/window_open_apitest.cc b/chrome/browser/extensions/window_open_apitest.cc index ae378ee..2308309 100644 --- a/chrome/browser/extensions/window_open_apitest.cc +++ b/chrome/browser/extensions/window_open_apitest.cc
@@ -241,9 +241,9 @@ last_loaded_extension_id() + "/test.html"); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), start_url)); WebContents* newtab = nullptr; - ASSERT_NO_FATAL_FAILURE( - OpenWindow(browser()->tab_strip_model()->GetActiveWebContents(), - start_url.Resolve("newtab.html"), true, true, &newtab)); + ASSERT_NO_FATAL_FAILURE(OpenWindow(GetActiveWebContents(), + start_url.Resolve("newtab.html"), true, + true, &newtab)); EXPECT_EQ(true, content::EvalJs(newtab, "testExtensionApi()")); } @@ -262,9 +262,9 @@ bool expect_success = false; GURL broken_extension_url( "chrome-extension://thisissurelynotavalidextensionid/newtab.html"); - ASSERT_NO_FATAL_FAILURE(OpenWindow( - browser()->tab_strip_model()->GetActiveWebContents(), - broken_extension_url, new_page_in_same_process, expect_success, &newtab)); + ASSERT_NO_FATAL_FAILURE( + OpenWindow(GetActiveWebContents(), broken_extension_url, + new_page_in_same_process, expect_success, &newtab)); EXPECT_EQ(broken_extension_url, newtab->GetPrimaryMainFrame()->GetLastCommittedURL()); @@ -283,7 +283,7 @@ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GURL("about:blank"))); WebContents* newtab = nullptr; ASSERT_NO_FATAL_FAILURE( - OpenWindow(browser()->tab_strip_model()->GetActiveWebContents(), + OpenWindow(GetActiveWebContents(), GURL(std::string(extensions::kExtensionScheme) + url::kStandardSchemeSeparator + last_loaded_extension_id() + "/newtab.html"), @@ -307,9 +307,8 @@ // test.html is not web-accessible and should not be loaded. GURL extension_url(extension->GetResourceURL("test.html")); content::CreateAndLoadWebContentsObserver windowed_observer; - ASSERT_TRUE( - content::ExecJs(browser()->tab_strip_model()->GetActiveWebContents(), - "window.open('" + extension_url.spec() + "');")); + ASSERT_TRUE(content::ExecJs(GetActiveWebContents(), + "window.open('" + extension_url.spec() + "');")); content::WebContents* newtab = windowed_observer.Wait(); ASSERT_TRUE(newtab); @@ -332,8 +331,7 @@ ASSERT_TRUE(extension); GURL extension_url(extension->GetResourceURL("test.html")); - content::WebContents* tab = - browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* tab = GetActiveWebContents(); // Navigate to the non-web-accessible URL from chrome:// and // chrome-search:// pages. Verify that the page loads correctly.
diff --git a/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsControllerRobolectricTest.java b/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsControllerRobolectricTest.java index c226b742..50723bd 100644 --- a/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsControllerRobolectricTest.java +++ b/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsControllerRobolectricTest.java
@@ -320,14 +320,13 @@ assertEquals(FOOTER, itemList.get(4).type); } + // TODO(crbug.com/433880876): Remove assertions for continue button with maybeShowContinueButton + // changes. @Test @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) - public void testPaymentAppsShown() { - // TODO REMOVE DIS? - // TODO(crbug.com/433169258): Remove dependence on Ewallets once the FOP selector header, - // footer, and additional info implementations have been updated. + public void testEwalletAndPaymentAppsShown() { mCoordinator.showSheetForPaymentLink( - List.of(EWALLET_1, EWALLET_2), List.of(PAYMENT_APP_1, PAYMENT_APP_2)); + List.of(EWALLET_1), List.of(PAYMENT_APP_1, PAYMENT_APP_2)); // Verify the screen contents set in the model when 2 payment apps exist. ModelList itemList = @@ -335,10 +334,10 @@ assertThat(itemList.size(), is(7)); assertEquals(HEADER, itemList.get(0).type); assertEquals(EWALLET, itemList.get(1).type); - assertEquals(EWALLET, itemList.get(2).type); + assertEquals(PAYMENT_APP, itemList.get(2).type); assertEquals(PAYMENT_APP, itemList.get(3).type); - assertEquals(PAYMENT_APP, itemList.get(4).type); - assertEquals(ADDITIONAL_INFO, itemList.get(5).type); + assertEquals(ADDITIONAL_INFO, itemList.get(4).type); + assertEquals(CONTINUE_BUTTON, itemList.get(5).type); assertEquals(FOOTER, itemList.get(6).type); } @@ -372,21 +371,37 @@ assertEquals(FOOTER, itemList.get(4).type); } + // TODO(crbug.com/433880876): Add assertions for continue button with maybeShowContinueButton + // changes. @Test @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) public void testSinglePaymentAppShown() { - mCoordinator.showSheetForPaymentLink(List.of(EWALLET_1), List.of(PAYMENT_APP_1)); + mCoordinator.showSheetForPaymentLink(List.of(), List.of(PAYMENT_APP_1)); // Verify the screen contents set in the model when only 1 payment app exists. ModelList itemList = mFacilitatedPaymentsPaymentMethodsModel.get(SCREEN_VIEW_MODEL).get(SCREEN_ITEMS); - assertThat(itemList.size(), is(6)); + assertThat(itemList.size(), is(4)); assertEquals(HEADER, itemList.get(0).type); - assertEquals(EWALLET, itemList.get(1).type); + assertEquals(PAYMENT_APP, itemList.get(1).type); + assertEquals(ADDITIONAL_INFO, itemList.get(2).type); + assertEquals(FOOTER, itemList.get(3).type); + } + + @Test + @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) + public void testMultiplePaymentAppsShown() { + mCoordinator.showSheetForPaymentLink(List.of(), List.of(PAYMENT_APP_1, PAYMENT_APP_2)); + // Verify the screen contents set in the model when only 1 payment app account exists. + ModelList itemList = + mFacilitatedPaymentsPaymentMethodsModel.get(SCREEN_VIEW_MODEL).get(SCREEN_ITEMS); + + assertThat(itemList.size(), is(5)); + assertEquals(HEADER, itemList.get(0).type); + assertEquals(PAYMENT_APP, itemList.get(1).type); assertEquals(PAYMENT_APP, itemList.get(2).type); assertEquals(ADDITIONAL_INFO, itemList.get(3).type); - assertEquals(CONTINUE_BUTTON, itemList.get(4).type); - assertEquals(FOOTER, itemList.get(5).type); + assertEquals(FOOTER, itemList.get(4).type); } @Test @@ -458,6 +473,61 @@ } @Test + @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) + public void testEwalletPaymentLinkGenericHeaderTitleUsed() { + mCoordinator.showSheetForPaymentLink(List.of(EWALLET_1, EWALLET_3), List.of()); + + // Verify the header model uses the generic title when multiple providers are displayed. + ModelList itemList = + mFacilitatedPaymentsPaymentMethodsModel.get(SCREEN_VIEW_MODEL).get(SCREEN_ITEMS); + PropertyModel header = itemList.get(0).model; + + assertThat(header.get(TITLE), is("Pay without switching apps")); + } + + @Test + @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) + public void testEwalletPaymentLinkSpecificHeaderTitleUsed() { + mCoordinator.showSheetForPaymentLink(List.of(EWALLET_2, EWALLET_3), List.of()); + + // Verify the header model uses the provider specific title when all eWallets use the same + // provider. + ModelList itemList = + mFacilitatedPaymentsPaymentMethodsModel.get(SCREEN_VIEW_MODEL).get(SCREEN_ITEMS); + PropertyModel header = itemList.get(0).model; + + assertThat(header.get(TITLE), is("Pay with eWalletName2 without switching apps")); + } + + @Test + @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) + public void testEwalletAndPaymentAppSpecificHeaderTitleUsed() { + mCoordinator.showSheetForPaymentLink(List.of(EWALLET_2), List.of(PAYMENT_APP_1)); + + // Verify the header model uses the provider specific title when all eWallets use the same + // provider. + ModelList itemList = + mFacilitatedPaymentsPaymentMethodsModel.get(SCREEN_VIEW_MODEL).get(SCREEN_ITEMS); + PropertyModel header = itemList.get(0).model; + + assertThat(header.get(TITLE), is("Pay instantly without QR upload")); + } + + @Test + @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) + public void testPaymentAppSpecificHeaderTitleUsed() { + mCoordinator.showSheetForPaymentLink(List.of(), List.of(PAYMENT_APP_1)); + + // Verify the header model uses the provider specific title when all eWallets use the same + // provider. + ModelList itemList = + mFacilitatedPaymentsPaymentMethodsModel.get(SCREEN_VIEW_MODEL).get(SCREEN_ITEMS); + PropertyModel header = itemList.get(0).model; + + assertThat(header.get(TITLE), is("Pay instantly without QR upload")); + } + + @Test public void testUiEventsAreForwardedToDelegate() { for (int uiEvent : Arrays.asList(
diff --git a/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsMediator.java b/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsMediator.java index a96d976..7297f69 100644 --- a/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsMediator.java +++ b/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsMediator.java
@@ -276,6 +276,48 @@ @VisibleForTesting ListItem buildPaymentLinkHeader( Context context, List<Ewallet> ewallets, List<ResolveInfo> apps) { + PropertyModel.Builder headerBuilder = new PropertyModel.Builder(HeaderProperties.ALL_KEYS); + if (!ewallets.isEmpty()) { + int productIconHeight = + (int) + context.getResources() + .getDimension( + R.dimen.facilitated_payments_gpay_icon_header_height); + headerBuilder + .with(PRODUCT_ICON_DRAWABLE_ID, R.drawable.google_pay) + .with(PRODUCT_ICON_HEIGHT, productIconHeight) + .with( + PRODUCT_ICON_CONTENT_DESCRIPTION_ID, + R.string.facilitated_payments_google_pay); + } + headerBuilder.with(TITLE, getPaymentLinkHeaderTitle(context, ewallets, apps)); + + if (ewallets.size() == 1 && !ewallets.get(0).getIsFidoEnrolled() && apps.isEmpty()) { + headerBuilder.with(SECURITY_CHECK_DRAWABLE_ID, R.drawable.security_check_illustration); + headerBuilder.with( + DESCRIPTION_ID, + R.string.ewallet_first_time_check_payment_methods_bottom_sheet_description); + } + + return new ListItem( + FacilitatedPaymentsPaymentMethodsProperties.ItemType.HEADER, headerBuilder.build()); + } + + // This method will always return a valid title, there should not be any case where eWallet and + // payment app both are not present. + private String getPaymentLinkHeaderTitle( + Context context, List<Ewallet> ewallets, List<ResolveInfo> apps) { + if (apps != null + && !apps.isEmpty() + && ChromeFeatureList.isEnabled( + ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT)) { + return context.getString( + R.string.facilitated_payments_non_card_payment_methods_bottom_sheet_title); + } + + assert ewallets != null && !ewallets.isEmpty() + : "At least a single eWallet must be present."; + // This will contain the shared ewallet name if all eWallets have the same name; // otherwise, it will contain `null`. Optional<String> sharedEwalletName = Optional.of(ewallets.get(0).getEwalletName()); @@ -285,44 +327,15 @@ break; } } - - String title; if (sharedEwalletName.isPresent()) { - title = - context.getString( - R.string - .facilitated_payments_payment_methods_bottom_sheet_detailed_title, - sharedEwalletName.get()); - } else { - title = - context.getString( - R.string - .facilitated_payments_payment_methods_bottom_sheet_generic_title); + // If all ewallets have same name, return a specific title containing that eWallet name. + return context.getString( + R.string.facilitated_payments_payment_methods_bottom_sheet_detailed_title, + sharedEwalletName.get()); } - - int productIconHeight = - (int) - context.getResources() - .getDimension(R.dimen.facilitated_payments_gpay_icon_header_height); - - PropertyModel.Builder headerBuilder = - new PropertyModel.Builder(HeaderProperties.ALL_KEYS) - .with(PRODUCT_ICON_DRAWABLE_ID, R.drawable.google_pay) - .with(PRODUCT_ICON_HEIGHT, productIconHeight) - .with( - PRODUCT_ICON_CONTENT_DESCRIPTION_ID, - R.string.facilitated_payments_google_pay) - .with(TITLE, title); - - if (ewallets.size() == 1 && !ewallets.get(0).getIsFidoEnrolled()) { - headerBuilder.with(SECURITY_CHECK_DRAWABLE_ID, R.drawable.security_check_illustration); - headerBuilder.with( - DESCRIPTION_ID, - R.string.ewallet_first_time_check_payment_methods_bottom_sheet_description); - } - - return new ListItem( - FacilitatedPaymentsPaymentMethodsProperties.ItemType.HEADER, headerBuilder.build()); + // If ewallets have different names, return a generic title. + return context.getString( + R.string.facilitated_payments_payment_methods_bottom_sheet_generic_title); } private ListItem buildPixFooter() {
diff --git a/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsViewTest.java b/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsViewTest.java index e3a53e0..df4b90f 100644 --- a/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsViewTest.java +++ b/chrome/browser/facilitated_payments/ui/android/internal/java/src/org/chromium/chrome/browser/facilitated_payments/FacilitatedPaymentsPaymentMethodsViewTest.java
@@ -9,6 +9,7 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasToString; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertNotNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; @@ -57,6 +58,9 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Features.DisableFeatures; +import org.chromium.base.test.util.Features.EnableFeatures; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.transit.ChromeTransitTestRules; @@ -80,6 +84,7 @@ /** Instrumentation tests for {@link FacilitatedPaymentsPaymentMethodsView}. */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@DisableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) public final class FacilitatedPaymentsPaymentMethodsViewTest { private static final BankAccount BANK_ACCOUNT_1 = new BankAccount.Builder() @@ -346,6 +351,69 @@ assertThat(getPaymentAppNameAt(1).getText(), is(PAYMENT_APP_2_NAME)); } + // This test checks that the header security image and header description are not shown and + // header product icon is present to user when eWallet and payment app both are available. + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) + public void testPaymentAppHeaderWhenBothEwalletAndPaymentAppAvailable() { + runOnUiThreadBlocking( + () -> { + mModel.set(SCREEN, FOP_SELECTOR); + mModel.get(SCREEN_VIEW_MODEL) + .get(SCREEN_ITEMS) + .add( + mMediator.buildPaymentLinkHeader( + mActivityTestRule.getActivity(), + List.of(EWALLET_3), + List.of(PAYMENT_APP_1))); + mModel.set(VISIBLE_STATE, SHOWN); + }); + + BottomSheetTestSupport.waitForOpen(mBottomSheetController); + + assertThat(getSheetItems().getChildCount(), is(1)); + ImageView headerSecurityCheckImage = getHeaderSecurityCheckImageAt(0); + TextView headerDescription = getHeaderDescriptionAt(0); + ImageView headerProductIcon = getHeaderProductIconAt(0); + + assertThat(headerProductIcon.getContentDescription(), is("Google Pay")); + assertThat(headerSecurityCheckImage.getVisibility(), is(View.GONE)); + assertThat(headerDescription.getVisibility(), is(View.GONE)); + } + + // This test checks that the header product icon, header security image and header description + // are not shown to user when only payment app is available. + @Test + @MediumTest + @EnableFeatures({ChromeFeatureList.FACILITATED_PAYMENTS_ENABLE_A2A_PAYMENT}) + public void + testPaymentAppProductionIconSecurtityCheckAndDescriptionNotVisibleWhenOnlyPaymentAppAvailable() { + runOnUiThreadBlocking( + () -> { + mModel.set(SCREEN, FOP_SELECTOR); + mModel.get(SCREEN_VIEW_MODEL) + .get(SCREEN_ITEMS) + .add( + mMediator.buildPaymentLinkHeader( + mActivityTestRule.getActivity(), + List.of(), + List.of(PAYMENT_APP_1))); + mModel.set(VISIBLE_STATE, SHOWN); + }); + + BottomSheetTestSupport.waitForOpen(mBottomSheetController); + + assertThat(getSheetItems().getChildCount(), is(1)); + ImageView headerSecurityCheckImage = getHeaderSecurityCheckImageAt(0); + TextView headerDescription = getHeaderDescriptionAt(0); + ImageView headerProductIcon = getHeaderProductIconAt(0); + + assertThat(headerProductIcon.getContentDescription(), nullValue()); + assertThat(headerSecurityCheckImage.getVisibility(), is(View.GONE)); + assertThat(headerDescription.getVisibility(), is(View.GONE)); + } + @Test @MediumTest public void testPixHeaderProductIconContentDescription() {
diff --git a/chrome/browser/favicon/content_favicon_driver_browsertest.cc b/chrome/browser/favicon/content_favicon_driver_browsertest.cc index 663ae94..7f36f77 100644 --- a/chrome/browser/favicon/content_favicon_driver_browsertest.cc +++ b/chrome/browser/favicon/content_favicon_driver_browsertest.cc
@@ -584,7 +584,9 @@ // have been processed in the HTML, because this is an example where Content // reports an incomplete favicon list (or, like in this test, falls back to the // default favicon.ico). -IN_PROC_BROWSER_TEST_F(ContentFaviconDriverTest, DoNotRemoveMappingIfStopped) { +// TODO: https://crbug.com/434752631 - Re-enable this test. +IN_PROC_BROWSER_TEST_F(ContentFaviconDriverTest, + DISABLED_DoNotRemoveMappingIfStopped) { ASSERT_TRUE(embedded_test_server()->Start()); GURL url = embedded_test_server()->GetURL("/favicon/slow_page_with_favicon.html");
diff --git a/chrome/browser/feedback/system_logs/log_sources/performance_log_source_unittest.cc b/chrome/browser/feedback/system_logs/log_sources/performance_log_source_unittest.cc index 9f407dd..18f0b45 100644 --- a/chrome/browser/feedback/system_logs/log_sources/performance_log_source_unittest.cc +++ b/chrome/browser/feedback/system_logs/log_sources/performance_log_source_unittest.cc
@@ -15,10 +15,10 @@ #include "chrome/browser/performance_manager/test_support/fake_power_monitor_source.h" #include "chrome/browser/performance_manager/test_support/test_user_performance_tuning_manager_environment.h" #include "chrome/test/base/browser_with_test_window_test.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/performance_manager/public/features.h" #include "components/performance_manager/public/user_tuning/prefs.h" +#include "components/prefs/pref_service.h" class QuitRunLoopOnPowerStateChangeObserver : public performance_manager::user_tuning::BatterySaverModeManager:: @@ -52,17 +52,16 @@ class PerformanceLogSourceTest : public BrowserWithTestWindowTest { public: - PerformanceLogSourceTest() - : testing_local_state_(TestingBrowserProcess::GetGlobal()) { - local_state_ = testing_local_state_.Get(); - } + PerformanceLogSourceTest() = default; PerformanceLogSourceTest(const PerformanceLogSourceTest&) = delete; PerformanceLogSourceTest& operator=(const PerformanceLogSourceTest&) = delete; ~PerformanceLogSourceTest() override = default; - void SetUp() override { environment_.SetUp(local_state_); } + void SetUp() override { + environment_.SetUp(TestingBrowserProcess::GetGlobal()->local_state()); + } void TearDown() override { environment_.TearDown(); @@ -86,7 +85,7 @@ BatterySaverModeState::kEnabled : performance_manager::user_tuning::prefs:: BatterySaverModeState::kDisabled; - local_state_->SetInteger( + TestingBrowserProcess::GetGlobal()->local_state()->SetInteger( performance_manager::user_tuning::prefs::kBatterySaverModeState, static_cast<int>(mode)); } @@ -113,10 +112,8 @@ ->RemoveObserver(observer.get()); } - ScopedTestingLocalState testing_local_state_; performance_manager::user_tuning::TestUserPerformanceTuningManagerEnvironment environment_; - raw_ptr<TestingPrefServiceSimple> local_state_ = nullptr; }; TEST_F(PerformanceLogSourceTest, CheckMemorySaverModeLogs) {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 381eaef5..87a0e10 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1736,11 +1736,6 @@ "expiry_milestone": 145 }, { - "name": "colorful-tab-group", - "owners": ["gambard@google.com", "bling-flags@google.com"], - "expiry_milestone": 140 - }, - { "name": "compare-confirmation-toast", "owners": ["mdjones@chromium.org", "meiliang@chromium.org", "chrome-shopping-eng@google.com"], "expiry_milestone": 135 @@ -1842,11 +1837,6 @@ "expiry_milestone": 150 }, { - "name": "copy-image-filename-to-clipboard", - "owners": [ "dmblack@google.com" ], - "expiry_milestone": 136 - }, - { "name": "cpa-spec-update", "owners": [ "eleanorlee@google.com", "wenyufu@chromium.org" ], "expiry_milestone": 145 @@ -1857,6 +1847,11 @@ "expiry_milestone": 145 }, { + "name": "cpe-passkey-largeblob-support", + "owners": ["rgod@google.com", "ambikaraj@google.com", "bling-transactions-eng@google.com"], + "expiry_milestone": 145 + }, + { "name": "cpe-passkey-prf-support", "owners": ["sugoi@chromium.org", "bling-transactions-eng@google.com"], "expiry_milestone": 145 @@ -2920,7 +2915,7 @@ { "name": "enable-bookmarks-selected-type-on-signin-for-testing", "owners": [ "msalama@chromium.org", "uno-desktop@google.com" ], - "expiry_milestone": 140 + "expiry_milestone": 143 }, { "name": "enable-bound-session-credentials", @@ -3542,11 +3537,6 @@ "expiry_milestone": 145 }, { - "name": "enable-fontations-backend", - "owners": [ "drott@chromium.org", "layout-dev@chromium.org" ], - "expiry_milestone": 136 - }, - { "name": "enable-force-dark", "owners": [ "beverloo@chromium.org", "pdr@chromium.org" ], // This flag enables an automatic dark mode for sites that do not support @@ -4648,7 +4638,7 @@ { "name": "enable-webusb-device-detection", "owners": [ "reillyg@chromium.org", "deviceapi-team@google.com" ], - "expiry_milestone": 140 + "expiry_milestone": 152 }, { "name": "enable-welcome-experience", @@ -4670,12 +4660,12 @@ { "name": "enable-welcome-tour", "owners": [ "//ash/user_education/welcome_tour/OWNERS" ], - "expiry_milestone": 140 + "expiry_milestone": 150 }, { "name": "enable-welcome-tour-force-user-eligibility", "owners": [ "//ash/user_education/welcome_tour/OWNERS" ], - "expiry_milestone": 140 + "expiry_milestone": 150 }, { "name": "enable-wifi-qos", @@ -4710,6 +4700,11 @@ "expiry_milestone": 140 }, { + "name": "enforce-management-disclaimer", + "owners": ["ydago@google.com", "cec-growth-eng@google.com"], + "expiry_milestone": 145 + }, + { "name": "enforce-mono-audio-capture", "owners": ["aaronyu@google.com", "chromeos-audio@google.com"], "expiry_milestone": 147 @@ -5169,7 +5164,7 @@ { "name": "fill-on-account-select", "owners": [ "kazinova@google.com", "vasilii@chromium.org" ], - "expiry_milestone": 141 + "expiry_milestone": 150 }, { "name": "fill-recovery-password", @@ -7794,7 +7789,7 @@ { "name": "password-form-clientside-classifier", "owners": ["kazinova@google.com", "vasilii@chromium.org", "chrome-password-manager-team@google.com"], - "expiry_milestone": 141 + "expiry_milestone": 146 }, { "name": "password-form-grouped-affiliations", @@ -8167,7 +8162,7 @@ { "name": "profiles-reordering", "owners": ["rsult@google.com", "chrome-signin-team@google.com"], - "expiry_milestone": 136 + "expiry_milestone": 146 }, { "name": "promise-icons", @@ -8493,7 +8488,7 @@ { "name": "reading-list-enable-sync-transport-mode-upon-sign-in", "owners": [ "mmrashad@google.com", "rsult@google.com", "uno-desktop@google.com" ], - "expiry_milestone": 141 + "expiry_milestone": 143 }, { "name": "realbox-secondary-zero-suggest", @@ -8654,11 +8649,6 @@ "expiry_milestone": 96 }, { - "name": "retain-omnibox-on-focus", - "owners": [ "dmblack@google.com", "chrome-omnibox-team@google.com" ], - "expiry_milestone": 140 - }, - { "name": "rewriter-api-for-gemini-nano", "owners": ["//chrome/browser/ai/OWNERS", "builtin-ai@chromium.org"], "expiry_milestone": 140 @@ -8964,7 +8954,7 @@ { "name": "service-worker-auto-preload", "owners": ["sisidovski@chromium.org", "chrome-worker@google.com"], - "expiry_milestone": 141 + "expiry_milestone": 144 }, { "name": "set-market-url-for-testing", @@ -9393,7 +9383,7 @@ { "name": "sync-enable-bookmarks-in-transport-mode", "owners": [ "msalama@chromium.org", "uno-desktop@google.com" ], - "expiry_milestone": 141 + "expiry_milestone": 143 }, { "name": "sync-point-graph-validation", @@ -9492,22 +9482,6 @@ "expiry_milestone": 150 }, { - "name": "tab-group-sync-android", - "owners": [ - "shaktisahu@chromium.org", - "clank-tab-dev@google.com" - ], - "expiry_milestone": 140 - }, - { - "name": "tab-group-sync-disable-network-layer", - "owners": [ - "shaktisahu@chromium.org", - "clank-tab-dev@google.com" - ], - "expiry_milestone": 140 - }, - { "name": "tab-group-sync-service-desktop-migration", "owners": [ "top-chrome-desktop-ui@google.com", "dljames@chromium.org", "dpenning@chromium.org" ], "expiry_milestone": 150
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 0b590583..b9c6128 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -334,11 +334,6 @@ const char kContentSettingsPartitioningDescription[] = "Partition content settings by StoragePartitions"; -const char kCopyImageFilenameToClipboardName[] = - "Copy image filename to clipboard."; -const char kCopyImageFilenameToClipboardDescription[] = - "Whether to write filename to the clipboard when copying image downloads."; - #if BUILDFLAG(IS_ANDROID) const char kCredentialManagementThirdPartyWebApiRequestForwardingName[] = "Credential Management Third Party Web API Request Forwarding"; @@ -2767,6 +2762,14 @@ "center on platforms where these are available."; #if BUILDFLAG(ENABLE_DICE_SUPPORT) +const char kEnforceManagementDisclaimerName[] = + "Enforce management disclaimer"; +const char kEnforceManagementDisclaimerDescription[] = + "When enabled, all signed in profiles that never saw the management " + "disclaimer will be shown the management disclaimer when they open Chrome. " + "Every time the primary signed in account changes to a managed account, " + "the management disclaimer will be shown."; + const char kOfferMigrationToDiceUsersName[] = "Offer migration to Dice users"; const char kOfferMigrationToDiceUsersDescription[] = "When enabled, offers the implicitly signed-in users a dialog to migrate " @@ -3613,18 +3616,6 @@ const char kResetShortcutCustomizationsDescription[] = "Resets all shortcut customizations on startup."; -#if BUILDFLAG(IS_ANDROID) -const char kRetainOmniboxOnFocusName[] = "Retain omnibox on focus"; -const char kRetainOmniboxOnFocusDescription[] = - "Whether the contents of the omnibox should be retained on focus as " - "opposed to being cleared. When this feature flag is enabled and the " - "omnibox contents are retained, focus events will also result in the " - "omnibox contents being fully selected so as to allow for easy replacement " - "by the user. Note that even with this feature flag enabled, only large " - "screen devices with an attached keyboard and precision pointer will " - "exhibit a change in behavior."; -#endif // BUILDFLAG(IS_ANDROID) - #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) const char kRootScrollbarFollowsTheme[] = "Make scrollbar follow theme"; const char kRootScrollbarFollowsThemeDescription[] = @@ -5347,11 +5338,6 @@ const char kHistoryPaneAndroidDescription[] = "Enables showing a new pane in the hub that displays History."; -const char kTabGroupSyncDisableNetworkLayerName[] = - "Tab Group Sync Disable Network Layer"; -const char kTabGroupSyncDisableNetworkLayerDescription[] = - "Disables network layer of tab group sync."; - const char kTabStripDensityChangeAndroidName[] = "Tab Strip Density Change"; const char kTabStripDensityChangeAndroidDescription[] = "Enables tab UI to switch to a denser layout when a peripheral(keyboard, "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 0d1783e..ed10893a 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -235,9 +235,6 @@ extern const char kContentSettingsPartitioningName[]; extern const char kContentSettingsPartitioningDescription[]; -extern const char kCopyImageFilenameToClipboardName[]; -extern const char kCopyImageFilenameToClipboardDescription[]; - #if BUILDFLAG(IS_ANDROID) extern const char kCredentialManagementThirdPartyWebApiRequestForwardingName[]; extern const char @@ -1603,6 +1600,9 @@ extern const char kNotificationsSystemFlagDescription[]; #if BUILDFLAG(ENABLE_DICE_SUPPORT) +extern const char kEnforceManagementDisclaimerName[]; +extern const char kEnforceManagementDisclaimerDescription[]; + extern const char kOfferMigrationToDiceUsersName[]; extern const char kOfferMigrationToDiceUsersDescription[]; #endif // BUILDFLAG(ENABLE_DICE_SUPPORT) @@ -2046,11 +2046,6 @@ #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || // BUILDFLAG(IS_ANDROID) -#if BUILDFLAG(IS_ANDROID) -extern const char kRetainOmniboxOnFocusName[]; -extern const char kRetainOmniboxOnFocusDescription[]; -#endif // BUILDFLAG(IS_ANDROID) - #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) extern const char kRootScrollbarFollowsTheme[]; extern const char kRootScrollbarFollowsThemeDescription[]; @@ -3095,9 +3090,6 @@ extern const char kHistoryPaneAndroidName[]; extern const char kHistoryPaneAndroidDescription[]; -extern const char kTabGroupSyncDisableNetworkLayerName[]; -extern const char kTabGroupSyncDisableNetworkLayerDescription[]; - extern const char kAndroidPinnedTabsName[]; extern const char kAndroidPinnedTabsDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 6b56a844..8252112 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -194,6 +194,7 @@ &history_clusters::internal::kJourneys, &history_clusters::internal::kOmniboxAction, &media::kAutoPictureInPictureAndroid, + &media::kContextMenuPictureInPictureAndroid, &kAccountForSuppressedKeyboardInsets, &kAdaptiveButtonInTopToolbarCustomizationV2, &kAdaptiveButtonInTopToolbarPageSummary,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 0c8428d..8b34f525 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -361,6 +361,8 @@ public static final String CONTEXTUAL_SEARCH_SUPPRESS_SHORT_VIEW = "ContextualSearchSuppressShortView"; public static final String CONTEXT_MENU_EMPTY_SPACE = "ContextMenuEmptySpace"; + public static final String CONTEXT_MENU_PICTURE_IN_PICTURE_ANDROID = + "ContextMenuPictureInPictureAndroid"; public static final String CONTEXT_MENU_TRANSLATE_WITH_GOOGLE_LENS = "ContextMenuTranslateWithGoogleLens"; public static final String CONTROLS_VISIBILITY_FROM_NAVIGATIONS = @@ -523,8 +525,6 @@ public static final String PRIVACY_SANDBOX_ADS_NOTICE_CCT = "PrivacySandboxAdsNoticeCCT"; public static final String PRIVACY_SANDBOX_AD_TOPICS_CONTENT_PARITY = "PrivacySandboxAdTopicsContentParity"; - public static final String PRIVACY_SANDBOX_RELATED_WEBSITE_SETS_UI = - "PrivacySandboxRelatedWebsiteSetsUi"; public static final String PRIVACY_SANDBOX_SENTIMENT_SURVEY = "PrivacySandboxSentimentSurvey"; public static final String PRIVACY_SANDBOX_SETTINGS_4 = "PrivacySandboxSettings4"; public static final String PROCESS_RANK_POLICY_ANDROID = "ProcessRankPolicyAndroid";
diff --git a/chrome/browser/glic/e2e_test/internal b/chrome/browser/glic/e2e_test/internal index f4ab390..f27c9a4 160000 --- a/chrome/browser/glic/e2e_test/internal +++ b/chrome/browser/glic/e2e_test/internal
@@ -1 +1 @@ -Subproject commit f4ab390c247970f942a1a850b4866c7e3ab43e69 +Subproject commit f27c9a46ebb7c3a2e484de830a1094c033e4a781
diff --git a/chrome/browser/glic/glic_zero_state_suggestions_manager.cc b/chrome/browser/glic/glic_zero_state_suggestions_manager.cc index da9e0b1..ddf909c 100644 --- a/chrome/browser/glic/glic_zero_state_suggestions_manager.cc +++ b/chrome/browser/glic/glic_zero_state_suggestions_manager.cc
@@ -97,16 +97,28 @@ pause_pinned_subscription_updates_ = false; } + // Also include the focused tab if there is one. + FocusedTabData focused_tab_data = sharing_manager_->GetFocusedTabData(); + content::WebContents* active_web_contents = + focused_tab_data.focus() ? focused_tab_data.focus()->GetContents() + : nullptr; + std::vector<content::WebContents*> contents_for_request = pinned_tab_data; + if (active_web_contents && + !Contains(contents_for_request, active_web_contents)) { + contents_for_request.push_back(active_web_contents); + } + if (contextual_cueing_service_) { // Debounce if we already have an outstanding request for the same set. std::optional<std::vector<content::WebContents*>> outstanding_pinned_tabs_contents = contextual_cueing_service_->GetOutstandingPinnedTabsContents(); if (outstanding_pinned_tabs_contents && - outstanding_pinned_tabs_contents->size() == pinned_tab_data.size() && + outstanding_pinned_tabs_contents->size() == + contents_for_request.size() && std::equal(outstanding_pinned_tabs_contents->begin(), outstanding_pinned_tabs_contents->end(), - pinned_tab_data.begin())) { + contents_for_request.begin())) { return; } @@ -116,14 +128,10 @@ MakePendingSuggestionsPtr(), mojom::ZeroStateSuggestionsOptions(is_first_run, supported_tools)); - FocusedTabData focused_tab_data = sharing_manager_->GetFocusedTabData(); - content::WebContents* active_web_contents = - focused_tab_data.focus() ? focused_tab_data.focus()->GetContents() - : nullptr; bool suggestions_pending = contextual_cueing_service_ ->GetContextualGlicZeroStateSuggestionsForPinnedTabs( - pinned_tab_data, is_first_run, supported_tools, + contents_for_request, is_first_run, supported_tools, active_web_contents, mojo::WrapCallbackWithDefaultInvokeIfNotRun( base::BindOnce(&GlicZeroStateSuggestionsManager::
diff --git a/chrome/browser/glic/host/glic_api_browsertest.cc b/chrome/browser/glic/host/glic_api_browsertest.cc index 40b61619..421b1538 100644 --- a/chrome/browser/glic/host/glic_api_browsertest.cc +++ b/chrome/browser/glic/host/glic_api_browsertest.cc
@@ -1844,6 +1844,17 @@ ExecuteJsTest(); } +IN_PROC_BROWSER_TEST_F(GlicApiTestWithOneTab, + testGetPinCandidatesWithPanelClosed) { + ExecuteJsTest(); + RunTestSequence(AddInstrumentedTab( + kSecondTab, embedded_test_server()->GetURL("/glic/test.html"))); + ContinueJsTest(); + // Opens the panel again. + RunTestSequence(ToggleGlicWindow(GlicWindowMode::kDetached)); + ContinueJsTest(); +} + class GlicGetHostCapabilityApiTest : public GlicApiTestWithOneTab, public ::testing::WithParamInterface<bool> {
diff --git a/chrome/browser/glic/widget/glic_window_hotkey_delegate_unittest.cc b/chrome/browser/glic/widget/glic_window_hotkey_delegate_unittest.cc index 60da7ee..54a712a 100644 --- a/chrome/browser/glic/widget/glic_window_hotkey_delegate_unittest.cc +++ b/chrome/browser/glic/widget/glic_window_hotkey_delegate_unittest.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -53,8 +52,7 @@ class GlicWindowHotkeyDelegateTest : public testing::Test { public: - GlicWindowHotkeyDelegateTest() - : local_state_(TestingBrowserProcess::GetGlobal()) {} + GlicWindowHotkeyDelegateTest() = default; void SetUp() override { testing::Test::SetUp(); @@ -100,7 +98,6 @@ std::unique_ptr<MockGlicView> mock_glic_view_; std::unique_ptr<GlicWindowHotkeyDelegate> delegate_; base::UserActionTester user_action_tester_; - ScopedTestingLocalState local_state_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<MockBrowserWindow> mock_browser_window_; std::unique_ptr<Browser>
diff --git a/chrome/browser/glic/widget/local_hotkey_manager_unittest.cc b/chrome/browser/glic/widget/local_hotkey_manager_unittest.cc index 3a1fc2a8..4203d2f 100644 --- a/chrome/browser/glic/widget/local_hotkey_manager_unittest.cc +++ b/chrome/browser/glic/widget/local_hotkey_manager_unittest.cc
@@ -13,9 +13,9 @@ #include "chrome/browser/glic/glic_pref_names.h" #include "chrome/browser/glic/test_support/mock_glic_window_controller.h" #include "chrome/browser/glic/widget/glic_window_controller.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" #include "components/prefs/testing_pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -115,7 +115,7 @@ class LocalHotkeyManagerTest : public testing::Test { public: - LocalHotkeyManagerTest() : local_state_(TestingBrowserProcess::GetGlobal()) {} + LocalHotkeyManagerTest() = default; void SetUp() override { mock_controller_ = std::make_unique<MockGlicWindowController>(); @@ -128,7 +128,6 @@ protected: base::test::TaskEnvironment task_environment_; - ScopedTestingLocalState local_state_; std::unique_ptr<MockGlicWindowController> mock_controller_; std::unique_ptr<LocalHotkeyManager> manager_; raw_ptr<FakeLocalHotkeyDelegate> fake_delegate_; @@ -189,7 +188,7 @@ // Change the pref to a new valid accelerator. ui::Accelerator new_focus_acc(ui::VKEY_X, ui::EF_CONTROL_DOWN); - local_state_.Get()->SetString( + TestingBrowserProcess::GetGlobal()->local_state()->SetString( prefs::kGlicFocusToggleHotkey, ui::Command::AcceleratorToString(new_focus_acc)); @@ -200,7 +199,8 @@ EXPECT_TRUE(fake_delegate_->IsRegistered(new_focus_acc)); // Change the pref to an empty string (clears the shortcut). - local_state_.Get()->SetString(prefs::kGlicFocusToggleHotkey, ""); + TestingBrowserProcess::GetGlobal()->local_state()->SetString( + prefs::kGlicFocusToggleHotkey, ""); // Should destroy the custom registration, no new one created. // Registration count remains the same as the previous step because one was @@ -221,7 +221,7 @@ // Set a valid pref. ui::Accelerator new_focus_acc(ui::VKEY_X, ui::EF_CONTROL_DOWN); - local_state_.Get()->SetString( + TestingBrowserProcess::GetGlobal()->local_state()->SetString( prefs::kGlicFocusToggleHotkey, ui::Command::AcceleratorToString(new_focus_acc)); EXPECT_EQ(LocalHotkeyManager::GetConfigurableAccelerator( @@ -229,7 +229,8 @@ new_focus_acc); // Set an invalid pref string (e.g., just a modifier). - local_state_.Get()->SetString(prefs::kGlicFocusToggleHotkey, "Ctrl"); + TestingBrowserProcess::GetGlobal()->local_state()->SetString( + prefs::kGlicFocusToggleHotkey, "Ctrl"); EXPECT_TRUE(LocalHotkeyManager::GetConfigurableAccelerator( LocalHotkeyManager::Hotkey::kFocusToggle) .IsEmpty());
diff --git a/chrome/browser/hid/chrome_hid_delegate_unittest.cc b/chrome/browser/hid/chrome_hid_delegate_unittest.cc index a043460..bad378a 100644 --- a/chrome/browser/hid/chrome_hid_delegate_unittest.cc +++ b/chrome/browser/hid/chrome_hid_delegate_unittest.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" @@ -1061,10 +1060,6 @@ profile_, GetHidConnectionTrackerTestingFactory()); return testing_profile; } - - private: - ScopedTestingLocalState testing_local_state_{ - TestingBrowserProcess::GetGlobal()}; }; class ChromeHidDelegateServiceWorkerTest
diff --git a/chrome/browser/media/webrtc/current_tab_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/current_tab_desktop_media_list_unittest.cc index cae9f84..35cbf3f 100644 --- a/chrome/browser/media/webrtc/current_tab_desktop_media_list_unittest.cc +++ b/chrome/browser/media/webrtc/current_tab_desktop_media_list_unittest.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/fake_profile_manager.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -37,6 +36,7 @@ #include "chrome/browser/ash/login/users/user_manager_delegate_impl.h" #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h" #include "chromeos/ash/components/settings/cros_settings.h" +#include "components/prefs/pref_service.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_manager_impl.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -58,8 +58,7 @@ class CurrentTabDesktopMediaListTest : public testing::Test { protected: - CurrentTabDesktopMediaListTest() - : local_state_(TestingBrowserProcess::GetGlobal()) {} + CurrentTabDesktopMediaListTest() = default; CurrentTabDesktopMediaListTest(const CurrentTabDesktopMediaListTest&) = delete; @@ -154,7 +153,6 @@ // The path to temporary directory used to contain the test operations. base::ScopedTempDir temp_dir_; - ScopedTestingLocalState local_state_; std::unique_ptr<content::RenderViewHostTestEnabler> rvh_test_enabler_; raw_ptr<Profile, DanglingUntriaged> profile_; @@ -175,7 +173,7 @@ user_manager::ScopedUserManager user_manager_{ std::make_unique<user_manager::UserManagerImpl>( std::make_unique<ash::UserManagerDelegateImpl>(), - local_state_.Get(), + TestingBrowserProcess::GetGlobal()->local_state(), ash::CrosSettings::Get())}; #endif };
diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc index e6d1e868..d06027f4 100644 --- a/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc +++ b/chrome/browser/media/webrtc/tab_desktop_media_list_unittest.cc
@@ -33,7 +33,6 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/fake_profile_manager.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" @@ -57,6 +56,7 @@ #include "chrome/browser/ash/login/users/user_manager_delegate_impl.h" #include "chrome/browser/ash/settings/scoped_cros_settings_test_helper.h" #include "chromeos/ash/components/settings/cros_settings.h" +#include "components/prefs/pref_service.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_manager_impl.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -148,9 +148,7 @@ TabDesktopMediaListTest& operator=(const TabDesktopMediaListTest&) = delete; protected: - TabDesktopMediaListTest() - : picker_called_from_web_contents_(GetParam()), - local_state_(TestingBrowserProcess::GetGlobal()) {} + TabDesktopMediaListTest() : picker_called_from_web_contents_(GetParam()) {} std::unique_ptr<content::WebContents> CreateWebContents( int favicon_greyscale) { @@ -320,7 +318,6 @@ // The path to temporary directory used to contain the test operations. base::ScopedTempDir temp_dir_; - ScopedTestingLocalState local_state_; std::unique_ptr<content::RenderViewHostTestEnabler> rvh_test_enabler_; raw_ptr<Profile, DanglingUntriaged> profile_; @@ -342,7 +339,7 @@ user_manager::ScopedUserManager user_manager_{ std::make_unique<user_manager::UserManagerImpl>( std::make_unique<ash::UserManagerDelegateImpl>(), - local_state_.Get(), + TestingBrowserProcess::GetGlobal()->local_state(), ash::CrosSettings::Get())}; #endif };
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics_unittest.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics_unittest.cc index f20ca32..1d848065 100644 --- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics_unittest.cc +++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics_unittest.cc
@@ -8,7 +8,6 @@ #include "base/test/metrics/histogram_tester.h" #include "build/build_config.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/prefs/testing_pref_service.h" #include "components/variations/variations_switches.h" @@ -83,13 +82,10 @@ // Dummy screen required by a ChromeBrowserMainExtraPartsMetrics test target. display::test::TestScreen test_screen_; - - // Scoped local state required for unit tests. - ScopedTestingLocalState local_state_; }; -ChromeBrowserMainExtraPartsMetricsTest::ChromeBrowserMainExtraPartsMetricsTest() - : local_state_(TestingBrowserProcess::GetGlobal()) { +ChromeBrowserMainExtraPartsMetricsTest:: + ChromeBrowserMainExtraPartsMetricsTest() { display::Screen::SetScreenInstance(&test_screen_); }
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor_unittest.cc b/chrome/browser/metrics/chrome_metrics_service_accessor_unittest.cc index 6115946..2be8b0f 100644 --- a/chrome/browser/metrics/chrome_metrics_service_accessor_unittest.cc +++ b/chrome/browser/metrics/chrome_metrics_service_accessor_unittest.cc
@@ -7,17 +7,15 @@ #include "build/branding_buildflags.h" #include "build/build_config.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/metrics/metrics_pref_names.h" +#include "components/prefs/pref_service.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" class ChromeMetricsServiceAccessorTest : public testing::Test { public: - ChromeMetricsServiceAccessorTest() - : testing_local_state_(TestingBrowserProcess::GetGlobal()) { - } + ChromeMetricsServiceAccessorTest() = default; ChromeMetricsServiceAccessorTest(const ChromeMetricsServiceAccessorTest&) = delete; @@ -25,12 +23,11 @@ const ChromeMetricsServiceAccessorTest&) = delete; PrefService* GetLocalState() { - return testing_local_state_.Get(); + return TestingBrowserProcess::GetGlobal()->local_state(); } private: content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState testing_local_state_; }; TEST_F(ChromeMetricsServiceAccessorTest, MetricsReportingEnabled) {
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client_unittest.cc b/chrome/browser/metrics/chrome_metrics_services_manager_client_unittest.cc index fe400d9..f5ec748 100644 --- a/chrome/browser/metrics/chrome_metrics_services_manager_client_unittest.cc +++ b/chrome/browser/metrics/chrome_metrics_services_manager_client_unittest.cc
@@ -10,12 +10,12 @@ #include "build/build_config.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/chrome_metrics_service_client.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/metrics/enabled_state_provider.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_state_manager.h" #include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" #include "components/prefs/testing_pref_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,11 +33,9 @@ ~ChromeMetricsServicesManagerClientTest() override = default; - PrefService* local_state() { return scoped_testing_local_state_.Get(); } - - private: - ScopedTestingLocalState scoped_testing_local_state_{ - TestingBrowserProcess::GetGlobal()}; + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } }; using IsClientInSampleTest = ChromeMetricsServicesManagerClientTest;
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc index da8119f..9ffccdd 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -1690,12 +1690,12 @@ per_tab_metrics.RecordPmfs(GetUkmRecorder()); #if BUILDFLAG(IS_CHROMEOS) - base::SystemMemoryInfoKB system_meminfo; + base::SystemMemoryInfo system_meminfo; if (base::GetSystemMemoryInfo(&system_meminfo)) { - int mem_used_mb = - (system_meminfo.total - system_meminfo.available) / 1024; + int64_t mem_used_mb = + (system_meminfo.total - system_meminfo.available).InMiB(); UMA_HISTOGRAM_LARGE_MEMORY_MB("Memory.System.MemAvailableMB", - system_meminfo.available / 1024); + system_meminfo.available.InMiB()); UMA_HISTOGRAM_LARGE_MEMORY_MB("Memory.System.MemUsedMB", mem_used_mb); } #endif
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 276b645a..3c02d4c3 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -52,7 +52,6 @@ #include "chrome/browser/ui/ash/session/test_session_controller.h" #include "chrome/services/sharing/nearby/decoder/advertisement_decoder.h" #include "chrome/services/sharing/public/cpp/advertisement.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" @@ -517,8 +516,8 @@ void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - fake_user_manager_.Reset( - std::make_unique<user_manager::FakeUserManager>(local_state_.Get())); + fake_user_manager_.Reset(std::make_unique<user_manager::FakeUserManager>( + TestingBrowserProcess::GetGlobal()->local_state())); profile_manager_ = std::make_unique<TestingProfileManager>( TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager_->SetUp()); @@ -1575,7 +1574,6 @@ // ChromeDownloadManagerDelegate. std::unique_ptr<net::test::MockNetworkChangeNotifier> network_notifier_; content::BrowserTaskEnvironment task_environment_; - ScopedTestingLocalState local_state_{TestingBrowserProcess::GetGlobal()}; user_manager::TypedScopedUserManager<user_manager::FakeUserManager> fake_user_manager_; raw_ptr<user_manager::User> user_ = nullptr;
diff --git a/chrome/browser/net/dns_probe_service_factory_unittest.cc b/chrome/browser/net/dns_probe_service_factory_unittest.cc index cea14a2..1a811d1 100644 --- a/chrome/browser/net/dns_probe_service_factory_unittest.cc +++ b/chrome/browser/net/dns_probe_service_factory_unittest.cc
@@ -21,10 +21,10 @@ #include "chrome/browser/net/stub_resolver_config_reader.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/common/pref_names.h" -#include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "components/error_page/common/net_error_info.h" #include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" #include "content/public/test/browser_task_environment.h" #include "mojo/public/cpp/bindings/remote.h" #include "net/dns/public/secure_dns_mode.h" @@ -44,14 +44,11 @@ public: DnsProbeServiceTest() : callback_called_(false), callback_result_(error_page::DNS_PROBE_MAX) { - local_state_ = std::make_unique<ScopedTestingLocalState>( - TestingBrowserProcess::GetGlobal()); - // SystemNetworkContextManager cannot be instantiated here, which normally // owns the StubResolverConfigReader instance, so inject a // StubResolverConfigReader instance here. - stub_resolver_config_reader_ = - std::make_unique<StubResolverConfigReader>(local_state_->Get()); + stub_resolver_config_reader_ = std::make_unique<StubResolverConfigReader>( + TestingBrowserProcess::GetGlobal()->local_state()); SystemNetworkContextManager::set_stub_resolver_config_reader_for_testing( stub_resolver_config_reader_.get()); } @@ -117,7 +114,9 @@ DnsProbeService* probe_service() const { return service_.get(); } - TestingPrefServiceSimple* local_state() { return local_state_->Get(); } + TestingPrefServiceSimple* local_state() { + return TestingBrowserProcess::GetGlobal()->GetTestingLocalState(); + } const std::string kDohTemplateGet = "https://bar.test/dns-query{?dns}"; const std::string kDohTemplatePost = "https://bar.test/dns-query"; @@ -134,7 +133,6 @@ std::unique_ptr<FakeHostResolverNetworkContext> network_context_; std::unique_ptr<FakeDnsConfigChangeManager> dns_config_change_manager_; std::unique_ptr<DnsProbeService> service_; - std::unique_ptr<ScopedTestingLocalState> local_state_; std::unique_ptr<StubResolverConfigReader> stub_resolver_config_reader_; bool callback_called_; DnsProbeStatus callback_result_;
diff --git a/chrome/browser/offline_pages/android/auto_fetch_page_load_watcher.cc b/chrome/browser/offline_pages/android/auto_fetch_page_load_watcher.cc index 308252de..95eb9a4 100644 --- a/chrome/browser/offline_pages/android/auto_fetch_page_load_watcher.cc +++ b/chrome/browser/offline_pages/android/auto_fetch_page_load_watcher.cc
@@ -361,9 +361,11 @@ } // TabModelObserver. - void TabPendingClosure(TabAndroid* tab, + void OnTabClosePending(const std::vector<TabAndroid*>& tabs, TabModel::TabClosingSource source) override { - impl_->TabClosed(tab->GetAndroidId()); + for (TabAndroid* tab : tabs) { + impl_->TabClosed(tab->GetAndroidId()); + } } // TabModelListObserver.
diff --git a/chrome/browser/page_content_annotations/page_content_annotations_service_browsertest.cc b/chrome/browser/page_content_annotations/page_content_annotations_service_browsertest.cc index 1215b814..27613a4 100644 --- a/chrome/browser/page_content_annotations/page_content_annotations_service_browsertest.cc +++ b/chrome/browser/page_content_annotations/page_content_annotations_service_browsertest.cc
@@ -1585,20 +1585,17 @@ : public PageContentAnnotationsServiceContentExtractionTest { public: void InitializeFeatureList() override { + const char* capture_delay = "5s"; +#if defined(MEMORY_SANITIZER) || defined(ADDRESS_SANITIZER) || !defined(NDEBUG) + capture_delay = "10s"; +#endif // defined(MEMORY_SANITIZER) || defined(ADDRESS_SANITIZER) || !defined(NDEBUG) scoped_feature_list_.InitAndEnableFeatureWithParameters( - features::kAnnotatedPageContentExtraction, {{"capture_delay", "4s"}}); + features::kAnnotatedPageContentExtraction, {{"capture_delay", capture_delay}}); } }; -// TODO(crbug.com/410068541): Test is slow for debug/sanitized builds. -// Reenable once timeouts are fixed. -#if defined(MEMORY_SANITIZER) || defined(ADDRESS_SANITIZER) || !defined(NDEBUG) -#define MAYBE_PdfPageCount DISABLED_PdfPageCount -#else -#define MAYBE_PdfPageCount PdfPageCount -#endif IN_PROC_BROWSER_TEST_F(PageContentAnnotationsServiceContentExtractionPdfTest, - MAYBE_PdfPageCount) { + PdfPageCount) { ukm::TestAutoSetUkmRecorder ukm_recorder; base::test::TestFuture<void> future; ukm_recorder.SetOnAddEntryCallback( @@ -1618,15 +1615,8 @@ kPdfPageCountName)); } -// TODO(crbug.com/410068541): Test is slow for debug/sanitized builds. -// Reenable once timeouts are fixed. -#if defined(MEMORY_SANITIZER) || defined(ADDRESS_SANITIZER) || !defined(NDEBUG) -#define MAYBE_TwoPdfPageLoads DISABLED_TwoPdfPageLoads -#else -#define MAYBE_TwoPdfPageLoads TwoPdfPageLoads -#endif IN_PROC_BROWSER_TEST_F(PageContentAnnotationsServiceContentExtractionPdfTest, - MAYBE_TwoPdfPageLoads) { + TwoPdfPageLoads) { ukm::TestAutoSetUkmRecorder ukm_recorder; base::test::TestFuture<void> future; ukm_recorder.SetOnAddEntryCallback(
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc index df5faf3..fb499ab 100644 --- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.cc
@@ -188,7 +188,7 @@ void ServiceWorkerPageLoadMetricsObserver::OnFirstPaintInPage( const page_load_metrics::mojom::PageLoadTiming& timing) { - if (!IsServiceWorkerControlled() || + if (!page_load_metrics::IsServiceWorkerControlled(GetDelegate()) || !page_load_metrics::WasStartedInForegroundOptionalEventInForeground( timing.paint_timing->first_paint, GetDelegate())) { return; @@ -199,7 +199,7 @@ void ServiceWorkerPageLoadMetricsObserver::OnFirstContentfulPaintInPage( const page_load_metrics::mojom::PageLoadTiming& timing) { - if (!IsServiceWorkerControlled()) { + if (!page_load_metrics::IsServiceWorkerControlled(GetDelegate())) { if (!page_load_metrics::WasStartedInForegroundOptionalEventInForeground( timing.paint_timing->first_contentful_paint, GetDelegate())) { return; @@ -288,7 +288,7 @@ GetDelegate())) { return; } - if (!IsServiceWorkerControlled()) { + if (!page_load_metrics::IsServiceWorkerControlled(GetDelegate())) { if (!page_load_metrics::IsGoogleSearchResultUrl(GetDelegate().GetUrl())) return; PAGE_LOAD_HISTOGRAM( @@ -311,7 +311,7 @@ if (!page_load_metrics::WasStartedInForegroundOptionalEventInForeground( timing.document_timing->load_event_start, GetDelegate())) return; - if (!IsServiceWorkerControlled()) { + if (!page_load_metrics::IsServiceWorkerControlled(GetDelegate())) { if (!page_load_metrics::IsGoogleSearchResultUrl(GetDelegate().GetUrl())) return; PAGE_LOAD_HISTOGRAM(internal::kHistogramNoServiceWorkerLoadSearch, @@ -328,8 +328,9 @@ void ServiceWorkerPageLoadMetricsObserver::OnFirstInputInPage( const page_load_metrics::mojom::PageLoadTiming& timing) { - if (!IsServiceWorkerControlled()) + if (!page_load_metrics::IsServiceWorkerControlled(GetDelegate())) { return; + } if (!page_load_metrics::WasStartedInForegroundOptionalEventInForeground( timing.interactive_timing->first_input_timestamp, GetDelegate())) { return; @@ -338,8 +339,9 @@ void ServiceWorkerPageLoadMetricsObserver::OnParseStart( const page_load_metrics::mojom::PageLoadTiming& timing) { - if (!IsServiceWorkerControlled()) + if (!page_load_metrics::IsServiceWorkerControlled(GetDelegate())) { return; + } if (page_load_metrics::WasStartedInForegroundOptionalEventInForeground( timing.parse_timing->parse_start, GetDelegate())) { @@ -369,8 +371,10 @@ void ServiceWorkerPageLoadMetricsObserver::OnLoadingBehaviorObserved( content::RenderFrameHost* rfh, int behavior_flags) { - if (!IsServiceWorkerControlled() || logged_ukm_event_) + if (!page_load_metrics::IsServiceWorkerControlled(GetDelegate()) || + logged_ukm_event_) { return; + } ukm::builders::PageLoad_ServiceWorkerControlled( GetDelegate().GetPageUkmSourceId()) .Record(ukm::UkmRecorder::Get()); @@ -392,8 +396,9 @@ } void ServiceWorkerPageLoadMetricsObserver::RecordTimingHistograms() { - if (!IsServiceWorkerControlled()) + if (!page_load_metrics::IsServiceWorkerControlled(GetDelegate())) { return; + } const page_load_metrics::ContentfulPaintTimingInfo& all_frames_largest_contentful_paint = @@ -426,15 +431,9 @@ RecordSubresourceLoad(); } -bool ServiceWorkerPageLoadMetricsObserver::IsServiceWorkerControlled() { - return (GetDelegate().GetMainFrameMetadata().behavior_flags & - blink::LoadingBehaviorFlag:: - kLoadingBehaviorServiceWorkerControlled) != 0; -} - bool ServiceWorkerPageLoadMetricsObserver:: IsServiceWorkerFetchHandlerSkippable() { - DCHECK(IsServiceWorkerControlled()); + DCHECK(page_load_metrics::IsServiceWorkerControlled(GetDelegate())); return (GetDelegate().GetMainFrameMetadata().behavior_flags & blink::LoadingBehaviorFlag:: kLoadingBehaviorServiceWorkerFetchHandlerSkippable) != 0; @@ -442,7 +441,7 @@ bool ServiceWorkerPageLoadMetricsObserver:: IsServiceWorkerEligibleForRaceNetworkRequest() { - CHECK(IsServiceWorkerControlled()); + CHECK(page_load_metrics::IsServiceWorkerControlled(GetDelegate())); return (GetDelegate().GetMainFrameMetadata().behavior_flags & blink::LoadingBehaviorFlag:: kLoadingBehaviorServiceWorkerRaceNetworkRequest);
diff --git a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h index f6d01f5..bfc9e6fe 100644 --- a/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/service_worker_page_load_metrics_observer.h
@@ -92,7 +92,6 @@ private: void RecordTimingHistograms(); - bool IsServiceWorkerControlled(); bool IsServiceWorkerFetchHandlerSkippable(); bool IsServiceWorkerEligibleForRaceNetworkRequest(); void RecordSubresourceLoad();
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/BUILD.gn b/chrome/browser/password_manager/android/grouped_affiliations/BUILD.gn index 081f0bc4..5d0a2c5 100644 --- a/chrome/browser/password_manager/android/grouped_affiliations/BUILD.gn +++ b/chrome/browser/password_manager/android/grouped_affiliations/BUILD.gn
@@ -104,6 +104,7 @@ "//components/browser_ui/bottomsheet/android:factory_java", "//components/browser_ui/bottomsheet/android:java", "//components/browser_ui/bottomsheet/android:manager_java", + "//components/browser_ui/bottomsheet/android/internal:java", "//components/browser_ui/theme/android:java_resources", "//third_party/jni_zero:jni_zero_java", "//third_party/junit",
diff --git a/chrome/browser/password_manager/android/grouped_affiliations/java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetModuleTest.java b/chrome/browser/password_manager/android/grouped_affiliations/java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetModuleTest.java index 802b3a91..1115f24 100644 --- a/chrome/browser/password_manager/android/grouped_affiliations/java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetModuleTest.java +++ b/chrome/browser/password_manager/android/grouped_affiliations/java/src/org/chromium/chrome/browser/grouped_affiliations/AcknowledgeGroupedCredentialSheetModuleTest.java
@@ -27,7 +27,6 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.Batch; -import org.chromium.base.test.util.DisabledTest; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerFactory; @@ -39,7 +38,6 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) @Batch(Batch.PER_CLASS) -@DisabledTest(message = "https://crbug.com/433898136") public class AcknowledgeGroupedCredentialSheetModuleTest { @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); @Mock private AcknowledgeGroupedCredentialSheetBridge.Natives mBridgeJniMock;
diff --git a/chrome/browser/performance_manager/metrics/metrics_provider_common.cc b/chrome/browser/performance_manager/metrics/metrics_provider_common.cc index fa64a10..f55ead18 100644 --- a/chrome/browser/performance_manager/metrics/metrics_provider_common.cc +++ b/chrome/browser/performance_manager/metrics/metrics_provider_common.cc
@@ -17,10 +17,6 @@ uint64_t kBytesPerMb = 1024 * 1024; -#if BUILDFLAG(IS_MAC) -uint64_t kKilobytesPerMb = 1024; -#endif - ui::AXMode::ModeFlagHistogramValue ModeFlagsToEnum(uint32_t mode_flags) { switch (mode_flags) { case ui::AXMode::kNativeAPIs: @@ -80,18 +76,13 @@ available_bytes * 100 / total_bytes); #if BUILDFLAG(IS_MAC) - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; if (base::GetSystemMemoryInfo(&info)) { base::UmaHistogramMemoryLargeMB( - "Memory.Experimental.MacFileBackedMemoryMB2", - info.file_backed / kKilobytesPerMb); - // `info.file_backed` is in kb, so multiply it by 1024 to get the amount of - // bytes + "Memory.Experimental.MacFileBackedMemoryMB2", info.file_backed.InMiB()); base::UmaHistogramPercentage( "Memory.Experimental.MacAvailableMemoryPercentFreePageCache2", - (available_bytes + - (base::checked_cast<uint64_t>(info.file_backed) * 1024u)) * - 100u / total_bytes); + (available_bytes + info.file_backed.InBytes()) * 100u / total_bytes); } #endif }
diff --git a/chrome/browser/performance_manager/policies/background_tab_loading_policy.cc b/chrome/browser/performance_manager/policies/background_tab_loading_policy.cc index 4a93348..10f322c3 100644 --- a/chrome/browser/performance_manager/policies/background_tab_loading_policy.cc +++ b/chrome/browser/performance_manager/policies/background_tab_loading_policy.cc
@@ -150,7 +150,11 @@ base::RepeatingClosure all_restored_tabs_loaded_callback) : all_restored_tabs_loaded_callback_( std::move(all_restored_tabs_loaded_callback)), - page_loader_(std::make_unique<mechanism::PageLoader>()) { + page_loader_(std::make_unique<mechanism::PageLoader>()), + memory_pressure_listener_( + FROM_HERE, + base::BindRepeating(&BackgroundTabLoadingPolicy::OnMemoryPressure, + base::Unretained(this))) { DCHECK(!g_background_tab_loading_policy); g_background_tab_loading_policy = this; max_simultaneous_tab_loads_ = CalculateMaxSimultaneousTabLoads( @@ -165,14 +169,12 @@ void BackgroundTabLoadingPolicy::OnPassedToGraph(Graph* graph) { graph->AddPageNodeObserver(this); - graph->AddSystemNodeObserver(this); graph->GetNodeDataDescriberRegistry()->RegisterDescriber(this, kDescriberName); } void BackgroundTabLoadingPolicy::OnTakenFromGraph(Graph* graph) { graph->GetNodeDataDescriberRegistry()->UnregisterDescriber(this); - graph->RemoveSystemNodeObserver(this); graph->RemovePageNodeObserver(this); }
diff --git a/chrome/browser/performance_manager/policies/background_tab_loading_policy.h b/chrome/browser/performance_manager/policies/background_tab_loading_policy.h index e4aac67..9b3cab3 100644 --- a/chrome/browser/performance_manager/policies/background_tab_loading_policy.h +++ b/chrome/browser/performance_manager/policies/background_tab_loading_policy.h
@@ -36,8 +36,7 @@ // background tab loading at all times. class BackgroundTabLoadingPolicy : public GraphOwned, public NodeDataDescriberDefaultImpl, - public PageNodeObserver, - public SystemNodeObserver { + public PageNodeObserver { public: // `all_restored_tabs_loaded_callback` is invoked when all tabs passed to // ScheduleLoadForRestoredTabs() are loaded. @@ -131,9 +130,8 @@ base::Value::Dict DescribeSystemNodeData( const SystemNode* node) const override; - // SystemNodeObserver: void OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel new_level) override; + base::MemoryPressureListener::MemoryPressureLevel new_level); // Returns the SiteDataReader instance for |page_node|, if any. Virtual for // testing. @@ -218,6 +216,8 @@ // The mechanism used to load the pages. std::unique_ptr<performance_manager::mechanism::PageLoader> page_loader_; + base::MemoryPressureListener memory_pressure_listener_; + // The set of PageNodes that have been restored for which we need to schedule // loads. std::vector<std::unique_ptr<PageNodeToLoadData>> page_nodes_to_load_;
diff --git a/chrome/browser/performance_manager/policies/background_tab_loading_policy_unittest.cc b/chrome/browser/performance_manager/policies/background_tab_loading_policy_unittest.cc index 0a1110e..285293e 100644 --- a/chrome/browser/performance_manager/policies/background_tab_loading_policy_unittest.cc +++ b/chrome/browser/performance_manager/policies/background_tab_loading_policy_unittest.cc
@@ -570,8 +570,9 @@ ::testing::Mock::VerifyAndClear(loader()); // Simulate memory pressure and expect the tab loader to disable loading. - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); + task_env().RunUntilIdle(); PageNodeImpl* page_node_impl = page_nodes[0].get();
diff --git a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc index e96e938..87e3b22 100644 --- a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc +++ b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc
@@ -37,13 +37,16 @@ } // namespace -UrgentPageDiscardingPolicy::UrgentPageDiscardingPolicy() = default; +UrgentPageDiscardingPolicy::UrgentPageDiscardingPolicy() + : memory_pressure_listener_( + FROM_HERE, + base::BindRepeating(&UrgentPageDiscardingPolicy::OnMemoryPressure, + base::Unretained(this))) {} UrgentPageDiscardingPolicy::~UrgentPageDiscardingPolicy() = default; void UrgentPageDiscardingPolicy::OnPassedToGraph(Graph* graph) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!handling_memory_pressure_notification_); - graph->AddSystemNodeObserver(this); DCHECK(PageDiscardingHelper::GetFromGraph(graph)) << "A PageDiscardingHelper instance should be registered against the " "graph in order to use this policy."; @@ -51,7 +54,6 @@ void UrgentPageDiscardingPolicy::OnTakenFromGraph(Graph* graph) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - graph->RemoveSystemNodeObserver(this); } #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h index a8dbd11..101c743 100644 --- a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h +++ b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h
@@ -19,8 +19,7 @@ namespace policies { // Urgently discard a tab when receiving a memory pressure signal. -class UrgentPageDiscardingPolicy : public GraphOwned, - public SystemNodeObserver { +class UrgentPageDiscardingPolicy : public GraphOwned { public: UrgentPageDiscardingPolicy(); ~UrgentPageDiscardingPolicy() override; @@ -36,9 +35,8 @@ static void DisableForTesting(); private: - // SystemNodeObserver: void OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel new_level) override; + base::MemoryPressureListener::MemoryPressureLevel new_level); // Callback called when a discard attempt has completed. void PostDiscardAttemptCallback(bool success); @@ -50,6 +48,8 @@ std::optional<memory_pressure::ReclaimTarget> reclaim_target_kb); #endif // BUILDFLAG(IS_CHROMEOS) + base::MemoryPressureListener memory_pressure_listener_; + // True while we are in the process of discarding tab(s) in response to a // memory pressure notification. It becomes false once we're done responding // to this notification.
diff --git a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc index 9cc44f15..a514d9d9 100644 --- a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc +++ b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc
@@ -53,7 +53,7 @@ .WillOnce( ::testing::DoAll(::testing::Invoke(&run_loop, &base::RunLoop::Quit), ::testing::Return(true))); - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MemoryPressureLevel:: MEMORY_PRESSURE_LEVEL_CRITICAL); run_loop.Run(); @@ -68,7 +68,7 @@ ::testing::DoAll(::testing::Invoke(&run_loop2, &base::RunLoop::Quit), ::testing::Return(true))); DiscardEligibilityPolicy::RemovesDiscardAttemptMarkerForTesting(page_node()); - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MemoryPressureLevel:: MEMORY_PRESSURE_LEVEL_CRITICAL); run_loop2.Run(); @@ -77,7 +77,7 @@ TEST_F(UrgentPageDiscardingPolicyTest, NoDiscardOnModeratePressure) { // No tab should be discarded on moderate pressure. - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MemoryPressureLevel:: MEMORY_PRESSURE_LEVEL_MODERATE); task_env().RunUntilIdle();
diff --git a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.cc b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.cc index 27f4a89..8f1fae3 100644 --- a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.cc +++ b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.cc
@@ -71,16 +71,15 @@ // Only handle the memory pressure notifications if the feature to swap on // moderate pressure is enabled. if (config_->swap_on_moderate_pressure) { - graph->AddSystemNodeObserver(this); + memory_pressure_listener_.emplace( + FROM_HERE, base::BindRepeating(&UserspaceSwapPolicy::OnMemoryPressure, + base::Unretained(this))); } } void UserspaceSwapPolicy::OnTakenFromGraph(Graph* graph) { - if (config_->swap_on_moderate_pressure) { - graph->RemoveSystemNodeObserver(this); - } - graph->RemoveProcessNodeObserver(this); + memory_pressure_listener_.reset(); } void UserspaceSwapPolicy::OnAllFramesInProcessFrozen(
diff --git a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h index 0f00794..f2cd887 100644 --- a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h +++ b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_USERSPACE_SWAP_POLICY_CHROMEOS_H_ #define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_USERSPACE_SWAP_POLICY_CHROMEOS_H_ +#include <optional> + #include "base/memory/memory_pressure_listener.h" #include "base/memory/raw_ref.h" #include "base/memory/weak_ptr.h" @@ -13,7 +15,6 @@ #include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h" #include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/graph/process_node.h" -#include "components/performance_manager/public/graph/system_node.h" namespace ash { namespace memory { @@ -28,9 +29,7 @@ // UserspaceSwapPolicy is a policy which will trigger a renderer to swap itself // via userspace. -class UserspaceSwapPolicy : public GraphOwned, - public ProcessNodeObserver, - public SystemNodeObserver { +class UserspaceSwapPolicy : public GraphOwned, public ProcessNodeObserver { public: UserspaceSwapPolicy(); @@ -48,10 +47,6 @@ void OnProcessNodeAdded(const ProcessNode* process_node) override; void OnProcessLifetimeChange(const ProcessNode* process_node) override; - // SystemNodeObserver: - void OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel new_level) override; - // Returns true if running on a platform that supports the kernel features // necessary for userspace swapping, most important would be userfaultfd(2). static bool UserspaceSwapSupportedAndEnabled(); @@ -103,11 +98,16 @@ uint64_t backing_store_available_bytes_ = 0; private: + void OnMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel new_level); + // A helper method which sets the last trim time to the specified time. void SetLastSwapTime(const ProcessNode* process_node, base::TimeTicks time); void PrintAllSwapMetrics(); + std::optional<base::MemoryPressureListener> memory_pressure_listener_; + std::unique_ptr<base::RepeatingTimer> metrics_timer_ = std::make_unique<base::RepeatingTimer>();
diff --git a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos_unittest.cc b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos_unittest.cc index db695d56..2b10862 100644 --- a/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos_unittest.cc +++ b/chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos_unittest.cc
@@ -228,7 +228,7 @@ // Triger memory pressure and we should observe the walk since we've never // walked before. - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); auto initial_walk_time = base::TimeTicks::Now(); FastForwardBy(base::Seconds(1)); @@ -238,7 +238,7 @@ // don't walk again even when we receive another moderate pressure // notification. FastForwardBy(base::Seconds(1)); - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); // Since it's been less than the graph walk frequency we don't expect to walk. ASSERT_EQ(initial_walk_time, policy()->get_last_graph_walk()); @@ -246,7 +246,7 @@ // Finally we will advance by a graph walk frequency and confirm we walk // again. FastForwardBy(policy()->config().graph_walk_frequency); - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); FastForwardBy(base::Seconds(1)); @@ -271,7 +271,7 @@ EXPECT_CALL(*policy(), SwapProcessNode(process_node().get())).Times(0); // Trigger moderate memory pressure to start the graph walk. - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); FastForwardBy(base::Seconds(1)); } @@ -291,7 +291,7 @@ EXPECT_CALL(*policy(), SwapProcessNode(process_node().get())).Times(1); // Trigger moderate memory pressure to start the graph walk. - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); FastForwardBy(base::Seconds(1)); } @@ -399,7 +399,7 @@ // swap. for (int i = 0; i < 3; ++i) { FastForwardBy(policy()->config().graph_walk_frequency); - system_node()->OnMemoryPressureForTesting( + base::MemoryPressureListener::SimulatePressureNotification( base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); } }
diff --git a/chrome/browser/prefs/BUILD.gn b/chrome/browser/prefs/BUILD.gn index 414d4f3..cfaf7dd 100644 --- a/chrome/browser/prefs/BUILD.gn +++ b/chrome/browser/prefs/BUILD.gn
@@ -308,6 +308,7 @@ "//chrome/browser/ui/tabs", "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/ui/tabs/organization", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/views/side_panel", "//chrome/browser/user_education", "//components/headless/policy",
diff --git a/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc b/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc index d6848c1..00f2493c 100644 --- a/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc +++ b/chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/preloading/bookmarkbar_preload/bookmarkbar_preload_pipeline.h" #include "base/metrics/histogram_functions.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/preloading/chrome_preloading.h" #include "chrome/browser/preloading/preloading_features.h" #include "chrome/browser/preloading/prerender/prerender_utils.h" @@ -50,6 +51,11 @@ bool BookmarkBarPreloadPipeline::StartPrerender( content::WebContents& web_contents, content::PreloadingPredictor predictor) { + if (base::FeatureList::IsEnabled( + features::kBookmarkTriggerForPrerender2KillSwitch)) { + return false; + } + // Helpers to create content::PreloadingAttempt. auto* preloading_data = content::PreloadingData::GetOrCreateForWebContents(&web_contents);
diff --git a/chrome/browser/privacy_budget/privacy_budget_browsertest.cc b/chrome/browser/privacy_budget/privacy_budget_browsertest.cc index 5069b23..40ef3ab 100644 --- a/chrome/browser/privacy_budget/privacy_budget_browsertest.cc +++ b/chrome/browser/privacy_budget/privacy_budget_browsertest.cc
@@ -662,7 +662,13 @@ } // namespace -IN_PROC_BROWSER_TEST_F(PrivacyBudgetGroupConfigBrowserTest, LoadsAGroup) { +// TODO(https://crbug.com/385000599): Flaky on linux-chromeos-rel builder. +#if BUILDFLAG(IS_CHROMEOS) +#define MAYBE_LoadsAGroup DISABLED_LoadsAGroup +#else +#define MAYBE_LoadsAGroup LoadsAGroup +#endif +IN_PROC_BROWSER_TEST_F(PrivacyBudgetGroupConfigBrowserTest, MAYBE_LoadsAGroup) { EXPECT_TRUE(base::FeatureList::IsEnabled(features::kIdentifiabilityStudy)); const auto* settings = blink::IdentifiabilityStudySettings::Get();
diff --git a/chrome/browser/private_network_access/local_network_access_browsertest.cc b/chrome/browser/private_network_access/local_network_access_browsertest.cc index 1b97ca71..6349fad4 100644 --- a/chrome/browser/private_network_access/local_network_access_browsertest.cc +++ b/chrome/browser/private_network_access/local_network_access_browsertest.cc
@@ -40,6 +40,9 @@ constexpr char kSharedWorkerHtmlPath[] = "/private_network_access/fetch-from-shared-worker-as-public-address.html"; +constexpr char kServiceWorkerHtmlPath[] = + "/private_network_access/fetch-from-service-worker-as-public-address.html"; + class LocalNetworkAccessBrowserTest : public policy::PolicyTest { public: using WebFeature = blink::mojom::WebFeature; @@ -228,7 +231,8 @@ EXPECT_TRUE(nav_manager.was_successful()); } -IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, WorkerDenyPermission) { +IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, + DedicatedWorkerDenyPermission) { ASSERT_TRUE(content::NavigateToURL( web_contents(), https_server().GetURL("a.com", kWorkerHtmlPath))); @@ -242,9 +246,12 @@ EXPECT_EQ("TypeError: Failed to fetch", content::EvalJs(web_contents(), content::JsReplace(script_template, fetch_url))); + CheckCounter(WebFeature::kPrivateNetworkAccessWithinWorker, 1); + CheckCounter(WebFeature::kLocalNetworkAccessWithinDedicatedWorker, 1); } -IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, WorkerAcceptPermission) { +IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, + DedicatedWorkerAcceptPermission) { ASSERT_TRUE(content::NavigateToURL( web_contents(), https_server().GetURL("a.com", kWorkerHtmlPath))); @@ -258,6 +265,86 @@ EXPECT_EQ("Access-Control-Allow-Origin: *", content::EvalJs(web_contents(), content::JsReplace(script_template, fetch_url))); + + CheckCounter(WebFeature::kPrivateNetworkAccessWithinWorker, 1); + CheckCounter(WebFeature::kLocalNetworkAccessWithinDedicatedWorker, 1); +} + +// TODO(crbug.com/406991278): Adding counters for LNA accesses within workers in +// third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc +// works for shared and dedicated workers, but operates oddly for service +// workers: +// +// * It counts the initial load of the service worker JS file +// * It doesn't count LNA requests without permission +// * It does count LNA request with permission (the AllowPermission test below) +// * Trying to check the count via CheckCounter() or WebFeatureHistogramTester +// does not work. +// +// Figure out how to add use counters for service worker fetches. +IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, + ServiceWorkerNoPermissionSet) { + ASSERT_TRUE(content::NavigateToURL( + web_contents(), https_server().GetURL("a.com", kServiceWorkerHtmlPath))); + + // Enable auto-accept of LNA permission requests (which shouldn't be checked). + bubble_factory()->set_response_type( + permissions::PermissionRequestManager::AutoResponseType::ACCEPT_ALL); + + EXPECT_EQ("ready", content::EvalJs(web_contents(), "setup();")); + GURL fetch_url = https_server().GetURL("b.com", kLnaPath); + std::string_view script_template = "fetch_from_service_worker($1);"; + // Failure to fetch URL, as for service workers the permission is only + // checked; if its not present we don't pop up a permission prompt. + // + // See the comment in + // StoragePartitionImpl::OnLocalNetworkAccessPermissionRequired for + // Context::kServiceWorker for more context. + EXPECT_EQ("TypeError: Failed to fetch", + content::EvalJs(web_contents(), + content::JsReplace(script_template, fetch_url))); +} + +IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, + ServiceWorkerDenyPermission) { + // Use enterprise policy to block LNA requests + policy::PolicyMap policies; + base::Value::List blocklist; + blocklist.Append(base::Value("*")); + SetPolicy(&policies, policy::key::kLocalNetworkAccessBlockedForUrls, + base::Value(std::move(blocklist))); + UpdateProviderPolicy(policies); + ASSERT_TRUE(content::NavigateToURL( + web_contents(), https_server().GetURL("a.com", kServiceWorkerHtmlPath))); + + EXPECT_EQ("ready", content::EvalJs(web_contents(), "setup();")); + GURL fetch_url = https_server().GetURL("b.com", kLnaPath); + std::string_view script_template = "fetch_from_service_worker($1);"; + // Failure to fetch URL. + EXPECT_EQ("TypeError: Failed to fetch", + content::EvalJs(web_contents(), + content::JsReplace(script_template, fetch_url))); +} + +IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, + ServiceWorkerAllowPermission) { + // Use enterprise policy to allow LNA requests + policy::PolicyMap policies; + base::Value::List allowlist; + allowlist.Append(base::Value("*")); + SetPolicy(&policies, policy::key::kLocalNetworkAccessAllowedForUrls, + base::Value(std::move(allowlist))); + UpdateProviderPolicy(policies); + ASSERT_TRUE(content::NavigateToURL( + web_contents(), https_server().GetURL("a.com", kServiceWorkerHtmlPath))); + + EXPECT_EQ("ready", content::EvalJs(web_contents(), "setup();")); + GURL fetch_url = https_server().GetURL("b.com", kLnaPath); + std::string_view script_template = "fetch_from_service_worker($1);"; + // Fetched URL + EXPECT_EQ("Access-Control-Allow-Origin: *", + content::EvalJs(web_contents(), + content::JsReplace(script_template, fetch_url))); } IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, @@ -275,6 +362,8 @@ EXPECT_EQ("TypeError: Failed to fetch", content::EvalJs(web_contents(), content::JsReplace(script_template, fetch_url))); + CheckCounter(WebFeature::kPrivateNetworkAccessWithinWorker, 1); + CheckCounter(WebFeature::kLocalNetworkAccessWithinSharedWorker, 1); } // Known to not work. See crbug.com/434744665. @@ -299,6 +388,8 @@ EXPECT_EQ("TypeError: Failed to fetch", content::EvalJs(web_contents(), content::JsReplace(script_template, fetch_url))); + CheckCounter(WebFeature::kPrivateNetworkAccessWithinWorker, 1); + CheckCounter(WebFeature::kLocalNetworkAccessWithinSharedWorker, 1); } IN_PROC_BROWSER_TEST_F(LocalNetworkAccessBrowserTest, @@ -611,6 +702,10 @@ ASSERT_TRUE(content::NavigateToURL(web_contents(), interceptor.EnabledHttpWorkerUrl())); + EXPECT_EQ(feature_histogram_tester.GetCount( + WebFeature:: + kLocalNetworkAccessNonSecureContextAllowedDeprecationTrial), + 1); // Enable auto-accept of LNA permission request. bubble_factory()->set_response_type(
diff --git a/chrome/browser/profiles/BUILD.gn b/chrome/browser/profiles/BUILD.gn index 42760c6f..6eaa8189 100644 --- a/chrome/browser/profiles/BUILD.gn +++ b/chrome/browser/profiles/BUILD.gn
@@ -231,6 +231,7 @@ "//chrome/browser/affiliations", "//chrome/browser/ai", "//chrome/browser/autocomplete", + "//chrome/browser/autocomplete:aim_eligibility_service", "//chrome/browser/autofill", "//chrome/browser/background", "//chrome/browser/bitmap_fetcher", @@ -337,6 +338,7 @@ "//chrome/browser/ui/media_router", "//chrome/browser/ui/performance_controls", "//chrome/browser/ui/tabs/organization", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/views/side_panel", "//chrome/browser/ui/webui/signin", "//chrome/browser/ui/webui/signin:login",
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc index ea4b262..f062bf7 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/accessibility/page_colors_factory.h" #include "chrome/browser/affiliations/affiliation_service_factory.h" #include "chrome/browser/ai/ai_data_keyed_service_factory.h" +#include "chrome/browser/autocomplete/aim_eligibility_service_factory.h" #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" #include "chrome/browser/autocomplete/document_suggestions_service_factory.h" #include "chrome/browser/autocomplete/in_memory_url_index_factory.h" @@ -671,6 +672,7 @@ #endif AffiliationServiceFactory::GetInstance(); AiDataKeyedServiceFactory::GetInstance(); + AimEligibilityServiceFactory::GetInstance(); #if BUILDFLAG(IS_ANDROID) AndroidSmsOtpBackendFactory::GetInstance(); #endif
diff --git a/chrome/browser/resources/ash/print_preview/ui/destination_dropdown_cros.ts b/chrome/browser/resources/ash/print_preview/ui/destination_dropdown_cros.ts index 35b5a0d..9ab7f51 100644 --- a/chrome/browser/resources/ash/print_preview/ui/destination_dropdown_cros.ts +++ b/chrome/browser/resources/ash/print_preview/ui/destination_dropdown_cros.ts
@@ -236,6 +236,8 @@ } break; } + default: + break; } }
diff --git a/chrome/browser/resources/ash/print_preview/ui/searchable_drop_down_cros.ts b/chrome/browser/resources/ash/print_preview/ui/searchable_drop_down_cros.ts index 9806f01..3d9d65c 100644 --- a/chrome/browser/resources/ash/print_preview/ui/searchable_drop_down_cros.ts +++ b/chrome/browser/resources/ash/print_preview/ui/searchable_drop_down_cros.ts
@@ -349,6 +349,8 @@ event.preventDefault(); break; } + default: + break; } }
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/ax_annotations_section.ts b/chrome/browser/resources/ash/settings/os_a11y_page/ax_annotations_section.ts index 07faced..58a64b9 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/ax_annotations_section.ts +++ b/chrome/browser/resources/ash/settings/os_a11y_page/ax_annotations_section.ts
@@ -16,7 +16,7 @@ import {PrefsMixin} from '/shared/settings/prefs/prefs_mixin.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {WebUiListenerMixin} from 'chrome://resources/ash/common/cr_elements/web_ui_listener_mixin.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -84,13 +84,15 @@ this.i18n('mainNodeAnnotationsDownloadingLabel'); case ScreenAiInstallStatus.DOWNLOAD_FAILED: return this.i18n('mainNodeAnnotationsDownloadErrorLabel'); + // Show the default subtitle if downloading is done. + // fallthrough case ScreenAiInstallStatus.DOWNLOADED: - // Show the default subtitle if downloading is done. - // fallthrough case ScreenAiInstallStatus.NOT_DOWNLOADED: // No subtitle update, so show a generic subtitle describing main node // annotations. return this.i18n('mainNodeAnnotationsSubtitle'); + default: + assertNotReached(); } } }
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_actions_add_dialog.ts b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_actions_add_dialog.ts index 25e25d4..0e27069 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_actions_add_dialog.ts +++ b/chrome/browser/resources/ash/settings/os_a11y_page/facegaze_actions_add_dialog.ts
@@ -349,6 +349,8 @@ case 'meta': newKeyCombination.modifiers!.search = true; break; + default: + break; } }); }
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/switch_access_action_assignment_pane.ts b/chrome/browser/resources/ash/settings/os_a11y_page/switch_access_action_assignment_pane.ts index 2d0516d7..34a107a7 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/switch_access_action_assignment_pane.ts +++ b/chrome/browser/resources/ash/settings/os_a11y_page/switch_access_action_assignment_pane.ts
@@ -238,6 +238,8 @@ case AssignmentState.WARN_CANNOT_REMOVE_LAST_SELECT_SWITCH: this.fireExitPane_(); break; + default: + break; } }
diff --git a/chrome/browser/resources/ash/settings/os_a11y_page/switch_access_setup_guide_dialog.ts b/chrome/browser/resources/ash/settings/os_a11y_page/switch_access_setup_guide_dialog.ts index 4c10659..e5336b9 100644 --- a/chrome/browser/resources/ash/settings/os_a11y_page/switch_access_setup_guide_dialog.ts +++ b/chrome/browser/resources/ash/settings/os_a11y_page/switch_access_setup_guide_dialog.ts
@@ -306,6 +306,9 @@ break; case SetupPageId.ASSIGN_PREVIOUS: action = SwitchAccessCommand.PREVIOUS; + break; + default: + break; } if (action) {
diff --git a/chrome/browser/resources/ash/settings/os_about_page/about_page_browser_proxy.ts b/chrome/browser/resources/ash/settings/os_about_page/about_page_browser_proxy.ts index 0f5abc4..8a2a0d41 100644 --- a/chrome/browser/resources/ash/settings/os_about_page/about_page_browser_proxy.ts +++ b/chrome/browser/resources/ash/settings/os_about_page/about_page_browser_proxy.ts
@@ -7,6 +7,7 @@ * the browser. */ +import {assertNotReached} from 'chrome://resources/js/assert.js'; import {sendWithPromise} from 'chrome://resources/js/cr.js'; export interface RegulatoryInfo { @@ -110,6 +111,8 @@ return 'aboutChannelLongTermSupportCandidate'; case BrowserChannel.LTS: return 'aboutChannelLongTermSupport'; + default: + assertNotReached(); } }
diff --git a/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts b/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts index 5d2760f..a2e9501 100644 --- a/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts +++ b/chrome/browser/resources/ash/settings/os_people_page/lock_screen_subpage.ts
@@ -515,6 +515,8 @@ case ConfigureResult.kFatalError: console.error('Error configuring recovery'); return; + default: + break; } } finally { this.recoveryChangeInProcess_ = false;
diff --git a/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts b/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts index 7d618419..8e5cacf 100644 --- a/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts +++ b/chrome/browser/resources/ash/settings/os_people_page/password_settings.ts
@@ -160,6 +160,8 @@ case ConfigureResult.kFatalError: console.error('Error removing Password'); break; + default: + break; } }
diff --git a/chrome/browser/resources/ash/settings/os_people_page/pin_settings.ts b/chrome/browser/resources/ash/settings/os_people_page/pin_settings.ts index 2e916df..ff983c6 100644 --- a/chrome/browser/resources/ash/settings/os_people_page/pin_settings.ts +++ b/chrome/browser/resources/ash/settings/os_people_page/pin_settings.ts
@@ -247,6 +247,8 @@ case ConfigureResult.kFatalError: console.error('Error removing PIN'); break; + default: + break; } // We always close the "more" menu, even when removePin call didn't work:
diff --git a/chrome/browser/resources/ash/settings/os_people_page/set_local_password_dialog.ts b/chrome/browser/resources/ash/settings/os_people_page/set_local_password_dialog.ts index 2ba5cd26..53274415 100644 --- a/chrome/browser/resources/ash/settings/os_people_page/set_local_password_dialog.ts +++ b/chrome/browser/resources/ash/settings/os_people_page/set_local_password_dialog.ts
@@ -104,6 +104,8 @@ this.showError_ = true; console.error('Internal error while setting local password'); return; + default: + break; } }
diff --git a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_app_permission_row.ts b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_app_permission_row.ts index d7adcf6..bc9e075 100644 --- a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_app_permission_row.ts +++ b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_app_permission_row.ts
@@ -160,6 +160,8 @@ case TriState.kAsk: this.permissionText_ = this.i18n('privacyHubPermissionAskText'); break; + default: + break; } }
diff --git a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_subpage.ts b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_subpage.ts index 04f8112..0f03658 100644 --- a/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_subpage.ts +++ b/chrome/browser/resources/ash/settings/os_privacy_page/privacy_hub_subpage.ts
@@ -17,6 +17,7 @@ import {PrefsMixin} from '/shared/settings/prefs/prefs_mixin.js'; import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js'; import {WebUiListenerMixin} from 'chrome://resources/ash/common/cr_elements/web_ui_listener_mixin.js'; +import {assertNotReached} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -296,6 +297,8 @@ return this.i18n('geolocationAreaOnlyAllowedForSystemSubtext'); case GeolocationAccessLevel.DISALLOWED: return this.i18n('geolocationAreaDisallowedSubtext'); + default: + assertNotReached(); } }
diff --git a/chrome/browser/resources/ash/settings/settings_scheduler_slider/settings_scheduler_slider.ts b/chrome/browser/resources/ash/settings/settings_scheduler_slider/settings_scheduler_slider.ts index 766db511..a303eb0 100644 --- a/chrome/browser/resources/ash/settings/settings_scheduler_slider/settings_scheduler_slider.ts +++ b/chrome/browser/resources/ash/settings/settings_scheduler_slider/settings_scheduler_slider.ts
@@ -354,6 +354,8 @@ case 'end': this.endDrag_(event); break; + default: + break; } }
diff --git a/chrome/browser/resources/compose/app.html b/chrome/browser/resources/compose/app.html index d5b7c5b..4844394 100644 --- a/chrome/browser/resources/compose/app.html +++ b/chrome/browser/resources/compose/app.html
@@ -477,7 +477,10 @@ <div id="firstRunContainer"> <div id="firstRunTopText">$i18n{firstRunMainTop}</div> - <div id="firstRunMidText">$i18n{firstRunMainMid}</div> + <div id="firstRunMidText" hidden="[[enterprise_]]"> + $i18nRaw{firstRunMainMid}</div> + <div id="firstRunMidTextEnterprise" hidden="[[!enterprise_]]"> + $i18nRaw{firstRunMainMidEnterprise}</div> <div id="firstRunBottomText" on-click="onFirstRunBottomTextClick_"> $i18nRaw{firstRunMainBottom} </div> @@ -611,9 +614,10 @@ <div id="submitFooter" class="footer" hidden$="[[submitted_]]"> <div class="footer-text"> - <div on-click="onFooterClick_"> - $i18nRaw{inputFooter} - </div> + <div on-click="onFooterClick_" hidden="[[enterprise_]]"> + $i18nRaw{inputFooter}</div> + <div on-click="onFooterClick_" hidden="[[!enterprise_]]"> + $i18nRaw{inputFooterEnterprise}</div> </div> <cr-button id="submitButton" class="action-button" on-click="onSubmit_" disabled="[[!isSubmitEnabled_]]">
diff --git a/chrome/browser/resources/compose/app.ts b/chrome/browser/resources/compose/app.ts index f8d32d09..7b851f4 100644 --- a/chrome/browser/resources/compose/app.ts +++ b/chrome/browser/resources/compose/app.ts
@@ -215,6 +215,10 @@ textSelected_: { type: Boolean, }, + enterprise_: { + type: Boolean, + value: loadTimeData.getBoolean('useEnterpriseWithoutLoggingPolicy'), + }, showMainAppDialog_: { type: Boolean, value: false, @@ -335,6 +339,7 @@ declare private elaborateChipIcon_: string; declare private formalizeChipIcon_: string; declare private textSelected_: boolean; + declare private enterprise_: boolean; declare private submitted_: boolean; declare private undoEnabled_: boolean; declare private redoEnabled_: boolean; @@ -497,7 +502,11 @@ // Embedded links do not work in WebUI so handle in the parent event // listener. if ((e.target as HTMLElement).tagName === 'A') { - this.apiProxy_.openComposeLearnMorePage(); + if (this.enterprise_) { + this.apiProxy_.openEnterpriseComposeLearnMorePage(); + } else { + this.apiProxy_.openComposeLearnMorePage(); + } } } @@ -689,6 +698,9 @@ case 'signInLink': this.apiProxy_.openSignInPage(); break; + case 'enterpriseLearnMore': + this.apiProxy_.openEnterpriseComposeLearnMorePage(); + break; default: this.apiProxy_.openComposeLearnMorePage(); }
diff --git a/chrome/browser/resources/compose/compose_api_proxy.ts b/chrome/browser/resources/compose/compose_api_proxy.ts index d067587..c6d61e11 100644 --- a/chrome/browser/resources/compose/compose_api_proxy.ts +++ b/chrome/browser/resources/compose/compose_api_proxy.ts
@@ -17,6 +17,7 @@ getRouter(): ComposeUntrustedDialogCallbackRouter; openBugReportingLink(): void; openComposeLearnMorePage(): void; + openEnterpriseComposeLearnMorePage(): void; openComposeSettings(): void; openFeedbackSurveyLink(): void; openSignInPage(): void; @@ -99,6 +100,10 @@ this.composeSessionPageHandler.openComposeLearnMorePage(); } + openEnterpriseComposeLearnMorePage() { + this.composeSessionPageHandler.openEnterpriseComposeLearnMorePage(); + } + openFeedbackSurveyLink() { this.composeSessionPageHandler.openFeedbackSurveyLink(); }
diff --git a/chrome/browser/resources/data_sharing/data_sharing_app.ts b/chrome/browser/resources/data_sharing/data_sharing_app.ts index 688b7ea..a068c27f 100644 --- a/chrome/browser/resources/data_sharing/data_sharing_app.ts +++ b/chrome/browser/resources/data_sharing/data_sharing_app.ts
@@ -422,6 +422,8 @@ return ProgressType.FAILED; case (Progress.SUCCEEDED): return ProgressType.SUCCEEDED; + default: + break; } return ProgressType.UNKNOWN; @@ -458,6 +460,8 @@ return DataSharingIntentType.ACCEPT_JOIN_AND_OPEN; case (LoggingIntent.ABANDON_JOIN): return DataSharingIntentType.ABANDON_JOIN; + default: + break; } return DataSharingIntentType.UNKNOWN; @@ -494,6 +498,8 @@ case FlowValues.JOIN: document.title = loadTimeData.getStringF('previewA11yName'); break; + default: + break; } switch (flow) {
diff --git a/chrome/browser/resources/discards/discards_tab.ts b/chrome/browser/resources/discards/discards_tab.ts index c6e8929..ed98f66 100644 --- a/chrome/browser/resources/discards/discards_tab.ts +++ b/chrome/browser/resources/discards/discards_tab.ts
@@ -219,6 +219,8 @@ return 'occluded'; case LifecycleUnitVisibility.VISIBLE: return 'visible'; + default: + assertNotReached(); } } @@ -237,6 +239,8 @@ return 'loading'; case LifecycleUnitLoadingState.LOADED: return 'loaded'; + default: + assertNotReached(); } } @@ -257,6 +261,8 @@ return 'suggested'; case LifecycleUnitDiscardReason.FROZEN_WITH_GROWING_MEMORY: return 'frozen with growing memory'; + default: + assertNotReached(); } } @@ -284,6 +290,8 @@ return 'hidden'; case LifecycleUnitVisibility.VISIBLE: return hasFocus ? 'active' : 'passive'; + default: + assertNotReached(); } } @@ -300,6 +308,8 @@ (new Date(Number(stateChangeTime.microseconds) / 1000) .toLocaleString()) : ''); + default: + assertNotReached(); } } @@ -381,6 +391,8 @@ return '✘️'; case CanFreeze.VARIES: return '~'; + default: + assertNotReached(); } }
diff --git a/chrome/browser/resources/glic/glic_api/glic_api.ts b/chrome/browser/resources/glic/glic_api/glic_api.ts index 7446599..5dbac8f 100644 --- a/chrome/browser/resources/glic/glic_api/glic_api.ts +++ b/chrome/browser/resources/glic/glic_api/glic_api.ts
@@ -605,8 +605,8 @@ * `ObservableValue` instances. So if a previous one existed, it will stop * receiving updates when a new one is obtained. * - * Dynamic updates can be a costly operation so the observable value should be - * released/destroyed as soon as it's not useful anymore. + * Dynamic updates can be a costly operation so the observable should be + * subscribed only while it is required. */ getPinCandidates? (options: GetPinCandidatesOptions): ObservableValue<PinCandidate[]>;
diff --git a/chrome/browser/resources/glic/glic_api_impl/glic_api_host.ts b/chrome/browser/resources/glic/glic_api_impl/glic_api_host.ts index 9245fb5d..ef7ee68 100644 --- a/chrome/browser/resources/glic/glic_api_impl/glic_api_host.ts +++ b/chrome/browser/resources/glic/glic_api_impl/glic_api_host.ts
@@ -260,8 +260,34 @@ } class PinCandidatesObserverImpl implements PinCandidatesObserver { + receiver?: PinCandidatesObserverReceiver; constructor( - private sender: PostMessageRequestSender, public observationId: number) {} + private sender: PostMessageRequestSender, + private handler: WebClientHandlerInterface, + private options: GetPinCandidatesOptions, public observationId: number) { + this.connectToSource(); + } + + // Stops requesting updates. This should be called on destruction, as well as + // when the panel is hidden to avoid incurring unnecessary costs. + disconnectFromSource() { + if (!this.receiver) { + return; + } + this.receiver.$.close(); + this.receiver = undefined; + } + + // Start/resume requesting updates. + connectToSource() { + if (this.receiver) { + return; + } + this.receiver = new PinCandidatesObserverReceiver(this); + this.handler.subscribeToPinCandidates( + getPinCandidatesOptionsFromClient(this.options), + this.receiver.$.bindNewPipeAndPassRemote()); + } onPinCandidatesChanged(candidates: PinCandidateMojo[]): void { const extras = new ResponseExtras(); @@ -819,13 +845,9 @@ options: GetPinCandidatesOptions, observationId: number, }): void { - const observer = - new PinCandidatesObserverImpl(this.sender, request.observationId); - const receiver = new PinCandidatesObserverReceiver(observer); - this.host.pinCandidatesObserver = {receiver, observer}; - this.handler.subscribeToPinCandidates( - getPinCandidatesOptionsFromClient(request.options), - receiver.$.bindNewPipeAndPassRemote()); + this.host.pinCandidatesObserver?.disconnectFromSource(); + this.host.pinCandidatesObserver = new PinCandidatesObserverImpl( + this.sender, this.handler, request.options, request.observationId); } glicBrowserUnsubscribeFromPinCandidates(request: {observationId: number}): @@ -833,9 +855,9 @@ if (!this.host.pinCandidatesObserver) { return; } - if (this.host.pinCandidatesObserver.observer.observationId === + if (this.host.pinCandidatesObserver.observationId === request.observationId) { - this.host.pinCandidatesObserver.receiver.$.close(); + this.host.pinCandidatesObserver.disconnectFromSource(); this.host.pinCandidatesObserver = undefined; } } @@ -929,10 +951,8 @@ private browserIsActive = true; private hasShownDebuggerAttachedWarning = false; detailedWebClientState = DetailedWebClientState.BOOTSTRAP_PENDING; - pinCandidatesObserver?: { - receiver: PinCandidatesObserverReceiver, - observer: PinCandidatesObserverImpl, - }; + // Present while the client is monitoring pin candidates. + pinCandidatesObserver?: PinCandidatesObserverImpl; constructor( private browserProxy: BrowserProxy, private windowProxy: WindowProxy, @@ -965,7 +985,7 @@ this.postMessageReceiver.destroy(); this.messageHandler.destroy(); this.sender.destroy(); - this.closePinCandidatesObserver(); + this.pinCandidatesObserver?.disconnectFromSource(); } // Called when the webview page is loaded. @@ -988,7 +1008,9 @@ this.panelOpenState = state; this.clientActiveObs.assignAndSignal(this.isClientActive()); if (state === PanelOpenState.CLOSED) { - this.closePinCandidatesObserver(); + this.pinCandidatesObserver?.disconnectFromSource(); + } else { + this.pinCandidatesObserver?.connectToSource(); } } @@ -1224,13 +1246,6 @@ `Glic.Api.RequestCounts.${suffix}`, event, GlicRequestEvent.MAX_VALUE + 1); } - - closePinCandidatesObserver() { - if (this.pinCandidatesObserver) { - this.pinCandidatesObserver.receiver.$.close(); - this.pinCandidatesObserver = undefined; - } - } } // LINT.IfChange(GlicRequestEvent)
diff --git a/chrome/browser/resources/lens/overlay/find_words_in_region.ts b/chrome/browser/resources/lens/overlay/find_words_in_region.ts index 4672f50..b81fc6f 100644 --- a/chrome/browser/resources/lens/overlay/find_words_in_region.ts +++ b/chrome/browser/resources/lens/overlay/find_words_in_region.ts
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {assertNotReached} from '//resources/js/assert.js'; + import type {CenterRotatedBox} from './geometry.mojom-webui.js'; import type {Word} from './text.mojom-webui.js'; @@ -180,6 +182,8 @@ return vertex.y >= selectionBounds.top; case ClippingEdge.BOTTOM: return vertex.y <= selectionBounds.bottom; + default: + assertNotReached(); } } @@ -211,5 +215,7 @@ (v1.x - v0.x) * (selectionBounds.bottom - v0.y) / (v1.y - v0.y), y: selectionBounds.bottom, }; + default: + assertNotReached(); } }
diff --git a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html index 75bacc1..b438a5a 100644 --- a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html +++ b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.html
@@ -189,6 +189,12 @@ position: absolute; width: 100%; z-index: 2; + display: none; + } + + /* Show the composebox when enabled. */ + :host([enable-aim-searchbox]) #composeboxContainer { + display: block; } :host(:not([show-upload-progress])) #uploadProgressBarContainer,
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar.ts b/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar.ts index 2528ae6..c55a757 100644 --- a/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar.ts +++ b/chrome/browser/resources/new_tab_page/modules/v2/calendar/calendar.ts
@@ -134,8 +134,7 @@ // Find the indices of all meetings that are not over. let expandableEventIndices: number[] = this.events.map((_, i) => i); expandableEventIndices = expandableEventIndices.filter((eventIndex) => { - const expandableEvent = this.events[eventIndex]; - assert(expandableEvent); + const expandableEvent = this.events[eventIndex]!; return toJsTimestamp(expandableEvent.endTime) > now; }); @@ -147,8 +146,7 @@ expandableEventIndices.sort( (a, b) => this.compareEventPriority_(a, b, in5Minutes)); - assert(expandableEventIndices[0]); - return expandableEventIndices[0]; + return expandableEventIndices[0]!; } protected hasDoubleBooked_() {
diff --git a/chrome/browser/resources/print_preview/data/state.ts b/chrome/browser/resources/print_preview/data/state.ts index 5ce180a..1a657e0 100644 --- a/chrome/browser/resources/print_preview/data/state.ts +++ b/chrome/browser/resources/print_preview/data/state.ts
@@ -96,6 +96,8 @@ case (State.CLOSING): assert(this.state_ !== State.HIDDEN); break; + default: + break; } const oldState = this.state_;
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_page.ts b/chrome/browser/resources/settings/autofill_page/autofill_page.ts index 8b044ef..00dcfb4 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_page.ts +++ b/chrome/browser/resources/settings/autofill_page/autofill_page.ts
@@ -147,6 +147,8 @@ case 'payments': triggerId = 'paymentManagerButton'; break; + default: + break; } assert(triggerId);
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.ts b/chrome/browser/resources/settings/languages_page/languages_page.ts index 2861b2c..3c0f5d7 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.ts +++ b/chrome/browser/resources/settings/languages_page/languages_page.ts
@@ -236,8 +236,15 @@ */ private isRestartRequired_( languageCode: string, prospectiveUILanguage: string): boolean { + if (!this.isConnected) { + // Mysteriously happens in SettingsLanguagePageTest.LanguageMenu. + return false; + } + + // Using getLanguageHelperInstance() directly for the same reason as in + // `canEnableSomeSupportedLanguage_` (see comment there). return prospectiveUILanguage === languageCode && - this.languageHelper_.requiresRestart(); + getLanguageHelperInstance().requiresRestart(); } private onCloseMenu_() {
diff --git a/chrome/browser/resources/settings/languages_page/spell_check_page.ts b/chrome/browser/resources/settings/languages_page/spell_check_page.ts index 6a68acc..877d0d7 100644 --- a/chrome/browser/resources/settings/languages_page/spell_check_page.ts +++ b/chrome/browser/resources/settings/languages_page/spell_check_page.ts
@@ -221,7 +221,10 @@ // `browser.enable_spellchecking` as the toggle for the 1 language as // well. if (this.spellCheckLanguages_.length === 1) { - this.languageHelper_.toggleSpellCheck( + // Need to call getLanguageHelperInstance() instead of + // this.languageHelper_ here, because Polymer observers fire before + // connectedCallback sometimes. + getLanguageHelperInstance().toggleSpellCheck( this.spellCheckLanguages_[0].language.code, !!this.getPref('browser.enable_spellchecking').value); }
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index aa8674a..62e878f 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -149,18 +149,6 @@ </settings-subpage> </template> - <template is="dom-if" if="[[shouldShowSafetyHub_]]"> - <template is="dom-if" route-path="/safetyCheck"> - <!-- TODO(crbug.com/40267370): Make the page searchable.--> - <settings-subpage id="safetyHub" page-title="$i18n{safetyHub}" - class="multi-card" no-search - learn-more-url="$i18n{safetyHubHelpCenterURL}"> - <settings-safety-hub-page prefs="{{prefs}}"> - </settings-safety-hub-page> - </settings-subpage> - </template> - </template> - <template is="dom-if" route-path="/security"> <settings-subpage id="security" page-title="$i18n{securityPageTitle}" associated-control="[[$$('#securityLinkRow')]]"
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.ts b/chrome/browser/resources/settings/privacy_page/privacy_page.ts index 55d8da47..acd814f 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.ts
@@ -275,13 +275,6 @@ value: ChooserType, }, - shouldShowSafetyHub_: { - type: Boolean, - value() { - return !loadTimeData.getBoolean('isGuest'); - }, - }, - enableKeyboardLockPrompt_: { type: Boolean, value: () => loadTimeData.getBoolean('enableKeyboardLockPrompt'), @@ -345,7 +338,6 @@ private privateStateTokensEnabled_: boolean; declare private autoPictureInPictureEnabled_: boolean; declare private capturedSurfaceControlEnabled_: boolean; - declare private shouldShowSafetyHub_: boolean; declare private enableWebAppInstallation_: boolean; declare private enableLocalNetworkAccessSetting_: boolean; declare private focusConfig_: FocusConfig;
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page_index.html b/chrome/browser/resources/settings/privacy_page/privacy_page_index.html index 61e265b..fbd9f4d 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page_index.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page_index.html
@@ -25,10 +25,16 @@ <template is="dom-if" if="[[showPage_(pageVisibility_.safetyHub)]]"> <template is="dom-if" if="[[renderView_( routes_.PRIVACY, currentRoute, inSearchMode)]]"> - <settings-section slot="view" id="safetyHubEntryPoint" - page-title="$i18n{safetyHub}"> - <settings-safety-hub-entry-point></settings-safety-hub-entry-point> - </settings-section> + <settings-safety-hub-entry-point slot="view" id="safetyHubEntryPoint"> + </settings-safety-hub-entry-point> + </template> + + <template is="dom-if" if="[[renderView_( + routes_.SAFETY_HUB, currentRoute, inSearchMode)]]"> + <!-- TODO(crbug.com/40267370): Make the page searchable.--> + <settings-safety-hub-page slot="view" id="safetyHub" no-search + data-parent-view-id="safetyHubEntryPoint" prefs="{{prefs}}"> + </settings-safety-hub-page> </template> </template>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page_index.ts b/chrome/browser/resources/settings/privacy_page/privacy_page_index.ts index e4bb8ff..69c54cc 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page_index.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_page_index.ts
@@ -135,6 +135,8 @@ case routes.SECURITY_KEYS: assert(this.enableSecurityKeysSubpage_); return ['securityKeys']; + case routes.SAFETY_HUB: + return ['safetyHub']; default: { if (this.isNonMigratedPrivacyRoute_(route)) { // Handle case where Privacy child route has not migrated to the new
diff --git a/chrome/browser/resources/settings/route.ts b/chrome/browser/resources/settings/route.ts index 6c4cea1..8188a1de 100644 --- a/chrome/browser/resources/settings/route.ts +++ b/chrome/browser/resources/settings/route.ts
@@ -22,6 +22,7 @@ if (visibility.safetyHub !== false) { r.SAFETY_HUB = r.PRIVACY.createChild('/safetyCheck'); + r.SAFETY_HUB.hasMigratedToPlugin = true; } if (loadTimeData.getBoolean('showPrivacyGuide')) {
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.html b/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.html index c697360..d1224fb 100644 --- a/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.html +++ b/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.html
@@ -4,11 +4,13 @@ } </style> -<settings-safety-hub-module class="cr-row first" id="module" - header$="[[headerString_]]" subheader$="[[subheaderString_]]" - header-icon-color$="[[headerIconColor_]]" header-icon="cr:security"> - <cr-button id="button" on-click="onClick_" slot="button-container" - class$="[[buttonClass_]]"> - $i18n{safetyHubEntryPointButtonLabel} - </cr-button> -</settings-safety-hub-module> +<settings-section page-title="$i18n{safetyHub}"> + <settings-safety-hub-module class="cr-row first" id="module" + header$="[[headerString_]]" subheader$="[[subheaderString_]]" + header-icon-color$="[[headerIconColor_]]" header-icon="cr:security"> + <cr-button id="button" on-click="onClick_" slot="button-container" + class$="[[buttonClass_]]"> + $i18n{safetyHubEntryPointButtonLabel} + </cr-button> + </settings-safety-hub-module> +</settings-section>
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.ts b/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.ts index ae1638c..26999e3 100644 --- a/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.ts +++ b/chrome/browser/resources/settings/safety_hub/safety_hub_entry_point.ts
@@ -6,6 +6,7 @@ import 'chrome://resources/cr_elements/icons.html.js'; import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import 'chrome://resources/cr_elements/cr_shared_style.css.js'; +import '../settings_page/settings_section.js'; import './safety_hub_module.js'; import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; @@ -13,8 +14,10 @@ import {routes} from '../route.js'; import {Router, RouteObserverMixin} from '../router.js'; +import type {Route} from '../router.js'; import type {MetricsBrowserProxy} from '../metrics_browser_proxy.js'; import {MetricsBrowserProxyImpl, SafetyHubEntryPoint} from '../metrics_browser_proxy.js'; +import {SettingsViewMixin} from '../settings_page/settings_view_mixin.js'; import type {EntryPointInfo, SafetyHubBrowserProxy} from './safety_hub_browser_proxy.js'; import {SafetyHubBrowserProxyImpl} from './safety_hub_browser_proxy.js'; @@ -30,7 +33,7 @@ } const SettingsSafetyHubEntryPointElementBase = - RouteObserverMixin(I18nMixin(PolymerElement)); + SettingsViewMixin(RouteObserverMixin(I18nMixin(PolymerElement))); export class SettingsSafetyHubEntryPointElement extends SettingsSafetyHubEntryPointElementBase { @@ -88,7 +91,9 @@ super.connectedCallback(); } - override currentRouteChanged() { + override currentRouteChanged(newRoute: Route, oldRoute?: Route) { + super.currentRouteChanged(newRoute, oldRoute); + if (Router.getInstance().getCurrentRoute() !== routes.PRIVACY) { return; } @@ -121,6 +126,13 @@ } Router.getInstance().navigateTo(routes.SAFETY_HUB); } + + // SettingsViewMixin implementation. + override getFocusConfig() { + return new Map([ + [routes.SAFETY_HUB.path, '#button'], + ]); + } } declare global {
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_page.html b/chrome/browser/resources/settings/safety_hub/safety_hub_page.html index 3ef282d..47bd9d23 100644 --- a/chrome/browser/resources/settings/safety_hub/safety_hub_page.html +++ b/chrome/browser/resources/settings/safety_hub/safety_hub_page.html
@@ -47,6 +47,8 @@ } </style> +<settings-subpage class="multi-card" page-title="$i18n{safetyHub}" + learn-more-url="$i18n{safetyHubHelpCenterURL}"> <h2 class="section-header cr-secondary-text first"> $i18n{safetyHubPageCardSectionHeader} </h2> @@ -104,3 +106,4 @@ </relaunch-confirmation-dialog> </template> </if> +</settings-supage>
diff --git a/chrome/browser/resources/settings/safety_hub/safety_hub_page.ts b/chrome/browser/resources/settings/safety_hub/safety_hub_page.ts index ac663575..3d93f7e 100644 --- a/chrome/browser/resources/settings/safety_hub/safety_hub_page.ts +++ b/chrome/browser/resources/settings/safety_hub/safety_hub_page.ts
@@ -9,6 +9,7 @@ */ import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; +import '../settings_page/settings_subpage.js'; import './safety_hub_card.js'; import './safety_hub_module.js'; @@ -24,6 +25,8 @@ import {RelaunchMixin, RestartType} from '../relaunch_mixin.js'; import {routes} from '../route.js'; import {RouteObserverMixin, Router} from '../router.js'; +import type {Route} from '../router.js'; +import {SettingsViewMixin} from '../settings_page/settings_view_mixin.js'; import type {CardInfo, NotificationPermission, SafetyHubBrowserProxy, UnusedSitePermissions} from './safety_hub_browser_proxy.js'; import {CardState, SafetyHubBrowserProxyImpl, SafetyHubEvent} from './safety_hub_browser_proxy.js'; @@ -38,8 +41,8 @@ }; } -const SettingsSafetyHubPageElementBase = RouteObserverMixin( - RelaunchMixin(PrefsMixin(WebUiListenerMixin(I18nMixin(PolymerElement))))); +const SettingsSafetyHubPageElementBase = RouteObserverMixin(SettingsViewMixin( + RelaunchMixin(PrefsMixin(WebUiListenerMixin(I18nMixin(PolymerElement)))))); export class SettingsSafetyHubPageElement extends SettingsSafetyHubPageElementBase { @@ -148,7 +151,9 @@ super.connectedCallback(); } - override currentRouteChanged() { + override currentRouteChanged(newRoute: Route, oldRoute?: Route) { + super.currentRouteChanged(newRoute, oldRoute); + if (Router.getInstance().getCurrentRoute() !== routes.SAFETY_HUB) { return; } @@ -427,6 +432,11 @@ this.metricsBrowserProxy_.recordSafetyHubDashboardAnyWarning(hasAnyWarning); } + + // SettingsViewMixin implementation. + override focusBackButton() { + this.shadowRoot!.querySelector('settings-subpage')!.focusBackButton(); + } } declare global {
diff --git a/chrome/browser/resources/tab_strip/playground/tab_playground.ts b/chrome/browser/resources/tab_strip/playground/tab_playground.ts index 6115bc81..8be7ad0 100644 --- a/chrome/browser/resources/tab_strip/playground/tab_playground.ts +++ b/chrome/browser/resources/tab_strip/playground/tab_playground.ts
@@ -128,8 +128,8 @@ if (tab.networkState === TabNetworkState.kWaiting) { this.faviconEl_.style.backgroundImage = 'none'; - } else if (tab.faviconUrl) { - this.faviconEl_.style.backgroundImage = `url(${tab.faviconUrl.url})`; + } else if (tab.favicon) { + this.faviconEl_.style.backgroundImage = `url(${tab.favicon.dataUrl.url})`; } else { this.faviconEl_.style.backgroundImage = getFavicon(''); }
diff --git a/chrome/browser/save_to_drive/BUILD.gn b/chrome/browser/save_to_drive/BUILD.gn new file mode 100644 index 0000000..553096c --- /dev/null +++ b/chrome/browser/save_to_drive/BUILD.gn
@@ -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. + +import("//pdf/features.gni") + +assert(enable_pdf_save_to_drive) + +source_set("save_to_drive") { + public = [ + "save_to_drive_flow.h", + ] + + sources = [ + "save_to_drive_flow.cc", + ] + + configs += [ + "//build/config/compiler:wexit_time_destructors", + "//build/config/compiler:wglobal_constructors", + ] + + deps = [ + "//content/public/browser", + ] +}
diff --git a/chrome/browser/save_to_drive/save_to_drive_flow.cc b/chrome/browser/save_to_drive/save_to_drive_flow.cc new file mode 100644 index 0000000..5a143177e --- /dev/null +++ b/chrome/browser/save_to_drive/save_to_drive_flow.cc
@@ -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. + +#include "chrome/browser/save_to_drive/save_to_drive_flow.h" + +#include "content/public/browser/document_user_data.h" +#include "content/public/browser/render_frame_host.h" + +namespace save_to_drive { + +SaveToDriveFlow::SaveToDriveFlow(content::RenderFrameHost* render_frame_host) + : content::DocumentUserData<SaveToDriveFlow>(render_frame_host) {} + +void SaveToDriveFlow::Run() { + // TODO(crbug.com/424208776): Implement the flow. +} + +void SaveToDriveFlow::Stop() { + DeleteForCurrentDocument(&render_frame_host()); + // Don't do anything else here. The flow will be destroyed after this line. +} + +DOCUMENT_USER_DATA_KEY_IMPL(SaveToDriveFlow); + +} // namespace save_to_drive
diff --git a/chrome/browser/save_to_drive/save_to_drive_flow.h b/chrome/browser/save_to_drive/save_to_drive_flow.h new file mode 100644 index 0000000..08ef6a4 --- /dev/null +++ b/chrome/browser/save_to_drive/save_to_drive_flow.h
@@ -0,0 +1,44 @@ +// 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 CHROME_BROWSER_SAVE_TO_DRIVE_SAVE_TO_DRIVE_FLOW_H_ +#define CHROME_BROWSER_SAVE_TO_DRIVE_SAVE_TO_DRIVE_FLOW_H_ + +#include "content/public/browser/document_user_data.h" + +namespace content { +class RenderFrameHost; +} // namespace content + +namespace save_to_drive { + +// This class is responsible for orchastrating the entire save to Drive flow +// on the browser process from showing the account chooser, reading the file +// size, and initiating the appropriate drive uploader to save the file to +// Drive. This flow will be tied to the lifetime of the document. It is +// responsible for cleaning up its resources when the flow is stopped. +class SaveToDriveFlow : public content::DocumentUserData<SaveToDriveFlow> { + public: + SaveToDriveFlow(const SaveToDriveFlow&) = delete; + SaveToDriveFlow& operator=(const SaveToDriveFlow&) = delete; + ~SaveToDriveFlow() override = default; + + // Starts the save to Drive flow. + void Run(); + + // Cleans up the flow and its resources. This is called when the flow is + // aborted or completed. + void Stop(); + + private: + friend class content::DocumentUserData<SaveToDriveFlow>; + + explicit SaveToDriveFlow(content::RenderFrameHost* render_frame_host); + + DOCUMENT_USER_DATA_KEY_DECL(); +}; + +} // namespace save_to_drive + +#endif // CHROME_BROWSER_SAVE_TO_DRIVE_SAVE_TO_DRIVE_FLOW_H_
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_observer_android_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_observer_android_browsertest.cc index 51631d6..1c09a64 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_observer_android_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_observer_android_browsertest.cc
@@ -4,7 +4,12 @@ #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" +#include <memory> +#include <string_view> +#include <utility> + #include "base/functional/bind.h" +#include "base/memory/weak_ptr.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/scoped_feature_list.h" @@ -53,18 +58,20 @@ SupervisedUserServiceFactory::GetInstance()->SetTestingFactory( context, base::BindRepeating( &SupervisedUserNavigationObserverAndroidBrowserTest:: - BuildSupervisedUserService, + BuildTestSupervisedUserService, base::Unretained(this))); } content::WebContents* web_contents() { return chrome_test_utils::GetActiveWebContents(this); } - FakeContentFiltersObserverBridge* search_content_filters_observer() { - return search_content_filters_observer_.get(); + base::WeakPtr<FakeContentFiltersObserverBridge> search_content_filter() { + return supervised_user_service() + ->search_content_filters_observer_weak_ptr(); } - FakeContentFiltersObserverBridge* browser_content_filters_observer() { - return browser_content_filters_observer_.get(); + base::WeakPtr<FakeContentFiltersObserverBridge> browser_content_filter() { + return supervised_user_service() + ->browser_content_filters_observer_weak_ptr(); } MockUrlCheckerClient* url_checker_client() { return url_checker_client_; } base::HistogramTester& histogram_tester() { return histogram_tester_; } @@ -96,9 +103,9 @@ command_line->AppendSwitch(switches::kIgnoreGooglePortNumbers); } - // Builds a SupervisedUserService with a fake content filters observer bridge - // exposed for testing. - std::unique_ptr<KeyedService> BuildSupervisedUserService( + // TestSupervisedUserService is a wrapper around SupervisedUserService that + // provides test-only interfaces. + std::unique_ptr<KeyedService> BuildTestSupervisedUserService( content::BrowserContext* browser_context) { Profile* profile = Profile::FromBrowserContext(browser_context); @@ -109,7 +116,7 @@ std::make_unique<MockUrlCheckerClient>(); url_checker_client_ = url_checker_client.get(); - return std::make_unique<SupervisedUserService>( + return std::make_unique<TestSupervisedUserService>( IdentityManagerFactory::GetForProfile(profile), profile->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(), @@ -123,33 +130,17 @@ *profile->GetPrefs(), std::make_unique<FakeURLFilterDelegate>(), std::move(url_checker_client)), std::make_unique<SupervisedUserServicePlatformDelegate>(*profile), - base::BindRepeating( - &SupervisedUserNavigationObserverAndroidBrowserTest::CreateBridge, - base::Unretained(this))); + InitialSupervisionState::kUnsupervised); } - // Creates a fake content filters observer bridge for testing, and binds it to - // this test fixture. - std::unique_ptr<ContentFiltersObserverBridge> CreateBridge( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled) { - std::unique_ptr<FakeContentFiltersObserverBridge> bridge = - std::make_unique<FakeContentFiltersObserverBridge>( - setting_name, on_enabled, on_disabled); - if (setting_name == kSearchContentFiltersSettingName) { - search_content_filters_observer_ = bridge.get(); - } - if (setting_name == kBrowserContentFiltersSettingName) { - browser_content_filters_observer_ = bridge.get(); - } - return bridge; + TestSupervisedUserService* supervised_user_service() { + return static_cast<TestSupervisedUserService*>( + SupervisedUserServiceFactory::GetInstance()->GetForProfile( + GetProfile())); } base::HistogramTester histogram_tester_; raw_ptr<MockUrlCheckerClient> url_checker_client_; - raw_ptr<FakeContentFiltersObserverBridge> search_content_filters_observer_; - raw_ptr<FakeContentFiltersObserverBridge> browser_content_filters_observer_; base::test::ScopedFeatureList scoped_feature_list_{ kPropagateDeviceContentFiltersToSupervisedUser}; }; @@ -158,7 +149,7 @@ // search query params are not appended. IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationObserverAndroidBrowserTest, DontPropagateSearchContentFilterSettingWhenDisabled) { - ASSERT_FALSE(search_content_filters_observer()->IsEnabled()); + ASSERT_FALSE(search_content_filter()->IsEnabled()); // The loaded URL is exactly as requested. EXPECT_TRUE(content::NavigateToURL( @@ -172,7 +163,7 @@ // feature consistency. IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationObserverAndroidBrowserTest, LoadSafeSearchResultsWithSearchContentFilterPreset) { - search_content_filters_observer()->SetEnabled(true); + search_content_filter()->SetEnabled(true); GURL url = embedded_test_server()->GetURL("google.com", "/search?q=cat"); // The final url will be different: with safe search query params. @@ -186,7 +177,7 @@ // params are appended. IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationObserverAndroidBrowserTest, PreexistingSafeSearchParamsAreRemovedBeforeAppending) { - search_content_filters_observer()->SetEnabled(true); + search_content_filter()->SetEnabled(true); GURL url = embedded_test_server()->GetURL("google.com", "/search?safe=off&ssui=on&q=cat"); @@ -210,7 +201,7 @@ EXPECT_TRUE(content::NavigateToURL(web_contents(), url)); content::TestNavigationObserver navigation_observer(web_contents()); - search_content_filters_observer()->SetEnabled(true); + search_content_filter()->SetEnabled(true); navigation_observer.Wait(); // Key part: the search results are reloaded with extra query params. @@ -227,7 +218,7 @@ content::TestNavigationObserver navigation_observer(web_contents()); // Turn the filtering on. That will trigger a url check which is resolved to // restricted. - browser_content_filters_observer()->SetEnabled(true); + browser_content_filter()->SetEnabled(true); navigation_observer.Wait(); } @@ -336,7 +327,7 @@ // In this test to facilitate the back button click, one url is allowed but // others are not. All navigations are subject to classification in this test. - browser_content_filters_observer()->SetEnabled(true); + browser_content_filter()->SetEnabled(true); // Three classification calls are expected: // 1. when the page is first loaded
diff --git a/chrome/browser/sync/BUILD.gn b/chrome/browser/sync/BUILD.gn index 7fef238..571e978 100644 --- a/chrome/browser/sync/BUILD.gn +++ b/chrome/browser/sync/BUILD.gn
@@ -178,6 +178,7 @@ deps += [ "//chrome/browser/accessibility/tree_fixing:prefs", "//chrome/browser/ui/tabs:tab_strip", + "//chrome/browser/ui/tabs/saved_tab_groups", ] } if (enable_extensions_core) {
diff --git a/chrome/browser/sync/sync_service_factory.cc b/chrome/browser/sync/sync_service_factory.cc index b91091ce..d8f58453 100644 --- a/chrome/browser/sync/sync_service_factory.cc +++ b/chrome/browser/sync/sync_service_factory.cc
@@ -149,9 +149,7 @@ return service; #elif BUILDFLAG(IS_ANDROID) const bool enable_tab_group_sync = - tab_groups::IsTabGroupSyncEnabled(profile->GetPrefs()) && - !base::FeatureList::IsEnabled( - tab_groups::kTabGroupSyncDisableNetworkLayer); + tab_groups::IsTabGroupSyncEnabled(profile->GetPrefs()); tab_groups::TabGroupTrial::OnTabGroupSyncEnabled(enable_tab_group_sync); if (!enable_tab_group_sync) { return nullptr;
diff --git a/chrome/browser/sync/test/integration/BUILD.gn b/chrome/browser/sync/test/integration/BUILD.gn index 26411e5..c5ffec9 100644 --- a/chrome/browser/sync/test/integration/BUILD.gn +++ b/chrome/browser/sync/test/integration/BUILD.gn
@@ -217,6 +217,7 @@ "//chrome/browser/search_engines", "//chrome/browser/themes", "//chrome/browser/ui:ui_features", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/web_applications:features", "//chrome/browser/web_applications:web_applications_test_support", "//chrome/common",
diff --git a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac_win_linux.cc b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac_win_linux.cc index 4fc3b29..f07e8d3 100644 --- a/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac_win_linux.cc +++ b/chrome/browser/sync/test/integration/two_client_web_apps_integration_test_mac_win_linux.cc
@@ -41,9 +41,17 @@ helper_.CheckLaunchIconShown(); } +// TODO(crbug.com/436571232): Disabled on Debug Linux due to flakiness. +#if BUILDFLAG(IS_LINUX) && !defined(NDEBUG) +#define MAYBE_WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_40Client2_45Standalone_46Standalone_7Standalone_12Standalone_69Standalone_24 \ + DISABLED_WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_40Client2_45Standalone_46Standalone_7Standalone_12Standalone_69Standalone_24 +#else +#define MAYBE_WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_40Client2_45Standalone_46Standalone_7Standalone_12Standalone_69Standalone_24 \ + WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_40Client2_45Standalone_46Standalone_7Standalone_12Standalone_69Standalone_24 +#endif IN_PROC_BROWSER_TEST_F( WebAppIntegration, - WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_40Client2_45Standalone_46Standalone_7Standalone_12Standalone_69Standalone_24) { + MAYBE_WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_40Client2_45Standalone_46Standalone_7Standalone_12Standalone_69Standalone_24) { // Test contents are generated by script. Please do not modify! // See `docs/webapps/why-is-this-test-failing.md` or // `docs/webapps/integration-testing-framework` for more info. @@ -657,9 +665,17 @@ helper_.CheckAppInListNotLocallyInstalled(Site::kStandalone); } +// TODO(crbug.com/436571232): Disabled on Debug Linux due to flakiness. +#if BUILDFLAG(IS_LINUX) && !defined(NDEBUG) +#define MAYBE_WAI_InstallMenuStandalone_SwitchProfileClientsClient2_SyncTurnOff_SwitchProfileClientsClient1_UninstallFromAppSettingsStandalone_SyncTurnOn_SwitchProfileClientsClient2 \ + DISABLED_WAI_InstallMenuStandalone_SwitchProfileClientsClient2_SyncTurnOff_SwitchProfileClientsClient1_UninstallFromAppSettingsStandalone_SyncTurnOn_SwitchProfileClientsClient2 +#else +#define MAYBE_WAI_InstallMenuStandalone_SwitchProfileClientsClient2_SyncTurnOff_SwitchProfileClientsClient1_UninstallFromAppSettingsStandalone_SyncTurnOn_SwitchProfileClientsClient2 \ + WAI_InstallMenuStandalone_SwitchProfileClientsClient2_SyncTurnOff_SwitchProfileClientsClient1_UninstallFromAppSettingsStandalone_SyncTurnOn_SwitchProfileClientsClient2 +#endif IN_PROC_BROWSER_TEST_F( WebAppIntegration, - WAI_InstallMenuStandalone_SwitchProfileClientsClient2_SyncTurnOff_SwitchProfileClientsClient1_UninstallFromAppSettingsStandalone_SyncTurnOn_SwitchProfileClientsClient2) { + MAYBE_WAI_InstallMenuStandalone_SwitchProfileClientsClient2_SyncTurnOff_SwitchProfileClientsClient1_UninstallFromAppSettingsStandalone_SyncTurnOn_SwitchProfileClientsClient2) { // Test contents are generated by script. Please do not modify! // See `docs/webapps/why-is-this-test-failing.md` or // `docs/webapps/integration-testing-framework` for more info.
diff --git a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabSwitcherGroupSuggestionService.java b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabSwitcherGroupSuggestionService.java index 4232dce..71d3e15 100644 --- a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabSwitcherGroupSuggestionService.java +++ b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabSwitcherGroupSuggestionService.java
@@ -98,7 +98,8 @@ } @Override - public void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) { + public void onTabClosePending( + List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) { clearSuggestions(); } };
diff --git a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/VersionUpdateIphHandler.java b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/VersionUpdateIphHandler.java index 6b018310..c74192f1 100644 --- a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/VersionUpdateIphHandler.java +++ b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/VersionUpdateIphHandler.java
@@ -4,8 +4,9 @@ package org.chromium.chrome.browser.tab_ui; +import static android.text.TextUtils.isEmpty; + import static org.chromium.chrome.browser.tabmodel.TabGroupTitleUtils.getDisplayableTitle; -import static org.chromium.components.collaboration.messaging.MessageUtils.extractTabGroupId; import android.content.Context; import android.view.View; @@ -13,7 +14,6 @@ import org.chromium.base.Token; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.chrome.browser.collaboration.messaging.MessagingBackendServiceFactory; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncServiceFactory; @@ -22,17 +22,18 @@ import org.chromium.chrome.browser.user_education.UserEducationHelper; import org.chromium.components.browser_ui.widget.highlight.ViewHighlighter.HighlightParams; import org.chromium.components.browser_ui.widget.highlight.ViewHighlighter.HighlightShape; -import org.chromium.components.collaboration.messaging.MessagingBackendService; -import org.chromium.components.collaboration.messaging.PersistentMessage; import org.chromium.components.feature_engagement.FeatureConstants; import org.chromium.components.prefs.PrefService; +import org.chromium.components.tab_group_sync.LocalTabGroupId; import org.chromium.components.tab_group_sync.MessageType; +import org.chromium.components.tab_group_sync.SavedTabGroup; import org.chromium.components.tab_group_sync.TabGroupSyncService; import org.chromium.components.tab_group_sync.VersioningMessageController; import org.chromium.components.user_prefs.UserPrefs; +import java.util.ArrayList; import java.util.List; -import java.util.Optional; +import java.util.Set; /** Handles showing IPH when a user updates Chrome and regains access to a shared tab group. */ @NullMarked @@ -42,111 +43,86 @@ private VersionUpdateIphHandler() {} /** - * Attempts to show IPH on the tab switcher button if conditions for a version update message - * are met. + * Attempts to show IPH on the anchor view if conditions for a version update message are met. * * @param userEducationHelper Helper for showing IPHs. - * @param tabSwitcherButton The view to anchor the IPH to. - * @param profile The current user profile. - * @param info Information about the tab model dot (containing the group title). + * @param anchorView The view to anchor the IPH to. + * @param filter The current tab group model filter. + * @param expectsAutoOpen The expected value of the "auto-open tab groups" setting. The IPH will + * only be shown if the setting's actual value matches this expected value. */ - public static void maybeShowTabSwitcherButtonIph( + public static void maybeShowVersioningIph( UserEducationHelper userEducationHelper, - View tabSwitcherButton, - Profile profile, - TabModelDotInfo info) { - if (wontShowIphForProfile(profile)) return; - - assert profile != null; - if (!isAutoOpenEnabled(profile)) return; - - VersioningMessageController versioningMessageController = - getVersioningMessageController(profile); - if (shouldNotShowIph(versioningMessageController)) return; - - Context context = tabSwitcherButton.getContext(); - String contentString = - context.getString(R.string.tab_group_update_iph_text, info.tabGroupTitle); - showIph(userEducationHelper, tabSwitcherButton, contentString, versioningMessageController); + View anchorView, + TabGroupModelFilter filter, + boolean expectsAutoOpen) { + Profile profile = getProfile(filter); + if (profile == null || expectsAutoOpen != isAutoOpenEnabled(profile)) return; + showIph(userEducationHelper, anchorView, profile, filter); } - /** - * Attempts to show IPH on the tab group pane button if conditions for a version update message - * are met. - * - * @param userEducationHelper Helper for showing IPHs. - * @param filter The current tab group model filter. - * @param anchorView The view to anchor the IPH to within the tab group pane. - */ - public static void maybeShowTabGroupPaneButtonIph( - UserEducationHelper userEducationHelper, TabGroupModelFilter filter, View anchorView) { - Profile profile = filter.getTabModel().getProfile(); - if (wontShowIphForProfile(profile)) return; - - assert profile != null; - if (isAutoOpenEnabled(profile)) return; - + private static void showIph( + UserEducationHelper userEducationHelper, + View anchorView, + Profile profile, + TabGroupModelFilter filter) { VersioningMessageController versioningMessageController = getVersioningMessageController(profile); if (shouldNotShowIph(versioningMessageController)) return; - MessagingBackendService messagingBackendService = - MessagingBackendServiceFactory.getForProfile(profile); - assert messagingBackendService != null; - - List<PersistentMessage> messages = - messagingBackendService.getMessages( - Optional.of(MessageType.VERSION_UPDATED_MESSAGE)); - if (messages.isEmpty()) return; - Context context = anchorView.getContext(); - String tabGroupTitle = getTabGroupTitleFromMessages(context, filter, messages); - if (tabGroupTitle == null) return; + List<String> sharedGroupTitles = new ArrayList<>(); - String iphText = context.getString(R.string.tab_group_update_iph_text, tabGroupTitle); - showIph(userEducationHelper, anchorView, iphText, versioningMessageController); + TabGroupSyncService tabGroupSyncService = TabGroupSyncServiceFactory.getForProfile(profile); + if (tabGroupSyncService == null) return; + + Set<Token> allTabGroupIds = filter.getAllTabGroupIds(); + if (allTabGroupIds.isEmpty()) return; + + for (Token groupId : allTabGroupIds) { + SavedTabGroup group = tabGroupSyncService.getGroup(new LocalTabGroupId(groupId)); + if (group == null || isEmpty(group.collaborationId)) continue; + sharedGroupTitles.add(getDisplayableTitle(context, filter, groupId)); + break; + } + + if (sharedGroupTitles.isEmpty()) return; + sharedGroupTitles.size(); + String iphText = + context.getString(R.string.tab_group_update_iph_text, sharedGroupTitles.get(0)); + + userEducationHelper.requestShowIph( + new IphCommandBuilder( + anchorView.getResources(), + FeatureConstants.TAB_GROUP_SHARE_VERSION_UPDATE_FEATURE, + iphText, + iphText) + .setAnchorView(anchorView) + .setHighlightParams(new HighlightParams(HighlightShape.CIRCLE)) + .setOnShowCallback( + () -> + versioningMessageController.onMessageUiShown( + MessageType.VERSION_UPDATED_MESSAGE)) + .build()); } private static boolean wontShowIphForProfile(@Nullable Profile profile) { return profile == null || profile.isOffTheRecord(); } + @Nullable + private static Profile getProfile(TabGroupModelFilter filter) { + Profile profile = filter.getTabModel().getProfile(); + if (wontShowIphForProfile(profile)) return null; + return profile; + } + private static VersioningMessageController getVersioningMessageController(Profile profile) { TabGroupSyncService tabGroupSyncService = TabGroupSyncServiceFactory.getForProfile(profile); assert tabGroupSyncService != null; return tabGroupSyncService.getVersioningMessageController(); } - private static @Nullable String getTabGroupTitleFromMessages( - Context context, TabGroupModelFilter filter, List<PersistentMessage> messages) { - for (PersistentMessage message : messages) { - Token tabGroupId = extractTabGroupId(message); - if (tabGroupId != null) { - String title = getDisplayableTitle(context, filter, tabGroupId); - if (title != null) return title; - } - } - return null; - } - - private static void showIph( - UserEducationHelper userEducationHelper, - View anchorView, - String contentString, - VersioningMessageController versioningMessageController) { - userEducationHelper.requestShowIph( - new IphCommandBuilder( - anchorView.getResources(), - FeatureConstants.TAB_GROUP_SHARE_VERSION_UPDATE_FEATURE, - contentString, - contentString) - .setAnchorView(anchorView) - .setHighlightParams(new HighlightParams(HighlightShape.CIRCLE)) - .build()); - - versioningMessageController.onMessageUiShown(MessageType.VERSION_UPDATED_MESSAGE); - } - private static boolean shouldNotShowIph(VersioningMessageController controller) { return !controller.isInitialized() || !controller.shouldShowMessageUi(MessageType.VERSION_UPDATED_MESSAGE);
diff --git a/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/TabSwitcherGroupSuggestionServiceUnitTest.java b/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/TabSwitcherGroupSuggestionServiceUnitTest.java index ae80f78..8ac76efc 100644 --- a/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/TabSwitcherGroupSuggestionServiceUnitTest.java +++ b/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/TabSwitcherGroupSuggestionServiceUnitTest.java
@@ -237,7 +237,7 @@ verify(mSuggestionLifecycleObserverHandler).onSuggestionIgnored(); reset(mSuggestionLifecycleObserverHandler); - observer.tabPendingClosure(mockTab, 0); + observer.onTabClosePending(Collections.singletonList(mockTab), /* isAllTabs= */ false, 0); verify(mSuggestionLifecycleObserverHandler).onSuggestionIgnored(); }
diff --git a/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/VersionUpdateIphHandlerUnitTest.java b/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/VersionUpdateIphHandlerUnitTest.java index 6e5053f1..1b8fc71 100644 --- a/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/VersionUpdateIphHandlerUnitTest.java +++ b/chrome/browser/tab_ui/android/junit/src/org/chromium/chrome/browser/tab_ui/VersionUpdateIphHandlerUnitTest.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.tab_ui; +import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -27,7 +28,6 @@ import org.chromium.base.Token; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.chrome.browser.collaboration.messaging.MessagingBackendServiceFactory; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncServiceFactory; @@ -35,29 +35,23 @@ import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.user_education.IphCommand; import org.chromium.chrome.browser.user_education.UserEducationHelper; -import org.chromium.components.collaboration.messaging.MessageAttribution; -import org.chromium.components.collaboration.messaging.MessagingBackendService; -import org.chromium.components.collaboration.messaging.PersistentMessage; -import org.chromium.components.collaboration.messaging.TabGroupMessageMetadata; import org.chromium.components.prefs.PrefService; import org.chromium.components.tab_group_sync.LocalTabGroupId; import org.chromium.components.tab_group_sync.MessageType; +import org.chromium.components.tab_group_sync.SavedTabGroup; import org.chromium.components.tab_group_sync.TabGroupSyncService; import org.chromium.components.tab_group_sync.VersioningMessageController; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.components.user_prefs.UserPrefsJni; import java.util.Collections; -import java.util.List; -import java.util.Optional; +import java.util.Set; /** Unit tests for {@link VersionUpdateIphHandler}. */ @RunWith(BaseRobolectricTestRunner.class) public class VersionUpdateIphHandlerUnitTest { private static final String FAKE_GROUP_TITLE = "FAKE_GROUP_TITLE"; private static final Token FAKE_TOKEN = new Token(1L, 2L); - private static final TabModelDotInfo DOT_INFO = - new TabModelDotInfo(/* showDot= */ true, FAKE_GROUP_TITLE); @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @@ -67,27 +61,26 @@ @Mock private TabModel mTabModel; @Mock private TabGroupSyncService mTabGroupSyncService; @Mock private VersioningMessageController mVersioningMessageController; - @Mock private MessagingBackendService mMessagingBackendService; @Mock private PrefService mPrefService; @Mock private UserPrefs.Natives mUserPrefsJniMock; @Captor private ArgumentCaptor<IphCommand> mIphCommandCaptor; + private Context mContext; private View mAnchorView; @Before public void setUp() { - Context context = + mContext = new ContextThemeWrapper( ApplicationProvider.getApplicationContext(), R.style.Theme_BrowserUI_DayNight); - mAnchorView = new View(context); + mAnchorView = new View(mContext); when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); when(mPrefService.getBoolean(Pref.AUTO_OPEN_SYNCED_TAB_GROUPS)).thenReturn(true); TabGroupSyncServiceFactory.setForTesting(mTabGroupSyncService); - MessagingBackendServiceFactory.setForTesting(mMessagingBackendService); UserPrefsJni.setInstanceForTesting(mUserPrefsJniMock); when(mProfile.isOffTheRecord()).thenReturn(false); @@ -97,94 +90,129 @@ when(mVersioningMessageController.shouldShowMessageUi(MessageType.VERSION_UPDATED_MESSAGE)) .thenReturn(true); when(mTabGroupModelFilter.getTabModel()).thenReturn(mTabModel); - when(mTabGroupModelFilter.getTabGroupTitle(any(Token.class))).thenReturn(FAKE_GROUP_TITLE); + when(mTabGroupModelFilter.tabGroupExists(FAKE_TOKEN)).thenReturn(true); + when(mTabGroupModelFilter.getTabGroupTitle(FAKE_TOKEN)).thenReturn(FAKE_GROUP_TITLE); when(mTabModel.getProfile()).thenReturn(mProfile); + + SavedTabGroup group = new SavedTabGroup(); + group.collaborationId = "COLLABORATION_ID"; + group.title = FAKE_GROUP_TITLE; + when(mTabGroupModelFilter.getAllTabGroupIds()).thenReturn(Set.of(FAKE_TOKEN)); + when(mTabGroupSyncService.getGroup(new LocalTabGroupId(FAKE_TOKEN))).thenReturn(group); } @Test - public void testTabSwitcherButtonIph_isShown() { - VersionUpdateIphHandler.maybeShowTabSwitcherButtonIph( - mUserEducationHelper, mAnchorView, mProfile, DOT_INFO); + public void testIph_autoOpenEnabled() { + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ true); - verify(mUserEducationHelper).requestShowIph(any()); - verify(mVersioningMessageController).onMessageUiShown(MessageType.VERSION_UPDATED_MESSAGE); - } - - @Test - public void testTabSwitcherButtonIph_notShown_offTheRecord() { - when(mProfile.isOffTheRecord()).thenReturn(true); - VersionUpdateIphHandler.maybeShowTabSwitcherButtonIph( - mUserEducationHelper, mAnchorView, mProfile, DOT_INFO); - verify(mUserEducationHelper, never()).requestShowIph(any()); - } - - @Test - public void testTabSwitcherButtonIph_notShown_autoOpenEnabled() { - when(mVersioningMessageController.isInitialized()).thenReturn(false); - VersionUpdateIphHandler.maybeShowTabSwitcherButtonIph( - mUserEducationHelper, mAnchorView, mProfile, DOT_INFO); - verify(mUserEducationHelper, never()).requestShowIph(any()); - } - - @Test - public void testTabSwitcherButtonIph_notShown_controllerShouldNotShow() { - when(mVersioningMessageController.shouldShowMessageUi(MessageType.VERSION_UPDATED_MESSAGE)) - .thenReturn(false); - VersionUpdateIphHandler.maybeShowTabSwitcherButtonIph( - mUserEducationHelper, mAnchorView, mProfile, DOT_INFO); - verify(mUserEducationHelper, never()).requestShowIph(any()); - } - - @Test - public void testTabGroupPaneButtonIph_isShown() { - when(mPrefService.getBoolean(Pref.AUTO_OPEN_SYNCED_TAB_GROUPS)).thenReturn(false); - PersistentMessage message = createMessage(FAKE_TOKEN); - when(mMessagingBackendService.getMessages(Optional.of(MessageType.VERSION_UPDATED_MESSAGE))) - .thenReturn(List.of(message)); - - VersionUpdateIphHandler.maybeShowTabGroupPaneButtonIph( - mUserEducationHelper, mTabGroupModelFilter, mAnchorView); verify(mUserEducationHelper).requestShowIph(mIphCommandCaptor.capture()); + + IphCommand command = mIphCommandCaptor.getValue(); + String expectedText = + mContext.getString(R.string.tab_group_update_iph_text, FAKE_GROUP_TITLE); + assertEquals(expectedText, command.contentString); + command.onShowCallback.run(); + verify(mVersioningMessageController).onMessageUiShown(MessageType.VERSION_UPDATED_MESSAGE); } @Test - public void testTabGroupPaneButtonIph_notShown_autoOpenEnabled() { + public void testIph_autoOpenDisabled() { + when(mPrefService.getBoolean(Pref.AUTO_OPEN_SYNCED_TAB_GROUPS)).thenReturn(false); + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ false); + + verify(mUserEducationHelper).requestShowIph(mIphCommandCaptor.capture()); + + IphCommand command = mIphCommandCaptor.getValue(); + command.onShowCallback.run(); + + verify(mVersioningMessageController).onMessageUiShown(MessageType.VERSION_UPDATED_MESSAGE); + } + + @Test + public void testIph_notShown() { + when(mPrefService.getBoolean(Pref.AUTO_OPEN_SYNCED_TAB_GROUPS)).thenReturn(false); + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ true); + verify(mUserEducationHelper, never()).requestShowIph(any()); + + when(mPrefService.getBoolean(Pref.AUTO_OPEN_SYNCED_TAB_GROUPS)).thenReturn(true); + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ false); + verify(mUserEducationHelper, never()).requestShowIph(any()); + } + + @Test + public void testIph_profileOffTheRecord() { + when(mProfile.isOffTheRecord()).thenReturn(true); + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ true); + verify(mUserEducationHelper, never()).requestShowIph(any()); + } + + @Test + public void testIph_controllerNotInitialized() { + when(mVersioningMessageController.isInitialized()).thenReturn(false); + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ true); + verify(mUserEducationHelper, never()).requestShowIph(any()); + } + + @Test + public void testIph_controllerShouldNotShow() { when(mVersioningMessageController.shouldShowMessageUi(MessageType.VERSION_UPDATED_MESSAGE)) .thenReturn(false); - VersionUpdateIphHandler.maybeShowTabGroupPaneButtonIph( - mUserEducationHelper, mTabGroupModelFilter, mAnchorView); + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ true); verify(mUserEducationHelper, never()).requestShowIph(any()); } @Test - public void testTabGroupPaneButtonIph_notShown_noMessages() { - when(mMessagingBackendService.getMessages(Optional.of(MessageType.VERSION_UPDATED_MESSAGE))) - .thenReturn(Collections.emptyList()); - VersionUpdateIphHandler.maybeShowTabGroupPaneButtonIph( - mUserEducationHelper, mTabGroupModelFilter, mAnchorView); + public void testIph_noTabGroups() { + when(mTabGroupModelFilter.getAllTabGroupIds()).thenReturn(Collections.emptySet()); + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ true); verify(mUserEducationHelper, never()).requestShowIph(any()); } @Test - public void testTabGroupPaneButtonIph_notShown_noTitle() { - PersistentMessage message = createMessage(FAKE_TOKEN); - when(mMessagingBackendService.getMessages(Optional.of(MessageType.VERSION_UPDATED_MESSAGE))) - .thenReturn(List.of(message)); - VersionUpdateIphHandler.maybeShowTabGroupPaneButtonIph( - mUserEducationHelper, mTabGroupModelFilter, mAnchorView); + public void testIph_noSharedTabGroups() { + SavedTabGroup group = new SavedTabGroup(); + group.collaborationId = null; + group.title = FAKE_GROUP_TITLE; + when(mTabGroupSyncService.getGroup(new LocalTabGroupId(FAKE_TOKEN))).thenReturn(group); + + VersionUpdateIphHandler.maybeShowVersioningIph( + mUserEducationHelper, + mAnchorView, + mTabGroupModelFilter, + /* expectsAutoOpen= */ true); verify(mUserEducationHelper, never()).requestShowIph(any()); } - - private PersistentMessage createMessage(Token tabGroupId) { - TabGroupMessageMetadata metadata = new TabGroupMessageMetadata(); - metadata.localTabGroupId = new LocalTabGroupId(tabGroupId); - - MessageAttribution attribution = new MessageAttribution(); - attribution.tabGroupMetadata = metadata; - - PersistentMessage message = new PersistentMessage(); - message.attribution = attribution; - return message; - } }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java index b68c3c8b..482c8dad 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java
@@ -246,4 +246,9 @@ public int getMultiSelectedTabsCount() { return 0; } + + @Override + public int findFirstNonPinnedTabIndex() { + return 0; + } }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java index 749e450..1ac5e7c 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
@@ -401,4 +401,9 @@ public int getMultiSelectedTabsCount() { return mDelegateModel.getMultiSelectedTabsCount(); } + + @Override + public int findFirstNonPinnedTabIndex() { + return mDelegateModel.findFirstNonPinnedTabIndex(); + } }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupModelFilterImpl.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupModelFilterImpl.java index c3a9ce2..05ff54d 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupModelFilterImpl.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupModelFilterImpl.java
@@ -277,6 +277,7 @@ private void createSingleTabGroupInternal(Tab tab, Token tabGroupId) { assert tab.getTabGroupId() == null; + unpinTabIfNeeded(tab); int rootId = tab.getRootId(); mGroupIdToRootIdMap.put(tabGroupId, rootId); @@ -347,6 +348,7 @@ } for (int i = 0; i < tabsToMerge.size(); i++) { Tab tab = tabsToMerge.get(i); + unpinTabIfNeeded(tab); for (TabGroupModelFilterObserver observer : mGroupFilterObserver) { observer.willMergeTabToGroup(tab, destinationRootId, destinationTabGroupId); } @@ -372,6 +374,7 @@ resetFilterState(); if (!wasDestinationTabInAGroup) { + unpinTabIfNeeded(destinationTab); for (TabGroupModelFilterObserver observer : mGroupFilterObserver) { observer.didMergeTabToGroup(destinationTab, /* isDestinationTab= */ true); } @@ -460,6 +463,7 @@ if (wasDestinationTabInAGroup) { destinationTabGroupId = destinationTab.getTabGroupId(); } else { + unpinTabIfNeeded(destinationTab); Token mergedTabGroupId = null; for (Tab tab : tabs) { mergedTabGroupId = tab.getTabGroupId(); @@ -507,6 +511,7 @@ // Iterate through all tabs to set the proper new group creation status. for (int i = 0; i < tabs.size(); i++) { Tab tab = tabs.get(i); + unpinTabIfNeeded(tab); for (TabGroupModelFilterObserver observer : mGroupFilterObserver) { observer.willMergeTabToGroup(tab, destinationRootId, destinationTabGroupId); @@ -920,6 +925,7 @@ Tab parentTab = getParentTab(tab); if (!fromUndo && shouldGroupWithParent(tab, parentTab)) { if (parentTab != null) { + unpinTabIfNeeded(tab); Token oldTabGroupId = parentTab.getTabGroupId(); Token newTabGroupId = getOrCreateTabGroupId(parentTab); if (!Objects.equals(oldTabGroupId, newTabGroupId)) { @@ -1487,6 +1493,14 @@ return getTabModel().isIncognito(); } + private void unpinTabIfNeeded(@Nullable Tab tab) { + if (tab == null) return; + + if (tab.getIsPinned()) { + getTabModel().unpinTab(tab.getId()); + } + } + @Override public List<Tab> getRepresentativeTabList() { int size = getIndividualTabAndGroupCount(); @@ -1985,17 +1999,10 @@ // class. @Override - public void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) { - for (TabModelObserver observer : mFilteredObservers) { - observer.tabPendingClosure(tab, closingSource); - } - } - - @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) { for (TabModelObserver observer : mFilteredObservers) { - observer.multipleTabsPendingClosure(tabs, isAllTabs, closingSource); + observer.onTabClosePending(tabs, isAllTabs, closingSource); } }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupModelFilterImplUnitTest.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupModelFilterImplUnitTest.java index 39869cba..0b6ec64 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupModelFilterImplUnitTest.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupModelFilterImplUnitTest.java
@@ -2955,4 +2955,56 @@ .destinationGroupTitleCollapsed; })); } + + @Test + public void testCreateSingleTabGroup_UnpinsTab() { + when(mTab1.getIsPinned()).thenReturn(true); + mTabGroupModelFilter.createSingleTabGroup(mTab1); + verify(mTabModel).unpinTab(mTab1.getId()); + } + + @Test + public void testMergeTabsToGroup_UnpinsDestinationTab() { + when(mTab1.getIsPinned()).thenReturn(true); + mTabGroupModelFilter.mergeTabsToGroup(mTab2.getId(), mTab1.getId()); + verify(mTabModel).unpinTab(mTab1.getId()); + } + + @Test + public void testMergeTabsToGroup_UnpinsSourceTab() { + when(mTab1.getIsPinned()).thenReturn(true); + mTabGroupModelFilter.mergeTabsToGroup(mTab1.getId(), mTab2.getId()); + verify(mTabModel).unpinTab(mTab1.getId()); + } + + @Test + public void testMergeListOfTabsToGroup_UnpinsMultiplePinnedTabs() { + mTabGroupModelFilter.moveTabOutOfGroupInDirection(TAB2_ID, /* trailing= */ true); + + when(mTab1.getIsPinned()).thenReturn(true); + when(mTab2.getIsPinned()).thenReturn(true); + List<Tab> tabsToMerge = new ArrayList<>(Arrays.asList(mTab1, mTab2)); + + mTabGroupModelFilter.mergeListOfTabsToGroup( + tabsToMerge, mTab5, /* indexInGroup= */ null, false); + + verify(mTabModel).unpinTab(mTab1.getId()); + verify(mTabModel).unpinTab(mTab2.getId()); + } + + @Test + public void testMergeListOfTabsToGroup_UnpinsPinnedSourceAndDestination() { + mTabGroupModelFilter.moveTabOutOfGroupInDirection(TAB2_ID, /* trailing= */ true); + mTabGroupModelFilter.moveTabOutOfGroupInDirection(TAB5_ID, /* trailing= */ true); + + when(mTab1.getIsPinned()).thenReturn(true); + when(mTab5.getIsPinned()).thenReturn(true); + List<Tab> tabsToMerge = new ArrayList<>(Arrays.asList(mTab1)); + + mTabGroupModelFilter.mergeListOfTabsToGroup( + tabsToMerge, mTab5, /* indexInGroup= */ null, false); + + verify(mTabModel).unpinTab(mTab1.getId()); + verify(mTabModel).unpinTab(mTab5.getId()); + } }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupTitleUtils.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupTitleUtils.java index 38665f1..a72df2a1 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupTitleUtils.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupTitleUtils.java
@@ -16,6 +16,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.tab.Tab; +import java.util.List; import java.util.Objects; /** Helper class to handle tab group title related utilities. */ @@ -67,7 +68,13 @@ ? tabGroupModelFilter.getTabGroupTitle(assumeNonNull(tabGroupId)) : null; if (TextUtils.isEmpty(explicitTitle)) { - int tabCount = tabGroupModelFilter.getTabCountForGroup(tabGroupId); + int tabCount = 0; + List<Tab> tabsInGroup = tabGroupModelFilter.getTabsInGroup(assumeNonNull(tabGroupId)); + for (Tab tab : tabsInGroup) { + if (!tab.isClosing()) { + tabCount++; + } + } return getDefaultTitle(context, tabCount); } else { return explicitTitle;
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupTitleUtilsUnitTest.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupTitleUtilsUnitTest.java index 2e3e540..965a680 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupTitleUtilsUnitTest.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabGroupTitleUtilsUnitTest.java
@@ -13,6 +13,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -34,6 +35,10 @@ import org.chromium.base.ContextUtils; import org.chromium.base.Token; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.tab.Tab; + +import java.util.ArrayList; +import java.util.List; /** Tests for {@link TabGroupTitleUtils}. */ @RunWith(BaseRobolectricTestRunner.class) @@ -52,6 +57,9 @@ @Mock SharedPreferences.Editor mPutStringEditor; @Mock SharedPreferences.Editor mRemoveEditor; @Mock TabGroupModelFilter mTabGroupModelFilter; + @Mock Tab mTab1; + @Mock Tab mTab2; + @Mock Tab mTab3; Context mContext; @@ -143,11 +151,92 @@ @Test public void testGetDisplayableTitle_Fallback() { int tabCount = 4567; + when(mTabGroupModelFilter.tabGroupExists(TAB_GROUP_ID)).thenReturn(true); when(mTabGroupModelFilter.getTabGroupTitle(TAB_GROUP_ID)).thenReturn(""); - when(mTabGroupModelFilter.getTabCountForGroup(TAB_GROUP_ID)).thenReturn(tabCount); + + List<Tab> tabs = new ArrayList<>(); + for (int i = 0; i < tabCount; i++) { + Tab tab = mock(Tab.class); + when(tab.isClosing()).thenReturn(false); + tabs.add(tab); + } + when(mTabGroupModelFilter.getTabsInGroup(TAB_GROUP_ID)).thenReturn(tabs); + String title = TabGroupTitleUtils.getDisplayableTitle( mContext, mTabGroupModelFilter, TAB_GROUP_ID); assertTrue(title.contains(String.valueOf(tabCount))); } + + @Test + public void testGetDisplayableTitle_FallbackNoClosingTabs() { + when(mTabGroupModelFilter.tabGroupExists(TAB_GROUP_ID)).thenReturn(true); + when(mTabGroupModelFilter.getTabGroupTitle(TAB_GROUP_ID)).thenReturn(null); + List<Tab> tabs = new ArrayList<>(); + tabs.add(mTab1); + tabs.add(mTab2); + when(mTab1.isClosing()).thenReturn(false); + when(mTab2.isClosing()).thenReturn(false); + when(mTabGroupModelFilter.getTabsInGroup(TAB_GROUP_ID)).thenReturn(tabs); + + String title = + TabGroupTitleUtils.getDisplayableTitle( + mContext, mTabGroupModelFilter, TAB_GROUP_ID); + + assertTrue(title.contains("2")); + } + + @Test + public void testGetDisplayableTitle_FallbackSomeClosingTabs() { + when(mTabGroupModelFilter.tabGroupExists(TAB_GROUP_ID)).thenReturn(true); + when(mTabGroupModelFilter.getTabGroupTitle(TAB_GROUP_ID)).thenReturn(null); + List<Tab> tabs = new ArrayList<>(); + tabs.add(mTab1); + tabs.add(mTab2); + tabs.add(mTab3); + when(mTab1.isClosing()).thenReturn(false); + when(mTab2.isClosing()).thenReturn(true); + when(mTab3.isClosing()).thenReturn(false); + when(mTabGroupModelFilter.getTabsInGroup(TAB_GROUP_ID)).thenReturn(tabs); + + String title = + TabGroupTitleUtils.getDisplayableTitle( + mContext, mTabGroupModelFilter, TAB_GROUP_ID); + + assertTrue(title.contains("2")); + assertFalse(title.contains("3")); + } + + @Test + public void testGetDisplayableTitle_FallbackAllClosingTabs() { + when(mTabGroupModelFilter.tabGroupExists(TAB_GROUP_ID)).thenReturn(true); + when(mTabGroupModelFilter.getTabGroupTitle(TAB_GROUP_ID)).thenReturn(null); + List<Tab> tabs = new ArrayList<>(); + tabs.add(mTab1); + tabs.add(mTab2); + when(mTab1.isClosing()).thenReturn(true); + when(mTab2.isClosing()).thenReturn(true); + when(mTabGroupModelFilter.getTabsInGroup(TAB_GROUP_ID)).thenReturn(tabs); + + String title = + TabGroupTitleUtils.getDisplayableTitle( + mContext, mTabGroupModelFilter, TAB_GROUP_ID); + + assertTrue(title.contains("0")); + assertFalse(title.contains("2")); + } + + @Test + public void testGetDisplayableTitle_FallbackNoTabs() { + when(mTabGroupModelFilter.tabGroupExists(TAB_GROUP_ID)).thenReturn(true); + when(mTabGroupModelFilter.getTabGroupTitle(TAB_GROUP_ID)).thenReturn(null); + List<Tab> tabs = new ArrayList<>(); + when(mTabGroupModelFilter.getTabsInGroup(TAB_GROUP_ID)).thenReturn(tabs); + + String title = + TabGroupTitleUtils.getDisplayableTitle( + mContext, mTabGroupModelFilter, TAB_GROUP_ID); + + assertTrue(title.contains("0")); + } }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java index 8b3eb29..dd1cfee7 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java
@@ -188,4 +188,11 @@ * @return The total count of selected tabs. */ int getMultiSelectedTabsCount(); + + /** + * Returns the index of the first non-pinned tab in the model. + * + * @return The index of the first non-pinned tab, or the model count if all tabs are pinned. + */ + int findFirstNonPinnedTabIndex(); }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java index e7858811..ef622316 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java
@@ -113,23 +113,14 @@ default void didChangePinState(Tab tab) {} /** - * Called when a tab is pending closure, i.e. the user has just closed it, but it can still be - * undone. At this point, the Tab has been removed from the TabModel and can only be accessed - * via {@link TabModel#getComprehensiveModel()}. + * Called right before when tabs are pending closure, i.e. the user has just closed them, but it + * can still be undone. * - * @param tab The tab that is pending closure. + * @param tabs The list of {@link Tab}s that are pending closure. + * @param isAllTabs Whether tabs are all the tabs. * @param closingSource The tab closing source, e.g. the tablet tab strip. */ - default void tabPendingClosure(Tab tab, @TabClosingSource int closingSource) {} - - /** - * Called when multiple tabs are pending closure. - * - * @param tabs The tabs that are pending closure. - * @param isAllTabs Whether |tabs| are all the tabs. - * @param closingSource The tab closing source, e.g. the tablet tab strip. - */ - default void multipleTabsPendingClosure( + default void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) {} /** @@ -179,8 +170,7 @@ // TODO(crbug.com/381471263): The following methods are still in development and will // replace the existing tab closure events in the near future. Methods being replaced are - // tabPendingClosure, multipleTabsPendingClosure, tabClosureUndone, - // allTabsClosureUndone, tabClosureCommitted, willCloseAllTabs, + // tabClosureUndone, allTabsClosureUndone, tabClosureCommitted, willCloseAllTabs, // willCloseMultipleTabs and allTabsClosureCommitted. /** * Called right before {@code tabs} will be destroyed. @@ -191,15 +181,6 @@ default void onTabCloseImmediate(List<Tab> tabs, boolean isAllTabs) {} /** - * Called right before when tabs are pending closure, i.e. the user has just closed them, but it - * can still be undone. - * - * @param tabs The list of {@link Tab}s that are pending closure. - * @param isAllTabs Whether tabs are all the tabs. - */ - default void onTabClosePending(List<Tab> tabs, boolean isAllTabs) {} - - /** * Called right before {@code tabs} closure is committed permanently and cannot be undone. * * @param tabs The list of {@link Tab}s that are closed.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index b810f717..2096234 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1019,15 +1019,6 @@ "confirm_bubble_model.h", "focus_tab_after_navigation_helper.cc", "focus_tab_after_navigation_helper.h", - "web_applications/web_app_dialog_utils.cc", - "web_applications/web_app_dialog_utils.h", - - # TODO(crbug.com/369756821): this file includes //c/b/ash/crosapi headers, - # and hence needs to depend on //c/b/ash/crosapi GN target. This causes a circular - # dependency that is not trivial to sort out. - # When crosapi code gets deleted during the lacros sunset, move this file to the - # appropriated build target. - "global_media_controls/media_notification_service.cc", "intent_picker_tab_helper.cc", "intent_picker_tab_helper.h", "layout_constants.cc", @@ -1087,45 +1078,6 @@ "singleton_tabs.h", "tab_modal_confirm_dialog_delegate.cc", "tab_modal_confirm_dialog_delegate.h", - "tabs/saved_tab_groups/collaboration_messaging_observer.cc", - "tabs/saved_tab_groups/collaboration_messaging_observer.h", - "tabs/saved_tab_groups/collaboration_messaging_observer_factory.cc", - "tabs/saved_tab_groups/collaboration_messaging_observer_factory.h", - "tabs/saved_tab_groups/collaboration_messaging_page_action_controller.cc", - "tabs/saved_tab_groups/collaboration_messaging_page_action_controller.h", - "tabs/saved_tab_groups/collaboration_messaging_tab_data.cc", - "tabs/saved_tab_groups/collaboration_messaging_tab_data.h", - "tabs/saved_tab_groups/instant_message_queue_processor.cc", - "tabs/saved_tab_groups/instant_message_queue_processor.h", - "tabs/saved_tab_groups/local_tab_group_listener.cc", - "tabs/saved_tab_groups/local_tab_group_listener.h", - "tabs/saved_tab_groups/most_recent_shared_tab_update_store.cc", - "tabs/saved_tab_groups/most_recent_shared_tab_update_store.h", - "tabs/saved_tab_groups/saved_tab_group_controller.h", - "tabs/saved_tab_groups/saved_tab_group_keyed_service.cc", - "tabs/saved_tab_groups/saved_tab_group_keyed_service.h", - "tabs/saved_tab_groups/saved_tab_group_metrics.cc", - "tabs/saved_tab_groups/saved_tab_group_metrics.h", - "tabs/saved_tab_groups/saved_tab_group_model_listener.cc", - "tabs/saved_tab_groups/saved_tab_group_model_listener.h", - "tabs/saved_tab_groups/saved_tab_group_pref_names.cc", - "tabs/saved_tab_groups/saved_tab_group_pref_names.h", - "tabs/saved_tab_groups/saved_tab_group_service_factory.cc", - "tabs/saved_tab_groups/saved_tab_group_service_factory.h", - "tabs/saved_tab_groups/saved_tab_group_utils.cc", - "tabs/saved_tab_groups/saved_tab_group_utils.h", - "tabs/saved_tab_groups/saved_tab_group_web_contents_listener.cc", - "tabs/saved_tab_groups/saved_tab_group_web_contents_listener.h", - "tabs/saved_tab_groups/session_service_tab_group_sync_observer.cc", - "tabs/saved_tab_groups/session_service_tab_group_sync_observer.h", - "tabs/saved_tab_groups/shared_tab_group_feedback_controller.cc", - "tabs/saved_tab_groups/shared_tab_group_feedback_controller.h", - "tabs/saved_tab_groups/tab_group_action_context_desktop.cc", - "tabs/saved_tab_groups/tab_group_action_context_desktop.h", - "tabs/saved_tab_groups/tab_group_sync_delegate_desktop.cc", - "tabs/saved_tab_groups/tab_group_sync_delegate_desktop.h", - "tabs/saved_tab_groups/tab_group_sync_service_proxy.cc", - "tabs/saved_tab_groups/tab_group_sync_service_proxy.h", "uma_browsing_activity_observer.cc", "uma_browsing_activity_observer.h", "unload_controller.cc", @@ -1136,6 +1088,8 @@ "views/file_system_access/file_system_access_scroll_panel.h", "views/search_engine_choice/search_engine_choice_dialog_view.cc", "views/search_engine_choice/search_engine_choice_dialog_view.h", + "web_applications/web_app_dialog_utils.cc", + "web_applications/web_app_dialog_utils.h", "webui/bookmarks/bookmark_prefs.cc", "webui/bookmarks/bookmark_prefs.h", "webui/bookmarks/bookmarks_message_handler.cc", @@ -1464,6 +1418,8 @@ "//chrome/browser/ui/tabs:glic_impl", "//chrome/browser/ui/tabs/organization", "//chrome/browser/ui/tabs/organization:impl", + "//chrome/browser/ui/tabs/saved_tab_groups", + "//chrome/browser/ui/tabs/saved_tab_groups:impl", "//chrome/browser/ui/task_manager", "//chrome/browser/ui/thumbnails", "//chrome/browser/ui/translate:impl", @@ -1604,6 +1560,7 @@ "//components/endpoint_fetcher", "//components/enterprise/common:files_scan_data", "//components/feedback/proto", + "//components/headless/console_message_logger", "//components/headless/policy", "//components/history_embeddings", "//components/keep_alive_registry", @@ -1627,10 +1584,6 @@ "//components/regional_capabilities:country_access_reason", "//components/safe_browsing/core/common:safe_browsing_policy_handler", "//components/safety_check", - "//components/saved_tab_groups/delegate", - "//components/saved_tab_groups/internal", - "//components/saved_tab_groups/internal:tab_group_sync_bridge", - "//components/saved_tab_groups/public", "//components/search_provider_logos", "//components/services/app_service", "//components/supervised_user/core/common", @@ -1726,6 +1679,7 @@ "//chrome/browser/ui/privacy_sandbox:impl", "//chrome/browser/ui/tabs/alert:impl", "//chrome/browser/ui/tabs/organization:impl", + "//chrome/browser/ui/tabs/saved_tab_groups:impl", "//chrome/browser/ui/toasts:impl", "//chrome/browser/ui/webui/customize_buttons", "//chrome/browser/ui/webui/customize_buttons:impl",
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java index 5b3c55bc2..206912e 100644 --- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java +++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
@@ -709,8 +709,22 @@ dialog.show(); } + @Nullable + private ListItem getInstanceListItem(InstanceInfo item) { + ModelList list = mIsInactiveListShowing ? mInactiveModelList : mActiveModelList; + for (ListItem listItem : list) { + if (listItem.model.get(InstanceSwitcherItemProperties.INSTANCE_ID) == item.instanceId) { + return listItem; + } + } + return null; + } + private void showNameWindowDialog(InstanceInfo item) { + RecordUserAction.record("Android.WindowManager.NameWindow"); int style = R.style.Theme_Chromium_Multiwindow_RenameWindowDialog; + ListItem listItem = assumeNonNull(getInstanceListItem(item)); + String currentTitle = listItem.model.get(InstanceSwitcherItemProperties.TITLE); Dialog dialog = new Dialog(mContext, style); dialog.setCanceledOnTouchOutside(true); dialog.setContentView(R.layout.rename_window_dialog); @@ -721,7 +735,7 @@ TextInputLayout textInputLayout = dialog.findViewById(R.id.new_window_title); TextInputEditText editText = dialog.findViewById(R.id.title_input_text); - editText.setText(mUiUtils.getItemTitle(item)); + editText.setText(currentTitle); editText.requestFocus(); Window window = assumeNonNull(dialog.getWindow()); window.setSoftInputMode( @@ -733,17 +747,13 @@ v -> { String newTitle = Objects.toString(editText.getText(), "").trim(); if (!TextUtils.isEmpty(newTitle)) { - ModelList list = - mIsInactiveListShowing ? mInactiveModelList : mActiveModelList; - for (ListItem listItem : list) { - if (listItem.model.get(InstanceSwitcherItemProperties.INSTANCE_ID) - == item.instanceId) { - listItem.model.set(InstanceSwitcherItemProperties.TITLE, newTitle); - break; - } + RecordUserAction.record("Android.WindowManager.SaveWindowName"); + if (!newTitle.equals(currentTitle)) { + listItem.model.set(InstanceSwitcherItemProperties.TITLE, newTitle); + RecordUserAction.record("Android.WindowManager.ChangeWindowName"); + mRenameWindowCallback.onResult(new Pair<>(item.instanceId, newTitle)); } dialog.dismiss(); - mRenameWindowCallback.onResult(new Pair<>(item.instanceId, newTitle)); } else { textInputLayout.setError( mContext.getString(
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java index d01fd5f..6ea0ea7 100644 --- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java +++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinatorTest.java
@@ -965,6 +965,16 @@ onView(withId(R.id.active_instance_list)) .inRoot(isDialog()) .check(matches(atPosition(1, hasDescendant(withText(newName))))); + + // Reopen the name window dialog. + clickMoreButtonAtPosition(1, R.id.active_instance_list); + onView(withText(R.string.instance_switcher_name_window)) + .inRoot(withDecorView(withClassName(containsString("Popup")))) + .check(matches(isDisplayed())) + .perform(click()); + + // Check that the input text field is updated. + onView(withId(R.id.title_input_text)).inRoot(isDialog()).check(matches(withText(newName))); } @Test
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImpl.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImpl.java index bc45ccc..f5556bfb 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImpl.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImpl.java
@@ -66,12 +66,14 @@ String hint, String accessibilityHint, /* SuggestTemplateInfo.TemplateAction.ActionType */ int actionType, - String actionUri) { - if (actionType == SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE && !mDialerAvailable) { + String actionUri, + boolean showAsActionButton) { + if (actionType == SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE + && !mDialerAvailable) { return null; } return new OmniboxActionInSuggest( - nativeInstance, hint, accessibilityHint, actionType, actionUri); + nativeInstance, hint, accessibilityHint, actionType, actionUri, showAsActionButton); } @Override
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImplUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImplUnitTest.java index f0ec93b..0705d1f 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImplUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImplUnitTest.java
@@ -83,7 +83,13 @@ assertNotNull( OmniboxActionInSuggest.from( OmniboxActionFactoryImpl.get() - .buildActionInSuggest(0, "hint", "accessibility", 1, "url"))); + .buildActionInSuggest( + 0, + "hint", + "accessibility", + 1, + "url", + /* showAsActionButton= */ false))); } @Test @@ -96,7 +102,8 @@ "hint", "accessibility", SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE, - "url")); + "url", + /* showAsActionButton= */ false)); } @Test @@ -109,6 +116,7 @@ "hint", "accessibility", SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE, - "url")); + "url", + /* showAsActionButton= */ false)); } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggest.java index ece022b..2ed94c8d 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggest.java
@@ -11,8 +11,8 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.chrome.browser.omnibox.OmniboxMetrics; -import org.chromium.components.omnibox.SuggestTemplateInfoProto.SuggestTemplateInfo; import org.chromium.components.omnibox.R; +import org.chromium.components.omnibox.SuggestTemplateInfoProto.SuggestTemplateInfo; import org.chromium.components.omnibox.action.OmniboxAction; import org.chromium.components.omnibox.action.OmniboxActionDelegate; import org.chromium.components.omnibox.action.OmniboxActionId; @@ -35,14 +35,16 @@ String hint, String accessibilityHint, /* SuggestTemplateInfo.TemplateAction.ActionType */ int actionType, - String actionUri) { + String actionUri, + boolean showAsActionButton) { super( OmniboxActionId.ACTION_IN_SUGGEST, nativeInstance, hint, accessibilityHint, ICON_MAP.get(actionType, DEFAULT_ICON), - R.style.TextAppearance_ChipText); + R.style.TextAppearance_ChipText, + showAsActionButton); this.actionType = actionType; mActionUri = actionUri; } @@ -70,6 +72,11 @@ map.put( SuggestTemplateInfo.TemplateAction.ActionType.REVIEWS_VALUE, new ChipIcon(R.drawable.action_reviews, true)); + map.put( + SuggestTemplateInfo.TemplateAction.ActionType.CHROME_AIM_VALUE, + new ChipIcon( + org.chromium.chrome.browser.omnibox.R.drawable.search_spark_black_24dp, + true)); return map; } @@ -89,6 +96,7 @@ switch (actionType) { case SuggestTemplateInfo.TemplateAction.ActionType.REVIEWS_VALUE: + case SuggestTemplateInfo.TemplateAction.ActionType.CHROME_AIM_VALUE: delegate.loadPageInCurrentTab(assumeNonNull(intent.getDataString())); actionStarted = true; break;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggestUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggestUnitTest.java index 2817648e..4b76697 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggestUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggestUnitTest.java
@@ -29,6 +29,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.HistogramWatcher; import org.chromium.chrome.browser.omnibox.OmniboxMetrics; import org.chromium.chrome.browser.omnibox.R; import org.chromium.components.embedder_support.util.UrlConstants; @@ -47,7 +48,8 @@ List.of( SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE, SuggestTemplateInfo.TemplateAction.ActionType.DIRECTIONS_VALUE, - SuggestTemplateInfo.TemplateAction.ActionType.REVIEWS_VALUE); + SuggestTemplateInfo.TemplateAction.ActionType.REVIEWS_VALUE, + SuggestTemplateInfo.TemplateAction.ActionType.CHROME_AIM_VALUE); private static final SuggestTemplateInfo.TemplateAction EMPTY_INFO = SuggestTemplateInfo.TemplateAction.getDefaultInstance(); @@ -60,7 +62,13 @@ public void creation_usesCustomIconForKnownActionTypes() { for (var kesemActionType : sKnownActionTypes) { var action = - new OmniboxActionInSuggest(0, "hint", "accessibility", kesemActionType, ""); + new OmniboxActionInSuggest( + 0, + "hint", + "accessibility", + kesemActionType, + "", + /* showAsActionButton= */ false); assertNotEquals(OmniboxAction.DEFAULT_ICON, action.icon); } } @@ -71,7 +79,12 @@ if (sKnownActionTypes.contains(kesemActionType.getNumber())) continue; var action = new OmniboxActionInSuggest( - 0, "hint", "accessibility", kesemActionType.getNumber(), ""); + 0, + "hint", + "accessibility", + kesemActionType.getNumber(), + "", + /* showAsActionButton= */ false); assertEquals(OmniboxAction.DEFAULT_ICON, action.icon); } } @@ -82,7 +95,12 @@ AssertionError.class, () -> new OmniboxActionInSuggest( - 0, null, "", SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE, "")); + 0, + null, + "", + SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE, + "", + /* showAsActionButton= */ false)); } @Test @@ -91,7 +109,12 @@ AssertionError.class, () -> new OmniboxActionInSuggest( - 0, "", "", SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE, "")); + 0, + "", + "", + SuggestTemplateInfo.TemplateAction.ActionType.CALL_VALUE, + "", + /* showAsActionButton= */ false)); } @Test @@ -111,7 +134,8 @@ "hint", "accessibility", null, - R.style.TextAppearance_ChipText) { + R.style.TextAppearance_ChipText, + /* showAsActionButton= */ false) { @Override public void execute(OmniboxActionDelegate d) {} })); @@ -126,14 +150,16 @@ "hint", "accessibility", SuggestTemplateInfo.TemplateAction.ActionType.REVIEWS_VALUE, - "")); + "", + /* showAsActionButton= */ false)); } /** Create Action in Suggest with a supplied definition. */ private OmniboxAction buildActionInSuggest( SuggestTemplateInfo.TemplateAction.ActionType type, Intent intent) { var uri = intent.toUri(Intent.URI_INTENT_SCHEME); - return new OmniboxActionInSuggest(0, "wink", "accessibility", type.getNumber(), uri); + return new OmniboxActionInSuggest( + 0, "wink", "accessibility", type.getNumber(), uri, /* showAsActionButton= */ false); } @Test @@ -287,4 +313,29 @@ assertEquals(UrlConstants.CHROME_DINO_URL, url); verifyNoMoreInteractions(mDelegate); } + + @Test + public void executeActionInSuggest_executeAim() { + var intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(UrlConstants.CHROME_DINO_URL)); + + var histogramWatcher = + HistogramWatcher.newSingleRecordWatcher( + "Android.Omnibox.ActionInSuggest.IntentResult", + OmniboxMetrics.ActionInSuggestIntentResult.SUCCESS); + + buildActionInSuggest(SuggestTemplateInfo.TemplateAction.ActionType.CHROME_AIM, intent) + .execute(mDelegate); + + verify(mDelegate, times(1)).isIncognito(); + + histogramWatcher.assertExpected(); + + verify(mDelegate, times(1)).loadPageInCurrentTab(mUrlCaptor.capture()); + + var url = mUrlCaptor.getValue(); + assertNotNull(url); + assertEquals(UrlConstants.CHROME_DINO_URL, url); + verifyNoMoreInteractions(mDelegate); + } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxAnswerAction.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxAnswerAction.java index 436e50e..f9b3706 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxAnswerAction.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxAnswerAction.java
@@ -28,7 +28,8 @@ hint, accessibilityHint, NO_ICON, - R.style.TextAppearance_ChipText); + R.style.TextAppearance_ChipText, + /* showAsActionButton= */ false); } @Override
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedal.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedal.java index 4fa1bbb..99c05bd 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedal.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedal.java
@@ -40,7 +40,8 @@ pedalId == OmniboxPedalId.PLAY_CHROME_DINO_GAME ? DINO_GAME_ICON : OmniboxAction.DEFAULT_ICON, - R.style.TextAppearance_ChipText); + R.style.TextAppearance_ChipText, + /* showAsActionButton= */ false); this.pedalId = pedalId; }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedalUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedalUnitTest.java index f6c1d481..9db90d6 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedalUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedalUnitTest.java
@@ -89,7 +89,8 @@ "", "", null, - R.style.TextAppearance_ChipText) { + R.style.TextAppearance_ChipText, + /* showAsActionButton= */ false) { @Override public void execute(OmniboxActionDelegate d) {} }));
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessor.java index 97b0afc..4655ce5 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessor.java
@@ -67,25 +67,35 @@ return; } - var actionChipList = suggestion.getActions(); + var actions = suggestion.getActions(); var modelList = new ModelList(); - for (OmniboxAction chip : actionChipList) { + for (OmniboxAction action : actions) { + // Skip the action that is shown as button, instead of chip. + if (action.showAsActionButton) { + continue; + } + final var chipModel = new PropertyModel.Builder(ChipProperties.ALL_KEYS) - .with(ChipProperties.TEXT, chip.hint) - .with(ChipProperties.CONTENT_DESCRIPTION, chip.accessibilityHint) + .with(ChipProperties.TEXT, action.hint) + .with(ChipProperties.CONTENT_DESCRIPTION, action.accessibilityHint) .with(ChipProperties.ENABLED, true) - .with(ChipProperties.CLICK_HANDLER, m -> executeAction(chip, position)) - .with(ChipProperties.ICON, chip.icon.iconRes) - .with(ChipProperties.APPLY_ICON_TINT, chip.icon.tintWithTextColor) + .with( + ChipProperties.CLICK_HANDLER, + m -> executeAction(action, position)) + .with(ChipProperties.ICON, action.icon.iconRes) + .with(ChipProperties.APPLY_ICON_TINT, action.icon.tintWithTextColor) .with( ChipProperties.PRIMARY_TEXT_APPEARANCE, - chip.primaryTextAppearance) + action.primaryTextAppearance) .build(); modelList.add(new ListItem(ActionChipsProperties.ViewType.CHIP, chipModel)); - mVisibleActions.put(chip, position); + mVisibleActions.put(action, position); + } + if (modelList.size() == 0) { + return; } model.set(ActionChipsProperties.ACTION_CHIPS, modelList);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessorUnitTest.java index 193840ad..82340f1 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessorUnitTest.java
@@ -72,7 +72,8 @@ "hint", "accessibility hint", OmniboxAction.DEFAULT_ICON, - textAppearance) { + textAppearance, + /* showAsActionButton= */ false) { @Override public void execute(OmniboxActionDelegate delegate) {} };
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorUnitTest.java index a1a80f3..f75dda5 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorUnitTest.java
@@ -38,17 +38,21 @@ import org.chromium.chrome.browser.omnibox.styles.OmniboxImageSupplier; import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; +import org.chromium.chrome.browser.omnibox.suggestions.action.OmniboxActionInSuggest; import org.chromium.components.metrics.OmniboxEventProtos.OmniboxEventProto.PageClassification; import org.chromium.components.omnibox.AutocompleteInput; import org.chromium.components.omnibox.AutocompleteMatch; import org.chromium.components.omnibox.AutocompleteMatchBuilder; import org.chromium.components.omnibox.OmniboxFeatureList; import org.chromium.components.omnibox.OmniboxSuggestionType; +import org.chromium.components.omnibox.SuggestTemplateInfoProto.SuggestTemplateInfo; +import org.chromium.components.omnibox.action.OmniboxAction; import org.chromium.components.omnibox.suggestions.OmniboxSuggestionUiType; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; +import java.util.List; import java.util.Optional; /** Tests for {@link BaseSuggestionViewProcessor}. */ @@ -131,6 +135,18 @@ mProcessor.populateModel(mInput, mSuggestion, mModel, 0); } + private void createSuggestionWithActions( + int type, boolean isSearch, GURL url, List<OmniboxAction> actions) { + mSuggestion = + new AutocompleteMatchBuilder(type) + .setIsSearch(isSearch) + .setUrl(url) + .setActions(actions) + .build(); + mModel = mProcessor.createModel(); + mProcessor.populateModel(mInput, mSuggestion, mModel, 0); + } + @Test public void suggestionFavicons_showFaviconWhenAvailable() { final ArgumentCaptor<Callback<Bitmap>> callback = ArgumentCaptor.forClass(Callback.class); @@ -356,4 +372,77 @@ Assert.assertEquals(null, actions); } } + + @Test + public void addActionButtonIfAvailable() { + // No action button. + { + createSuggestion( + OmniboxSuggestionType.OPEN_TAB, + /* isSearch= */ false, + /* hasTabMatch= */ false, + TEST_URL); + var actions = mModel.get(BaseSuggestionViewProperties.ACTION_BUTTONS); + Assert.assertEquals(null, actions); + } + + // No action button. + { + createSuggestionWithActions( + OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, + /* isSearch= */ true, + TEST_URL, + List.of( + new OmniboxActionInSuggest( + 0, + "hint", + "accessibility", + SuggestTemplateInfo.TemplateAction.ActionType.REVIEWS_VALUE, + "https://google.com", + /* showAsActionButton= */ false))); + + var actions = mModel.get(BaseSuggestionViewProperties.ACTION_BUTTONS); + Assert.assertEquals(null, actions); + } + + // One action button is added. + { + createSuggestionWithActions( + OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, + /* isSearch= */ true, + TEST_URL, + List.of( + new OmniboxActionInSuggest( + 0, + "hint", + "accessibility", + SuggestTemplateInfo.TemplateAction.ActionType.REVIEWS_VALUE, + "https://google.com", + /* showAsActionButton= */ false), + new OmniboxActionInSuggest( + 0, + "hint2", + "accessibility2", + SuggestTemplateInfo.TemplateAction.ActionType.CHROME_AIM_VALUE, + "https://google.com", + /* showAsActionButton= */ true), + new OmniboxActionInSuggest( + 0, + "hint3", + "accessibility3", + SuggestTemplateInfo.TemplateAction.ActionType.CHROME_AIM_VALUE, + "https://google.com", + /* showAsActionButton= */ true))); + + var actions = mModel.get(BaseSuggestionViewProperties.ACTION_BUTTONS); + Assert.assertEquals(1, actions.size()); + + var action = actions.get(0); + + Assert.assertEquals("accessibility2", action.accessibilityDescription); + Assert.assertEquals( + R.drawable.search_spark_black_24dp, + shadowOf(action.icon.drawable).getCreatedFromResId()); + } + } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java index 0eb0c6e..fbf74c66 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessor.java
@@ -256,6 +256,29 @@ if (suggestion.isSearchSuggestion()) { fetchImage(model, suggestion.getImageUrl()); } + + addActionButtonIfAvailable(suggestion, model, position); + } + + private void addActionButtonIfAvailable( + AutocompleteMatch suggestion, PropertyModel model, int position) { + for (var action : suggestion.getActions()) { + if (!action.showAsActionButton) { + continue; + } + setActionButtons( + model, + List.of( + new Action( + OmniboxDrawableState.forSmallIcon( + mContext, action.icon.iconRes, true), + action.accessibilityHint, + () -> { + mSuggestionHost.onOmniboxActionClicked(action, position); + }))); + // Only one action button is supported. + return; + } } @Override
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java index bf193fb..727ff5b 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java
@@ -34,9 +34,18 @@ @VisibleForTesting static final WritableBooleanPropertyKey ALLOW_WRAP_AROUND = new WritableBooleanPropertyKey(); + /** The custom content description for the suggestion view. */ + @VisibleForTesting + static final WritableObjectPropertyKey<String> CONTENT_DESCRIPTION = + new WritableObjectPropertyKey<>(); + static final PropertyKey[] ALL_UNIQUE_KEYS = new PropertyKey[] { - IS_SEARCH_SUGGESTION, TEXT_LINE_1_TEXT, TEXT_LINE_2_TEXT, ALLOW_WRAP_AROUND + IS_SEARCH_SUGGESTION, + TEXT_LINE_1_TEXT, + TEXT_LINE_2_TEXT, + ALLOW_WRAP_AROUND, + CONTENT_DESCRIPTION }; static final PropertyKey[] ALL_KEYS =
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java index 32f9e72..4462750 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java
@@ -64,6 +64,8 @@ if (tv.getMaxLines() != maxLines) { tv.setMaxLines(maxLines); } + } else if (propertyKey == SuggestionViewProperties.CONTENT_DESCRIPTION) { + view.setContentDescription(model.get(SuggestionViewProperties.CONTENT_DESCRIPTION)); } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tabgroup/TabGroupSuggestionProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tabgroup/TabGroupSuggestionProcessor.java index a4ef658..747deb44 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tabgroup/TabGroupSuggestionProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tabgroup/TabGroupSuggestionProcessor.java
@@ -13,6 +13,7 @@ import android.text.style.ImageSpan; import androidx.annotation.ColorInt; +import androidx.annotation.StringRes; import androidx.core.content.ContextCompat; import org.chromium.build.annotations.NullMarked; @@ -87,6 +88,7 @@ model.set( SuggestionViewProperties.TEXT_LINE_2_TEXT, new SuggestionSpannable(suggestion.getDescription())); + model.set(SuggestionViewProperties.CONTENT_DESCRIPTION, getContentDescription(suggestion)); } private SuggestionSpannable getTitleSpannable(AutocompleteMatch suggestion) { @@ -118,4 +120,20 @@ /* flags= */ Spannable.SPAN_INCLUSIVE_EXCLUSIVE); return titleSpannable; } + + private String getContentDescription(AutocompleteMatch suggestion) { + int plainColorId = Integer.parseInt(assumeNonNull(suggestion.getImageDominantColor())); + @TabGroupColorId + int colorId = TabGroupColorPickerUtils.getTabGroupCardColorId(plainColorId); + @StringRes + int colorDescRes = + TabGroupColorPickerUtils.getTabGroupColorPickerItemColorAccessibilityString( + colorId); + String colorDesc = mContext.getString(colorDescRes); + return mContext.getString( + R.string.accessibility_tab_group_suggestion_description, + suggestion.getDisplayText(), + colorDesc, + suggestion.getDescription()); + } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tabgroup/TabGroupSuggestionProcessorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tabgroup/TabGroupSuggestionProcessorUnitTest.java index 615d2dea..154a43d 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tabgroup/TabGroupSuggestionProcessorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/tabgroup/TabGroupSuggestionProcessorUnitTest.java
@@ -129,5 +129,13 @@ .subSequence( 3, mModel.get(SuggestionViewProperties.TEXT_LINE_1_TEXT).length()) .toString()); + + String targetString = + mContext.getString( + R.string.accessibility_tab_group_suggestion_description, + TITLE, + "Red", + DESCRIPTION); + Assert.assertEquals(targetString, mModel.get(SuggestionViewProperties.CONTENT_DESCRIPTION)); } }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index ef734f9..d98b6076 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -4230,21 +4230,6 @@ <message name="IDS_MENU_READER_MODE_PREFS" desc="Menu item to show reader mode preferences pane, which allows users to change the appearance (font size, theme, etc.) of the page. [CHAR_LIMIT=27]"> Appearance </message> - <message name="IDS_READER_MODE_BOTTOM_SHEET_TITLE" desc="Title of the Reading Mode bottom sheet. [CHAR_LIMIT=27]"> - Reading mode - </message> - <message name="IDS_READER_MODE_BOTTOM_SHEET_CONTENT_DESCRIPTION" desc="Content description of the Reading Mode bottom sheet."> - Reading mode bottom sheet - </message> - <message name="IDS_READER_MODE_BOTTOM_SHEET_CLOSED_CONTENT_DESCRIPTION" desc="Content description of the Reading Mode bottom sheet when closed."> - Reading mode bottom sheet closed - </message> - <message name="IDS_READER_MODE_BOTTOM_SHEET_HALF_HEIGHT_CONTENT_DESCRIPTION" desc="Content description of the Reading Mode bottom sheet when opened at half height."> - Reading mode bottom sheet opened at half height - </message> - <message name="IDS_READER_MODE_BOTTOM_SHEET_FULL_HEIGHT_CONTENT_DESCRIPTION" desc="Content description of the Reading Mode bottom sheet when opened at full height."> - Reading mode bottom sheet opened at full height - </message> <message name="IDS_MENU_SETTINGS" desc="Menu item for opening browser settings. [CHAR_LIMIT=27]"> Settings </message> @@ -6983,6 +6968,9 @@ <message name="IDS_ACCESSIBILITY_SEARCH_LOUPE_TOOLTIP_TEXT" desc="Content description for opening up the tab search window, which allows users to search their tabs."> Open tab search </message> + <message name="IDS_ACCESSIBILITY_TAB_GROUP_SUGGESTION_DESCRIPTION" desc="Content description for a tab group suggestion. Clicking the suggestion will open the tab group. TITLE_OF_GROUP is the title of the group. COLOR_NAME is the color of this group. URL_LIST is the list of tab urls in the group."> + Open <ph name="TITLE_OF_GROUP">%1$s<ex>Shopping cart</ex></ph> tab group, color <ph name="COLOR_NAME">%2$s<ex>Blue</ex></ph>, with sites <ph name="URL_LIST">%3$s<ex>amazon.com</ex></ph>. + </message> <!-- Default browser promo --> <message name="IDS_DEFAULT_BROWSER_PROMO_CARD_TITLE" desc="Title of a promotion about setting Chrome the default browser."> @@ -7023,6 +7011,25 @@ Group tabs </message> + <!-- Reader mode --> + <message name="IDS_READER_MODE_BOTTOM_SHEET_TITLE" desc="Title of the Reading Mode bottom sheet. [CHAR_LIMIT=27]"> + Reading mode + </message> + <message name="IDS_READER_MODE_BOTTOM_SHEET_CONTENT_DESCRIPTION" desc="Content description of the Reading Mode bottom sheet."> + Reading mode bottom sheet + </message> + <message name="IDS_READER_MODE_BOTTOM_SHEET_CLOSED_CONTENT_DESCRIPTION" desc="Content description of the Reading Mode bottom sheet when closed."> + Reading mode bottom sheet closed + </message> + <message name="IDS_READER_MODE_BOTTOM_SHEET_HALF_HEIGHT_CONTENT_DESCRIPTION" desc="Content description of the Reading Mode bottom sheet when opened at half height."> + Reading mode bottom sheet opened at half height + </message> + <message name="IDS_READER_MODE_BOTTOM_SHEET_FULL_HEIGHT_CONTENT_DESCRIPTION" desc="Content description of the Reading Mode bottom sheet when opened at full height."> + Reading mode bottom sheet opened at full height + </message> + <message name="IDS_READER_MODE_UNAVAILABLE_SNACKBAR_MESSAGE" desc="Snackbar message that shown when the user attempts to enter reader mode, but content extraction fails."> + Reader mode is unavailable + </message> </messages> </release> </grit>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESSIBILITY_TAB_GROUP_SUGGESTION_DESCRIPTION.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESSIBILITY_TAB_GROUP_SUGGESTION_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..951512f5 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESSIBILITY_TAB_GROUP_SUGGESTION_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +4dd1cd9afa1fc706e49ca34dc21fac604917461a \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READER_MODE_UNAVAILABLE_SNACKBAR_MESSAGE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READER_MODE_UNAVAILABLE_SNACKBAR_MESSAGE.png.sha1 new file mode 100644 index 0000000..458ac29 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_READER_MODE_UNAVAILABLE_SNACKBAR_MESSAGE.png.sha1
@@ -0,0 +1 @@ +85686099cafed75accecfa27e22ee2b40c6c7b8f \ No newline at end of file
diff --git a/chrome/browser/ui/android/tab_model/tab_collection_tab_model_impl.cc b/chrome/browser/ui/android/tab_model/tab_collection_tab_model_impl.cc index f43d86a..bed7b05 100644 --- a/chrome/browser/ui/android/tab_model/tab_collection_tab_model_impl.cc +++ b/chrome/browser/ui/android/tab_model/tab_collection_tab_model_impl.cc
@@ -366,6 +366,10 @@ return TabAndroid::FromTabHandle(*handle); } +int TabCollectionTabModelImpl::GetIndexOfFirstNonPinnedTab(JNIEnv* env) { + return tab_strip_collection_->IndexOfFirstNonPinnedTab(); +} + // Private methods: size_t TabCollectionTabModelImpl::GetSafeIndex(
diff --git a/chrome/browser/ui/android/tab_model/tab_collection_tab_model_impl.h b/chrome/browser/ui/android/tab_model/tab_collection_tab_model_impl.h index 6072a8d9..00cba0e 100644 --- a/chrome/browser/ui/android/tab_model/tab_collection_tab_model_impl.h +++ b/chrome/browser/ui/android/tab_model/tab_collection_tab_model_impl.h
@@ -128,6 +128,9 @@ // Gets the last shown tab for a group. TabAndroid* GetLastShownTabForGroup(JNIEnv* env, const base::Token& group_id); + // Returns the index of the first non-pinned tab. + int GetIndexOfFirstNonPinnedTab(JNIEnv* env); + private: // Returns a safe index for adding or moving a tab or tab group. // `is_tab_group` is used to indicate if we are working with a tab or a tab
diff --git a/chrome/browser/ui/android/tab_model/tab_model_observer.cc b/chrome/browser/ui/android/tab_model/tab_model_observer.cc index 6cf424c..780e8b7 100644 --- a/chrome/browser/ui/android/tab_model/tab_model_observer.cc +++ b/chrome/browser/ui/android/tab_model/tab_model_observer.cc
@@ -34,7 +34,7 @@ int new_index, int old_index) {} -void TabModelObserver::TabPendingClosure(TabAndroid* tab, +void TabModelObserver::OnTabClosePending(const std::vector<TabAndroid*>& tabs, TabModel::TabClosingSource source) {} void TabModelObserver::TabClosureUndone(TabAndroid* tab) {} @@ -44,9 +44,6 @@ void TabModelObserver::TabClosureCommitted(TabAndroid* tab) {} -void TabModelObserver::AllTabsPendingClosure( - const std::vector<raw_ptr<TabAndroid, VectorExperimental>>& tabs) {} - void TabModelObserver::AllTabsClosureCommitted() {} void TabModelObserver::TabRemoved(TabAndroid* tab) {}
diff --git a/chrome/browser/ui/android/tab_model/tab_model_observer.h b/chrome/browser/ui/android/tab_model/tab_model_observer.h index 0fcaeec..f10ac5f 100644 --- a/chrome/browser/ui/android/tab_model/tab_model_observer.h +++ b/chrome/browser/ui/android/tab_model/tab_model_observer.h
@@ -49,10 +49,10 @@ // another. virtual void DidMoveTab(TabAndroid* tab, int new_index, int old_index); - // Called when a tab is pending closure (ie, the user has just closed it, but - // it can still be undone). At this point the |tab| has been removed from the + // Called when tabs are pending closure (ie, the user has just closed it, but + // it can still be undone). At this point the tabs have been removed from the // TabModel. - virtual void TabPendingClosure(TabAndroid* tab, + virtual void OnTabClosePending(const std::vector<TabAndroid*>& tabs, TabModel::TabClosingSource source); // Called when all |tabs| closure is undone. @@ -65,10 +65,6 @@ // Called when a |tab| closure is committed and can't be undone anymore. virtual void TabClosureCommitted(TabAndroid* tab); - // Called when all |tabs| are pending closure. - virtual void AllTabsPendingClosure( - const std::vector<raw_ptr<TabAndroid, VectorExperimental>>& tabs); - // Called when an all tabs closure has been committed and can't be undone // anymore. virtual void AllTabsClosureCommitted();
diff --git a/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc b/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc index 517cdaa..b575d47 100644 --- a/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc +++ b/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.cc
@@ -140,15 +140,13 @@ } } -void TabModelObserverJniBridge::TabPendingClosure( +void TabModelObserverJniBridge::OnTabClosePending( JNIEnv* env, - const JavaParamRef<jobject>& jtab, + const std::vector<TabAndroid*>& tabs, int jsource) { - TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab); - CHECK(tab); TabModel::TabClosingSource source = GetTabClosingSource(env, jsource); for (auto& observer : model_observers_) { - observer.TabPendingClosure(tab, source); + observer.OnTabClosePending(tabs, source); } } @@ -183,17 +181,6 @@ } } -void TabModelObserverJniBridge::AllTabsPendingClosure( - JNIEnv* env, - const JavaParamRef<jobjectArray>& jtabs) { - std::vector<raw_ptr<TabAndroid, VectorExperimental>> tabs = - TabAndroid::GetAllNativeTabs(env, - ScopedJavaLocalRef<jobjectArray>(jtabs)); - for (auto& observer : model_observers_) { - observer.AllTabsPendingClosure(tabs); - } -} - void TabModelObserverJniBridge::AllTabsClosureCommitted(JNIEnv* env) { for (auto& observer : model_observers_) { observer.AllTabsClosureCommitted();
diff --git a/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h b/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h index 7973f00..8feb46f 100644 --- a/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h +++ b/chrome/browser/ui/android/tab_model/tab_model_observer_jni_bridge.h
@@ -7,6 +7,8 @@ #include <jni.h> +#include <vector> + #include "base/android/jni_weak_ref.h" #include "base/android/scoped_java_ref.h" #include "base/memory/raw_ref.h" @@ -15,6 +17,7 @@ #include "chrome/browser/ui/tabs/tab_list_interface_observer.h" class TabModel; +class TabAndroid; // Bridges calls between the C++ and the Java TabModelObservers. Functions in // this class do little more than translating between Java TabModelObserver @@ -66,8 +69,8 @@ int new_index, int cur_index); - void TabPendingClosure(JNIEnv* env, - const base::android::JavaParamRef<jobject>& jtab, + void OnTabClosePending(JNIEnv* env, + const std::vector<TabAndroid*>& tabs, int source); void TabClosureUndone(JNIEnv* env, @@ -79,10 +82,6 @@ void TabClosureCommitted(JNIEnv* env, const base::android::JavaParamRef<jobject>& jtab); - void AllTabsPendingClosure( - JNIEnv* env, - const base::android::JavaParamRef<jobjectArray>& jtabs); - void AllTabsClosureCommitted(JNIEnv* env); void TabRemoved(JNIEnv* env,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinator.java index c0d634db..5cf0018 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinator.java
@@ -5,7 +5,7 @@ package org.chromium.chrome.browser.toolbar.top; import static org.chromium.build.NullUtil.assumeNonNull; -import static org.chromium.chrome.browser.tab_ui.VersionUpdateIphHandler.maybeShowTabSwitcherButtonIph; +import static org.chromium.chrome.browser.tab_ui.VersionUpdateIphHandler.maybeShowVersioningIph; import android.content.Context; import android.content.res.ColorStateList; @@ -23,19 +23,18 @@ import org.chromium.base.CallbackController; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.OneshotSupplier; -import org.chromium.base.supplier.Supplier; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.layouts.LayoutStateProvider; import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver; import org.chromium.chrome.browser.layouts.LayoutType; -import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.CurrentTabObserver; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab_ui.TabModelDotInfo; import org.chromium.chrome.browser.tabmodel.IncognitoStateProvider; +import org.chromium.chrome.browser.tabmodel.TabGroupModelFilter; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.chrome.browser.theme.ThemeColorProvider; @@ -69,7 +68,6 @@ private final OneshotSupplier<Boolean> mPromoShownOneshotSupplier; private final CurrentTabObserver mPageLoadObserver; private final ObservableSupplier<TabModelSelector> mTabModelSelectorSupplier; - private final Supplier<Profile> mProfileSupplier; private final Callback<Integer> mTabCountSupplierObserver = this::onUpdateTabCount; private final Callback<TabModelDotInfo> mNotificationDotObserver = this::onUpdateNotificationDot; @@ -96,7 +94,6 @@ * @param layoutStateProviderSupplier Allows observing layout state. * @param activityTabSupplier Supplier of the activity tab. * @param tabModelSelectorSupplier Supplier for @{@link TabModelSelector}. - * @param versionUpdateIphHandler Aids in showing the version update IPH. */ public ToggleTabStackButtonCoordinator( Context context, @@ -107,15 +104,13 @@ ObservableSupplier<@Nullable Tab> activityTabSupplier, ObservableSupplier<TabModelSelector> tabModelSelectorSupplier, ThemeColorProvider themeColorProvider, - IncognitoStateProvider incognitoStateProvider, - Supplier<Profile> profileSupplier) { + IncognitoStateProvider incognitoStateProvider) { super(themeColorProvider, incognitoStateProvider); mContext = context; mToggleTabStackButton = toggleTabStackButton; mUserEducationHelper = userEducationHelper; mPromoShownOneshotSupplier = promoShownOneshotSupplier; mTabModelSelectorSupplier = tabModelSelectorSupplier; - mProfileSupplier = profileSupplier; layoutStateProviderSupplier.onAvailable( mCallbackController.makeCancelable(this::setLayoutStateProvider)); @@ -323,6 +318,19 @@ void handlePageLoadFinished() { if (!mToggleTabStackButton.isShown()) return; + TabGroupModelFilter tabGroupModelFilter = + mTabModelSelectorSupplier + .get() + .getTabGroupModelFilterProvider() + .getCurrentTabGroupModelFilter(); + if (tabGroupModelFilter != null) { + maybeShowVersioningIph( + mUserEducationHelper, + mToggleTabStackButton, + tabGroupModelFilter, + /* expectsAutoOpen= */ false); + } + HighlightParams params = new HighlightParams(HighlightShape.CIRCLE); params.setBoundsRespectPadding(true); IphCommandBuilder builder = null; @@ -405,12 +413,6 @@ private void onUpdateNotificationDot(TabModelDotInfo tabModelDotInfo) { mToggleTabStackButton.onUpdateNotificationDot(tabModelDotInfo); if (tabModelDotInfo.showDot && mUserEducationHelper != null) { - maybeShowTabSwitcherButtonIph( - mUserEducationHelper, - mToggleTabStackButton, - mProfileSupplier.get(), - tabModelDotInfo); - String tabGroupTitle = tabModelDotInfo.tabGroupTitle; String contentString = mContext.getString(R.string.tab_group_update_iph_text, tabGroupTitle);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java index 414c797..68c1050 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToggleTabStackButtonCoordinatorTest.java
@@ -43,6 +43,8 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab_ui.TabModelDotInfo; import org.chromium.chrome.browser.tabmodel.IncognitoStateProvider; +import org.chromium.chrome.browser.tabmodel.TabGroupModelFilter; +import org.chromium.chrome.browser.tabmodel.TabGroupModelFilterProvider; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.theme.TopUiThemeColorProvider; @@ -72,6 +74,8 @@ @Mock private OnClickListener mOnClickListener; @Mock private OnLongClickListener mOnLongClickListener; @Mock private TabModelSelector mTabModelSelector; + @Mock private TabGroupModelFilterProvider mTabGroupModelFilterProvider; + @Mock private TabGroupModelFilter mTabGroupModelFilter; @Mock private TabModel mStandardTabModel; @Mock private TabModel mIncognitoTabModel; @Mock private TopUiThemeColorProvider mTopUIThemeProvider; @@ -126,6 +130,11 @@ mTabModelSelectorSupplier.set(mTabModelSelector); when(mTabModelSelector.getCurrentModel()).thenReturn(mStandardTabModel); when(mTabModelSelector.getModel(true)).thenReturn(mIncognitoTabModel); + when(mTabModelSelector.getTabGroupModelFilterProvider()) + .thenReturn(mTabGroupModelFilterProvider); + when(mTabGroupModelFilter.getTabModel()).thenReturn(mStandardTabModel); + when(mTabGroupModelFilterProvider.getCurrentTabGroupModelFilter()) + .thenReturn(mTabGroupModelFilter); when(mStandardTabModel.isIncognitoBranded()).thenReturn(false); when(mIncognitoTabModel.isIncognitoBranded()).thenReturn(true); when(mIncognitoTabModel.getCount()).thenReturn(0); @@ -152,8 +161,7 @@ new ObservableSupplierImpl<>(), mTabModelSelectorSupplier, mTopUIThemeProvider, - mIncognitoStateProvider, - () -> mProfile); + mIncognitoStateProvider); coordinator.initializeWithNative( mOnClickListener,
diff --git a/chrome/browser/ui/ash/new_window/DEPS b/chrome/browser/ui/ash/new_window/DEPS index c408665..88e2e49 100644 --- a/chrome/browser/ui/ash/new_window/DEPS +++ b/chrome/browser/ui/ash/new_window/DEPS
@@ -10,7 +10,6 @@ "+chrome/browser/ash/system_web_apps/apps/calculator_app", "+chrome/browser/ash/system_web_apps/apps/camera_app", "+chrome/browser/ash/system_web_apps/system_web_app_manager.h", - "+chrome/browser/browser_process.h", "+chrome/browser/chromeos/arc", "+chrome/browser/chromeos/network", "+chrome/browser/extensions/extension_util.h", @@ -40,6 +39,7 @@ specific_include_rules = { "chrome_new_window_client_browsertest\\.cc": [ + "+chrome/browser/browser_process.h", "+chrome/browser/ui/browser_list.h", "+chrome/test", ],
diff --git a/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc b/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc index 20ef63c..412beaceb 100644 --- a/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc +++ b/chrome/browser/ui/ash/shelf/shelf_context_menu_unittest.cc
@@ -45,7 +45,9 @@ #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/chrome_ash_test_base.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/ash/components/browser_context_helper/annotated_account_id.h" #include "chromeos/ash/components/dbus/chunneld/chunneld_client.h" #include "chromeos/ash/components/dbus/cicerone/cicerone_client.h" #include "chromeos/ash/components/dbus/concierge/concierge_client.h" @@ -53,9 +55,15 @@ #include "chromeos/ash/experiences/arc/metrics/arc_metrics_constants.h" #include "chromeos/ash/experiences/arc/mojom/app.mojom.h" #include "chromeos/ash/experiences/arc/test/fake_app_instance.h" +#include "components/account_id/account_id.h" #include "components/exo/shell_surface_util.h" #include "components/policy/core/common/policy_pref_names.h" #include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" +#include "components/user_manager/fake_user_manager_delegate.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/test_helper.h" +#include "components/user_manager/user_manager_impl.h" #include "components/viz/test/test_gpu_service_holder.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/base/l10n/l10n_util.h" @@ -100,7 +108,10 @@ ShelfContextMenuTest& operator=(const ShelfContextMenuTest&) = delete; protected: - ShelfContextMenuTest() = default; + ShelfContextMenuTest() { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kDisableDefaultApps); + } ~ShelfContextMenuTest() override = default; void SetUp() override { @@ -109,12 +120,19 @@ ash::ConciergeClient::InitializeFake(); ash::SeneschalClient::InitializeFake(); + user_manager_.Reset(std::make_unique<user_manager::UserManagerImpl>( + std::make_unique<user_manager::FakeUserManagerDelegate>(), + TestingBrowserProcess::GetGlobal()->GetTestingLocalState())); ChromeAshTestBase::SetUp(); - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kDisableDefaultApps); - + const AccountId account_id = + AccountId::FromUserEmailGaiaId("test@test", GaiaId("12345")); + ASSERT_TRUE(user_manager::TestHelper(user_manager_.Get()) + .AddRegularUser(account_id)); + user_manager_->UserLoggedIn( + account_id, user_manager::TestHelper::GetFakeUsernameHash(account_id)); profile_ = std::make_unique<TestingProfile>(); + ash::AnnotatedAccountId::Set(profile_.get(), account_id); extensions::TestExtensionSystem* extension_system( static_cast<extensions::TestExtensionSystem*>( @@ -205,6 +223,7 @@ profile_.reset(); ChromeAshTestBase::TearDown(); + user_manager_.Reset(); ash::SeneschalClient::Shutdown(); ash::ConciergeClient::Shutdown(); @@ -244,6 +263,7 @@ viz::TestGpuServiceHolder::ScopedAllowRacyFeatureListOverrides gpu_thread_allow_racy_overrides_; base::test::ScopedCommandLine scoped_command_line_; + user_manager::ScopedUserManager user_manager_; std::unique_ptr<TestingProfile> profile_; std::unique_ptr<CrostiniTestHelper> crostini_helper_; ArcAppTest arc_test_;
diff --git a/chrome/browser/ui/bookmarks/BUILD.gn b/chrome/browser/ui/bookmarks/BUILD.gn index f2d6be38..78e0b543 100644 --- a/chrome/browser/ui/bookmarks/BUILD.gn +++ b/chrome/browser/ui/bookmarks/BUILD.gn
@@ -71,6 +71,7 @@ "//chrome/browser/ui/browser_window", "//chrome/browser/ui/tabs:tab_group", "//chrome/browser/ui/tabs:tab_strip", + "//chrome/browser/ui/tabs/saved_tab_groups", "//components/bookmarks/common", "//components/bookmarks/managed", "//components/saved_tab_groups/public:features",
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index dec508b3..8d9845fc 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -59,6 +59,7 @@ #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/file_select_helper.h" #include "chrome/browser/first_run/first_run.h" +#include "chrome/browser/headless/headless_mode_util.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/lifetime/browser_shutdown.h" #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" @@ -173,6 +174,7 @@ #include "components/custom_handlers/register_protocol_handler_permission_request.h" #include "components/favicon/content/content_favicon_driver.h" #include "components/find_in_page/find_tab_helper.h" +#include "components/headless/console_message_logger/headless_console_message_logger.h" #include "components/infobars/content/content_infobar_manager.h" #include "components/javascript_dialogs/tab_modal_dialog_manager.h" #include "components/keep_alive_registry/keep_alive_registry.h" @@ -2280,6 +2282,22 @@ return false; } +bool Browser::DidAddMessageToConsole( + content::WebContents* source, + blink::mojom::ConsoleMessageLevel log_level, + const std::u16string& message, + int32_t line_no, + const std::u16string& source_id) { + static bool is_headless_mode = headless::IsHeadlessMode(); + if (is_headless_mode) { + const bool is_builtin_component = !!source->GetWebUI(); + headless::LogConsoleMessage(log_level, message, line_no, + is_builtin_component, source_id); + return true; + } + return false; +} + void Browser::BeforeUnloadFired(WebContents* web_contents, bool proceed, bool* proceed_to_fire_unload) {
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h index a87e55f9..a99ff54 100644 --- a/chrome/browser/ui/browser.h +++ b/chrome/browser/ui/browser.h
@@ -933,6 +933,11 @@ const ui::Event& event) override; void ContentsZoomChange(bool zoom_in) override; bool TakeFocus(content::WebContents* source, bool reverse) override; + bool DidAddMessageToConsole(content::WebContents* source, + blink::mojom::ConsoleMessageLevel log_level, + const std::u16string& message, + int32_t line_no, + const std::u16string& source_id) override; void BeforeUnloadFired(content::WebContents* source, bool proceed, bool* proceed_to_fire_unload) override;
diff --git a/chrome/browser/ui/browser_window/BUILD_OWNERS b/chrome/browser/ui/browser_window/BUILD_OWNERS new file mode 100644 index 0000000..1ee02c3 --- /dev/null +++ b/chrome/browser/ui/browser_window/BUILD_OWNERS
@@ -0,0 +1,5 @@ +# Owners for all BUILD.gn files under this directory and its subdirectories. + +file://chrome/browser/ui/browser_window/public/android/OWNERS + +rdevlin.cronin@chromium.org
diff --git a/chrome/browser/ui/browser_window/OWNERS b/chrome/browser/ui/browser_window/OWNERS new file mode 100644 index 0000000..7cc8bec --- /dev/null +++ b/chrome/browser/ui/browser_window/OWNERS
@@ -0,0 +1 @@ +per-file BUILD.gn=file:BUILD_OWNERS
diff --git a/chrome/browser/ui/browser_window/internal/BUILD.gn b/chrome/browser/ui/browser_window/internal/BUILD.gn index 57f3c73..580403d 100644 --- a/chrome/browser/ui/browser_window/internal/BUILD.gn +++ b/chrome/browser/ui/browser_window/internal/BUILD.gn
@@ -50,6 +50,7 @@ "//chrome/browser/ui/tabs:glic", "//chrome/browser/ui/tabs:tab_list_bridge", "//chrome/browser/ui/tabs/organization", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/tabs/tab_strip_api", "//chrome/browser/ui/toasts", "//chrome/browser/ui/toolbar/chrome_labs", @@ -99,9 +100,11 @@ sources += [ "android/android_base_window_unittest.cc", "android/android_browser_window_unittest.cc", + "android/browser_window_interface_iterator_android_unittest.cc", ] deps += [ "//base", + "//chrome/browser/ui/browser_window", "//chrome/browser/ui/browser_window/test:native_unit_test_support_java", "//chrome/browser/ui/browser_window/test:native_unit_test_support_jni", "//components/sessions:session_id", @@ -128,6 +131,7 @@ sources = [ "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBaseWindow.java", "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBrowserWindow.java", + "android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroid.java", "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java", "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerFactory.java", "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java", @@ -146,6 +150,7 @@ sources = [ "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBaseWindow.java", "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBrowserWindow.java", + "android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroid.java", ] }
diff --git a/chrome/browser/ui/browser_window/internal/OWNERS b/chrome/browser/ui/browser_window/internal/OWNERS new file mode 100644 index 0000000..b306d870 --- /dev/null +++ b/chrome/browser/ui/browser_window/internal/OWNERS
@@ -0,0 +1 @@ +per-file BUILD.gn=file://chrome/browser/ui/browser_window/BUILD_OWNERS
diff --git a/chrome/browser/ui/browser_window/internal/android/browser_window_interface_iterator_android.cc b/chrome/browser/ui/browser_window/internal/android/browser_window_interface_iterator_android.cc index e7491df..bb30e4dd 100644 --- a/chrome/browser/ui/browser_window/internal/android/browser_window_interface_iterator_android.cc +++ b/chrome/browser/ui/browser_window/internal/android/browser_window_interface_iterator_android.cc
@@ -4,10 +4,26 @@ #include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h" +#include "base/android/jni_android.h" #include "chrome/browser/ui/browser_window/internal/android/android_browser_window.h" +#include "chrome/browser/ui/browser_window/internal/jni/BrowserWindowInterfaceIteratorAndroid_jni.h" + +namespace { +using base::android::AttachCurrentThread; +} // namespace std::vector<BrowserWindowInterface*> GetAllBrowserWindowInterfaces() { - return AndroidBrowserWindow::GetAllAndroidBrowserWindowsByCreationTime(); + std::vector<int64_t> browser_window_ptr_values = + Java_BrowserWindowInterfaceIteratorAndroid_getAllBrowserWindowInterfaces( + AttachCurrentThread()); + + std::vector<BrowserWindowInterface*> browser_windows; + for (int64_t ptr_value : browser_window_ptr_values) { + browser_windows.emplace_back( + reinterpret_cast<BrowserWindowInterface*>(ptr_value)); + } + + return browser_windows; } std::vector<BrowserWindowInterface*>
diff --git a/chrome/browser/ui/browser_window/internal/android/browser_window_interface_iterator_android_unittest.cc b/chrome/browser/ui/browser_window/internal/android/browser_window_interface_iterator_android_unittest.cc new file mode 100644 index 0000000..962ff7c6 --- /dev/null +++ b/chrome/browser/ui/browser_window/internal/android/browser_window_interface_iterator_android_unittest.cc
@@ -0,0 +1,77 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h" + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "chrome/browser/ui/browser_window/public/browser_window_interface.h" +#include "chrome/browser/ui/browser_window/test/native_unit_test_support_jni/BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport_jni.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +using base::android::AttachCurrentThread; + +bool VectorContains(const std::vector<BrowserWindowInterface*>& vector, + const BrowserWindowInterface* value) { + return std::find(vector.begin(), vector.end(), value) != vector.end(); +} +} // namespace + +class BrowserWindowInterfaceIteratorAndroidUnitTest : public testing::Test { + public: + BrowserWindowInterfaceIteratorAndroidUnitTest() = default; + ~BrowserWindowInterfaceIteratorAndroidUnitTest() override = default; + + BrowserWindowInterface* CreateBrowserWindow(int task_id) { + return reinterpret_cast<BrowserWindowInterface*>( + Java_BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport_createBrowserWindow( + base::android::AttachCurrentThread(), task_id)); + } + + void DestroyBrowserWindow(int task_id) { + Java_BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport_destroyBrowserWindow( + base::android::AttachCurrentThread(), task_id); + } + + void TearDown() override { + Java_BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport_destroyAllBrowserWindows( + base::android::AttachCurrentThread()); + } +}; + +TEST_F(BrowserWindowInterfaceIteratorAndroidUnitTest, + GetAllBrowserWindowInterfacesReturnsEmptyVectorWhenNoWindowsExist) { + std::vector<BrowserWindowInterface*> browser_windows = + GetAllBrowserWindowInterfaces(); + EXPECT_TRUE(browser_windows.empty()); +} + +TEST_F(BrowserWindowInterfaceIteratorAndroidUnitTest, + GetAllBrowserWindowInterfacesReturnsAllWindows) { + BrowserWindowInterface* browser_window1 = CreateBrowserWindow(/*task_id=*/1); + BrowserWindowInterface* browser_window2 = CreateBrowserWindow(/*task_id=*/2); + + std::vector<BrowserWindowInterface*> browser_windows = + GetAllBrowserWindowInterfaces(); + + EXPECT_EQ(2u, browser_windows.size()); + EXPECT_TRUE(VectorContains(browser_windows, browser_window1)); + EXPECT_TRUE(VectorContains(browser_windows, browser_window2)); +} + +TEST_F(BrowserWindowInterfaceIteratorAndroidUnitTest, + GetAllBrowserWindowInterfacesDoesNotReturnDestroyedWindows) { + CreateBrowserWindow(/*task_id=*/1); + BrowserWindowInterface* browser_window2 = CreateBrowserWindow(/*task_id=*/2); + CreateBrowserWindow(/*task_id=*/3); + DestroyBrowserWindow(/*task_id=*/1); + DestroyBrowserWindow(/*task_id=*/3); + + std::vector<BrowserWindowInterface*> browser_windows = + GetAllBrowserWindowInterfaces(); + + EXPECT_EQ(1u, browser_windows.size()); + EXPECT_TRUE(VectorContains(browser_windows, browser_window2)); +}
diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroid.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroid.java new file mode 100644 index 0000000..acb9f44 --- /dev/null +++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroid.java
@@ -0,0 +1,25 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.ui.browser_window; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JniType; + +import org.chromium.build.annotations.NullMarked; + +/** + * Java class implementing the native functions in {@code + * browser_window_interface_iterator_android.cc}. + */ +@NullMarked +final class BrowserWindowInterfaceIteratorAndroid { + private BrowserWindowInterfaceIteratorAndroid() {} + + @CalledByNative + @JniType("std::vector<int64_t>") + private static long[] getAllBrowserWindowInterfaces() { + return ChromeAndroidTaskTrackerImpl.getInstance().getAllNativeBrowserWindowPtrs(); + } +}
diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java index a21e3def..34898a4 100644 --- a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java +++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java
@@ -74,6 +74,20 @@ } } + /** Returns an array of the native {@code BrowserWindowInterface} addresses. */ + long[] getAllNativeBrowserWindowPtrs() { + synchronized (mTasksLock) { + long[] nativeBrowserWindowPtrs = new long[mTasks.size()]; + + int index = 0; + for (var task : mTasks.values()) { + nativeBrowserWindowPtrs[index] = task.getOrCreateNativeBrowserWindowPtr(); + index++; + } + return nativeBrowserWindowPtrs; + } + } + /** * Removes all {@link ChromeAndroidTask}s. * @@ -82,7 +96,7 @@ * * <p>This method must be called on the UI thread. */ - public void removeAllForTesting() { + void removeAllForTesting() { synchronized (mTasksLock) { mTasks.forEach((taskId, task) -> task.destroy()); mTasks.clear();
diff --git a/chrome/browser/ui/browser_window/stub/OWNERS b/chrome/browser/ui/browser_window/stub/OWNERS new file mode 100644 index 0000000..b306d870 --- /dev/null +++ b/chrome/browser/ui/browser_window/stub/OWNERS
@@ -0,0 +1 @@ +per-file BUILD.gn=file://chrome/browser/ui/browser_window/BUILD_OWNERS
diff --git a/chrome/browser/ui/browser_window/stub/android/OWNERS b/chrome/browser/ui/browser_window/stub/android/OWNERS new file mode 100644 index 0000000..fdbd9d54 --- /dev/null +++ b/chrome/browser/ui/browser_window/stub/android/OWNERS
@@ -0,0 +1 @@ +file://chrome/browser/ui/browser_window/public/android/OWNERS
diff --git a/chrome/browser/ui/browser_window/test/BUILD.gn b/chrome/browser/ui/browser_window/test/BUILD.gn index f60893ee..f07d8960 100644 --- a/chrome/browser/ui/browser_window/test/BUILD.gn +++ b/chrome/browser/ui/browser_window/test/BUILD.gn
@@ -28,13 +28,16 @@ sources = [ "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBaseWindowNativeUnitTestSupport.java", "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBrowserWindowNativeUnitTestSupport.java", + "android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport.java", ] deps = [ + ":junit_test_support", "//build/android:build_java", "//chrome/browser/ui/browser_window:java", "//chrome/browser/ui/browser_window/internal:java", "//third_party/jni_zero:jni_zero_java", "//third_party/mockito:mockito_java", + "//ui/android:ui_no_recycler_view_java", ] srcjar_deps = [ ":native_unit_test_support_jni" ] } @@ -45,6 +48,7 @@ sources = [ "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBaseWindowNativeUnitTestSupport.java", "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBrowserWindowNativeUnitTestSupport.java", + "android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport.java", ] } }
diff --git a/chrome/browser/ui/browser_window/test/OWNERS b/chrome/browser/ui/browser_window/test/OWNERS new file mode 100644 index 0000000..b306d870 --- /dev/null +++ b/chrome/browser/ui/browser_window/test/OWNERS
@@ -0,0 +1 @@ +per-file BUILD.gn=file://chrome/browser/ui/browser_window/BUILD_OWNERS
diff --git a/chrome/browser/ui/browser_window/test/android/OWNERS b/chrome/browser/ui/browser_window/test/android/OWNERS new file mode 100644 index 0000000..fdbd9d54 --- /dev/null +++ b/chrome/browser/ui/browser_window/test/android/OWNERS
@@ -0,0 +1 @@ +file://chrome/browser/ui/browser_window/public/android/OWNERS
diff --git a/chrome/browser/ui/browser_window/test/android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport.java b/chrome/browser/ui/browser_window/test/android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport.java new file mode 100644 index 0000000..3159e14 --- /dev/null +++ b/chrome/browser/ui/browser_window/test/android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport.java
@@ -0,0 +1,35 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.ui.browser_window; + +import org.jni_zero.CalledByNative; + +import org.chromium.build.annotations.NullMarked; + +/** Supports {@code browser_window_interface_iterator_android_unittest.cc}. */ +@NullMarked +final class BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport { + + private BrowserWindowInterfaceIteratorAndroidNativeUnitTestSupport() {} + + @CalledByNative + private static long createBrowserWindow(int taskId) { + var mockActivityWindowAndroid = + ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(taskId); + var chromeAndroidTask = + ChromeAndroidTaskTrackerImpl.getInstance().obtainTask(mockActivityWindowAndroid); + return chromeAndroidTask.getOrCreateNativeBrowserWindowPtr(); + } + + @CalledByNative + private static void destroyBrowserWindow(int taskId) { + ChromeAndroidTaskTrackerImpl.getInstance().remove(taskId); + } + + @CalledByNative + private static void destroyAllBrowserWindows() { + ChromeAndroidTaskTrackerImpl.getInstance().removeAllForTesting(); + } +}
diff --git a/chrome/browser/ui/extensions/extension_install_blocked_dialog_browsertest.cc b/chrome/browser/ui/extensions/extension_install_blocked_dialog_browsertest.cc index 817652c6..368b476 100644 --- a/chrome/browser/ui/extensions/extension_install_blocked_dialog_browsertest.cc +++ b/chrome/browser/ui/extensions/extension_install_blocked_dialog_browsertest.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/test/test_browser_dialog.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" +#include "third_party/skia/include/core/SkBitmap.h" class ExtensionInstallBlockedDialogTest : public DialogBrowserTest { public:
diff --git a/chrome/browser/ui/extensions/reload_page_dialog_controller.cc b/chrome/browser/ui/extensions/reload_page_dialog_controller.cc index 8093be5..937c540b 100644 --- a/chrome/browser/ui/extensions/reload_page_dialog_controller.cc +++ b/chrome/browser/ui/extensions/reload_page_dialog_controller.cc
@@ -26,6 +26,9 @@ namespace { +// Whether the dialog should be accepted without showing it on tests. +std::optional<bool> g_accept_bubble_for_testing_ = std::nullopt; + std::u16string GetTitle( const std::vector<extensions::ReloadPageDialogController::ExtensionInfo>& extensions_info) { @@ -65,6 +68,15 @@ void ReloadPageDialogController::TriggerShow( const std::vector<const Extension*>& extensions) { + // For testing, callers can use AcceptDialogForTesting() to pre-determine + // the dialog's result. This bypasses showing the dialog. + if (g_accept_bubble_for_testing_.has_value()) { + if (*g_accept_bubble_for_testing_) { + OnAcceptSelected(); + } + return; + } + if (!base::FeatureList::IsEnabled( extensions_features::kExtensionsMenuAccessControl)) { for (const Extension* extension : extensions) { @@ -106,6 +118,13 @@ } } +// static +base::AutoReset<std::optional<bool>> +ReloadPageDialogController::AcceptDialogForTesting(bool accept_dialog) { + return base::AutoReset<std::optional<bool>>(&g_accept_bubble_for_testing_, + accept_dialog); +} + void ReloadPageDialogController::Show() { ui::DialogModel::Builder dialog_builder; dialog_builder.SetTitle(GetTitle(extensions_info_))
diff --git a/chrome/browser/ui/extensions/reload_page_dialog_controller.h b/chrome/browser/ui/extensions/reload_page_dialog_controller.h index b8fb02d..4d95cf0 100644 --- a/chrome/browser/ui/extensions/reload_page_dialog_controller.h +++ b/chrome/browser/ui/extensions/reload_page_dialog_controller.h
@@ -7,6 +7,7 @@ #include <vector> +#include "base/auto_reset.h" #include "base/functional/callback.h" #include "base/functional/callback_forward.h" #include "base/memory/weak_ptr.h" @@ -48,10 +49,9 @@ // Starts the process of showing the dialog for the given `extensions`. void TriggerShow(const std::vector<const Extension*>& extensions); - // Reloads the active page once the dialog is accepted. - // TODO(crbug.com/424012380): Move to a private function once - // accept_bubble_for_testing_ is moved here from ExtensionActionRunner. - void OnAcceptSelected(); + // For testing: + [[nodiscard]] static base::AutoReset<std::optional<bool>> + AcceptDialogForTesting(bool accept_dialog); private: // Shows the reload page dialog with the extensions information gathered in @@ -65,6 +65,9 @@ base::OnceClosure done_callback, const gfx::Image& icon); + // Reloads the active page once the dialog is accepted. + void OnAcceptSelected(); + raw_ptr<content::WebContents> web_contents_; raw_ptr<content::BrowserContext> browser_context_;
diff --git a/chrome/browser/ui/global_media_controls/BUILD.gn b/chrome/browser/ui/global_media_controls/BUILD.gn index a893fc00..22f8543 100644 --- a/chrome/browser/ui/global_media_controls/BUILD.gn +++ b/chrome/browser/ui/global_media_controls/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//chrome/common/features.gni") + assert(is_win || is_mac || is_linux || is_chromeos) source_set("global_media_controls") { @@ -47,7 +49,7 @@ ] if (is_chromeos) { - deps = [ "//ash" ] + public_deps += [ "//ash" ] } } @@ -61,6 +63,7 @@ "media_item_ui_metrics.cc", "media_notification_device_monitor.cc", "media_notification_device_provider_impl.cc", + "media_notification_service.cc", "media_notification_service_factory.cc", "media_toolbar_button_controller.cc", "media_toolbar_button_controller_delegate.cc", @@ -73,6 +76,7 @@ "//chrome/browser/feature_engagement", "//chrome/browser/media/router:media_router_feature", "//chrome/browser/ui:browser_list", + "//chrome/browser/ui/tabs:tab_strip", "//components/favicon/content", "//components/favicon/core", "//components/feature_engagement/public", @@ -81,6 +85,9 @@ "//media/remoting:remoting_device_capability", "//services/metrics/public/cpp:ukm_builders", ] + if (enable_glic) { + deps += [ "//chrome/browser/glic" ] + } public_deps = [ "//chrome/browser:browser_public_dependencies" ] }
diff --git a/chrome/browser/ui/lens/lens_composebox_controller.cc b/chrome/browser/ui/lens/lens_composebox_controller.cc index e7bea2e..3cc13fc 100644 --- a/chrome/browser/ui/lens/lens_composebox_controller.cc +++ b/chrome/browser/ui/lens/lens_composebox_controller.cc
@@ -27,4 +27,8 @@ std::move(pending_searchbox_handler)); } +void LensComposeboxController::CloseUI() { + composebox_handler_.reset(); +} + } // namespace lens
diff --git a/chrome/browser/ui/lens/lens_composebox_controller.h b/chrome/browser/ui/lens/lens_composebox_controller.h index 6ab0d61..1f4b1322 100644 --- a/chrome/browser/ui/lens/lens_composebox_controller.h +++ b/chrome/browser/ui/lens/lens_composebox_controller.h
@@ -39,6 +39,9 @@ mojo::PendingReceiver<searchbox::mojom::PageHandler> pending_searchbox_handler); + // Cleans up any any state associated with this UI instance. + void CloseUI(); + private: // Owns this. const raw_ptr<LensSearchController> lens_search_controller_;
diff --git a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc index 5468c5e..55c7539 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc +++ b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc
@@ -7306,16 +7306,10 @@ static_cast<int64_t>(lens::MimeType::kAnnotatedPageContent)); } -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) -#define MAYBE_RecordQueryIssuesBeforeZpsShownInSessionHistograms \ - DISABLED_RecordQueryIssuesBeforeZpsShownInSessionHistograms -#else -#define MAYBE_RecordQueryIssuesBeforeZpsShownInSessionHistograms \ - RecordQueryIssuesBeforeZpsShownInSessionHistograms -#endif +// TODO - crbug.com/400650442: Deflake and re-enable this test. IN_PROC_BROWSER_TEST_F( LensOverlayControllerBrowserTest, - MAYBE_RecordQueryIssuesBeforeZpsShownInSessionHistograms) { + DISABLED_RecordQueryIssuesBeforeZpsShownInSessionHistograms) { base::HistogramTester histogram_tester; ukm::TestAutoSetUkmRecorder test_ukm_recorder; WaitForPaint(kDocumentWithNonAsciiCharacters);
diff --git a/chrome/browser/ui/lens/lens_overlay_query_controller_unittest.cc b/chrome/browser/ui/lens/lens_overlay_query_controller_unittest.cc index e20e0c5d..91dc9da 100644 --- a/chrome/browser/ui/lens/lens_overlay_query_controller_unittest.cc +++ b/chrome/browser/ui/lens/lens_overlay_query_controller_unittest.cc
@@ -311,7 +311,7 @@ GURL(url_response.url()), kGen204IdentifierQueryParameter, &url_gen204_id); ASSERT_TRUE(has_gen204_id); - ASSERT_TRUE(client_logs.has_paella_id()); + ASSERT_NE(client_logs.paella_id(), 0u); ASSERT_EQ(base::NumberToString(client_logs.paella_id()).c_str(), url_gen204_id); } @@ -537,7 +537,7 @@ 1); ASSERT_EQ(query_controller.sent_client_logs().lens_overlay_entry_point(), lens::LensOverlayClientLogs::APP_MENU); - ASSERT_TRUE(query_controller.sent_client_logs().has_paella_id()); + ASSERT_NE(query_controller.sent_client_logs().paella_id(), 0u); } TEST_F(LensOverlayQueryControllerTest, @@ -607,7 +607,7 @@ 1); ASSERT_EQ(query_controller.sent_client_logs().lens_overlay_entry_point(), lens::LensOverlayClientLogs::APP_MENU); - ASSERT_TRUE(query_controller.sent_client_logs().has_paella_id()); + ASSERT_NE(query_controller.sent_client_logs().paella_id(), 0u); } // Tests that the query controller attaches the server session id from the
diff --git a/chrome/browser/ui/lens/lens_search_controller.cc b/chrome/browser/ui/lens/lens_search_controller.cc index f531e7f..134cc85 100644 --- a/chrome/browser/ui/lens/lens_search_controller.cc +++ b/chrome/browser/ui/lens/lens_search_controller.cc
@@ -586,6 +586,7 @@ // dependent on the overlay controller. lens_overlay_controller_->CloseUI(dismissal_source); lens_searchbox_controller_->CloseUI(); + lens_composebox_controller_->CloseUI(); lens_permission_bubble_controller_.reset(); lens_contextualization_controller_->ResetState(); lens_overlay_side_panel_coordinator_->DeregisterEntryAndCleanup();
diff --git a/chrome/browser/ui/save_to_drive/BUILD.gn b/chrome/browser/ui/save_to_drive/BUILD.gn index e325877..2f27b4c 100644 --- a/chrome/browser/ui/save_to_drive/BUILD.gn +++ b/chrome/browser/ui/save_to_drive/BUILD.gn
@@ -9,7 +9,11 @@ "account_chooser_controller_delegate.h", "account_chooser_view_delegate.h", ] - public_deps = [ "//components/signin/public/identity_manager" ] + public_deps = [ + "//components/signin/public/identity_manager", + "//content/public/browser", + ] + deps = [ "//ui/display" ] } source_set("test_support") {
diff --git a/chrome/browser/ui/save_to_drive/add_account_dialog_controller.cc b/chrome/browser/ui/save_to_drive/add_account_dialog_controller.cc new file mode 100644 index 0000000..6fe1e13 --- /dev/null +++ b/chrome/browser/ui/save_to_drive/add_account_dialog_controller.cc
@@ -0,0 +1,94 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/save_to_drive/add_account_dialog_controller.h" + +#include "chrome/browser/signin/signin_promo.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/display/screen.h" + +namespace save_to_drive { + +namespace { +// Computes the bounds of the popup window. The popup window is centered in the +// source window, if the source window is large enough to contain the popup +// window. Otherwise, the popup window is centered in the screen. +gfx::Rect ComputePopupWindowBounds(content::WebContents* source_window) { + gfx::Rect source_window_bounds = source_window->GetContainerBounds(); + const int kPopupWindowWidth = 400; + const int kPopupWindowHeight = 484; + int x_coordinate; + int y_coordinate; + + if (source_window_bounds.width() >= kPopupWindowWidth && + source_window_bounds.height() >= kPopupWindowHeight) { + x_coordinate = source_window_bounds.x() + + ((source_window_bounds.width() - kPopupWindowWidth) / 2); + y_coordinate = source_window_bounds.y() + + ((source_window_bounds.height() - kPopupWindowHeight) / 2); + } else { + display::Screen* screen = display::Screen::GetScreen(); + gfx::Rect source_display_bounds = + screen->GetDisplayNearestView(source_window->GetNativeView()) + .work_area(); + x_coordinate = (source_display_bounds.width() - kPopupWindowWidth) / 2; + y_coordinate = (source_display_bounds.height() - kPopupWindowHeight) / 2; + } + return gfx::Rect(x_coordinate, y_coordinate, kPopupWindowWidth, + kPopupWindowHeight); +} +} // namespace + +AddAccountDialogController::AddAccountDialogController( + content::WebContents* web_contents) + : source_window_(web_contents) {} + +AddAccountDialogController::~AddAccountDialogController() { + Close(); +} + +void AddAccountDialogController::Close() { + if (!popup_window_) { + return; + } + // Store this in a local variable to avoid triggering the dangling pointer + // detector. + content::WebContents* popup = popup_window_; + popup_window_ = nullptr; + popup->Close(); +} + +void AddAccountDialogController::Show() { + if (popup_window_) { + ResizeAndFocusPopupWindow(); + return; + } + content::OpenURLParams params( + signin::GetAddAccountURLForDice("", GURL()), content::Referrer(), + WindowOpenDisposition::NEW_POPUP, ui::PAGE_TRANSITION_AUTO_TOPLEVEL, + /*is_renderer_initiated=*/false); + popup_window_ = source_window_->GetDelegate()->OpenURLFromTab( + source_window_, params, /*navigation_handle_callback=*/{}); + ResizeAndFocusPopupWindow(); + Observe(popup_window_); +} + +void AddAccountDialogController::WebContentsDestroyed() { + // The popup window is going away, make sure we don't keep a dangling pointer. + // This should happen before notifying the observer, where `this` will be + // destroyed. + popup_window_ = nullptr; +} + +void AddAccountDialogController::ResizeAndFocusPopupWindow() { + CHECK(popup_window_); + gfx::Rect popup_window_bounds = ComputePopupWindowBounds(source_window_); + popup_window_->GetDelegate()->SetContentsBounds(popup_window_, + popup_window_bounds); + popup_window_->GetDelegate()->ActivateContents(popup_window_); +} + +} // namespace save_to_drive
diff --git a/chrome/browser/ui/save_to_drive/add_account_dialog_controller.h b/chrome/browser/ui/save_to_drive/add_account_dialog_controller.h new file mode 100644 index 0000000..7173f34 --- /dev/null +++ b/chrome/browser/ui/save_to_drive/add_account_dialog_controller.h
@@ -0,0 +1,45 @@ +// 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 CHROME_BROWSER_UI_SAVE_TO_DRIVE_ADD_ACCOUNT_DIALOG_CONTROLLER_H_ +#define CHROME_BROWSER_UI_SAVE_TO_DRIVE_ADD_ACCOUNT_DIALOG_CONTROLLER_H_ + +#include "content/public/browser/web_contents_observer.h" +#include "ui/base/metadata/metadata_header_macros.h" + +namespace content { +class WebContents; +class NavigationHandle; +} // namespace content + +namespace save_to_drive { + +// This class is responsible for showing and hiding the add account dialog +// pop-up window in the Save to Drive Account Chooser flow. +class AddAccountDialogController : public content::WebContentsObserver { + public: + explicit AddAccountDialogController(content::WebContents* web_contents); + AddAccountDialogController(const AddAccountDialogController&) = delete; + AddAccountDialogController& operator=(const AddAccountDialogController&) = + delete; + ~AddAccountDialogController() override; + + // Closes the dialog if it is showing. + void Close(); + // Shows the dialog if it is not showing. + void Show(); + + // content::WebContentsObserver: + void WebContentsDestroyed() override; + + private: + // Resizes and focuses the add account dialog pop-up window. + void ResizeAndFocusPopupWindow(); + + raw_ptr<content::WebContents> source_window_ = nullptr; + raw_ptr<content::WebContents> popup_window_ = nullptr; +}; +} // namespace save_to_drive + +#endif // CHROME_BROWSER_UI_SAVE_TO_DRIVE_ADD_ACCOUNT_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/save_to_drive/add_account_dialog_controller_browsertest.cc b/chrome/browser/ui/save_to_drive/add_account_dialog_controller_browsertest.cc new file mode 100644 index 0000000..e8f4aff --- /dev/null +++ b/chrome/browser/ui/save_to_drive/add_account_dialog_controller_browsertest.cc
@@ -0,0 +1,135 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/save_to_drive/add_account_dialog_controller.h" + +#include "chrome/browser/ui/browser_list.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/ui_test_utils.h" +#include "chrome/test/interaction/interactive_browser_test.h" +#include "chrome/test/views/chrome_views_test_base.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_delegate.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/test_web_contents_factory.h" +#include "ui/base/interaction/interactive_test.h" +#include "ui/display/display_switches.h" +#include "ui/display/screen.h" +#include "ui/display/screen_base.h" +#include "ui/display/test/test_screen.h" +#include "ui/gfx/switches.h" + +namespace save_to_drive { +namespace { + +class AddAccountDialogControllerTest : public InteractiveBrowserTest { + public: + AddAccountDialogControllerTest() = default; + ~AddAccountDialogControllerTest() override = default; +}; + +IN_PROC_BROWSER_TEST_F(AddAccountDialogControllerTest, ShowAndHide) { + ASSERT_EQ(BrowserList::GetInstance()->size(), 1u); + AddAccountDialogController dialog( + browser()->tab_strip_model()->GetActiveWebContents()); + + // Show the dialog. + dialog.Show(); + // A new browser window should open. + ASSERT_EQ(BrowserList::GetInstance()->size(), 2u); + Browser* popup_browser = BrowserList::GetInstance()->get(1); + ASSERT_TRUE(popup_browser); + EXPECT_TRUE(popup_browser->is_type_popup()); + + // Close the dialog. + dialog.Close(); + // The popup window should close. + ui_test_utils::WaitForBrowserToClose(popup_browser); + ASSERT_EQ(BrowserList::GetInstance()->size(), 1u); +} + +IN_PROC_BROWSER_TEST_F(AddAccountDialogControllerTest, AtMostOnePopupWindow) { + ASSERT_EQ(BrowserList::GetInstance()->size(), 1u); + AddAccountDialogController dialog( + browser()->tab_strip_model()->GetActiveWebContents()); + + // Show the dialog. + dialog.Show(); + // A new browser window should open. + EXPECT_EQ(BrowserList::GetInstance()->size(), 2u); + + // Show the dialog again. + dialog.Show(); + // The second call should not open a new window. + EXPECT_EQ(BrowserList::GetInstance()->size(), 2u); + Browser* popup_browser = BrowserList::GetInstance()->get(1); + ASSERT_TRUE(popup_browser); + EXPECT_TRUE(popup_browser->is_type_popup()); +} + +IN_PROC_BROWSER_TEST_F(AddAccountDialogControllerTest, + PopupAtCenterOfSourceWindow) { + // Set the source window size to be large enough to contain the popup window. + gfx::Rect source_window_bounds = gfx::Rect(0, 0, 1000, 1000); + browser()->window()->SetBounds(source_window_bounds); + ASSERT_EQ(BrowserList::GetInstance()->size(), 1u); + AddAccountDialogController dialog( + browser()->tab_strip_model()->GetActiveWebContents()); + + // Show the dialog. + dialog.Show(); + // A new browser window should open. + ASSERT_EQ(BrowserList::GetInstance()->size(), 2u); + Browser* popup_browser = BrowserList::GetInstance()->get(1); + ASSERT_TRUE(popup_browser); + EXPECT_TRUE(popup_browser->is_type_popup()); + + // Check popup size. The size is computed in add_account_dialog_controller.cc. + // kPopupWindowWidth = 400, kPopupWindowPreferredHeight = 484. + gfx::Rect bounds = popup_browser->window()->GetBounds(); + EXPECT_EQ(bounds.width(), 400); + EXPECT_EQ(bounds.height(), 484); + // This can be platform specific, so we only check that the popup is within + // the source window. + EXPECT_GT(bounds.x(), source_window_bounds.x()); + EXPECT_LT(bounds.x(), + source_window_bounds.x() + source_window_bounds.width()); + EXPECT_GT(bounds.y(), source_window_bounds.y()); + EXPECT_LT(bounds.y(), + source_window_bounds.y() + source_window_bounds.height()); +} + +IN_PROC_BROWSER_TEST_F( + AddAccountDialogControllerTest, + PopupPositionedInCenterOfScreenIfSourceWindowIsTooSmall) { + // Set the source window size to be too small to contain the popup window. + gfx::Rect source_window_bounds = gfx::Rect(0, 0, 0, 0); + browser()->window()->SetBounds(source_window_bounds); + ASSERT_EQ(BrowserList::GetInstance()->size(), 1u); + AddAccountDialogController dialog( + browser()->tab_strip_model()->GetActiveWebContents()); + + // Show the dialog. + dialog.Show(); + // A new browser window should open. + ASSERT_EQ(BrowserList::GetInstance()->size(), 2u); + Browser* popup_browser = BrowserList::GetInstance()->get(1); + ASSERT_TRUE(popup_browser); + EXPECT_TRUE(popup_browser->is_type_popup()); + + // Check popup size. The size is computed in add_account_dialog_controller.cc. + // kPopupWindowWidth = 400, kPopupWindowPreferredHeight = 484. + gfx::Rect bounds = popup_browser->window()->GetBounds(); + EXPECT_EQ(bounds.width(), 400); + EXPECT_EQ(bounds.height(), 484); + // This can be platform specific, so we only check that the popup is not + // centered in the source window. + EXPECT_GT(bounds.x(), source_window_bounds.x()); + EXPECT_GT(bounds.y(), source_window_bounds.y()); +} + +} // namespace +} // namespace save_to_drive
diff --git a/chrome/browser/ui/search_engines/BUILD.gn b/chrome/browser/ui/search_engines/BUILD.gn index fd1dcc7..c875a8b 100644 --- a/chrome/browser/ui/search_engines/BUILD.gn +++ b/chrome/browser/ui/search_engines/BUILD.gn
@@ -33,6 +33,7 @@ deps = [ "//base:i18n", "//chrome/app:generated_resources", + "//chrome/browser/autocomplete:aim_eligibility_service", "//chrome/browser/favicon", "//chrome/browser/profiles:profile", "//chrome/browser/search_engines",
diff --git a/chrome/browser/ui/search_engines/keyword_editor_controller.cc b/chrome/browser/ui/search_engines/keyword_editor_controller.cc index b6f31ae..41b7fd9 100644 --- a/chrome/browser/ui/search_engines/keyword_editor_controller.cc +++ b/chrome/browser/ui/search_engines/keyword_editor_controller.cc
@@ -6,9 +6,10 @@ #include "base/feature_list.h" #include "base/metrics/user_metrics.h" +#include "chrome/browser/autocomplete/aim_eligibility_service.h" +#include "chrome/browser/autocomplete/aim_eligibility_service_factory.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/ui/search_engines/template_url_table_model.h" -#include "components/omnibox/common/omnibox_features.h" #include "components/prefs/pref_registry_simple.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_data.h" @@ -18,7 +19,10 @@ KeywordEditorController::KeywordEditorController(Profile* profile) : url_model_(TemplateURLServiceFactory::GetForProfile(profile)) { - table_model_ = std::make_unique<TemplateURLTableModel>(url_model_); + raw_ptr<AimEligibilityService> aim_eligibility_service = + AimEligibilityServiceFactory::GetForProfile(profile); + table_model_ = std::make_unique<TemplateURLTableModel>( + url_model_, aim_eligibility_service->IsAimEligible()); } KeywordEditorController::~KeywordEditorController() = default;
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.cc b/chrome/browser/ui/search_engines/template_url_table_model.cc index eb1b991..f7f0e85 100644 --- a/chrome/browser/ui/search_engines/template_url_table_model.cc +++ b/chrome/browser/ui/search_engines/template_url_table_model.cc
@@ -94,8 +94,11 @@ } // namespace internal TemplateURLTableModel::TemplateURLTableModel( - TemplateURLService* template_url_service) - : observer_(nullptr), template_url_service_(template_url_service) { + TemplateURLService* template_url_service, + bool ai_mode_enabled) + : observer_(nullptr), + template_url_service_(template_url_service), + ai_mode_enabled_(ai_mode_enabled) { DCHECK(template_url_service); template_url_service_->AddObserver(this); template_url_service_->Load(); @@ -114,14 +117,23 @@ extension_entries; // Keywords that can be made the default first. for (TemplateURL* template_url : urls) { - // Don't include the expanded set of starter pack keywords if the expansion - // feature flag is not enabled. - if ((template_url->starter_pack_id() == - template_url_starter_pack_data::kGemini && - !OmniboxFieldTrial::IsStarterPackExpansionEnabled()) || - (template_url->starter_pack_id() == - template_url_starter_pack_data::kPage && - !omnibox_feature_configs::ContextualSearch::Get().starter_pack_page)) { + // Skip @gemini if feature disabled. + if (template_url->starter_pack_id() == + template_url_starter_pack_data::kGemini && + !OmniboxFieldTrial::IsStarterPackExpansionEnabled()) { + continue; + } + // Skip @page if feature disabled. + if (template_url->starter_pack_id() == + template_url_starter_pack_data::kPage && + !omnibox_feature_configs::ContextualSearch::Get().starter_pack_page) { + continue; + } + // Skip @aimode if feature disabled. + if (template_url->starter_pack_id() == + template_url_starter_pack_data::kAiMode && + (!omnibox_feature_configs::Toolbelt::Get().enabled || + !ai_mode_enabled_)) { continue; }
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.h b/chrome/browser/ui/search_engines/template_url_table_model.h index c1802ce..6d89e1a1 100644 --- a/chrome/browser/ui/search_engines/template_url_table_model.h +++ b/chrome/browser/ui/search_engines/template_url_table_model.h
@@ -60,7 +60,8 @@ class TemplateURLTableModel : public ui::TableModel, TemplateURLServiceObserver { public: - explicit TemplateURLTableModel(TemplateURLService* template_url_service); + TemplateURLTableModel(TemplateURLService* template_url_service, + bool ai_mode_enabled); TemplateURLTableModel(const TemplateURLTableModel&) = delete; TemplateURLTableModel& operator=(const TemplateURLTableModel&) = delete; @@ -148,6 +149,9 @@ // Index of the last other engine in entries_. This is used to determine the // group boundaries. size_t last_other_engine_index_; + + // Whether to show the @aimode keyword. This depends on user eligibility. + bool ai_mode_enabled_; }; #endif // CHROME_BROWSER_UI_SEARCH_ENGINES_TEMPLATE_URL_TABLE_MODEL_H_
diff --git a/chrome/browser/ui/signin/dice_migration_service.cc b/chrome/browser/ui/signin/dice_migration_service.cc index 1cd3b6a..e01bde2 100644 --- a/chrome/browser/ui/signin/dice_migration_service.cc +++ b/chrome/browser/ui/signin/dice_migration_service.cc
@@ -403,6 +403,15 @@ browser_ = browser->AsWeakPtr(); dialog_widget_->Show(); + // Update the dialog shown count and time. Note that the user may not interact + // with the dialog at all, for example, if they close the browser. Or, the + // dialog may be shown on a browser that is minimized. These cases still count + // as showing the dialog. This is better than the alternate of updating the + // shown count and time only when the user interacts with the dialog, which + // might cause the dialog to be show on every browser startup if the user + // never interacts with it. + UpdateDialogShownCountAndTime(); + // Close the dialog when the avatar pill is clicked. avatar_button_observer_ = std::make_unique<AvatarButtonObserver>(avatar_button, this); @@ -423,8 +432,6 @@ avatar_button_observer_.reset(); dialog_widget_observation_.Reset(); dialog_widget_ = nullptr; - Browser* browser = browser_.get(); - browser_.reset(); switch (widget->closed_reason()) { // Losing focus should not close the dialog. case views::Widget::ClosedReason::kLostFocus: @@ -432,35 +439,31 @@ case views::Widget::ClosedReason::kUnspecified: LogDialogCloseReason( dialog_close_reason_.value_or(DialogCloseReason::kUnspecified)); - return; + break; case views::Widget::ClosedReason::kAcceptButtonClicked: { LogDialogCloseReason(DialogCloseReason::kAccepted); const bool migrated = MaybeMigrateUser(profile_); base::UmaHistogramBoolean(kUserMigratedHistogram, migrated); if (migrated) { - const bool toast_triggered = browser && MaybeShowToast(browser); + const bool toast_triggered = browser_ && MaybeShowToast(browser_.get()); base::UmaHistogramBoolean(kToastTriggeredHistogram, toast_triggered); } } break; case views::Widget::ClosedReason::kCancelButtonClicked: // Cancel button is only available in the non-"final" variant. - CHECK_LT(GetDialogShownCount(), kMaxDialogShownCount - 1); + CHECK_LT(GetDialogShownCount(), kMaxDialogShownCount); LogDialogCloseReason(DialogCloseReason::kCancelled); break; case views::Widget::ClosedReason::kCloseButtonClicked: // Close button is only available in the "final" variant. - CHECK_EQ(GetDialogShownCount(), kMaxDialogShownCount - 1); + CHECK_EQ(GetDialogShownCount(), kMaxDialogShownCount); LogDialogCloseReason(DialogCloseReason::kClosed); break; case views::Widget::ClosedReason::kEscKeyPressed: LogDialogCloseReason(DialogCloseReason::kEscKeyPressed); break; } - // The dialog is considered shown if the user interacts with it, i.e. the user - // accepts or dismisses the dialog. This is better than just tracking when the - // dialog was actually shown, since the user might have dismissed the dialog - // unknowingly, for example, by closing the browser. - UpdateDialogShownCountAndTime(); + browser_.reset(); } void DiceMigrationService::OnPrimaryAccountChanged(
diff --git a/chrome/browser/ui/signin/dice_migration_service.h b/chrome/browser/ui/signin/dice_migration_service.h index ad87225..262d0974 100644 --- a/chrome/browser/ui/signin/dice_migration_service.h +++ b/chrome/browser/ui/signin/dice_migration_service.h
@@ -28,17 +28,9 @@ } // namespace views // Tracks the number of times the DICe migration dialog has been shown. -// IMPORTANT(!): The dialog is considered shown only if the user interacts with -// it, i.e. the user accepts or dismisses the dialog. This is better than just -// tracking when the dialog was actually shown, since the user might have -// dismissed the dialog unknowingly, for example, by closing the browser. extern const char kDiceMigrationDialogShownCount[]; // Tracks the last time the DICe migration dialog was shown. -// IMPORTANT(!): The dialog is considered shown only if the user interacts with -// it, i.e. the user accepts or dismisses the dialog. This is better than just -// tracking when the dialog was actually shown, since the user might have -// dismissed the dialog unknowingly, for example, by closing the browser. extern const char kDiceMigrationDialogLastShownTime[]; // Tracks whether the user has been migrated to explicitly signed-in state
diff --git a/chrome/browser/ui/signin/dice_migration_service_browsertest.cc b/chrome/browser/ui/signin/dice_migration_service_browsertest.cc index 63a3b7c..f93fc056 100644 --- a/chrome/browser/ui/signin/dice_migration_service_browsertest.cc +++ b/chrome/browser/ui/signin/dice_migration_service_browsertest.cc
@@ -343,50 +343,11 @@ GetDiceMigrationService()->GetDialogWidgetForTesting(); ASSERT_TRUE(widget); - // The dialog shown count is not incremented yet. - EXPECT_EQ(GetPrefs()->GetInteger(kDiceMigrationDialogShownCount), 1); - - views::test::WidgetDestroyedWaiter waiter(widget); - // Simulate closing the dialog. - GetDiceMigrationService()->GetDialogWidgetForTesting()->CloseWithReason( - views::Widget::ClosedReason::kCancelButtonClicked); - waiter.Wait(); - // The dialog shown count is now incremented. EXPECT_EQ(GetPrefs()->GetInteger(kDiceMigrationDialogShownCount), 2); } DICE_MIGRATION_TEST_F(DiceMigrationServiceBrowserTest, - DoNotIncrementDialogShownCountIfNotInteractedWith) { - // The user is implicitly signed in. - ASSERT_TRUE(IsImplicitlySignedIn()); - - // Set the current dialog shown count to 1. - GetPrefs()->SetInteger(kDiceMigrationDialogShownCount, 1); - - // Show the migration bubble. - base::OneShotTimer& timer = - GetDiceMigrationService()->GetDialogTriggerTimerForTesting(); - ASSERT_TRUE(timer.IsRunning()); - timer.FireNow(); - - views::Widget* widget = - GetDiceMigrationService()->GetDialogWidgetForTesting(); - ASSERT_TRUE(widget); - - // The dialog shown count is not incremented yet. - EXPECT_EQ(GetPrefs()->GetInteger(kDiceMigrationDialogShownCount), 1); - - views::test::WidgetDestroyedWaiter waiter(widget); - // Simulate the dialog being closed without any user interaction. - signin::ClearPrimaryAccount(GetIdentityManager()); - waiter.Wait(); - - // The dialog shown count is not incremented. - EXPECT_EQ(GetPrefs()->GetInteger(kDiceMigrationDialogShownCount), 1); -} - -DICE_MIGRATION_TEST_F(DiceMigrationServiceBrowserTest, UpdateDialogLastShownTime) { // The user is implicitly signed in. ASSERT_TRUE(IsImplicitlySignedIn()); @@ -400,21 +361,47 @@ // Show the migration bubble. FireDialogTriggerTimer(); + ASSERT_TRUE(GetDiceMigrationService()->GetDialogWidgetForTesting()); + + // The dialog last shown time is now updated. + EXPECT_GE(GetPrefs()->GetTime(kDiceMigrationDialogLastShownTime), time_now); +} + +DICE_MIGRATION_TEST_F(DiceMigrationServiceBrowserTest, + DoNotUpdateDialogShownCountAndTimeUponInteraction) { + // The user is implicitly signed in. + ASSERT_TRUE(IsImplicitlySignedIn()); + + // Set the current dialog shown count to 1. + GetPrefs()->SetInteger(kDiceMigrationDialogShownCount, 1); + + base::Time time_now = base::Time::Now(); + ASSERT_LT(GetPrefs()->GetTime(kDiceMigrationDialogLastShownTime), time_now); + + // Show the migration bubble. + base::OneShotTimer& timer = + GetDiceMigrationService()->GetDialogTriggerTimerForTesting(); + ASSERT_TRUE(timer.IsRunning()); + timer.FireNow(); + views::Widget* widget = GetDiceMigrationService()->GetDialogWidgetForTesting(); ASSERT_TRUE(widget); - // The dialog last shown time is not updated yet. - EXPECT_LT(GetPrefs()->GetTime(kDiceMigrationDialogLastShownTime), time_now); + // The dialog shown count is incremented. + ASSERT_EQ(GetPrefs()->GetInteger(kDiceMigrationDialogShownCount), 2); + // The dialog last shown time is updated. + ASSERT_GE(GetPrefs()->GetTime(kDiceMigrationDialogLastShownTime), time_now); + time_now = GetPrefs()->GetTime(kDiceMigrationDialogLastShownTime); - // Simulate closing the dialog. views::test::WidgetDestroyedWaiter waiter(widget); - GetDiceMigrationService()->GetDialogWidgetForTesting()->CloseWithReason( - views::Widget::ClosedReason::kCancelButtonClicked); + // Simulate clicking on accept button. + widget->CloseWithReason(views::Widget::ClosedReason::kAcceptButtonClicked); waiter.Wait(); - // The dialog last shown time is now updated. - EXPECT_GE(GetPrefs()->GetTime(kDiceMigrationDialogLastShownTime), time_now); + // The dialog shown count and time are not updated anymore. + EXPECT_EQ(GetPrefs()->GetInteger(kDiceMigrationDialogShownCount), 2); + EXPECT_EQ(GetPrefs()->GetTime(kDiceMigrationDialogLastShownTime), time_now); } IN_PROC_BROWSER_TEST_F(DiceMigrationServiceBrowserTest,
diff --git a/chrome/browser/ui/tabs/BUILD.gn b/chrome/browser/ui/tabs/BUILD.gn index 1b393c3..4aee809 100644 --- a/chrome/browser/ui/tabs/BUILD.gn +++ b/chrome/browser/ui/tabs/BUILD.gn
@@ -171,6 +171,7 @@ "//chrome/browser/ui/browser_window", "//chrome/browser/ui/color:color_headers", "//chrome/browser/ui/tabs:tab_strip", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/toasts", "//chrome/browser/ui/toasts/api:toasts", @@ -486,6 +487,7 @@ "//chrome/browser/ui/lens", "//chrome/browser/ui/performance_controls", "//chrome/browser/ui/tabs/alert:tab_alert", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/thumbnails", "//chrome/browser/ui/toolbar", "//chrome/browser/ui/toolbar/pinned_toolbar", @@ -637,6 +639,7 @@ "//chrome/browser/ui:ui_features", "//chrome/browser/ui/browser_window", "//chrome/browser/ui/tabs/organization", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/web_applications", "//chrome/browser/web_applications:prevent_close_test_support", "//chrome/browser/web_applications:web_applications_test_support",
diff --git a/chrome/browser/ui/tabs/alert/OWNERS b/chrome/browser/ui/tabs/alert/OWNERS new file mode 100644 index 0000000..e0688a2 --- /dev/null +++ b/chrome/browser/ui/tabs/alert/OWNERS
@@ -0,0 +1 @@ +stluong@chromium.org \ No newline at end of file
diff --git a/chrome/browser/ui/tabs/glic_actor_task_icon_controller.cc b/chrome/browser/ui/tabs/glic_actor_task_icon_controller.cc index 434c07c..e126063 100644 --- a/chrome/browser/ui/tabs/glic_actor_task_icon_controller.cc +++ b/chrome/browser/ui/tabs/glic_actor_task_icon_controller.cc
@@ -49,6 +49,9 @@ case actor::ui::ActorUiStateManagerInterface::UiState::kCheckTasks: tab_strip_action_container_->TriggerGlicActorTaskIconCheckTasksNudge(); break; + case actor::ui::ActorUiStateManagerInterface::UiState::kCompleteTasks: + tab_strip_action_container_->TriggerGlicActorTaskIconCompleteTasksNudge(); + break; case actor::ui::ActorUiStateManagerInterface::UiState::kInactive: tab_strip_action_container_->HideGlicActorTaskIcon(); break;
diff --git a/chrome/browser/ui/tabs/organization/BUILD.gn b/chrome/browser/ui/tabs/organization/BUILD.gn index 91282da..9ebe01c9 100644 --- a/chrome/browser/ui/tabs/organization/BUILD.gn +++ b/chrome/browser/ui/tabs/organization/BUILD.gn
@@ -126,6 +126,7 @@ "//chrome/browser/ui/tabs:tab_group", "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/ui/tabs:test_support", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/tabs/saved_tab_groups:test_support", "//chrome/test:test_support", "//components/optimization_guide/core:model_execution",
diff --git a/chrome/browser/ui/tabs/public/tab_features.h b/chrome/browser/ui/tabs/public/tab_features.h index 7e22f15..d7c0c48 100644 --- a/chrome/browser/ui/tabs/public/tab_features.h +++ b/chrome/browser/ui/tabs/public/tab_features.h
@@ -24,7 +24,6 @@ class PwaInstallPageActionController; class ReadAnythingSidePanelController; class SidePanelRegistry; -class TabCaptureContentsBorderHelper; class TabResourceUsageTabHelper; class TabUIHelper; class TranslatePageActionController; @@ -413,9 +412,6 @@ std::unique_ptr<TabCreationMetricsController> tab_creation_metrics_controller_; - std::unique_ptr<TabCaptureContentsBorderHelper> - tab_capture_contents_border_helper_; - std::unique_ptr<autofill::BubbleManager> autofill_bubble_manager_; // Must be the last member.
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/BUILD.gn b/chrome/browser/ui/tabs/saved_tab_groups/BUILD.gn index eee4868..39e20b5 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/BUILD.gn +++ b/chrome/browser/ui/tabs/saved_tab_groups/BUILD.gn
@@ -6,6 +6,255 @@ import("//chrome/common/features.gni") +source_set("saved_tab_groups") { + sources = [ + "collaboration_messaging_observer.h", + "collaboration_messaging_observer_factory.h", + "collaboration_messaging_page_action_controller.h", + "collaboration_messaging_tab_data.h", + "instant_message_queue_processor.h", + "local_tab_group_listener.h", + "most_recent_shared_tab_update_store.h", + "saved_tab_group_controller.h", + "saved_tab_group_keyed_service.h", + "saved_tab_group_metrics.h", + "saved_tab_group_model_listener.h", + "saved_tab_group_pref_names.h", + "saved_tab_group_service_factory.h", + "saved_tab_group_utils.h", + "saved_tab_group_web_contents_listener.h", + "session_service_tab_group_sync_observer.h", + "shared_tab_group_feedback_controller.h", + "tab_group_action_context_desktop.h", + "tab_group_sync_delegate_desktop.h", + "tab_group_sync_service_proxy.h", + ] + public_deps = [ + "//base", + "//chrome/browser/profiles:profile", + "//chrome/browser/ui:browser_list", + "//chrome/browser/ui/browser_window", + "//chrome/browser/ui/tabs:tab_group", + "//chrome/browser/ui/tabs:tab_strip", + "//chrome/browser/ui/tabs:tab_strip_model_observer", + "//chrome/browser/ui/toasts", + "//chrome/browser/ui/views/page_action", + "//components/collaboration/public", + "//components/data_sharing/public:group_data", + "//components/keyed_service/core", + "//components/pref_registry", + "//components/prefs", + "//components/saved_tab_groups/delegate", + "//components/saved_tab_groups/internal:model", + "//components/saved_tab_groups/public", + "//components/sessions:session_id", + "//components/sync/base", + "//components/sync/model", + "//components/tab_groups", + "//components/tabs:public", + "//components/user_education/common", + "//content/public/browser", + "//ui/base", + "//ui/base:types", + "//ui/gfx", + "//ui/gfx/range", + "//url", + ] +} + +source_set("impl") { + sources = [ + "collaboration_messaging_observer.cc", + "collaboration_messaging_observer_factory.cc", + "collaboration_messaging_page_action_controller.cc", + "collaboration_messaging_tab_data.cc", + "instant_message_queue_processor.cc", + "local_tab_group_listener.cc", + "most_recent_shared_tab_update_store.cc", + "saved_tab_group_keyed_service.cc", + "saved_tab_group_metrics.cc", + "saved_tab_group_model_listener.cc", + "saved_tab_group_pref_names.cc", + "saved_tab_group_service_factory.cc", + "saved_tab_group_utils.cc", + "saved_tab_group_web_contents_listener.cc", + "session_service_tab_group_sync_observer.cc", + "shared_tab_group_feedback_controller.cc", + "tab_group_action_context_desktop.cc", + "tab_group_sync_delegate_desktop.cc", + "tab_group_sync_service_proxy.cc", + ] + deps = [ + ":saved_tab_groups", + "//base", + "//chrome/app:generated_resources", + "//chrome/app/vector_icons", + "//chrome/browser:browser_process", + "//chrome/browser/favicon", + "//chrome/browser/image_fetcher", + "//chrome/browser/profiles", + "//chrome/browser/profiles:profile", + "//chrome/browser/signin", + "//chrome/browser/sync", + "//chrome/browser/sync:factories", + "//chrome/browser/ui:browser_element_identifiers", + "//chrome/browser/ui:browser_list", + "//chrome/browser/ui/actions:actions_headers", + "//chrome/browser/ui/bookmarks", + "//chrome/browser/ui/browser_window", + "//chrome/browser/ui/page_action:icon_type", + "//chrome/browser/ui/tabs:tab_group", + "//chrome/browser/ui/tabs:tab_strip", + "//chrome/browser/ui/tabs:tab_strip_model_observer", + "//chrome/browser/ui/tabs:tabs_public", + "//chrome/browser/ui/toasts", + "//chrome/browser/ui/toasts/api:toasts", + "//chrome/browser/ui/user_education", + "//chrome/browser/ui/views/page_action", + "//chrome/browser/ui/views/toolbar", + "//chrome/common", + "//chrome/common:channel_info", + "//chrome/common:constants", + "//components/collaboration/public", + "//components/data_sharing/public", + "//components/data_sharing/public:features", + "//components/data_sharing/public:group_data", + "//components/favicon/core", + "//components/favicon_base", + "//components/feature_engagement/public:feature_constants", + "//components/image_fetcher/core", + "//components/pref_registry", + "//components/prefs", + "//components/saved_tab_groups/internal", + "//components/saved_tab_groups/internal:tab_group_sync_bridge", + "//components/saved_tab_groups/public", + "//components/saved_tab_groups/public:features", + "//components/saved_tab_groups/public:prefs", + "//components/sessions:session_id", + "//components/signin/public/base", + "//components/signin/public/identity_manager", + "//components/sync/base", + "//components/sync/base:features", + "//components/sync/model", + "//components/sync/service", + "//components/sync_device_info", + "//components/tab_groups", + "//components/tabs:public", + "//components/user_education/common", + "//content/public/browser", + "//ui/base", + "//ui/color:color_headers", + "//ui/compositor", + "//ui/gfx", + "//ui/gfx/range", + "//ui/views", + "//url", + ] + public_deps = [ "//chrome/browser:browser_public_dependencies" ] +} + +source_set("unit_tests") { + testonly = true + sources = [ + "collaboration_messaging_page_action_controller_unittest.cc", + "collaboration_messaging_tab_data_unittest.cc", + "instant_message_queue_processor_unittest.cc", + "saved_tab_group_keyed_service_unittest.cc", + "tab_group_sync_service_proxy_unittest.cc", + ] + deps = [ + ":saved_tab_groups", + ":test_support", + "//base", + "//base/test:test_support", + "//chrome/app:generated_resources", + "//chrome/browser/favicon", + "//chrome/browser/ui:ui_features", + "//chrome/browser/ui/actions:actions_headers", + "//chrome/browser/ui/tabs:tab_group", + "//chrome/browser/ui/tabs:tab_model", + "//chrome/browser/ui/tabs:tab_strip", + "//chrome/browser/ui/tabs:tabs_public", + "//chrome/browser/ui/toasts", + "//chrome/browser/ui/toasts/api:toasts", + "//chrome/browser/ui/views/page_action:test_support", + "//chrome/common", + "//chrome/test:test_support", + "//components/collaboration/public", + "//components/data_sharing:test_support", + "//components/data_sharing/public", + "//components/data_sharing/public:features", + "//components/data_sharing/public:group_data", + "//components/saved_tab_groups/internal:model", + "//components/saved_tab_groups/public", + "//components/saved_tab_groups/public:features", + "//components/saved_tab_groups/test_support", + "//components/signin/public/base", + "//components/tab_groups", + "//components/tabs:public", + "//components/tabs:test_support", + "//content/public/browser", + "//content/test:test_support", + "//testing/gtest", + "//ui/base", + "//ui/base:types", + "//ui/base/mojom:ui_base_types", + ] +} + +source_set("browser_tests") { + testonly = true + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + sources = [ + "collaboration_messaging_observer_browsertest.cc", + "saved_tab_group_web_contents_listener_browsertest.cc", + "tab_group_sync_delegate_browsertest.cc", + "tab_group_sync_navigation_browser_test.cc", + ] + deps = [ + ":saved_tab_groups", + "//base", + "//base/test:test_support", + "//chrome/browser", + "//chrome/browser/profiles:profile", + "//chrome/browser/sync", + "//chrome/browser/sync:factories", + "//chrome/browser/ui", + "//chrome/browser/ui:browser_element_identifiers", + "//chrome/browser/ui/browser_window", + "//chrome/browser/ui/tabs:tab_group", + "//chrome/browser/ui/tabs:tab_strip", + "//chrome/browser/ui/tabs:tabs_public", + "//chrome/browser/ui/toasts", + "//chrome/common", + "//chrome/common:channel_info", + "//chrome/test:test_support_ui", + "//components/collaboration/public", + "//components/collaboration/public:empty_messaging_backend_service", + "//components/data_sharing/public:features", + "//components/keyed_service/content", + "//components/keyed_service/core", + "//components/prefs", + "//components/saved_tab_groups/internal", + "//components/saved_tab_groups/internal:model", + "//components/saved_tab_groups/internal:service_test_utils", + "//components/saved_tab_groups/public", + "//components/saved_tab_groups/public:features", + "//components/sync/base", + "//components/sync/model", + "//components/sync_device_info", + "//components/tab_groups", + "//components/tabs:public", + "//content/public/browser", + "//content/test:test_support", + "//net:test_support", + "//testing/gmock", + "//testing/gtest", + "//ui/views", + "//url", + ] +} + source_set("test_support") { sources = [ "tab_group_sync_service_initialized_observer.cc",
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_page_action_controller.h b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_page_action_controller.h index 1d630bf..8afed65 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_page_action_controller.h +++ b/chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_page_action_controller.h
@@ -8,7 +8,6 @@ #include "base/memory/raw_ref.h" #include "chrome/browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data.h" #include "chrome/browser/ui/views/page_action/page_action_view.h" -#include "chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.h" #include "components/tabs/public/tab_interface.h" #include "string.h" #include "ui/gfx/image/image.h"
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc index 52e001b2..7807c60 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc
@@ -39,6 +39,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" #include "chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.h" #include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h"
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h index ce06325..eb03f547 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h
@@ -12,7 +12,6 @@ #include "base/uuid.h" #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h" #include "chrome/browser/ui/tabs/tab_group_deletion_dialog_controller.h" -#include "chrome/browser/ui/views/tabs/recent_activity_bubble_dialog_view.h" #include "components/data_sharing/public/group_data.h" #include "components/saved_tab_groups/public/saved_tab_group.h" #include "components/saved_tab_groups/public/types.h"
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.cc b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.cc index d139508bb..1964508 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.cc
@@ -213,6 +213,11 @@ NOTIMPLEMENTED(); } +void TabGroupSyncServiceProxy::MakeTabGroupUnsharedForTesting( + const LocalTabGroupID& local_group_id) { + NOTIMPLEMENTED(); +} + void TabGroupSyncServiceProxy::AboutToUnShareTabGroup( const LocalTabGroupID& local_group_id, base::OnceClosure on_complete_callback) {
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.h b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.h index c68d92e19..22bf2be 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.h +++ b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.h
@@ -82,6 +82,8 @@ void MakeTabGroupSharedForTesting( const LocalTabGroupID& local_group_id, const syncer::CollaborationId& collaboration_id) override; + void MakeTabGroupUnsharedForTesting( + const LocalTabGroupID& local_group_id) override; void AboutToUnShareTabGroup(const LocalTabGroupID& local_group_id, base::OnceClosure on_complete_cb) override;
diff --git a/chrome/browser/ui/tabs/tab_features.cc b/chrome/browser/ui/tabs/tab_features.cc index e820be7..5387058 100644 --- a/chrome/browser/ui/tabs/tab_features.cc +++ b/chrome/browser/ui/tabs/tab_features.cc
@@ -68,7 +68,6 @@ #include "chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.h" #include "chrome/browser/ui/views/side_panel/extensions/extension_side_panel_manager.h" #include "chrome/browser/ui/views/side_panel/read_anything/read_anything_side_panel_controller.h" -#include "chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h" #include "chrome/browser/ui/views/translate/translate_page_action_controller.h" #include "chrome/browser/ui/views/zoom/zoom_view_controller.h" #include "chrome/browser/ui/web_applications/pwa_install_page_action.h" @@ -371,10 +370,6 @@ qwac_web_contents_observer_ = std::make_unique<QwacWebContentsObserver>(tab); } - - tab_capture_contents_border_helper_ = - GetUserDataFactory().CreateInstance<TabCaptureContentsBorderHelper>(tab, - tab); } TabResourceUsageTabHelper* TabFeatures::SetResourceUsageHelperForTesting(
diff --git a/chrome/browser/ui/tabs/tab_strip_api/BUILD.gn b/chrome/browser/ui/tabs/tab_strip_api/BUILD.gn index 14747f2..76ae3bb 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/BUILD.gn +++ b/chrome/browser/ui/tabs/tab_strip_api/BUILD.gn
@@ -61,11 +61,16 @@ cpp = "::tab_groups::TabGroupVisualData" }, { + mojom = "tabs_api.mojom.Image" + cpp = "::gfx::ImageSkia" + }, + { mojom = "tabs_api.mojom.SplitTabVisualData" cpp = "::split_tabs::SplitTabVisualData" }, ] traits_headers = [ + "//chrome/browser/ui/tabs/tab_strip_api/types/image_traits.h", "//chrome/browser/ui/tabs/tab_strip_api/types/node_id.h", "//chrome/browser/ui/tabs/tab_strip_api/types/node_id_traits.h", "//chrome/browser/ui/tabs/tab_strip_api/types/position.h", @@ -73,9 +78,11 @@ "//chrome/browser/ui/tabs/tab_strip_api/types/tab_group_visual_data_traits.h", "//chrome/browser/ui/tabs/tab_strip_api/types/split_tab_visual_data_traits.h", "//components/tab_groups/tab_group_visual_data.h", + "//ui/gfx/image/image_skia.h", "//components/tabs/public/split_tab_visual_data.h", ] traits_sources = [ + "//chrome/browser/ui/tabs/tab_strip_api/types/image_traits.cc", "//chrome/browser/ui/tabs/tab_strip_api/types/node_id_traits.cc", "//chrome/browser/ui/tabs/tab_strip_api/types/position_traits.cc", "//chrome/browser/ui/tabs/tab_strip_api/types/split_tab_visual_data_traits.cc",
diff --git a/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter.h b/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter.h index af8872a..6f4b381 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter.h +++ b/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter.h
@@ -25,6 +25,7 @@ virtual void RemoveObserver(TabStripModelObserver* observer) = 0; virtual std::vector<tabs::TabHandle> GetTabs() const = 0; virtual TabRendererData GetTabRendererData(int index) const = 0; + virtual const ui::ColorProvider& GetColorProvider() const = 0; virtual void CloseTab(size_t tab_index) = 0; virtual std::optional<int> GetIndexForHandle(tabs::TabHandle tab_handle) = 0; virtual void ActivateTab(size_t index) = 0;
diff --git a/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter_impl.cc b/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter_impl.cc index 676a24a..0ab078e 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter_impl.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter_impl.cc
@@ -11,6 +11,7 @@ #include "components/tabs/public/tab_collection.h" #include "components/tabs/public/tab_group.h" #include "components/tabs/public/tab_interface.h" +#include "content/public/browser/web_contents.h" namespace tabs_api { @@ -34,6 +35,13 @@ return TabRendererData::FromTabInModel(tab_strip_model_, index); } +const ui::ColorProvider& TabStripModelAdapterImpl::GetColorProvider() const { + content::WebContents* active_contents = + tab_strip_model_->GetActiveWebContents(); + CHECK(active_contents); + return active_contents->GetColorProvider(); +} + void TabStripModelAdapterImpl::CloseTab(size_t tab_index) { tab_strip_model_->CloseWebContentsAt(tab_index, TabCloseTypes::CLOSE_NONE); }
diff --git a/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter_impl.h b/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter_impl.h index bc1355a..b22f0c8 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter_impl.h +++ b/chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter_impl.h
@@ -27,6 +27,7 @@ void RemoveObserver(TabStripModelObserver* observer) override; std::vector<tabs::TabHandle> GetTabs() const override; TabRendererData GetTabRendererData(int index) const override; + const ui::ColorProvider& GetColorProvider() const override; void CloseTab(size_t tab_index) override; std::optional<int> GetIndexForHandle(tabs::TabHandle tab_handle) override; void ActivateTab(size_t index) override;
diff --git a/chrome/browser/ui/tabs/tab_strip_api/adapters/tree_builder/tab_walker.cc b/chrome/browser/ui/tabs/tab_strip_api/adapters/tree_builder/tab_walker.cc index b0ad3c3..1d0adf22 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/adapters/tree_builder/tab_walker.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/adapters/tree_builder/tab_walker.cc
@@ -6,6 +6,7 @@ #include "chrome/browser/ui/tabs/tab_renderer_data.h" #include "chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.h" +#include "content/public/browser/web_contents.h" namespace tabs_api { @@ -17,8 +18,14 @@ auto idx = model_->GetIndexOfTab(target_); CHECK(idx != TabStripModel::kNoTab) << "tab disappeared while walking through the model"; + + content::WebContents* contents = model_->GetWebContentsAt(idx); + CHECK(contents); + const ui::ColorProvider& provider = contents->GetColorProvider(); + auto mojo_tab = tabs_api::converters::BuildMojoTab( - target_->GetHandle(), TabRendererData::FromTabInModel(model_, idx)); + target_->GetHandle(), TabRendererData::FromTabInModel(model_, idx), + provider); mojo_tab_container->tab = std::move(mojo_tab); return mojo_tab_container;
diff --git a/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.cc b/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.cc index 46f1ee066c..a5d9786 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.cc
@@ -19,14 +19,14 @@ namespace tabs_api::converters { tabs_api::mojom::TabPtr BuildMojoTab(tabs::TabHandle handle, - const TabRendererData& data) { + const TabRendererData& data, + const ui::ColorProvider& color_provider) { auto result = tabs_api::mojom::Tab::New(); result->id = tabs_api::NodeId(tabs_api::NodeId::Type::kContent, base::NumberToString(handle.raw_value())); result->title = base::UTF16ToUTF8(data.title); - // TODO(crbug.com/414630734). Integrate the favicon_url after it is - // typemapped. + result->favicon = data.favicon.Rasterize(&color_provider); result->url = data.visible_url; result->network_state = data.network_state; if (handle.Get() != nullptr) {
diff --git a/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.h b/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.h index 0cc3f3c84..6db7111 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.h +++ b/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters.h
@@ -9,11 +9,13 @@ #include "chrome/browser/ui/tabs/tab_strip_api/tab_strip_api.mojom.h" #include "components/tabs/public/tab_collection.h" #include "components/tabs/public/tab_interface.h" +#include "ui/color/color_provider.h" namespace tabs_api::converters { tabs_api::mojom::TabPtr BuildMojoTab(tabs::TabHandle handle, - const TabRendererData& data); + const TabRendererData& data, + const ui::ColorProvider& color_provider); // Builds a mojom::TabCollectionPtr based off a TabCollection. // Note: Handle must be valid and point to a live TabCollection. There is a
diff --git a/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters_unittest.cc b/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters_unittest.cc index 21756a7..957aef3 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/converters/tab_converters_unittest.cc
@@ -10,6 +10,7 @@ #include "components/tabs/public/tab_collection.h" #include "components/tabs/public/tab_interface.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/color/color_provider.h" #include "url/gurl.h" namespace tabs_api::converters { @@ -23,11 +24,12 @@ TEST(TabStripServiceConverters, ConvertTab) { tabs::TabHandle handle(888); + ui::ColorProvider color_provider; TabRendererData data; data.visible_url = GURL("http://nowhere"); data.title = std::u16string(u"title"); - auto mojo = BuildMojoTab(handle, data); + auto mojo = BuildMojoTab(handle, data, color_provider); ASSERT_EQ("888", mojo->id.Id()); ASSERT_EQ(NodeId::Type::kContent, mojo->id.Type());
diff --git a/chrome/browser/ui/tabs/tab_strip_api/events/event_transformation.cc b/chrome/browser/ui/tabs/tab_strip_api/events/event_transformation.cc index 8610571..f81a121 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/events/event_transformation.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/events/event_transformation.cc
@@ -15,17 +15,18 @@ namespace tabs_api::events { -mojom::OnTabsCreatedEventPtr ToEvent(const TabStripModelChange::Insert& insert, - TabStripModel* tab_strip_model) { +mojom::OnTabsCreatedEventPtr ToEvent( + const TabStripModelChange::Insert& insert, + const tabs_api::TabStripModelAdapter* adapter) { auto event = mojom::OnTabsCreatedEvent::New(); for (auto& content : insert.contents) { auto tab_created = tabs_api::mojom::TabCreatedContainer::New(); auto pos = tabs_api::Position(content.index); tab_created->position = std::move(pos); - auto renderer_data = - TabRendererData::FromTabInModel(tab_strip_model, content.index); + auto renderer_data = adapter->GetTabRendererData(content.index); + const ui::ColorProvider& provider = adapter->GetColorProvider(); auto mojo_tab = tabs_api::converters::BuildMojoTab(content.tab->GetHandle(), - renderer_data); + renderer_data, provider); tab_created->tab = std::move(mojo_tab); event->tabs.emplace_back(std::move(tab_created)); @@ -70,7 +71,9 @@ if (index < tabs.size()) { auto& handle = tabs.at(index); auto renderer_data = adapter->GetTabRendererData(index); - event->tab = tabs_api::converters::BuildMojoTab(handle, renderer_data); + const ui::ColorProvider& color_provider = adapter->GetColorProvider(); + event->tab = tabs_api::converters::BuildMojoTab(handle, renderer_data, + color_provider); } return event;
diff --git a/chrome/browser/ui/tabs/tab_strip_api/events/event_transformation.h b/chrome/browser/ui/tabs/tab_strip_api/events/event_transformation.h index 8d9f459..bf995c0 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/events/event_transformation.h +++ b/chrome/browser/ui/tabs/tab_strip_api/events/event_transformation.h
@@ -18,8 +18,9 @@ // some of the conversions are not covered by unit tests and must be covered in // integration tests. -mojom::OnTabsCreatedEventPtr ToEvent(const TabStripModelChange::Insert& insert, - TabStripModel* tab_strip_model); +mojom::OnTabsCreatedEventPtr ToEvent( + const TabStripModelChange::Insert& insert, + const tabs_api::TabStripModelAdapter* adapter); mojom::OnTabsClosedEventPtr ToEvent(const TabStripModelChange::Remove& remove); mojom::OnTabMovedEventPtr ToEvent(const TabStripModelChange::Move& move); mojom::OnTabDataChangedEventPtr ToEvent(
diff --git a/chrome/browser/ui/tabs/tab_strip_api/events/tab_strip_event_recorder.cc b/chrome/browser/ui/tabs/tab_strip_api/events/tab_strip_event_recorder.cc index 8b9c8a9..d1b789ad 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/events/tab_strip_event_recorder.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/events/tab_strip_event_recorder.cc
@@ -54,7 +54,7 @@ NOTIMPLEMENTED(); break; case TabStripModelChange::Type::kInserted: - Handle(ToEvent(*change.GetInsert(), tab_strip_model)); + Handle(ToEvent(*change.GetInsert(), tab_strip_model_adapter_)); break; case TabStripModelChange::Type::kRemoved: Handle(ToEvent(*change.GetRemove()));
diff --git a/chrome/browser/ui/tabs/tab_strip_api/tab_strip_api_data_model.mojom b/chrome/browser/ui/tabs/tab_strip_api/tab_strip_api_data_model.mojom index c370037b..fc68b77 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/tab_strip_api_data_model.mojom +++ b/chrome/browser/ui/tabs/tab_strip_api/tab_strip_api_data_model.mojom
@@ -9,14 +9,17 @@ import "components/tab_groups/public/mojom/tab_group_types.mojom"; import "url/mojom/url.mojom"; +// Holds a data URL representation of an image, ie: favicon. +struct Image { + url.mojom.Url data_url; +}; + struct Tab { NodeId id; string title; url.mojom.Url url; - // TODO(crbug.com/414630734). The favicon should be typemapped to ImageModel - // in c++. Leave this as a data uri for now. - url.mojom.Url favicon_url; + Image favicon; array<tabs.mojom.TabAlertState> alert_states; tabs.mojom.TabNetworkState network_state;
diff --git a/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl.cc b/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl.cc index ed5ee97..7b14558 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl.cc
@@ -114,7 +114,10 @@ auto& handle = tabs.at(i); if (tab_id == handle.raw_value()) { auto renderer_data = tab_strip_model_adapter_->GetTabRendererData(i); - tab_result = tabs_api::converters::BuildMojoTab(handle, renderer_data); + const ui::ColorProvider& color_provider = + tab_strip_model_adapter_->GetColorProvider(); + tab_result = tabs_api::converters::BuildMojoTab(handle, renderer_data, + color_provider); } } @@ -164,7 +167,10 @@ auto renderer_data = tab_strip_model_adapter_->GetTabRendererData(tab_index.value()); - auto mojo_tab = tabs_api::converters::BuildMojoTab(tab_handle, renderer_data); + const ui::ColorProvider& color_provider = + tab_strip_model_adapter_->GetColorProvider(); + auto mojo_tab = tabs_api::converters::BuildMojoTab(tab_handle, renderer_data, + color_provider); std::move(callback).Run(base::ok(std::move(mojo_tab))); }
diff --git a/chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip_model_adapter.cc b/chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip_model_adapter.cc index ea14e09..390acbc 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip_model_adapter.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip_model_adapter.cc
@@ -25,6 +25,10 @@ return TabRendererData(); } +const ui::ColorProvider& ToyTabStripModelAdapter::GetColorProvider() const { + return color_provider_; +} + void ToyTabStripModelAdapter::CloseTab(size_t idx) { tab_strip_->CloseTab(idx); }
diff --git a/chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip_model_adapter.h b/chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip_model_adapter.h index 9e94dcd..6f3683a9 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip_model_adapter.h +++ b/chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip_model_adapter.h
@@ -8,6 +8,7 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/ui/tabs/tab_strip_api/adapters/tab_strip_model_adapter.h" #include "chrome/browser/ui/tabs/tab_strip_api/testing/toy_tab_strip.h" +#include "ui/color/color_provider.h" namespace tabs_api::testing { @@ -22,6 +23,7 @@ void RemoveObserver(TabStripModelObserver* observer) override; std::vector<tabs::TabHandle> GetTabs() const override; TabRendererData GetTabRendererData(int index) const override; + const ui::ColorProvider& GetColorProvider() const override; void CloseTab(size_t tab_index) override; std::optional<int> GetIndexForHandle(tabs::TabHandle tab_handle) override; void ActivateTab(size_t index) override; @@ -36,6 +38,7 @@ private: raw_ptr<ToyTabStrip> tab_strip_; + ui::ColorProvider color_provider_; }; } // namespace tabs_api::testing
diff --git a/chrome/browser/ui/tabs/tab_strip_api/types/image_traits.cc b/chrome/browser/ui/tabs/tab_strip_api/types/image_traits.cc new file mode 100644 index 0000000..b3b6798f --- /dev/null +++ b/chrome/browser/ui/tabs/tab_strip_api/types/image_traits.cc
@@ -0,0 +1,58 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/tabs/tab_strip_api/types/image_traits.h" + +#include "base/base64.h" +#include "base/containers/span.h" +#include "net/base/data_url.h" +#include "skia/ext/codec_utils.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/codec/png_codec.h" +#include "ui/gfx/image/image_skia.h" + +GURL mojo::StructTraits<MojoImageView, NativeImage>::data_url( + const NativeImage& native) { + if (native.isNull()) { + return GURL(); + } + const SkBitmap* bitmap = native.bitmap(); + if (!bitmap || bitmap->isNull()) { + return GURL(); + } + return GURL(skia::EncodePngAsDataUri(bitmap->pixmap())); +} + +bool mojo::StructTraits<MojoImageView, NativeImage>::Read(MojoImageView view, + NativeImage* out) { + GURL data_url; + if (!view.ReadDataUrl(&data_url)) { + return false; + } + + if (data_url.is_empty()) { + *out = gfx::ImageSkia(); + return true; + } + + if (!data_url.is_valid()) { + return false; + } + + std::string mime_type; + std::string charset; + std::string image_data; + if (!net::DataURL::Parse(data_url, &mime_type, &charset, &image_data)) { + return false; + } + + SkBitmap bitmap = + gfx::PNGCodec::Decode(base::as_bytes(base::span(image_data))); + if (bitmap.isNull()) { + return false; + } + + *out = gfx::ImageSkia::CreateFromBitmap(bitmap, 1.0f); + return true; +}
diff --git a/chrome/browser/ui/tabs/tab_strip_api/types/image_traits.h b/chrome/browser/ui/tabs/tab_strip_api/types/image_traits.h new file mode 100644 index 0000000..300f33c --- /dev/null +++ b/chrome/browser/ui/tabs/tab_strip_api/types/image_traits.h
@@ -0,0 +1,22 @@ +// 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 CHROME_BROWSER_UI_TABS_TAB_STRIP_API_TYPES_IMAGE_TRAITS_H_ +#define CHROME_BROWSER_UI_TABS_TAB_STRIP_API_TYPES_IMAGE_TRAITS_H_ + +#include "chrome/browser/ui/tabs/tab_strip_api/tab_strip_api_data_model.mojom.h" +#include "mojo/public/cpp/bindings/struct_traits.h" +#include "ui/gfx/image/image_skia.h" +#include "url/gurl.h" + +using MojoImageView = tabs_api::mojom::ImageDataView; +using NativeImage = gfx::ImageSkia; + +template <> +struct mojo::StructTraits<MojoImageView, NativeImage> { + static GURL data_url(const NativeImage& native); + static bool Read(MojoImageView view, NativeImage* out); +}; + +#endif // CHROME_BROWSER_UI_TABS_TAB_STRIP_API_TYPES_IMAGE_TRAITS_H_
diff --git a/chrome/browser/ui/tabs/tab_strip_api/types/tab_strip_service_traits_unittest.cc b/chrome/browser/ui/tabs/tab_strip_api/types/tab_strip_service_traits_unittest.cc index d2e360c..959b81d 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/types/tab_strip_service_traits_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/types/tab_strip_service_traits_unittest.cc
@@ -3,11 +3,13 @@ // found in the LICENSE file. #include "chrome/browser/ui/tabs/tab_strip_api/tab_strip_api.mojom.h" +#include "chrome/browser/ui/tabs/tab_strip_api/types/image_traits.h" #include "chrome/browser/ui/tabs/tab_strip_api/types/node_id_traits.h" #include "chrome/browser/ui/tabs/tab_strip_api/types/position_traits.h" #include "components/tab_groups/tab_group_visual_data.h" #include "components/tabs/public/split_tab_visual_data.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" namespace tabs_api { namespace { @@ -62,5 +64,21 @@ ASSERT_TRUE(original == deserialized); } +TEST(TabsStripServiceMojoTraitsTest, ConvertImage) { + SkBitmap bitmap; + bitmap.allocN32Pixels(1, 1); + bitmap.eraseColor(SK_ColorRED); + gfx::ImageSkia original = gfx::ImageSkia::CreateFromBitmap(bitmap, 1.0f); + + std::vector<uint8_t> serialized = mojom::Image::Serialize(&original); + + gfx::ImageSkia deserialized; + ASSERT_TRUE(mojom::Image::Deserialize(serialized, &deserialized)); + + ASSERT_FALSE(deserialized.isNull()); + ASSERT_EQ(original.bitmap()->getColor(0, 0), + deserialized.bitmap()->getColor(0, 0)); +} + } // namespace } // namespace tabs_api
diff --git a/chrome/browser/ui/toasts/BUILD.gn b/chrome/browser/ui/toasts/BUILD.gn index c83c584f..1aead54 100644 --- a/chrome/browser/ui/toasts/BUILD.gn +++ b/chrome/browser/ui/toasts/BUILD.gn
@@ -50,6 +50,7 @@ "//chrome/browser:browser_public_dependencies", "//chrome/browser/profiles:profile", "//chrome/browser/ui:browser_element_identifiers", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/views/side_panel", "//components/data_sharing/public:features", "//components/plus_addresses:features",
diff --git a/chrome/browser/ui/views/autofill/popup/lazy_loading_image_view_unittest.cc b/chrome/browser/ui/views/autofill/popup/lazy_loading_image_view_unittest.cc index 0a3ce08..484a7d7 100644 --- a/chrome/browser/ui/views/autofill/popup/lazy_loading_image_view_unittest.cc +++ b/chrome/browser/ui/views/autofill/popup/lazy_loading_image_view_unittest.cc
@@ -9,6 +9,7 @@ #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/test/views/chrome_views_test_base.h" #include "components/vector_icons/vector_icons.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_unittest_util.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc index 5732fe3..a1b89a6 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc
@@ -459,17 +459,6 @@ class PrerenderBookmarkBarOnPressedNavigationTest : public PrerenderBookmarkBarNavigationTestBase { public: - PrerenderBookmarkBarOnPressedNavigationTest() { - // Mousedown prerender trigger is disabled explicitly and onHover delay is - // set to 0ms for testing. - scoped_feature_list_.InitWithFeaturesAndParameters( - { - {features::kBookmarkTriggerForPrerender2, - {{"prerender_bookmarkbar_on_mouse_pressed_trigger", "true"}}}, - }, - /*disabled_features=*/{}); - } - const content::test::PreloadingAttemptUkmEntryBuilder& ukm_entry_builder() { return *ukm_entry_builder_; } @@ -670,12 +659,8 @@ : public PrerenderBookmarkBarNavigationTestBase { public: PrerenderBookmarkBarDisabledNavigationTest() { - scoped_feature_list_.InitWithFeaturesAndParameters( - { - {features::kBookmarkTriggerForPrerender2, - {{"prerender_bookmarkbar_on_mouse_pressed_trigger", "false"}}}, - }, - /*disabled_features=*/{}); + scoped_feature_list_.InitAndEnableFeature( + features::kBookmarkTriggerForPrerender2KillSwitch); } const content::test::PreloadingAttemptUkmEntryBuilder& ukm_entry_builder() {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_button.cc b/chrome/browser/ui/views/bookmarks/bookmark_button.cc index 617cd930..0e67beb 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_button.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_button.cc
@@ -173,35 +173,30 @@ base::Unretained(this), *url_)); } - if (base::FeatureList::IsEnabled(features::kBookmarkTriggerForPreconnect) || - base::FeatureList::IsEnabled(features::kBookmarkTriggerForPrerender2)) { - // Now we should register the callback function that will be used to - // compute the preloading recall. - if (auto* web_contents = - browser_->tab_strip_model()->GetActiveWebContents()) { - content::PreloadingData* preloading_data = - content::PreloadingData::GetOrCreateForWebContents(web_contents); - preloading_data->SetIsNavigationInDomainCallback( - chrome_preloading_predictor::kMouseHoverOrMouseDownOnBookmarkBar, - base::BindRepeating( - [](content::NavigationHandle* navigation_handle) -> bool { - return ui::PageTransitionCoreTypeIs( - navigation_handle->GetPageTransition(), - ui::PAGE_TRANSITION_AUTO_BOOKMARK) && - ui::PageTransitionIsNewNavigation( - navigation_handle->GetPageTransition()); - })); - } + // Now we should register the callback function that will be used to + // compute the preloading recall. + if (auto* web_contents = + browser_->tab_strip_model()->GetActiveWebContents()) { + content::PreloadingData* preloading_data = + content::PreloadingData::GetOrCreateForWebContents(web_contents); + preloading_data->SetIsNavigationInDomainCallback( + chrome_preloading_predictor::kMouseHoverOrMouseDownOnBookmarkBar, + base::BindRepeating( + [](content::NavigationHandle* navigation_handle) -> bool { + return ui::PageTransitionCoreTypeIs( + navigation_handle->GetPageTransition(), + ui::PAGE_TRANSITION_AUTO_BOOKMARK) && + ui::PageTransitionIsNewNavigation( + navigation_handle->GetPageTransition()); + })); } } void BookmarkButton::OnMouseExited(const ui::MouseEvent& event) { BookmarkButtonBase::OnMouseExited(event); - if (base::FeatureList::IsEnabled(features::kBookmarkTriggerForPrerender2)) { - preloading_timer_.Stop(); - if (bookmarkbar_preload_manager_) { - bookmarkbar_preload_manager_->ResetPrerender(); - } + preloading_timer_.Stop(); + if (bookmarkbar_preload_manager_) { + bookmarkbar_preload_manager_->ResetPrerender(); } } @@ -211,8 +206,7 @@ base::UmaHistogramEnumeration("Prerender.Experimental.BookmarkMetrics", PreloadBookmarkMetricsEvent::kMouseDown); } - if (event.IsOnlyLeftMouseButton() && - base::FeatureList::IsEnabled(features::kBookmarkTriggerForPrerender2)) { + if (event.IsOnlyLeftMouseButton()) { StartPrerendering(*url_); } return result; @@ -246,7 +240,6 @@ } void BookmarkButton::StartPrerendering(GURL url) { - CHECK(base::FeatureList::IsEnabled(features::kBookmarkTriggerForPrerender2)); auto* active_web_contents = browser_->tab_strip_model()->GetActiveWebContents(); if (!active_web_contents) {
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_interactive_uitest.cc b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_interactive_uitest.cc index 8736cf6f..b270bda 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_interactive_uitest.cc
@@ -1413,19 +1413,15 @@ auto extension = InstallExtensionWithHostPermissions("All Urls Extension", "<all_urls>"); + // Automatically accept the reload page dialog that appears when changing site + // access. + auto reload_page_dialog_reset = + extensions::ReloadPageDialogController::AcceptDialogForTesting(true); RunTestSequence( InstrumentTab(kTab), NavigateWebContents( kTab, embedded_test_server()->GetURL("example.com", "/title1.html")), - // Automatically accept the reload page dialog that appears when - // changing site access. - Do([&]() { - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - extensions::ExtensionActionRunner::GetForWebContents(web_contents) - ->accept_bubble_for_testing(true); - }), OpenExtensionsMenu(), CheckView(
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_unittest.cc b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_unittest.cc index 93b4b11..06c1b0fd 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_unittest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view_unittest.cc
@@ -721,10 +721,11 @@ l10n_util::GetStringUTF16( IDS_EXTENSIONS_MENU_MAIN_PAGE_EXTENSION_SITE_ACCESS_ON_CLICK)); + auto reload_page_dialog_reset = + extensions::ReloadPageDialogController::AcceptDialogForTesting(false); auto* action_runner = extensions::ExtensionActionRunner::GetForWebContents(web_contents); ASSERT_TRUE(action_runner); - action_runner->accept_bubble_for_testing(false); // When extension is granted tab permissions it has: // - site interaction is "granted".
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc index 962898a..5153671 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc
@@ -623,10 +623,8 @@ { // Since we are revoking permissions, automatically accept the reload page // bubble to update the permissions. - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - extensions::ExtensionActionRunner::GetForWebContents(web_contents) - ->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + extensions::ReloadPageDialogController::AcceptDialogForTesting(true); extensions::PermissionsManagerWaiter waiter( extensions::PermissionsManager::Get(profile())); context_menu->ExecuteCommand(
diff --git a/chrome/browser/ui/views/extensions/extensions_toolbar_container_interactive_uitest.cc b/chrome/browser/ui/views/extensions/extensions_toolbar_container_interactive_uitest.cc index 312c6b6..bb8d033 100644 --- a/chrome/browser/ui/views/extensions/extensions_toolbar_container_interactive_uitest.cc +++ b/chrome/browser/ui/views/extensions/extensions_toolbar_container_interactive_uitest.cc
@@ -802,7 +802,8 @@ // Allow the extension to run on this site. This should show a refresh page // bubble. Accept the bubble. content::TestNavigationObserver observer(web_contents); - runner->accept_bubble_for_testing(true); + auto reload_page_dialog_reset = + extensions::ReloadPageDialogController::AcceptDialogForTesting(true); extension_menu->ExecuteCommand( extensions::ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_SITE, /*event_flags=*/0); @@ -844,7 +845,8 @@ // Allow the extension to run on all sites this time. This should again show // a refresh bubble. Dismiss it. - runner->accept_bubble_for_testing(false); + auto reload_page_dialog_reset = + extensions::ReloadPageDialogController::AcceptDialogForTesting(false); extension_menu->ExecuteCommand( extensions::ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_ALL_SITES, /*event_flags=*/0); @@ -1072,10 +1074,10 @@ // Click the request access button to always grants site access. A reload // page dialog will appear since extension A needs a page reload to run its // action. - auto* action_runner = - extensions::ExtensionActionRunner::GetForWebContents(web_contents); const bool kReloadBubbleAccepted = GetParam(); - action_runner->accept_bubble_for_testing(kReloadBubbleAccepted); + auto reload_page_dialog_reset = + extensions::ReloadPageDialogController::AcceptDialogForTesting( + kReloadBubbleAccepted); ExtensionTestMessageListener script_injection_listener("injection succeeded"); ClickButton(request_access_button()); WaitForAnimation();
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 6781ea6..356c08ce94 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -4474,8 +4474,6 @@ extension_keybinding_registry_.get()) { registry->set_registry_for_active_window(nullptr); } - - immersive_mode_controller()->OnWidgetActivationChanged(widget, active); } void BrowserView::OnWidgetBoundsChanged(views::Widget* widget,
diff --git a/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc b/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc index 18d2ce7..ed5d35f 100644 --- a/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc +++ b/chrome/browser/ui/views/frame/browser_view_layout_unittest.cc
@@ -146,7 +146,6 @@ void OnFindBarVisibleBoundsChanged( const gfx::Rect& new_visible_bounds) override {} bool ShouldStayImmersiveAfterExitingFullscreen() override { return true; } - void OnWidgetActivationChanged(views::Widget* widget, bool active) override {} int GetMinimumContentOffset() const override { return 0; } int GetExtraInfobarOffset() const override { return 0; } void OnContentFullscreenChanged(bool is_content_fullscreen) override {}
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller.h b/chrome/browser/ui/views/frame/immersive_mode_controller.h index e125ba4..b1949ce 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller.h +++ b/chrome/browser/ui/views/frame/immersive_mode_controller.h
@@ -114,13 +114,6 @@ // in which case we should stay in immersive mode. virtual bool ShouldStayImmersiveAfterExitingFullscreen() = 0; - // Called by browser view to indicate the widget activation has changed. - // Immersive mode should be enabled/disabled if the widget is - // active/nonactive when the auto hide title bars in tablet mode feature is - // on. - virtual void OnWidgetActivationChanged(views::Widget* widget, - bool active) = 0; - // Returns the minimum y-offset for the web contents. Used on Mac to prevent // find results from hiding under the top chrome when the find bar is in use. virtual int GetMinimumContentOffset() const = 0;
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc index 2787b14..87c42dde 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc
@@ -130,44 +130,6 @@ display::Screen::GetScreen()->InTabletMode(); } -void ImmersiveModeControllerChromeos::OnWidgetActivationChanged( - views::Widget* widget, - bool active) { - if (browser_view_->GetSupportsTabStrip()) { - return; - } - - if (!display::Screen::GetScreen()->InTabletMode()) { - return; - } - - // Avoid using immersive mode in locked fullscreen as it allows the user to - // exit the locked mode. Keep immersive mode enabled if the webapp is locked - // for OnTask (only relevant for non-web browser scenarios). - // TODO(b/365146870): Remove once we consolidate locked fullscreen with - // OnTask. - Browser* const browser = browser_view_->browser(); - bool avoid_using_immersive_mode = - platform_util::IsBrowserLockedFullscreen(browser); - if (browser->IsLockedForOnTask()) { - avoid_using_immersive_mode = false; - } - if (avoid_using_immersive_mode) { - return; - } - - DCHECK_EQ(browser_view_->frame(), widget); - if (widget->GetNativeWindow()->GetProperty(chromeos::kWindowStateTypeKey) == - chromeos::WindowStateType::kFloated) { - SetEnabled(false); - return; - } - - // Enable immersive mode if the widget is activated. Do not disable immersive - // mode if the widget deactivates, but is not minimized. - SetEnabled(active || !widget->IsMinimized()); -} - int ImmersiveModeControllerChromeos::GetMinimumContentOffset() const { return 0; }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h index 366c885..94b8d840 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.h
@@ -48,7 +48,6 @@ void OnFindBarVisibleBoundsChanged( const gfx::Rect& new_visible_bounds_in_screen) override; bool ShouldStayImmersiveAfterExitingFullscreen() override; - void OnWidgetActivationChanged(views::Widget* widget, bool active) override; int GetMinimumContentOffset() const override; int GetExtraInfobarOffset() const override; void OnContentFullscreenChanged(bool is_content_fullscreen) override;
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_mac.h b/chrome/browser/ui/views/frame/immersive_mode_controller_mac.h index 5abf84a..964cc004 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_mac.h +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_mac.h
@@ -90,7 +90,6 @@ void OnFindBarVisibleBoundsChanged( const gfx::Rect& new_visible_bounds_in_screen) override; bool ShouldStayImmersiveAfterExitingFullscreen() override; - void OnWidgetActivationChanged(views::Widget* widget, bool active) override; int GetMinimumContentOffset() const override; int GetExtraInfobarOffset() const override; void OnContentFullscreenChanged(bool is_content_fullscreen) override;
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm b/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm index 793e4a46..2211090 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm
@@ -295,10 +295,6 @@ return false; } -void ImmersiveModeControllerMac::OnWidgetActivationChanged( - views::Widget* widget, - bool active) {} - int ImmersiveModeControllerMac::GetMinimumContentOffset() const { if (find_bar_visible_ && !fullscreen_utils::IsAlwaysShowToolbarEnabled(browser_view_->browser()) &&
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_stub.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_stub.cc index 85bc767..e492d6c 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_stub.cc +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_stub.cc
@@ -41,10 +41,6 @@ return false; } -void ImmersiveModeControllerStub::OnWidgetActivationChanged( - views::Widget* widget, - bool active) {} - int ImmersiveModeControllerStub::GetMinimumContentOffset() const { return 0; }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_stub.h b/chrome/browser/ui/views/frame/immersive_mode_controller_stub.h index 2965eae4..1bf8eb82 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_stub.h +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_stub.h
@@ -24,7 +24,6 @@ void OnFindBarVisibleBoundsChanged( const gfx::Rect& new_visible_bounds_in_screen) override; bool ShouldStayImmersiveAfterExitingFullscreen() override; - void OnWidgetActivationChanged(views::Widget* widget, bool active) override; int GetMinimumContentOffset() const override; int GetExtraInfobarOffset() const override; void OnContentFullscreenChanged(bool is_content_fullscreen) override;
diff --git a/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc index 98f7714..b39c3f6 100644 --- a/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
@@ -446,10 +446,8 @@ }))); } -// TODO(crbug.com/399212996): Flaky on linux_chromium_asan_rel_ng and -// chromium/ci/Linux Chromium OS ASan LSan Tests (1). -#if (defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER)) && \ - (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) +// TODO(crbug.com/399212996): Flaky on Linux and ChromeOS. +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) #define MAYBE_ResizesViaKeyboard DISABLED_ResizesViaKeyboard #else #define MAYBE_ResizesViaKeyboard ResizesViaKeyboard
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc index da051a9f..abdd43c 100644 --- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc +++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
@@ -1092,8 +1092,10 @@ EXPECT_EQ("4", content::EvalJs(contents, "getSelectedValue();")); } -IN_PROC_BROWSER_TEST_F(TopControlsSlideControllerTest, - TestScrollingMaximizedPageBeforeGoingToTabletMode) { +// TODO(crbug.com/436706865): Re-enable this test. +IN_PROC_BROWSER_TEST_F( + TopControlsSlideControllerTest, + DISABLED_TestScrollingMaximizedPageBeforeGoingToTabletMode) { // If the page exists in a maximized browser window before going to tablet // mode, the layout that results from going to tablet mode does not change // the size of the page viewport. Hence, the visual properties of the renderer @@ -1192,8 +1194,9 @@ bool seen_intermediate_ratios_ = false; }; +// TODO(crbug.com/436709208): Re-enable this test. IN_PROC_BROWSER_TEST_F(TopControlsSlideControllerTest, - TestIntermediateSliding) { + DISABLED_TestIntermediateSliding) { ToggleTabletMode(); ASSERT_TRUE(GetTabletModeEnabled()); EXPECT_TRUE(top_controls_slide_controller()->IsEnabled());
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc index d953a476c..10ca143 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc +++ b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view.cc
@@ -25,6 +25,7 @@ #include "components/vector_icons/vector_icons.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h"
diff --git a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc index 8e8d856e..4992642 100644 --- a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc +++ b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/location_bar/location_bar_view.h" #include "components/omnibox/common/omnibox_features.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/pointer/touch_ui_controller.h"
diff --git a/chrome/browser/ui/views/page_action/page_action_properties_provider.cc b/chrome/browser/ui/views/page_action/page_action_properties_provider.cc index 2996be1..af100cd 100644 --- a/chrome/browser/ui/views/page_action/page_action_properties_provider.cc +++ b/chrome/browser/ui/views/page_action/page_action_properties_provider.cc
@@ -71,6 +71,7 @@ { .histogram_name = "PwaInstall", .type = PageActionIconType::kPwaInstall, + .element_identifier = kInstallPwaElementId, }, }, {
diff --git a/chrome/browser/ui/views/page_info/chosen_object_view.cc b/chrome/browser/ui/views/page_info/chosen_object_view.cc index 68796855..2dd8dc65 100644 --- a/chrome/browser/ui/views/page_info/chosen_object_view.cc +++ b/chrome/browser/ui/views/page_info/chosen_object_view.cc
@@ -35,8 +35,6 @@ std::unique_ptr<PageInfoUI::ChosenObjectInfo> info, std::u16string display_name) : info_(std::move(info)) { - // TODO(crbug.com/40064612): Directly subclass `RichControlsContainerView` - // instead of adding it as the only child. SetUseDefaultFillLayout(true); row_view_ = AddChildView(std::make_unique<RichControlsContainerView>()); row_view_->SetTitle(display_name);
diff --git a/chrome/browser/ui/views/page_info/page_info_main_view.cc b/chrome/browser/ui/views/page_info/page_info_main_view.cc index 8d0c03d..7009a73 100644 --- a/chrome/browser/ui/views/page_info/page_info_main_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_main_view.cc
@@ -243,6 +243,8 @@ const PermissionInfoList& permission_info_list, ChosenObjectInfoList chosen_object_info_list) { if (permission_info_list.empty() && chosen_object_info_list.empty()) { + toggle_rows_.clear(); + syncable_permission_rows_.clear(); permissions_view_->RemoveAllChildViews(); return; }
diff --git a/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc b/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc index d802343..db10ad7 100644 --- a/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc +++ b/chrome/browser/ui/views/page_info/permission_toggle_row_view.cc
@@ -71,8 +71,6 @@ : permission_(permission), delegate_(delegate), navigation_handler_(navigation_handler) { - // TODO(crbug.com/40064612): Directly subclass `RichControlsContainerView` - // instead of adding it as the only child. SetUseDefaultFillLayout(true); row_view_ = AddChildView(std::make_unique<RichControlsContainerView>());
diff --git a/chrome/browser/ui/views/performance_controls/memory_saver_interactive_ui_test.cc b/chrome/browser/ui/views/performance_controls/memory_saver_interactive_ui_test.cc index 68c384d..954f0268 100644 --- a/chrome/browser/ui/views/performance_controls/memory_saver_interactive_ui_test.cc +++ b/chrome/browser/ui/views/performance_controls/memory_saver_interactive_ui_test.cc
@@ -442,8 +442,16 @@ } // Page Action chip should collapses after navigating to a tab without a chip +// TODO(crbug.com/436684093) Flaky on Mac. +#if BUILDFLAG(IS_MAC) +#define MAYBE_PageActionChipCollapseOnTabSwitch \ + DISABLED_PageActionChipCollapseOnTabSwitch +#else +#define MAYBE_PageActionChipCollapseOnTabSwitch \ + PageActionChipCollapseOnTabSwitch +#endif IN_PROC_BROWSER_TEST_P(MemorySaverChipInteractiveTest, - PageActionChipCollapseOnTabSwitch) { + MAYBE_PageActionChipCollapseOnTabSwitch) { RunTestSequence( InstrumentTab(kFirstTabContents, 0), NavigateWebContents(kFirstTabContents, GetURL()), @@ -499,8 +507,14 @@ } // Page Action chip should only show on discarded non-chrome pages +// TODO(crbug.com/436684093) Flaky on Mac. +#if BUILDFLAG(IS_MAC) +#define MAYBE_ChipShowsOnNonChromeSites DISABLED_ChipShowsOnNonChromeSites +#else +#define MAYBE_ChipShowsOnNonChromeSites ChipShowsOnNonChromeSites +#endif IN_PROC_BROWSER_TEST_P(MemorySaverChipInteractiveTest, - ChipShowsOnNonChromeSites) { + MAYBE_ChipShowsOnNonChromeSites) { // Any Chrome page that can be reliably discarded. This was // previously the NTP, but NTP is sometimes ineligible for proactive tab // discard.
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view_browsertest.cc b/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view_browsertest.cc index 3da552ee..8ebda6d 100644 --- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view_browsertest.cc +++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view_browsertest.cc
@@ -51,6 +51,7 @@ #include "content/public/test/cursor_utils.h" #include "content/public/test/test_utils.h" #include "net/dns/mock_host_resolver.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" #include "ui/events/base_event_utils.h" #include "ui/gfx/animation/animation.h"
diff --git a/chrome/browser/ui/views/side_panel/BUILD.gn b/chrome/browser/ui/views/side_panel/BUILD.gn index 4ffe08b..bae6cc0 100644 --- a/chrome/browser/ui/views/side_panel/BUILD.gn +++ b/chrome/browser/ui/views/side_panel/BUILD.gn
@@ -151,6 +151,7 @@ "//chrome/browser/ui/extensions", "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/ui/tabs:tabs_public", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/user_education", "//chrome/browser/ui/views/toolbar", "//chrome/browser/ui/webui:webui_util",
diff --git a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.cc index 6c02761..5cebc0d 100644 --- a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.cc +++ b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.cc
@@ -23,6 +23,7 @@ #include "components/collaboration/public/features.h" #include "components/saved_tab_groups/public/saved_tab_group.h" #include "components/saved_tab_groups/public/tab_group_sync_service.h" +#include "components/saved_tab_groups/public/types.h" #include "components/strings/grit/components_strings.h" #include "components/tab_groups/tab_group_id.h" #include "ui/base/l10n/l10n_util.h" @@ -41,9 +42,15 @@ tab_groups::SavedTabGroupUtils::GetServiceForProfile( browser_->GetProfile())) { browser_->GetTabStripModel()->AddObserver(this); + tab_groups::SavedTabGroupUtils::GetServiceForProfile(browser_->GetProfile()) + ->AddObserver(this); } -CommentsSidePanelCoordinator::~CommentsSidePanelCoordinator() = default; +CommentsSidePanelCoordinator::~CommentsSidePanelCoordinator() { + browser_->GetTabStripModel()->RemoveObserver(this); + tab_groups::SavedTabGroupUtils::GetServiceForProfile(browser_->GetProfile()) + ->RemoveObserver(this); +} void CommentsSidePanelCoordinator::OnTabStripModelChanged( TabStripModel* tab_strip_model, @@ -71,8 +78,20 @@ UpdateVisuals(tab); } -// TODO(crbug.com/433773768): This should also be called when the current tab -// group becomes shared/unshared. +void CommentsSidePanelCoordinator::OnTabGroupUpdated( + const tab_groups::SavedTabGroup& group, + tab_groups::TriggerSource source) { + // Only handle updates to the active group. + std::optional<tab_groups::TabGroupId> active_group_id = + browser_->GetTabStripModel()->GetActiveTabGroupId(); + if (!active_group_id.has_value() || + active_group_id.value() != group.local_group_id()) { + return; + } + + UpdateVisuals(browser_->GetActiveTabInterface()); +} + void CommentsSidePanelCoordinator::UpdateVisuals( const tabs::TabInterface* tab) { // Only update the title if change contains a new tab.
diff --git a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.h b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.h index cbd450b..6a76ba6 100644 --- a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.h +++ b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator.h
@@ -9,6 +9,7 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" +#include "components/saved_tab_groups/public/tab_group_sync_service.h" class BrowserWindowInterface; class SidePanelEntryScope; @@ -19,7 +20,8 @@ struct TabStripSelectionChange; namespace tab_groups { -class TabGroupSyncService; +class SavedTabGroup; +enum class TriggerSource; } // namespace tab_groups namespace views { @@ -28,7 +30,9 @@ // CommentsSidePanelCoordinator handles the creation and registration of // the comments SidePanelEntry. -class CommentsSidePanelCoordinator : public TabStripModelObserver { +class CommentsSidePanelCoordinator + : public TabStripModelObserver, + public tab_groups::TabGroupSyncService::Observer { public: // TODO(crbug.com/434203413): Remove dependency on BrowserView by implementing // a PinnedToolbarActionsController. @@ -46,6 +50,10 @@ tabs::TabInterface* tab, int index) override; + // TabGroupSyncService::Observer + void OnTabGroupUpdated(const tab_groups::SavedTabGroup& group, + tab_groups::TriggerSource source) override; + // Returns whether CommentsSidePanelCoordinator is supported. // If this returns false, it should not be registered with the side // panel registry.
diff --git a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator_interactive_uitest.cc b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator_interactive_uitest.cc index fa89c2f..05e7852 100644 --- a/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator_interactive_uitest.cc +++ b/chrome/browser/ui/views/side_panel/comments/comments_side_panel_coordinator_interactive_uitest.cc
@@ -25,6 +25,7 @@ #include "components/feature_engagement/public/feature_constants.h" #include "components/saved_tab_groups/public/features.h" #include "components/saved_tab_groups/public/tab_group_sync_service.h" +#include "components/saved_tab_groups/public/types.h" #include "components/signin/public/base/consent_level.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" @@ -196,6 +197,53 @@ WaitForShow(kSharedTabGroupCommentsActionElementId)); } +// Verify the comments action is shown when a tab group becomes shared. +IN_PROC_BROWSER_TEST_F(CommentsSidePanelCoordinatorInteractiveUiTest, + CommentActionIsVisible_SharingGroup) { + tab_groups::TabGroupId group_id = CreateNewTabGroup(); + + const int non_shared_tab_index = 0; + browser()->tab_strip_model()->ActivateTabAt(non_shared_tab_index); + + RunTestSequence( + WaitForShow(kTabGroupHeaderElementId), + EnsureNotPresent(kSharedTabGroupCommentsActionElementId), + // Share the group. + Do([&] { + ShareTabGroup( + group_id, syncer::CollaborationId("fake_collaboration_id"), + data_sharing::MemberRole::kOwner, /*should_sign_in=*/false); + + // Trigger observers to fire by updating the group's visual data. + tab_group_sync_service()->UpdateVisualData(group_id, + browser() + ->GetTabStripModel() + ->group_model() + ->GetTabGroup(group_id) + ->visual_data()); + }), + WaitForShow(kSharedTabGroupCommentsActionElementId), + // Unshare the group. + Do([&] { + EXPECT_TRUE(tab_group_sync_service() + ->GetGroup(group_id) + ->is_shared_tab_group()); + tab_group_sync_service()->MakeTabGroupUnsharedForTesting(group_id); + EXPECT_FALSE(tab_group_sync_service() + ->GetGroup(group_id) + ->is_shared_tab_group()); + + // Trigger observers to fire by updating the group's visual data. + tab_group_sync_service()->UpdateVisualData(group_id, + browser() + ->GetTabStripModel() + ->group_model() + ->GetTabGroup(group_id) + ->visual_data()); + }), + WaitForHide(kSharedTabGroupCommentsActionElementId)); +} + // Verify the comments side panel will resume visilibity when switching to a // non-shared tab and back. IN_PROC_BROWSER_TEST_F(CommentsSidePanelCoordinatorInteractiveUiTest,
diff --git a/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.cc b/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.cc index d4109c8..855fc48f 100644 --- a/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.cc +++ b/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.cc
@@ -6,18 +6,14 @@ #include "base/containers/contains.h" #include "base/feature_list.h" -#include "base/functional/bind.h" #include "build/build_config.h" #include "chrome/browser/browser_features.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/views/frame/browser_view.h" -#include "components/tabs/public/tab_interface.h" #include "content/public/browser/browser_thread.h" -#include "ui/base/unowned_user_data/scoped_unowned_user_data.h" #include "ui/gfx/color_palette.h" -#include "ui/gfx/geometry/rect.h" #if BUILDFLAG(IS_WIN) #include "ui/views/widget/native_widget_aura.h" @@ -44,24 +40,58 @@ GetColorProvider()->GetColor(kColorCapturedTabContentsBorder))); } }; + +void InitContentsBorderWidget(content::WebContents* web_contents) { + Browser* const browser = chrome::FindBrowserWithTab(web_contents); + if (!browser) { + return; + } + + BrowserView* const browser_view = + BrowserView::GetBrowserViewForBrowser(browser); + if (!browser_view || browser_view->contents_border_widget()) { + return; + } + + views::Widget* widget = new views::Widget; + views::Widget::InitParams params( + views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET, + views::Widget::InitParams::TYPE_POPUP); + params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; + views::Widget* frame = browser_view->contents_web_view()->GetWidget(); + params.parent = frame->GetNativeView(); + params.context = frame->GetNativeWindow(); + // Make the widget non-top level. + params.child = true; + params.name = "TabSharingContentsBorder"; + params.remove_standard_frame = true; + // Let events go through to underlying view. + params.accept_events = false; + params.activatable = views::Widget::InitParams::Activatable::kNo; +#if BUILDFLAG(IS_WIN) + params.native_widget = new views::NativeWidgetAura(widget); +#endif // BUILDFLAG(IS_WIN) + + widget->Init(std::move(params)); + widget->SetContentsView(std::make_unique<BorderView>()); + widget->SetVisibilityChangedAnimationsEnabled(false); + widget->SetOpacity(0.50f); + + // TODO(crbug.com/40207590): Associate each captured tab with its own widget. + // Otherwise, if tab A captures B, and tab C captures D, and all are in + // the same browser window, then either the A<-B or C<-D sessions ending, + // hides the widget, and there's no good way of avoiding it (other than + // associating distinct captured tabs with their own border). + // After this fix, capturing a given tab X twice will still yield one widget. + browser_view->set_contents_border_widget(widget); +} + } // namespace -DEFINE_USER_DATA(TabCaptureContentsBorderHelper); - -// static: -TabCaptureContentsBorderHelper* TabCaptureContentsBorderHelper::From( - tabs::TabInterface* tab_interface) { - return Get(tab_interface->GetUnownedUserDataHost()); -} - TabCaptureContentsBorderHelper::TabCaptureContentsBorderHelper( - tabs::TabInterface& tab_interface) - : tab_interface_(tab_interface), - scoped_unowned_user_data_(tab_interface.GetUnownedUserDataHost(), *this) { - tab_will_detach_subscription_ = tab_interface_->RegisterWillDetach( - base::BindRepeating(&TabCaptureContentsBorderHelper::TabWillDetach, - base::Unretained(this))); -} + content::WebContents* web_contents) + : content::WebContentsUserData<TabCaptureContentsBorderHelper>( + *web_contents) {} TabCaptureContentsBorderHelper::~TabCaptureContentsBorderHelper() = default; @@ -109,52 +139,6 @@ UpdateBlueBorderLocation(); } -void TabCaptureContentsBorderHelper::InitContentsBorderWidget() { - Browser* const browser = - tab_interface_->GetBrowserWindowInterface()->GetBrowserForMigrationOnly(); - if (!browser) { - return; - } - - BrowserView* const browser_view = - BrowserView::GetBrowserViewForBrowser(browser); - if (!browser_view || browser_view->contents_border_widget()) { - return; - } - - views::Widget* widget = new views::Widget; - views::Widget::InitParams params( - views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET, - views::Widget::InitParams::TYPE_POPUP); - params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; - views::Widget* frame = browser_view->contents_web_view()->GetWidget(); - params.parent = frame->GetNativeView(); - params.context = frame->GetNativeWindow(); - // Make the widget non-top level. - params.child = true; - params.name = "TabSharingContentsBorder"; - params.remove_standard_frame = true; - // Let events go through to underlying view. - params.accept_events = false; - params.activatable = views::Widget::InitParams::Activatable::kNo; -#if BUILDFLAG(IS_WIN) - params.native_widget = new views::NativeWidgetAura(widget); -#endif // BUILDFLAG(IS_WIN) - - widget->Init(std::move(params)); - widget->SetContentsView(std::make_unique<BorderView>()); - widget->SetVisibilityChangedAnimationsEnabled(false); - widget->SetOpacity(0.50f); - - // TODO(crbug.com/40207590): Associate each captured tab with its own widget. - // Otherwise, if tab A captures B, and tab C captures D, and all are in - // the same browser window, then either the A<-B or C<-D sessions ending, - // hides the widget, and there's no good way of avoiding it (other than - // associating distinct captured tabs with their own border). - // After this fix, capturing a given tab X twice will still yield one widget. - browser_view->set_contents_border_widget(widget); -} - void TabCaptureContentsBorderHelper::Update() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -166,15 +150,22 @@ return; } #endif // BUILDFLAG(IS_CHROMEOS) - Browser* const browser = - tab_interface_->GetBrowserWindowInterface()->GetBrowserForMigrationOnly(); + + content::WebContents* const web_contents = &GetWebContents(); + + Browser* const browser = chrome::FindBrowserWithTab(web_contents); + if (!browser) { + return; + } + BrowserView* const browser_view = BrowserView::GetBrowserViewForBrowser(browser); if (!browser_view) { return; } - const bool tab_visible = tab_interface_->IsActivated(); + const bool tab_visible = + (web_contents == browser->tab_strip_model()->GetActiveWebContents()); const bool contents_border_needed = tab_visible && !session_to_bounds_.empty(); @@ -182,7 +173,7 @@ if (!contents_border_needed) { return; } - InitContentsBorderWidget(); + InitContentsBorderWidget(web_contents); } views::Widget* const contents_border_widget = @@ -199,8 +190,13 @@ void TabCaptureContentsBorderHelper::UpdateBlueBorderLocation() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(!session_to_bounds_.empty()) << "No blue border should be shown."; - Browser* const browser = - tab_interface_->GetBrowserWindowInterface()->GetBrowserForMigrationOnly(); + + content::WebContents* const web_contents = &GetWebContents(); + + Browser* const browser = chrome::FindBrowserWithTab(web_contents); + if (!browser) { + return; + } BrowserView* const browser_view = BrowserView::GetBrowserViewForBrowser(browser); @@ -223,9 +219,4 @@ : std::nullopt; } -void TabCaptureContentsBorderHelper::TabWillDetach( - tabs::TabInterface* tab_interface, - tabs::TabInterface::DetachReason reason) { - session_to_bounds_.clear(); - Update(); -} +WEB_CONTENTS_USER_DATA_KEY_IMPL(TabCaptureContentsBorderHelper);
diff --git a/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h b/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h index 523cd54..27fdfb0 100644 --- a/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h +++ b/chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h
@@ -5,32 +5,24 @@ #ifndef CHROME_BROWSER_UI_VIEWS_TAB_SHARING_TAB_CAPTURE_CONTENTS_BORDER_HELPER_H_ #define CHROME_BROWSER_UI_VIEWS_TAB_SHARING_TAB_CAPTURE_CONTENTS_BORDER_HELPER_H_ -#include "base/callback_list.h" -#include "base/memory/raw_ref.h" -#include "components/tabs/public/tab_interface.h" -#include "ui/base/unowned_user_data/scoped_unowned_user_data.h" +#include "content/public/browser/web_contents_user_data.h" -namespace gfx { -class Rect; +namespace content { +class WebContents; } // Helps track whether the contents-border should be drawn. // TODO(crbug.com/40207590): Support dynamic borders for tabs that only // have a single capturer. -class TabCaptureContentsBorderHelper { +class TabCaptureContentsBorderHelper + : public content::WebContentsUserData<TabCaptureContentsBorderHelper> { public: - DECLARE_USER_DATA(TabCaptureContentsBorderHelper); - - static TabCaptureContentsBorderHelper* From( - tabs::TabInterface* tab_interface); - // Used to identify |TabSharingUIViews| instances to // |TabCaptureContentsBorderHelper|, without passing pointers, // which is less robust lifetime-wise. using CaptureSessionId = uint32_t; - explicit TabCaptureContentsBorderHelper(tabs::TabInterface& tab_interface); - ~TabCaptureContentsBorderHelper(); + ~TabCaptureContentsBorderHelper() override; void OnCapturerAdded(CaptureSessionId capture_session_id); void OnCapturerRemoved(CaptureSessionId capture_session_id); @@ -42,7 +34,9 @@ const std::optional<gfx::Rect>& region_capture_rect); private: - void InitContentsBorderWidget(); + friend WebContentsUserData; + + explicit TabCaptureContentsBorderHelper(content::WebContents* web_contents); // Decide whether the blue border should be shown, and where. void Update(); @@ -50,7 +44,7 @@ // Given that the blue border should be shown, draw it at the right location. void UpdateBlueBorderLocation(); - // Determines the correct location of the blue border. + // Determines the correct location of the ble border. // 1. If multiple captures of the WebContents exist, the blue border is drawn // around the entire tab's content area. // 2. If a single capture of the WebContents exists, the blue border @@ -59,9 +53,6 @@ // and aroun the cropped area if cropping is used. std::optional<gfx::Rect> GetBlueBorderLocation() const; - void TabWillDetach(tabs::TabInterface* tab_interface, - tabs::TabInterface::DetachReason reason); - // Each capture session has a unique |uint32_t| ID, and is mapped to // an optional<Rect>, whose value is as follows: // * If the capture session's last known state was uncropped - nullopt. @@ -70,12 +61,7 @@ // capture-target consisted of zero pixels within the viewport. std::map<CaptureSessionId, std::optional<gfx::Rect>> session_to_bounds_; - raw_ref<tabs::TabInterface> tab_interface_; - - base::CallbackListSubscription tab_will_detach_subscription_; - - ui::ScopedUnownedUserData<TabCaptureContentsBorderHelper> - scoped_unowned_user_data_; + WEB_CONTENTS_USER_DATA_KEY_DECL(); }; #endif // CHROME_BROWSER_UI_VIEWS_TAB_SHARING_TAB_CAPTURE_CONTENTS_BORDER_HELPER_H_
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc index cd9c4cfa..ccba212 100644 --- a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc +++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc
@@ -36,7 +36,6 @@ #include "chrome/browser/ui/views/tab_sharing/tab_capture_contents_border_helper.h" #include "components/infobars/content/content_infobar_manager.h" #include "components/infobars/core/infobar.h" -#include "components/tabs/public/tab_interface.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/desktop_media_id.h" @@ -256,8 +255,12 @@ return; } - auto* const helper = TabCaptureContentsBorderHelper::From( - tabs::TabInterface::GetFromContents(shared_tab_)); + auto* const helper = + TabCaptureContentsBorderHelper::FromWebContents(shared_tab_); + if (!helper) { + return; + } + helper->OnRegionCaptureRectChanged(capture_session_id_, region_capture_rect); } @@ -570,20 +573,14 @@ void TabSharingUIViews::UpdateTabCaptureData(WebContents* contents, TabCaptureUpdate update) { - // Only update tab capture data `contents` aren't being destroyed - // because the capture data should be automatically updated on - // destruction. - if (!contents || contents->IsBeingDestroyed()) { + if (!contents) { return; } - tabs::TabInterface* const tab_interface = - tabs::TabInterface::MaybeGetFromContents(contents); - if (!tab_interface || !tab_interface->GetTabFeatures()) { - return; - } + TabCaptureContentsBorderHelper::CreateForWebContents(contents); + auto* const helper = + TabCaptureContentsBorderHelper::FromWebContents(contents); - auto* const helper = TabCaptureContentsBorderHelper::From(tab_interface); switch (update) { case TabCaptureUpdate::kCaptureAdded: helper->OnCapturerAdded(capture_session_id_);
diff --git a/chrome/browser/ui/views/tabs/glic_actor_task_icon.cc b/chrome/browser/ui/views/tabs/glic_actor_task_icon.cc index 76d4fd4..e9dbc05 100644 --- a/chrome/browser/ui/views/tabs/glic_actor_task_icon.cc +++ b/chrome/browser/ui/views/tabs/glic_actor_task_icon.cc
@@ -104,6 +104,18 @@ SetTooltipText(glic_actor_task_icon_check_task_tooltip_text); } +void GlicActorTaskIcon::ShowCompleteTasksLabel() { + // TODO(crbug.com/431015299): Replace with finalized strings when ready. + const std::u16string glic_actor_task_icon_complete_task_label = + u"Task complete"; + const std::u16string glic_actor_task_icon_complete_task_tooltip_text = + u"Task complete"; + + HighlightTaskIcon(); + SetText(glic_actor_task_icon_complete_task_label); + SetTooltipText(glic_actor_task_icon_complete_task_tooltip_text); +} + GlicActorTaskIcon::~GlicActorTaskIcon() = default; BEGIN_METADATA(GlicActorTaskIcon)
diff --git a/chrome/browser/ui/views/tabs/glic_actor_task_icon.h b/chrome/browser/ui/views/tabs/glic_actor_task_icon.h index 196e566..47241a0 100644 --- a/chrome/browser/ui/views/tabs/glic_actor_task_icon.h +++ b/chrome/browser/ui/views/tabs/glic_actor_task_icon.h
@@ -40,6 +40,9 @@ // Sets the task icon to the task needs assistance state. void ShowCheckTasksLabel(); + // Sets the task icon to the task complete state. + void ShowCompleteTasksLabel(); + // Sets the task icon to its default colors, label, and tooltip text. void SetTaskIconToDefault();
diff --git a/chrome/browser/ui/views/tabs/tab_strip_action_container.cc b/chrome/browser/ui/views/tabs/tab_strip_action_container.cc index e8a2aea2..5996f829 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_action_container.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_action_container.cc
@@ -612,6 +612,19 @@ #endif // BUILDFLAG(ENABLE_GLIC) } +void TabStripActionContainer::TriggerGlicActorTaskIconCompleteTasksNudge() { +#if BUILDFLAG(ENABLE_GLIC) + CHECK(glic_actor_task_icon_); + // Make sure the task icon is visible, for example if another window was + // opened after the CompleteTask state was sent. + ShowGlicActorTaskIcon(); + glic_actor_task_icon_->ShowCompleteTasksLabel(); + ShowTabStripNudge(glic_actor_task_icon_); +#else + NOTREACHED(); +#endif // BUILDFLAG(ENABLE_GLIC) +} + void TabStripActionContainer::ShowGlicActorTaskIcon() { #if BUILDFLAG(ENABLE_GLIC) CHECK(glic_actor_button_container_);
diff --git a/chrome/browser/ui/views/tabs/tab_strip_action_container.h b/chrome/browser/ui/views/tabs/tab_strip_action_container.h index 5e24a745..11d6c3e1 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_action_container.h +++ b/chrome/browser/ui/views/tabs/tab_strip_action_container.h
@@ -144,6 +144,7 @@ // UI Controls for the GlicActorTaskIcon: void TriggerGlicActorTaskIconCheckTasksNudge(); + void TriggerGlicActorTaskIconCompleteTasksNudge(); void ShowGlicActorTaskIcon(); void HideGlicActorTaskIcon(); bool GetIsShowingGlicActorTaskIconNudge();
diff --git a/chrome/browser/ui/views/toolbar/BUILD.gn b/chrome/browser/ui/views/toolbar/BUILD.gn index 1818896a..978fcbb 100644 --- a/chrome/browser/ui/views/toolbar/BUILD.gn +++ b/chrome/browser/ui/views/toolbar/BUILD.gn
@@ -137,6 +137,7 @@ "//chrome/browser/ui/tabs:tab_enums", "//chrome/browser/ui/tabs:tab_strip", "//chrome/browser/ui/tabs:tab_strip_model_observer", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/views/download", "//chrome/browser/ui/views/frame:toolbar_button_provider", "//chrome/browser/ui/views/page_action",
diff --git a/chrome/browser/ui/views/user_education/feature_promo_dialog_interactive_uitest.cc b/chrome/browser/ui/views/user_education/feature_promo_dialog_interactive_uitest.cc index 99a6c76..64b6f63 100644 --- a/chrome/browser/ui/views/user_education/feature_promo_dialog_interactive_uitest.cc +++ b/chrome/browser/ui/views/user_education/feature_promo_dialog_interactive_uitest.cc
@@ -17,12 +17,16 @@ #include "chrome/browser/apps/app_service/app_registry_cache_waiter.h" #include "chrome/browser/banners/test_app_banner_manager_desktop.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/actions/chrome_action_id.h" +#include "chrome/browser/ui/page_action/page_action_icon_type.h" +#include "chrome/browser/ui/tabs/public/tab_features.h" #include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h" #include "chrome/browser/ui/views/location_bar/intent_chip_button.h" +#include "chrome/browser/ui/views/page_action/page_action_controller.h" #include "chrome/browser/ui/views/page_action/page_action_icon_controller.h" #include "chrome/browser/ui/views/page_action/page_action_icon_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" @@ -204,12 +208,24 @@ auto* app_banner_manager = webapps::TestAppBannerManagerDesktop::FromWebContents(web_contents); app_banner_manager->WaitForInstallableCheck(); + // TODO(crbug.com/376283433): The legacy page action has a bug that prevents + // it from displaying in "chip" mode (just the icon shows). We force the + // migrated page action to be collapsed for now to ensure consistency in the + // snapshot. + // This can be removed once the page action migration path is fully rolled + // out. + if (IsPageActionMigrated(PageActionIconType::kPwaInstall)) { + browser() + ->GetActiveTabInterface() + ->GetTabFeatures() + ->page_action_controller() + ->HideSuggestionChip(kActionInstallPwa); + } EXPECT_TRUE(BrowserView::GetBrowserViewForBrowser(browser()) - ->toolbar() - ->location_bar() - ->page_action_icon_controller() - ->GetIconView(PageActionIconType::kPwaInstall) + ->toolbar_button_provider() + ->GetPageActionView(kActionInstallPwa) ->GetVisible()); + browser()->window()->Activate(); ui_test_utils::BrowserActivationWaiter(browser()).WaitForActivation();
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc index 096fc98..8b7dd69 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
@@ -1317,9 +1317,17 @@ helper_.CheckInstallIconNotShown(); } +// TODO(crbug.com/436571232): Disabled on Debug Linux due to flakiness. +#if BUILDFLAG(IS_LINUX) && !defined(NDEBUG) +#define MAYBE_WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_69Standalone_79StandaloneStandaloneOriginal_24_26 \ + DISABLED_WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_69Standalone_79StandaloneStandaloneOriginal_24_26 +#else +#define MAYBE_WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_69Standalone_79StandaloneStandaloneOriginal_24_26 \ + WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_69Standalone_79StandaloneStandaloneOriginal_24_26 +#endif IN_PROC_BROWSER_TEST_F( WebAppIntegration, - WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_69Standalone_79StandaloneStandaloneOriginal_24_26) { + MAYBE_WAI_31Standalone_79StandaloneStandaloneOriginal_24_12Standalone_7Standalone_112StandaloneNotShown_69Standalone_79StandaloneStandaloneOriginal_24_26) { // Test contents are generated by script. Please do not modify! // See `docs/webapps/why-is-this-test-failing.md` or // `docs/webapps/integration-testing-framework` for more info.
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index d61ed4ee..a547938 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -57,12 +57,14 @@ #include "chrome/browser/shell_integration.h" #include "chrome/browser/ui/actions/chrome_action_id.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_actions.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" #include "chrome/browser/ui/intent_picker_tab_helper.h" +#include "chrome/browser/ui/page_action/page_action_icon_type.h" #include "chrome/browser/ui/startup/startup_browser_creator.h" #include "chrome/browser/ui/startup/web_app_startup_utils.h" #include "chrome/browser/ui/ui_features.h" @@ -167,6 +169,7 @@ #include "ui/views/test/dialog_test.h" #include "ui/views/test/widget_test.h" #include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_interactive_uitest_utils.h" #include "ui/webui/resources/cr_components/app_management/app_management.mojom-forward.h" #include "url/gurl.h" @@ -1353,10 +1356,23 @@ web_app::SetDontCloseOnDeactivateForTesting(); BrowserAddedWaiter browser_added_waiter; + views::test::PropertyWaiter( + base::BindRepeating(&views::View::GetVisible, + base::Unretained(pwa_install_view())), + /*expected_value=*/true) + .Wait(); ASSERT_TRUE(pwa_install_view()->GetVisible()); WebAppTestInstallWithOsHooksObserver install_observer(profile()); install_observer.BeginListening(); - pwa_install_view()->ExecuteForTesting(); + if (IsPageActionMigrated(PageActionIconType::kPwaInstall)) { + actions::ActionManager::Get() + .FindAction(kActionInstallPwa, + browser()->GetActions()->root_action_item()) + ->InvokeAction(); + } else { + browser()->window()->ExecutePageActionIconForTesting( + PageActionIconType::kPwaInstall); + } WaitForAndAcceptInstallDialogForSite(InstallableSiteToSite(site)); @@ -3260,6 +3276,11 @@ webapps::TestAppBannerManagerDesktop::FromWebContents(web_contents); app_banner_manager->WaitForInstallableCheck(); } + views::test::PropertyWaiter( + base::BindRepeating(&views::View::GetVisible, + base::Unretained(pwa_install_view())), + /*expected_value=*/true) + .Wait(); EXPECT_TRUE(pwa_install_view()->GetVisible()); AfterStateCheckAction(); } @@ -4713,11 +4734,11 @@ return profiles; } -PageActionIconView* WebAppIntegrationTestDriver::pwa_install_view() { - PageActionIconView* pwa_install_view = +IconLabelBubbleView* WebAppIntegrationTestDriver::pwa_install_view() { + IconLabelBubbleView* pwa_install_view = BrowserView::GetBrowserViewForBrowser(browser()) ->toolbar_button_provider() - ->GetPageActionIconView(PageActionIconType::kPwaInstall); + ->GetPageActionView(kActionInstallPwa); CHECK(pwa_install_view); return pwa_install_view; }
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h index 7a72c97..338268f 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
@@ -40,7 +40,7 @@ #endif class Browser; -class PageActionIconView; +class IconLabelBubbleView; namespace base { class CommandLine; @@ -501,7 +501,7 @@ Browser* app_browser() { return app_browser_; } WebAppProvider* provider() { return WebAppProvider::GetForTest(profile()); } - PageActionIconView* pwa_install_view(); + IconLabelBubbleView* pwa_install_view(); views::Button* intent_chip_view(); const net::EmbeddedTestServer& GetTestServerForSiteMode(Site site_mode) const;
diff --git a/chrome/browser/ui/web_applications/pwa_install_page_action_browsertest.cc b/chrome/browser/ui/web_applications/pwa_install_page_action_browsertest.cc index c0f1ca2..2e307a4f 100644 --- a/chrome/browser/ui/web_applications/pwa_install_page_action_browsertest.cc +++ b/chrome/browser/ui/web_applications/pwa_install_page_action_browsertest.cc
@@ -188,6 +188,10 @@ enabled_features.push_back( {features::kPageActionsMigration, {{features::kPageActionsMigrationPwaInstall.name, "true"}}}); + } else { + enabled_features.push_back( + {features::kPageActionsMigration, + {{features::kPageActionsMigrationPwaInstall.name, "false"}}}); } features_.InitAndEnableFeaturesWithParameters(enabled_features, {});
diff --git a/chrome/browser/ui/webui/ash/sys_internals/sys_internals_message_handler.cc b/chrome/browser/ui/webui/ash/sys_internals/sys_internals_message_handler.cc index febcb583..ae67eef 100644 --- a/chrome/browser/ui/webui/ash/sys_internals/sys_internals_message_handler.cc +++ b/chrome/browser/ui/webui/ash/sys_internals/sys_internals_message_handler.cc
@@ -12,6 +12,7 @@ #include <utility> #include <vector> +#include "base/byte_count.h" #include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/functional/bind.h" @@ -139,28 +140,26 @@ result->Set("cpus", std::move(cpu_results)); } -const double kBytesInKB = 1024; +double GetAvailablePhysicalMemory(const base::SystemMemoryInfo& info) { + base::ByteCount available = + info.available.is_zero() ? info.free + info.reclaimable : info.available; -double GetAvailablePhysicalMemory(const base::SystemMemoryInfoKB& info) { - double available = static_cast<double>( - info.available == 0 ? info.free + info.reclaimable : info.available); - - return available * kBytesInKB; + return available.InBytesF(); } -void SetMemValue(const base::SystemMemoryInfoKB& info, +void SetMemValue(const base::SystemMemoryInfo& info, const base::VmStatInfo& vmstat, base::Value::Dict* result) { DCHECK(result); base::Value::Dict mem_result; // For values that may exceed the range of 32-bit signed integer, use double. - double total = static_cast<double>(info.total) * kBytesInKB; + double total = info.total.InBytesF(); mem_result.Set("total", total); mem_result.Set("available", GetAvailablePhysicalMemory(info)); - double swap_total = static_cast<double>(info.swap_total) * kBytesInKB; + double swap_total = info.swap_total.InBytesF(); mem_result.Set("swapTotal", swap_total); - double swap_free = static_cast<double>(info.swap_free) * kBytesInKB; + double swap_free = info.swap_free.InBytesF(); mem_result.Set("swapFree", swap_free); mem_result.Set("pswpin", ToCounter(vmstat.pswpin)); @@ -321,7 +320,7 @@ DLOG(WARNING) << "Failed to get system CPU info."; cpu_infos.clear(); } - base::SystemMemoryInfoKB mem_info; + base::SystemMemoryInfo mem_info; if (!GetSystemMemoryInfo(&mem_info)) { DLOG(WARNING) << "Failed to get system memory info."; }
diff --git a/chrome/browser/ui/webui/compose/compose_untrusted_ui.cc b/chrome/browser/ui/webui/compose/compose_untrusted_ui.cc index 31ef40b..0fb1f524 100644 --- a/chrome/browser/ui/webui/compose/compose_untrusted_ui.cc +++ b/chrome/browser/ui/webui/compose/compose_untrusted_ui.cc
@@ -18,6 +18,8 @@ #include "chrome/grit/compose_resources_map.h" #include "chrome/grit/generated_resources.h" #include "components/compose/core/browser/compose_features.h" +#include "components/optimization_guide/core/feature_registry/feature_registration.h" +#include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" @@ -57,6 +59,7 @@ {"firstRunTitle", IDS_COMPOSE_FRE_TITLE}, {"firstRunMainTop", IDS_COMPOSE_FRE_MAIN_TOP}, {"firstRunMainMid", IDS_COMPOSE_FRE_MAIN_MID}, + {"firstRunMainMidEnterprise", IDS_COMPOSE_FRE_MAIN_MID_ENTERPRISE}, {"firstRunMainBottom", IDS_COMPOSE_EXPERIMENTAL_DISCLAIMER_FOOTER}, {"firstRunOkButton", IDS_COMPOSE_FRE_OK_BUTTON}, {"dialogTitle", IDS_COMPOSE_DIALOG_TITLE}, @@ -68,6 +71,7 @@ {"inputModeChipElaborate", IDS_COMPOSE_INPUT_MODE_ELABORATE}, {"inputModeChipFormalize", IDS_COMPOSE_INPUT_MODE_FORMALIZE}, {"inputFooter", IDS_COMPOSE_INPUT_FOOTER}, + {"inputFooterEnterprise", IDS_COMPOSE_INPUT_FOOTER_ENTERPRISE}, {"submitButton", IDS_COMPOSE_SUBMIT_BUTTON}, {"onDeviceUsedFooter", IDS_COMPOSE_FOOTER_FISHFOOD_ON_DEVICE_USED}, {"resultFooter", IDS_COMPOSE_EXPERIMENTAL_DISCLAIMER_FOOTER}, @@ -139,6 +143,16 @@ raw_ptr<Profile> profile = Profile::FromWebUI(web_ui); content::URLDataSource::Add(profile, std::make_unique<ThemeSource>( profile, /*serve_untrusted=*/true)); + + PrefService* pref_service = profile->GetPrefs(); + bool is_enterprise_without_logging = + pref_service->GetInteger( + optimization_guide::prefs::kComposeEnterprisePolicyAllowed) == + static_cast<int>( + optimization_guide::model_execution::prefs:: + ModelExecutionEnterprisePolicyValue::kAllowWithoutLogging); + source->AddBoolean("useEnterpriseWithoutLoggingPolicy", + is_enterprise_without_logging); } ComposeUntrustedUI::~ComposeUntrustedUI() = default;
diff --git a/chrome/browser/ui/webui/new_tab_page/composebox/composebox_handler.cc b/chrome/browser/ui/webui/new_tab_page/composebox/composebox_handler.cc index f532c6e..387cef6 100644 --- a/chrome/browser/ui/webui/new_tab_page/composebox/composebox_handler.cc +++ b/chrome/browser/ui/webui/new_tab_page/composebox/composebox_handler.cc
@@ -12,6 +12,8 @@ #include "components/omnibox/composebox/composebox_image_helper.h" #include "content/public/browser/page_navigator.h" +using composebox::SessionState; + namespace { class ComposeboxOmniboxClient final : public SearchboxOmniboxClient { public:
diff --git a/chrome/browser/ui/webui/new_tab_page/composebox/composebox_handler_unittest.cc b/chrome/browser/ui/webui/new_tab_page/composebox/composebox_handler_unittest.cc index 458cb20..b6bab8f 100644 --- a/chrome/browser/ui/webui/new_tab_page/composebox/composebox_handler_unittest.cc +++ b/chrome/browser/ui/webui/new_tab_page/composebox/composebox_handler_unittest.cc
@@ -41,6 +41,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/webui/resources/cr_components/composebox/composebox.mojom.h" +using composebox::SessionState; + namespace { constexpr int kImageCompressionQuality = 30; constexpr int kImageMaxArea = 1000000;
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc index e76510d..07ae0d82 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
@@ -65,6 +65,7 @@ #include "chrome/browser/ui/webui/new_tab_page/ntp_pref_names.h" #include "chrome/browser/ui/webui/webui_embedding_context.h" #include "chrome/browser/ui/webui/webui_util_desktop.h" +#include "chrome/browser/ui/webui_browser/webui_browser.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" @@ -896,6 +897,12 @@ return; } + // TODO(webium): FooterController depends on BrowserView, but WebUIBrowser + // doesn't have a BrowserView. + if (webui_browser::IsWebUIBrowserEnabled()) { + return; + } + auto* browser = webui::GetBrowserWindowInterface(web_contents_); if (!browser) { // TODO(crbug.com/378475391): NTP should always load into a WebContents @@ -1328,6 +1335,12 @@ return; } + // TODO(webium): FooterController depends on BrowserView, but WebUIBrowser + // doesn't have a BrowserView. + if (webui_browser::IsWebUIBrowserEnabled()) { + return; + } + footer_controller_observation_.Reset(); auto* browser = webui::GetBrowserWindowInterface(web_contents_); if (!browser) {
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index a1c0f7b..334a72f 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -1059,7 +1059,7 @@ module_id_details_, IdentityManagerFactory::GetForProfile(profile_)); update.Set("modulesEnabled", modules_enabled); - const auto* ntp_promo_controller = + auto* ntp_promo_controller = UserEducationServiceFactory::GetForBrowserContext(profile_) ->ntp_promo_controller(); const bool show_ntp_promos =
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_privacy_sandbox_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_privacy_sandbox_provider.cc index 7bfe924..45a3aabf 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_privacy_sandbox_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_privacy_sandbox_provider.cc
@@ -271,16 +271,6 @@ IDS_SETTINGS_ALLOW_THIRD_PARTY_COOKIES_EXPAND_A11Y_LABEL}, {"blockThirdPartyCookiesExpandA11yLabel", IDS_SETTINGS_BLOCK_THIRD_PARTY_COOKIES_EXPAND_A11Y_LABEL}, - // All sites RWS - {"allSitesRwsFilterViewTitle", IDS_ALL_SITES_RWS_FILTER_VIEW_TITLE}, - {"allSitesRwsFilterViewStorageDescription", - IDS_ALL_SITES_RWS_FILTER_VIEW_STORAGE_DESCRIPTION}, - {"allSitesShowRwsButton", IDS_ALL_SITES_SHOW_RWS_BUTTON}, - {"allSitesRwsMembershipLabel", IDS_ALL_SITES_RWS_LABEL}, - {"allSitesRwsDeleteDataButtonLabel", - IDS_ALL_SITES_RWS_DELETE_DATA_BUTTON_LABEL}, - {"allSitesRwsDeleteDataDialogTitle", - IDS_ALL_SITES_RWS_DELETE_DATA_DIALOG_TITLE}, // Ad Topics Content Parity - Ad Topics Settings {"adTopicsPageToggleSubLabel", IDS_SETTINGS_AD_TOPICS_PAGE_TOGGLE_SUB_LABEL}, @@ -458,14 +448,6 @@ l10n_util::GetStringUTF16( IDS_SETTINGS_SITE_SUGGESTED_ADS_PAGE_DISCLAIMER_LINK_ARIA_DESCRIPTION), kPrivacyPolicyFunc, kPrivacyPolicyId)); - // RWS description - const char* rws_learn_more_url = chrome::kRelatedWebsiteSetsLearnMoreURL; - html_source->AddString( - "allSitesRwsFilterViewDescription", - l10n_util::GetStringFUTF16( - IDS_ALL_SITES_RWS_FILTER_VIEW_DESCRIPTION, - base::ASCIIToUTF16(rws_learn_more_url), - l10n_util::GetStringUTF16(IDS_SETTINGS_OPENS_IN_NEW_TAB))); // Incognito tracking protections description const char* incognito_tracking_protections_learn_more_url = chrome::kIncognitoTrackingProtectionsLearnMoreUrl;
diff --git a/chrome/browser/usb/android/java/src/org/chromium/chrome/browser/usb/UsbNotificationManager.java b/chrome/browser/usb/android/java/src/org/chromium/chrome/browser/usb/UsbNotificationManager.java index 5e909fa5..e61e729 100644 --- a/chrome/browser/usb/android/java/src/org/chromium/chrome/browser/usb/UsbNotificationManager.java +++ b/chrome/browser/usb/android/java/src/org/chromium/chrome/browser/usb/UsbNotificationManager.java
@@ -69,7 +69,7 @@ return mNotificationIds.contains(notificationId); } - public void onStartCommand(Intent intent, int flags, int startId) { + public void onStartCommand(@Nullable Intent intent, int flags, int startId) { if (intent == null || intent.getExtras() == null) { cancelPreviousUsbNotifications(); mDelegate.stopSelf();
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index 976544b..c89595a 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1754395000-9f0d646361158acafac4420493be0e0226f04a52-b8cb67458c6ac65f7505e10374ec9241c3958362.profdata +chrome-android32-main-1754459891-dacd7d41855e054f26c29852d16257b90ae1dd91-507b8c95a05e192a0776c5d0722d86b424dbad67.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index d846dd54..789ab42f 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1754407672-aec7abf401b0b0786852d870bbb314e2d4b2f46d-415ef2979d60fc4b27a1c18ea879ea500a202e8a.profdata +chrome-android64-main-1754462458-b7d6fb7317287eb5434cbf7ccd0fba5020d5c2f1-98ca93b654786792bf22b09c5909f7fe074d23a4.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt index 8f2a7216..7414917 100644 --- a/chrome/build/android-desktop-x64.pgo.txt +++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@ -chrome-android-desktop-x64-main-1754395000-a66ea6f897131fc59725d2436d0f4a441062205e-b8cb67458c6ac65f7505e10374ec9241c3958362.profdata +chrome-android-desktop-x64-main-1754459891-a3a4a7a17726b7a1cb0bb274ede03f1e4651d3c8-507b8c95a05e192a0776c5d0722d86b424dbad67.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 34ae6093..bd8e78d 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1754395000-3f71422875a62c42c73ff8539774997e6aa36392-b8cb67458c6ac65f7505e10374ec9241c3958362.profdata +chrome-mac-arm-main-1754452768-8210e36237bd66e29e4fe99fff214a73e61cde94-a8119a58ba85f1aa2a9fc888b454d8ab1e61eb79.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 4804b5f8..e171a380 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1754330378-613648034a2f7cd4882ea9ec089273e8904725fa-113eb8f9486c2d3af7db164c49d6171b81fa9b26.profdata +chrome-mac-main-1754459891-e00b0b9d8da3034e0577da9d836ec23a2d44083b-507b8c95a05e192a0776c5d0722d86b424dbad67.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 5452f12..b2a2836 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1754384288-39ca15e89f62cd375dd8edc9f047912d10b74c53-31aaaf406e98c35949135b7e2c04091ef8f8c8a8.profdata +chrome-win32-main-1754449066-31ca83129fa2bf4a5086920edd142cebdd0ebaa3-753d0e90882e69c79eb660388d7112f9292c2b4e.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index c1b2fa1..844fa92 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1754384288-c7668861c8b6d7de44fb37224df3fdacc657512a-31aaaf406e98c35949135b7e2c04091ef8f8c8a8.profdata +chrome-win64-main-1754438291-34644ea9727cf8326c8286e5773f33fb7005a1e6-f1d0cdd45d788cba03faaa896d9a0c21c88b9114.profdata
diff --git a/chrome/common/compose/compose.mojom b/chrome/common/compose/compose.mojom index c7bb60c..c4628e5 100644 --- a/chrome/common/compose/compose.mojom +++ b/chrome/common/compose/compose.mojom
@@ -184,6 +184,10 @@ // page. OpenComposeLearnMorePage(); + // Asks the Browser to open a new tab navigated to the Chrome Generative AI + // features and policies page. + OpenEnterpriseComposeLearnMorePage(); + // Asks the Browser to open a new tab navigated to the Dogfood feedback // survey. OpenFeedbackSurveyLink();
diff --git a/chrome/installer/util/initial_preferences.cc b/chrome/installer/util/initial_preferences.cc index 48ae7b2..52fb66c 100644 --- a/chrome/installer/util/initial_preferences.cc +++ b/chrome/installer/util/initial_preferences.cc
@@ -325,6 +325,10 @@ return true; } +const base::Value::Dict* InitialPreferences::GetBookmarksBlock() const { + return initial_dictionary_->FindDict(initial_preferences::kBookmarksBlock); +} + std::string InitialPreferences::GetCompressedVariationsSeed() { return ExtractPrefString(variations::prefs::kVariationsCompressedSeed); }
diff --git a/chrome/installer/util/initial_preferences.h b/chrome/installer/util/initial_preferences.h index c03cb7d..7ef3ca3 100644 --- a/chrome/installer/util/initial_preferences.h +++ b/chrome/installer/util/initial_preferences.h
@@ -165,6 +165,60 @@ // } bool GetExtensionsBlock(const base::Value::Dict*& extensions) const; + // The initial preferences file can include a bookmarks block that gets + // imported on the first run. This block contains bookmark and folder nodes + // that get recursively visited and imported. + // + // Bookmark nodes must have 'name', 'type' (set to 'url') and 'url' fields. + // Folder nodes must have 'name', 'type' (set to 'folder') and 'children' + // fields. + // + // Example block: + // { + // "bookmarks": { + // "first_run_bookmarks": { + // "children": [ + // { + // "name": "ABC", + // "type": "url", + // "url": "https://google.com" + // }, + // { + // "name": "XYZ", + // "type": "url", + // "url": "https://facebook.com" + // }, + // { + // "name": "Folder 1", + // "type": "folder", + // "children": [ + // { + // "name": "ABC", + // "type": "url", + // "url": "https://google.com" + // }, + // { + // "name": "Folder 2", + // "type": "folder", + // "children": [ + // { + // "name": "ABC", + // "type": "url", + // "url": "https://google.com" + // } + // ] + // } + // ] + // } + // ] + // } + // } + // } + // + // The return value can be a nullptr if this dict is not specified in the + // initial preferences file. + const base::Value::Dict* GetBookmarksBlock() const; + // Returns the compressed variations seed entry from the initial prefs. std::string GetCompressedVariationsSeed();
diff --git a/chrome/installer/util/initial_preferences_constants.h b/chrome/installer/util/initial_preferences_constants.h index 0aef7bb..41accbe 100644 --- a/chrome/installer/util/initial_preferences_constants.h +++ b/chrome/installer/util/initial_preferences_constants.h
@@ -74,6 +74,8 @@ inline constexpr char kVerboseLogging[] = "verbose_logging"; // Name of the block that contains the extensions on the initial preferences. inline constexpr char kExtensionsBlock[] = "extensions.settings"; +// Name of the block that contains the bookmarks on the initial preferences. +inline constexpr char kBookmarksBlock[] = "bookmarks"; // Boolean. Allow Chrome to be downgraded to a previous version if true. inline constexpr char kAllowDowngrade[] = "allow_downgrade";
diff --git a/chrome/installer/util/initial_preferences_unittest.cc b/chrome/installer/util/initial_preferences_unittest.cc index 8948091c..b695ae8f 100644 --- a/chrome/installer/util/initial_preferences_unittest.cc +++ b/chrome/installer/util/initial_preferences_unittest.cc
@@ -227,6 +227,65 @@ "behllobkkfkfnphdnhnkndlbkcpglgmj.manifest.version")); } +// Test the parsing of bookmarks block from initial preferences. +TEST_F(InitialPreferencesTest, ValidateBookmarksJSON) { + constexpr char bookmarks_json_string[] = + "{ \n" + " \"bookmarks\": { \n" + " \"first_run_bookmarks\": { \n" + " \"children\": [ \n" + " { \n" + " \"name\": \"ABC\", \n" + " \"type\": \"url\", \n" + " \"url\": \"https://google.com\" \n" + " }, \n" + " { \n" + " \"name\": \"Folder1\", \n" + " \"type\": \"folder\", \n" + " \"children\": [ \n" + " { \n" + " \"name\": \"ABC\", \n" + " \"type\": \"url\", \n" + " \"url\": \"https://google.com\" \n" + " }, \n" + " { \n" + " \"name\": \"XYZ\", \n" + " \"type\": \"url\", \n" + " \"url\": \"https://facebook.com\" \n" + " } \n" + " ] \n" + " } \n" + " ] \n" + " } \n" + " } \n" + "} \n"; + ASSERT_TRUE(base::WriteFile(prefs_file(), bookmarks_json_string)); + + installer::InitialPreferences prefs(prefs_file()); + + const base::Value::Dict* bookmarks = prefs.GetBookmarksBlock(); + ASSERT_TRUE(bookmarks); + + ASSERT_TRUE(bookmarks->FindDict("first_run_bookmarks")); + + const base::Value::List* children = + bookmarks->FindListByDottedPath("first_run_bookmarks.children"); + ASSERT_TRUE(children); + ASSERT_EQ(children->size(), 2u); + + const base::Value::Dict* first_child = (*children)[0].GetIfDict(); + ASSERT_TRUE(first_child); + EXPECT_EQ(*first_child->FindString("name"), "ABC"); + EXPECT_EQ(*first_child->FindString("type"), "url"); + EXPECT_EQ(*first_child->FindString("url"), "https://google.com"); + + const base::Value::Dict* second_child = (*children)[1].GetIfDict(); + ASSERT_TRUE(second_child); + EXPECT_EQ(*second_child->FindString("name"), "Folder1"); + EXPECT_EQ(*second_child->FindString("type"), "folder"); + EXPECT_EQ(second_child->FindList("children")->size(), 2u); +} + // Test that we are parsing initial preferences correctly. TEST_F(InitialPreferencesTest, GetInstallPreferencesTest) { // Create a temporary prefs file.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index c870c515..a5efe182 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1878,6 +1878,7 @@ "//components/feed/core/v2:test_helpers", "//components/feed/mojom:mojo_bindings", "//components/fingerprinting_protection_filter/common:features", + "//components/fingerprinting_protection_filter/interventions/common:features", "//components/infobars/content", "//components/invalidation:test_support", "//components/messages/android", @@ -2581,6 +2582,7 @@ "//components/feedback/redaction_tool", "//components/fingerprinting_protection_filter/browser", "//components/fingerprinting_protection_filter/common", + "//components/fingerprinting_protection_filter/interventions/common:features", "//components/heavy_ad_intervention", "//components/history/content/browser", "//components/history/core/common", @@ -3549,10 +3551,6 @@ "../browser/ui/tab_modal_confirm_dialog_browsertest.cc", "../browser/ui/tab_modal_confirm_dialog_browsertest.h", "../browser/ui/tab_ui_helper_browsertest.cc", - "../browser/ui/tabs/saved_tab_groups/collaboration_messaging_observer_browsertest.cc", - "../browser/ui/tabs/saved_tab_groups/saved_tab_group_web_contents_listener_browsertest.cc", - "../browser/ui/tabs/saved_tab_groups/tab_group_sync_delegate_browsertest.cc", - "../browser/ui/tabs/saved_tab_groups/tab_group_sync_navigation_browser_test.cc", "../browser/ui/test/browser_ui_browsertest.cc", "../browser/ui/test/browser_ui_test_base.cc", "../browser/ui/test/browser_ui_test_base.h", @@ -3942,6 +3940,8 @@ "//chrome/browser/ui/tabs:glic", "//chrome/browser/ui/tabs/organization", "//chrome/browser/ui/tabs/organization:browser_tests", + "//chrome/browser/ui/tabs/saved_tab_groups", + "//chrome/browser/ui/tabs/saved_tab_groups:browser_tests", "//chrome/browser/ui/toolbar", "//chrome/browser/ui/toolbar/chrome_labs", "//chrome/browser/ui/toolbar/pinned_toolbar", @@ -4121,6 +4121,15 @@ } } + if (enable_pdf_save_to_drive) { + sources += [ + "../browser/ui/save_to_drive/add_account_dialog_controller_browsertest.cc", + "//chrome/browser/ui/save_to_drive/add_account_dialog_controller.cc", + "//chrome/browser/ui/save_to_drive/add_account_dialog_controller.h", + ] + deps += [ "//chrome/browser/ui/save_to_drive" ] + } + if (enable_request_header_integrity) { deps += [ "//chrome/common/request_header_integrity:browser_tests" ] } @@ -8098,11 +8107,6 @@ "../browser/ui/passwords/password_manager_navigation_throttle_unittest.cc", "../browser/ui/passwords/well_known_change_password_navigation_throttle_unittest.cc", "../browser/ui/recently_audible_helper_unittest.cc", - "../browser/ui/tabs/saved_tab_groups/collaboration_messaging_page_action_controller_unittest.cc", - "../browser/ui/tabs/saved_tab_groups/collaboration_messaging_tab_data_unittest.cc", - "../browser/ui/tabs/saved_tab_groups/instant_message_queue_processor_unittest.cc", - "../browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service_unittest.cc", - "../browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy_unittest.cc", "../browser/ui/url_identity_unittest.cc", "../browser/ui/views/accessibility/theme_tracking_non_accessible_image_view_unittest.cc", "../browser/ui/views/autofill/address_editor_view_unittest.cc", @@ -8275,6 +8279,8 @@ "//chrome/browser/ui/tabs:unit_tests", "//chrome/browser/ui/tabs/organization", "//chrome/browser/ui/tabs/organization:unit_tests", + "//chrome/browser/ui/tabs/saved_tab_groups", + "//chrome/browser/ui/tabs/saved_tab_groups:unit_tests", "//chrome/browser/ui/task_manager:unit_tests", "//chrome/browser/ui/thumbnails", "//chrome/browser/ui/thumbnails:unit_tests", @@ -10091,6 +10097,9 @@ "//services/network/public/mojom:url_loader_base", "//url", ] + if (enable_pdf_save_to_drive) { + deps += [ "//chrome/browser/save_to_drive" ] + } } if (enable_pdf_save_to_drive) { @@ -11705,6 +11714,7 @@ "//chrome/browser/ui/tabs:tab_group", "//chrome/browser/ui/tabs:tab_menu", "//chrome/browser/ui/tabs:tab_model", + "//chrome/browser/ui/tabs/saved_tab_groups", "//chrome/browser/ui/toolbar:interactive_ui_tests", "//chrome/browser/ui/toolbar/cast", "//chrome/browser/ui/toolbar/pinned_toolbar",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HistoryPaneStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HistoryPaneStation.java index 0cb9f43..8e4bd8d 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HistoryPaneStation.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/hub/HistoryPaneStation.java
@@ -38,16 +38,29 @@ } /** Expect history entries to be displayed in the history pane. */ - public HistoryWithEntriesFacility expectEntries() { - return noopTo().enterFacility(new HistoryWithEntriesFacility()); + public HistoryWithEntriesFacility expectEntries(boolean isLLFDevice) { + return noopTo().enterFacility(new HistoryWithEntriesFacility(isLLFDevice)); } /** Expect no history to be displayed in the history pane. */ - public void expectEmptyState() { + public void expectEmptyState(boolean isLLFDevice) { var emptyHistory = new Facility<>("EmptyState"); - emptyHistory.declareView(withText("You’ll find your history here")); - emptyHistory.declareView( - withText("You can see the pages you’ve visited or delete them from your history")); + if (isLLFDevice) { + emptyHistory.declareView( + withText( + "Can’t find that page. Check your spelling or try a search on" + + " Google.")); + emptyHistory.declareView( + withText( + "Try searching for something else or open full Chrome history to see" + + " more results.")); + } else { + emptyHistory.declareView(withText("You’ll find your history here")); + emptyHistory.declareView( + withText( + "You can see the pages you’ve visited or delete them from your" + + " history")); + } emptyHistory.declareNoView(withId(R.id.history_page_recycler_view)); noopTo().enterFacility(emptyHistory); } @@ -57,8 +70,13 @@ public final ViewElement<View> recyclerViewElement; public final ViewElement<View> searchButtonElement; - public HistoryWithEntriesFacility() { + public HistoryWithEntriesFacility(boolean mIsLLFDevice) { recyclerViewElement = declareView(withId(R.id.history_page_recycler_view)); + if (mIsLLFDevice) { + searchButtonElement = null; + declareNoView(withId(R.id.search_menu_id)); + return; + } searchButtonElement = declareView(withId(R.id.search_menu_id)); } @@ -73,7 +91,8 @@ } /** Open the history search. */ - public HistorySearchFacility openSearch() { + public HistorySearchFacility openSearch(boolean isLLFDevice) { + if (isLLFDevice) return noopTo().enterFacility(new HistorySearchFacility()); return searchButtonElement.clickTo().enterFacility(new HistorySearchFacility()); } }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java index e157762..9f3e00d 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
@@ -701,7 +701,7 @@ final TabModelObserver observer = new TabModelObserver() { @Override - public void multipleTabsPendingClosure( + public void onTabClosePending( List<Tab> tabs, boolean isAllTabs, @TabClosingSource int closingSource) {
diff --git a/chrome/test/base/chrome_test_utils.cc b/chrome/test/base/chrome_test_utils.cc index 15117a9..bd7b0432 100644 --- a/chrome/test/base/chrome_test_utils.cc +++ b/chrome/test/base/chrome_test_utils.cc
@@ -31,6 +31,20 @@ #endif } +content::WebContents* GetWebContentsAt(const PlatformBrowserTest* browser_test, + int index) { +#if BUILDFLAG(IS_ANDROID) + for (const TabModel* model : TabModelList::models()) { + if (model->IsActiveModel()) { + return model->GetWebContentsAt(index); + } + } + NOTREACHED() << "No active TabModel??"; +#else + return browser_test->browser()->tab_strip_model()->GetWebContentsAt(index); +#endif +} + Profile* GetProfile(const PlatformBrowserTest* browser_test) { #if BUILDFLAG(IS_ANDROID) for (const TabModel* model : TabModelList::models()) {
diff --git a/chrome/test/base/chrome_test_utils.h b/chrome/test/base/chrome_test_utils.h index c145668..ccdf9f2 100644 --- a/chrome/test/base/chrome_test_utils.h +++ b/chrome/test/base/chrome_test_utils.h
@@ -27,6 +27,11 @@ content::WebContents* GetActiveWebContents( const PlatformBrowserTest* browser_test); +// Returns the WebContents at the specific index. On Android, this is the +// specific content from active model. +content::WebContents* GetWebContentsAt(const PlatformBrowserTest* browser_test, + int index); + // Returns the active Profile. On desktop this is in the first browser // window created by tests, more specific behaviour requires other means. Profile* GetProfile(const PlatformBrowserTest* browser_test);
diff --git a/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.html b/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.html new file mode 100644 index 0000000..c12df34 --- /dev/null +++ b/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.html
@@ -0,0 +1,16 @@ +<script> +async function setup() { + await navigator.serviceWorker.register('fetch-from-service-worker-as-public-address.js'); + await navigator.serviceWorker.ready; + return 'ready'; +} + +function fetch_from_service_worker(url) { + return new Promise(async resolve => { + const registration = await navigator.serviceWorker.ready; + const channel = new MessageChannel(); + channel.port1.onmessage = e => { resolve(e.data); }; + registration.active.postMessage({url}, [channel.port2]); + }); +} +</script>
diff --git a/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.html.mock-http-headers b/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.html.mock-http-headers new file mode 100644 index 0000000..374554ae1 --- /dev/null +++ b/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.html.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Content-Security-Policy: treat-as-public-address
diff --git a/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.js b/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.js new file mode 100644 index 0000000..cedc135a --- /dev/null +++ b/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.js
@@ -0,0 +1,21 @@ +// 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. + +async function handleMessage(e) { + try { + const response = await fetch(e.data.url); + if (!response.ok) { + e.ports[0].postMessage('bad response'); + return; + } + const text = await response.text(); + e.ports[0].postMessage(text); + } catch (error) { + e.ports[0].postMessage(`${error}`); + } +} + +self.addEventListener('message', e => { + e.waitUntil(handleMessage(e)); +});
diff --git a/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.js.mock-http-headers b/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.js.mock-http-headers new file mode 100644 index 0000000..56a3564c --- /dev/null +++ b/chrome/test/data/private_network_access/fetch-from-service-worker-as-public-address.js.mock-http-headers
@@ -0,0 +1,3 @@ +HTTP/1.1 200 OK +Content-Type: application/javascript +Content-Security-Policy: treat-as-public-address
diff --git a/chrome/test/data/webui/compose/test_compose_api_proxy.ts b/chrome/test/data/webui/compose/test_compose_api_proxy.ts index fb0c1f40..3ff1b43c 100644 --- a/chrome/test/data/webui/compose/test_compose_api_proxy.ts +++ b/chrome/test/data/webui/compose/test_compose_api_proxy.ts
@@ -73,6 +73,7 @@ 'logEditInput', 'openBugReportingLink', 'openComposeLearnMorePage', + 'openEnterpriseComposeLearnMorePage', 'openFeedbackSurveyLink', 'openSignInPage', 'requestInitialState', @@ -149,6 +150,10 @@ this.methodCalled('openComposeLearnMorePage'); } + openEnterpriseComposeLearnMorePage() { + this.methodCalled('openEnterpriseComposeLearnMorePage'); + } + openFeedbackSurveyLink() { this.methodCalled('openFeedbackSurveyLink'); }
diff --git a/chrome/test/data/webui/glic/api_test.ts b/chrome/test/data/webui/glic/api_test.ts index fae5f42f..9f829f33 100644 --- a/chrome/test/data/webui/glic/api_test.ts +++ b/chrome/test/data/webui/glic/api_test.ts
@@ -45,9 +45,10 @@ this.current = await waitFor(this.getSignal(this.readIndex++).promise); return this.current; } + /** Returns true if all values have been read. */ isEmpty(): boolean { - return this.readIndex === this.writeIndex; + return this.readIndex >= this.writeIndex; } unsubscribe() { this.subscriber.unsubscribe(); @@ -1325,6 +1326,27 @@ await getCandidatesEquals({maxCandidates: 1}, ''); } + async testGetPinCandidatesWithPanelClosed() { + assertTrue(!!this.host.pinTabs); + assertTrue(!!this.host.getPinCandidates); + + const sequence = + observeSequence(this.host.getPinCandidates!({maxCandidates: 10})); + sequence.waitFor(tabs => tabs.length === 1); + this.host.closePanel!(); + + // Open a tab. The client should not receive any updates. + await this.advanceToNextStep(); + await sleep(500); + while (!sequence.isEmpty()) { + assertEquals((await sequence.next()).length, 1); + } + + // Show the panel again. The client should receive an update. + await this.advanceToNextStep(); + sequence.waitFor(tabs => tabs.length === 2); + } + async testGetModelQualityClientId() { assertTrue(!!this.host.getModelQualityClientId); const clientId = await this.host.getModelQualityClientId();
diff --git a/chrome/test/data/webui/glic/test_client/index.html b/chrome/test/data/webui/glic/test_client/index.html index 56143a0..d6aedb1 100644 --- a/chrome/test/data/webui/glic/test_client/index.html +++ b/chrome/test/data/webui/glic/test_client/index.html
@@ -517,9 +517,13 @@ <button>⬆️ </button> </li> </ul> + <p>Candidates</p> + <label>Fetch Candidates?<input type="checkbox" id="enableShareCandidates"></label> + <div> <input type="text" id="shareCandidateQuery"/> <ul id="shareCandidates"> </ul> + </div> </div> <div class="section"> <h1>View Change</h1>
diff --git a/chrome/test/data/webui/glic/test_client/page_element_types.ts b/chrome/test/data/webui/glic/test_client/page_element_types.ts index a86fee3..4d5d10f 100644 --- a/chrome/test/data/webui/glic/test_client/page_element_types.ts +++ b/chrome/test/data/webui/glic/test_client/page_element_types.ts
@@ -132,6 +132,7 @@ fetchPinned: HTMLButtonElement; shareCandidateQuery: HTMLInputElement; shareCandidates: HTMLElement; + enableShareCandidates: HTMLInputElement; unpin: HTMLButtonElement; viewChangedBtn: HTMLButtonElement; viewChangedCurrentView: HTMLSelectElement;
diff --git a/chrome/test/data/webui/glic/test_client/sections/multi_tab.ts b/chrome/test/data/webui/glic/test_client/sections/multi_tab.ts index be0d37a..5df1299 100644 --- a/chrome/test/data/webui/glic/test_client/sections/multi_tab.ts +++ b/chrome/test/data/webui/glic/test_client/sections/multi_tab.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import type {PinCandidate, Subscriber, TabContextResult, TabData} from '/glic/glic_api/glic_api.js'; +import type {ObservableValue, PinCandidate, Subscriber, TabContextResult, TabData} from '/glic/glic_api/glic_api.js'; import {DEFAULT_PDF_SIZE_LIMIT} from '/glic/glic_api/glic_api.js'; import {client, getBrowser, logMessage} from '../client.js'; @@ -22,6 +22,7 @@ let state: PinnedTabState[] = []; let pinCandidateSubscriber: Subscriber|undefined; +let pinCandidateObservable: ObservableValue<PinCandidate[]>|undefined; function updateStateWithTabData(tabData: TabData[]) { state = state.filter((x) => { @@ -217,7 +218,6 @@ button.innerText = 'Share'; const clickHandler = async () => { await getBrowser()!.pinTabs!([candidate.tabData.tabId]); - await fetchCandidates(); }; button.addEventListener('click', clickHandler); li.appendChild(button); @@ -229,13 +229,15 @@ async function fetchCandidates() { if (pinCandidateSubscriber) { pinCandidateSubscriber.unsubscribe(); + pinCandidateSubscriber = undefined; } - pinCandidateSubscriber = getBrowser()! - .getPinCandidates!({ - maxCandidates: 10, - query: $.shareCandidateQuery.value, - }) - .subscribe(replaceCandidates); + if (!pinCandidateObservable) { + pinCandidateObservable = getBrowser()!.getPinCandidates!({ + maxCandidates: 10, + query: $.shareCandidateQuery.value, + }); + } + pinCandidateSubscriber = pinCandidateObservable!.subscribe(replaceCandidates); } client.getInitialized().then(async () => { @@ -288,19 +290,21 @@ await updateUi(); }); - $.shareCandidateQuery.addEventListener('focus', () => { - fetchCandidates(); + $.shareCandidateQuery.addEventListener('input', () => { + pinCandidateSubscriber?.unsubscribe(); + pinCandidateSubscriber = undefined; + pinCandidateObservable = undefined; + if ($.enableShareCandidates.checked) { + fetchCandidates(); + } }); - $.shareCandidateQuery.addEventListener('blur', () => { - if (pinCandidateSubscriber) { - pinCandidateSubscriber.unsubscribe(); + $.enableShareCandidates.addEventListener('click', () => { + if ($.enableShareCandidates.checked) { + fetchCandidates(); + } else { + pinCandidateSubscriber?.unsubscribe(); pinCandidateSubscriber = undefined; } - clearCandidates(); - }); - - $.shareCandidateQuery.addEventListener('input', () => { - fetchCandidates(); }); });
diff --git a/chrome/test/data/webui/settings/privacy_page_index_test.ts b/chrome/test/data/webui/settings/privacy_page_index_test.ts index b7148bd..2282e69 100644 --- a/chrome/test/data/webui/settings/privacy_page_index_test.ts +++ b/chrome/test/data/webui/settings/privacy_page_index_test.ts
@@ -59,23 +59,24 @@ await waitBeforeNextRender(index); assertActiveViews(defaultViews); - // Non-exhaustive list of PRIVACY child routes that have not been migrated - // to the new architecture (crbug.com/424223101), therefore the contents - // still reside in the 'old' <settings-basic-page> view. - const nonMigratedRoutes: Route[] = [ - routes.CLEAR_BROWSER_DATA, - routes.COOKIES, - routes.SAFETY_HUB, - routes.SECURITY, - routes.SITE_SETTINGS, - routes.SITE_SETTINGS_LOCATION, + // Non-exhaustive list of PRIVACY child routes to check. + // Some of these routs have not been migrated to the new architecture + // (crbug.com/424223101), therefore the contents still reside in the 'old' + // <settings-basic-page> view. + const routesToVisit: Array<{route: Route, viewId: string}> = [ + {route: routes.CLEAR_BROWSER_DATA, viewId: 'old'}, + {route: routes.COOKIES, viewId: 'old'}, + {route: routes.SAFETY_HUB, viewId: 'safetyHub'}, + {route: routes.SECURITY, viewId: 'old'}, + {route: routes.SITE_SETTINGS_LOCATION, viewId: 'old'}, + {route: routes.SITE_SETTINGS, viewId: 'old'}, ]; - for (const route of nonMigratedRoutes) { + for (const {route, viewId} of routesToVisit) { Router.getInstance().navigateTo(route); await flushTasks(); await waitBeforeNextRender(index); - assertActiveViews(['old']); + assertActiveViews([viewId]); } });
diff --git a/chrome/test/data/webui/settings/test_search_manager.ts b/chrome/test/data/webui/settings/test_search_manager.ts index ef4b022..9a086ac 100644 --- a/chrome/test/data/webui/settings/test_search_manager.ts +++ b/chrome/test/data/webui/settings/test_search_manager.ts
@@ -15,7 +15,6 @@ export class TestSearchManager extends TestBrowserProxy implements SearchManager { private matchesFound_: boolean = true; - private searchRequest_: SearchRequest|null = null; constructor() { super(['search']); @@ -25,14 +24,17 @@ this.matchesFound_ = matchesFound; } - search(text: string, page: Element) { + search(text: string, node: Element) { this.methodCalled('search', text); - if (this.searchRequest_ == null || !this.searchRequest_.isSame(text)) { - this.searchRequest_ = new SearchRequest(text, page); - this.searchRequest_.updateMatchCount(this.matchesFound_ ? 1 : 0); - this.searchRequest_.resolver.resolve(this.searchRequest_); - } - return this.searchRequest_.resolver.promise; + const request = new SearchRequest(text, node); + + const matchesFound = node.nodeType === Node.TEXT_NODE ? + this.matchesFound_ : + this.matchesFound_ && !node.hasAttribute('no-search'); + request.updateMatchCount(matchesFound ? 1 : 0); + request.resolver.resolve(request); + + return request.resolver.promise; } }
diff --git a/chrome/test/media_router/performance/BUILD.gn b/chrome/test/media_router/performance/BUILD.gn index ff3a241..c1928be11 100644 --- a/chrome/test/media_router/performance/BUILD.gn +++ b/chrome/test/media_router/performance/BUILD.gn
@@ -3,4 +3,11 @@ python_library("performance_test") { testonly = true pydeps_file = "performance_test.pydeps" + data = [ + "//.vpython3", + "//build/util/lib/proto", + "//fuchsia_web/av_testing/server.py", + "//fuchsia_web/av_testing/video.html", + "//build/fuchsia/test/repeating_log.py", + ] }
diff --git a/chrome/test/media_router/performance/performance_test.py b/chrome/test/media_router/performance/performance_test.py index d307a4e..79a64c9 100644 --- a/chrome/test/media_router/performance/performance_test.py +++ b/chrome/test/media_router/performance/performance_test.py
@@ -2,13 +2,401 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -""" Execute Media Router performance tests against miscellaneous test devices. """ import sys +import selenium +import os +import shutil +import subprocess +import socket +import time +import multiprocessing +import logging +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.chrome.options import Options as ChromeOptions +from contextlib import AbstractContextManager -# TODO(crbug.com/403338499): Implement tests. -def main() -> int: - print('Running Media Router performance tests.') - return 0 +MEASURES_ROOT = os.path.join(os.path.dirname(__file__), '..', '..', '..', + '..', 'build', 'util', 'lib', 'proto') +sys.path.append(MEASURES_ROOT) +import measures -if __name__ == "__main__": - sys.exit(main()) +CHROME_FUCHSIA_ROOT = os.path.join(os.path.dirname(__file__), '..', '..', + '..', '..', 'fuchsia_web', 'av_testing') +sys.path.append(CHROME_FUCHSIA_ROOT) +import server +import video_analyzer + +TEST_SCRIPTS_ROOT = os.path.join(os.path.dirname(__file__), '..', '..', + 'build', 'fuchsia', 'test') +sys.path.append(TEST_SCRIPTS_ROOT) +from repeating_log import RepeatingLog + +_CHROMEDRIVER_PORT = int(os.environ.get('CHROMEDRIVER_PORT', '49573')) +_SENDER = os.environ.get('SENDER') +_USERNAME = os.environ.get('USERNAME') +_PASSWORD = os.environ.get('PASSWORD') +_RECEIVER = os.environ.get('RECEIVER') +_SERVER_PORT = int(os.environ.get('SERVER_PORT', '8000')) + +recordings_dir = os.path.join(os.environ.get('TMPDIR', '/tmp'), 'recordings') +REMOTE_URL = f'http://127.0.0.1:{_CHROMEDRIVER_PORT}' +tunnel_proc = None +rec_proc = None + +VIDEOS = [ + { + 'name': '1080p30fpsAV1_foodmarket_sync.mp4', + 'fps': 30 + }, + { + 'name': '1080p30fpsH264_foodmarket_yt_sync.mp4', + 'fps': 30 + }, + { + 'name': '1080p60fpsHEVC_boat_sync.mp4', + 'fps': 60 + }, + { + 'name': '1080p60fpsVP9_boat_yt_sync.webm', + 'fps': 60 + } +] + +host_tunnel_cmd = [ + 'sshpass', + '-p', + _PASSWORD, + 'ssh', + '-L', + f'{_CHROMEDRIVER_PORT}:127.0.0.1:{_CHROMEDRIVER_PORT}', + f'{_USERNAME}@{_SENDER}', + '-N' +] + +sender_chromedriver_cmd = ( + f'nohup /opt/homebrew/bin/chromedriver --port={_CHROMEDRIVER_PORT} ' + f'--allowed-origins=\"*\" ' + f'--verbose ' + f'--log-path=/tmp/chromedriver_verbose.log ' + f'--enable-chrome-logs ' + f'> /dev/null 2>&1 &' +) + +sender_chromedriver_check_cmd = ( + f'ps aux | grep chromedriver | grep -v grep' +) + +sender_terminate_driver_cmd = ( + f'killall chromedriver' +) + +sender_status_cmd = ( + f'curl ' + f'-s ' + f'-o /dev/null ' + f'-w "%{{http_code}}" ' + f'http://127.0.0.1:{_CHROMEDRIVER_PORT}/status' +) + +class StartProcess(AbstractContextManager): + """Starts a multiprocessing.Process.""" + + def __init__(self, target, args, terminate: bool): + self._proc = multiprocessing.Process(target=target, args=args) + self._terminate = terminate + + def __enter__(self): + self._proc.start() + + def __exit__(self, exc_type, exc_value, traceback): + if self._terminate: + self._proc.terminate() + self._proc.join() + if not self._terminate: + assert self._proc.exitcode == 0 + +def send_ssh_command(hostname, _USERNAME, _PASSWORD, command, blocking=False): + ssh_command = ['sshpass', '-p', _PASSWORD, 'ssh', + f'{_USERNAME}@{hostname}', command] + if blocking: + process = subprocess.run( + ssh_command, + capture_output=True, + text=True, + timeout=60 + ) + else: + process = subprocess.Popen( + ssh_command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True + ) + + return process + +def setup_test_environment(): + send_ssh_command(_SENDER, _USERNAME, _PASSWORD, + sender_terminate_driver_cmd) + time.sleep(1) + + for _ in range(5): + result = send_ssh_command(_SENDER, _USERNAME, _PASSWORD, + sender_chromedriver_check_cmd, blocking=True) + + if not result.stdout.strip(): + logging.info("DEBUG: Old chromedriver processes confirmed gone.") + break + logging.info("DEBUG: Old chromedriver processes still present, " + "waiting...") + time.sleep(1) + else: + raise RuntimeError("Old chromedriver processes lingered even after " + "kill attempts.") + + send_ssh_command(_SENDER, _USERNAME, _PASSWORD, sender_chromedriver_cmd) + logging.info("Started chromedriver.") + + logging.info("Starting Chromedriver status check...") + for attempt in range(5): + try: + result = send_ssh_command(_SENDER, _USERNAME, _PASSWORD, + sender_status_cmd, blocking=True) + stdout = result.stdout.strip() + + if result.returncode == 0 and stdout == '200': + logging.info(f"SUCCESS: Attempt {attempt + 1}: " + "Chromedriver is ready.") + break + elif result.returncode == 7: + logging.info(f"info: Attempt {attempt + 1}: Connection refused " + "(curl code 7). Chromedriver not ready yet...") + else: + logging.warn(f"ERROR: Attempt {attempt + 1}: An unexpected " + "error occurred!") + logging.warn(f" --> Exit Code: {result.returncode}") + logging.warn(f" --> Stderr: {result.stderr.strip()}") + logging.warn(f" --> Stdout: {stdout}") + except subprocess.TimeoutExpired: + logging.warn(f"ERROR: Attempt {attempt + 1}: Status check timed " + "out. Retrying...") + except Exception as e: + logging.warn(f"ERROR: Attempt {attempt + 1}: A script-level error " + f"occurred: {e}. Retrying...") + + time.sleep(2) + else: + raise RuntimeError("Chromedriver did not become ready after multiple " + "attempts.") + + chrome_options = ChromeOptions() + chrome_options.add_argument("--enable-features=CastMediaRouteProvider," + "DialMediaRouteProvider") + chrome_options.add_argument("--enable-logging=stderr") + chrome_options.add_argument("--media-router-cast-allow-all-ips") + chrome_options.add_argument("--v=1") + chrome_options.add_argument("--vmodule=media_router*=2," + "discovery_mdns*=2,cast_channel*=2," + "webrtc_logging/*=2") + chrome_options.add_argument('--password-store=basic') + + tunnel_proc = subprocess.Popen(host_tunnel_cmd) + logging.info("Started tunnel.") + + logging.info(f"Attempting connection to {REMOTE_URL}.") + + driver = None + for i in range(20): + try: + driver = webdriver.Remote( + command_executor=REMOTE_URL, + options=chrome_options + ) + logging.info("Successfully connected!") + break + except: + logging.info("Tunnel not yet up. Sleeping ...") + time.sleep(2) + return driver, tunnel_proc + +def teardown_test_environment(driver, tunnel_proc, rec_proc): + if rec_proc is not None: + while rec_proc.poll() == None: + logging.info("Still recording...") + time.sleep(2) + logging.info("Recording finished.") + + if driver: + driver.quit() + logging.info("Terminated chromedriver.") + + if tunnel_proc and tunnel_proc.poll() is None: + tunnel_proc.terminate() + logging.info("Terminated tunnel.") + +def run_performance_test(video_file: str, framerate: int, driver: webdriver): + # force video output to mp4 + output_file = os.path.join(recordings_dir, + video_file.replace('.webm', '.mp4')) + host_recording_cmd = [ + 'ffmpeg', + '-y', + '-f', 'video4linux2', + '-framerate', str(framerate), + '-video_size', '3840x2160', + '-input_format', 'yuyv422', + '-i', '/dev/video0', + '-thread_queue_size', '1024', + '-c:v', 'libx264', + '-preset', 'ultrafast', + '-crf', '28', + '-pix_fmt', 'yuv420p', + '-g', '60', + '-t', '35', + output_file + ] + + driver.get("https://storage.googleapis.com/castapi/CastHelloVideo/" + "index.html") + time.sleep(2) + button_xpath = "//button[text()='Launch app']" + button = driver.find_element(By.XPATH, button_xpath) + button.click() + time.sleep(2) + driver.get(f'http://{socket.gethostbyname(socket.gethostname())}:' + f'{_SERVER_PORT}/video.html?file={video_file}') + + casting_initiated = False + + try: + logging.info("Enabling Cast discovery via CDP...") + enable_result = driver.execute_cdp_cmd("Cast.enable", + {"presentationUrl": ""}) + + time.sleep(5) + + # start recording + rec_proc_local = subprocess.Popen(host_recording_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True) + + logging.info("ffmpeg recording process started. Waiting for 'Stream " + "mapping:' confirmation...") + + while True: + line = rec_proc_local.stderr.readline() # Use local variable + if line: + line = line.strip() + logging.info(f"FFMPEG STARTUP: {line}") + if "Stream mapping:" in line: + logging.info("Started recording.") + break + + logging.info(f"Attempting to start tab mirroring directly to " + f"'{_RECEIVER}'...") + driver.execute_cdp_cmd("Cast.startTabMirroring", + {"sinkName": _RECEIVER}) + casting_initiated = True + logging.info(f"'Cast.startTabMirroring' command sent to {_RECEIVER}.") + + def _wait_js_condition(driver, element, condition: str) -> bool: + """Waits a condition on the element once a second for at most 30 + seconds, returns True if the condition met.""" + start = time.time() + while not driver.execute_script(f'return arguments[0].{condition};', + element): + if time.time() - start >= 30: + return False + time.sleep(1) + return True + + video = driver.find_element(By.ID, 'video') + + with measures.time_consumption(video_file, 'video_perf', 'playback', + 'loading'), \ + RepeatingLog(f'Waiting for video {video_file} to be loaded.'): + if not _wait_js_condition(driver, video, 'readyState >= 2'): + logging.warning( + '%s may never be loaded, still go ahead to play it.', + video_file) + measures.average(video_file, 'video_perf', 'playback', + 'failed_to_load').record(1) + + video.click() + logging.info("Started playing video.") + + logging.info("Casting for 30 seconds (script will then stop casting " + "and quit)...") + time.sleep(30) + + while rec_proc_local.poll() == None: # Use local variable + logging.info("still recording...") + time.sleep(2) + logging.info("recording finished.") + + results = video_analyzer.from_original_video( + output_file, f"/usr/local/cipd/videostack_videos_30s/{video_file}") + + if not results: + raise RuntimeError("Missing video analyzer results. See log for " + "further details.") + + def record(key: str) -> None: + # If the video_analyzer does not generate any result, treat it as an + # error and use the default value to filter them out instead of + # failing the tests. + # TODO(crbug.com/40935291): Revise the default value for errors. + measures.average(video_file, 'video_perf', key).record( + results.get(key, -128)) + + record('smoothness') + record('freezing') + record('dropped_frame_count') + record('total_frame_count') + record('dropped_frame_percentage') + logging.warning('Video analysis result of %s: %s', video_file, results) + + except Exception as e: + raise RuntimeError(f"Error during CDP Cast command: {e}\nCheck " + "the chromedriver log on the remote laptop for " + "more details.") + finally: + if driver: + if casting_initiated and _RECEIVER: + logging.info(f"Attempting to stop casting to '{_RECEIVER}'...") + try: + driver.execute_cdp_cmd("Cast.stopCasting", + {"sinkName": _RECEIVER}) + logging.info("'Cast.stopCasting' command sent.") + except Exception as stop_cast_error: + raise RuntimeError(f"Error stopping cast: " + f"{stop_cast_error}") + return rec_proc_local # Return the local rec_proc + +def main(): + logging.basicConfig(level=logging.INFO) + + if os.path.exists(recordings_dir): + shutil.rmtree(recordings_dir) + os.makedirs(recordings_dir) + for video in VIDEOS: + driver = None + tunnel_proc_instance = None + rec_proc_instance = None + + try: + driver, tunnel_proc_instance = setup_test_environment() + rec_proc_instance = run_performance_test(video['name'], + video['fps'], driver) + except Exception as e: + raise RuntimeError(f"Error during video {video['name']} test: {e}") + finally: + teardown_test_environment(driver, tunnel_proc_instance, + rec_proc_instance) + +if __name__ == '__main__': + with StartProcess(server.start, [ _SERVER_PORT ], True): + sys.exit(main()) \ No newline at end of file
diff --git a/chrome/test/media_router/performance/performance_test.pydeps b/chrome/test/media_router/performance/performance_test.pydeps index 4e92bcd0..e2305ea 100644 --- a/chrome/test/media_router/performance/performance_test.pydeps +++ b/chrome/test/media_router/performance/performance_test.pydeps
@@ -1,3 +1,14 @@ # Generated by running: # build/print_python_deps.py --root chrome/test/media_router/performance --output chrome/test/media_router/performance/performance_test.pydeps chrome/test/media_router/performance/performance_test.py +../../../../build/fuchsia/test/repeating_log.py +../../../../build/util/lib/proto/average.py +../../../../build/util/lib/proto/count.py +../../../../build/util/lib/proto/data_points.py +../../../../build/util/lib/proto/measure.py +../../../../build/util/lib/proto/measures.py +../../../../build/util/lib/proto/metric.py +../../../../build/util/lib/proto/test_script_metrics_pb2.py +../../../../build/util/lib/proto/time_consumption.py +../../../../fuchsia_web/av_testing/server.py +../../../../fuchsia_web/av_testing/video_analyzer.py performance_test.py
diff --git a/chrome/utility/BUILD.gn b/chrome/utility/BUILD.gn index c2310d08..edd0995 100644 --- a/chrome/utility/BUILD.gn +++ b/chrome/utility/BUILD.gn
@@ -143,7 +143,7 @@ "//components/autofill/core/common", "//components/user_data_importer/common", "//components/user_data_importer/content", - "//components/user_data_importer/utility:safari_data_importer", + "//components/user_data_importer/utility:bookmarks", "//services/proxy_resolver:lib", "//services/screen_ai", ]
diff --git a/chromecast/browser/cast_system_memory_pressure_evaluator.cc b/chromecast/browser/cast_system_memory_pressure_evaluator.cc index ac113e4..ad8b3a7 100644 --- a/chromecast/browser/cast_system_memory_pressure_evaluator.cc +++ b/chromecast/browser/cast_system_memory_pressure_evaluator.cc
@@ -86,20 +86,21 @@ base::MemoryPressureListener::MemoryPressureLevel level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE; - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; if (!base::GetSystemMemoryInfo(&info)) { LOG(ERROR) << "GetSystemMemoryInfo failed"; - } else if (system_reserved_kb_ != 0 || info.available != 0) { + } else if (system_reserved_kb_ != 0 || !info.available.is_zero()) { // Preferred memory pressure heuristic: // 1. Use /proc/meminfo's MemAvailable if possible, fall back to estimate // of free + buffers + cached otherwise. - const int total_available = (info.available != 0) - ? info.available - : (info.free + info.buffers + info.cached); + const int total_available = + (!info.available.is_zero()) + ? info.available.InKiB() + : (info.free + info.buffers + info.cached).InKiB(); // 2. Allow some memory to be 'reserved' on command line. const int available = total_available - system_reserved_kb_; - const int total = info.total - system_reserved_kb_; + const int total = info.total.InKiB() - system_reserved_kb_; DCHECK_GT(total, 0); const float ratio = available / static_cast<float>(total); @@ -110,10 +111,11 @@ } else { // Backup method purely using 'free' memory. It may generate more // pressure events than necessary, since more memory may actually be free. - if (info.free < kCriticalFreeMemoryKB) + if (info.free.InKiB() < kCriticalFreeMemoryKB) { level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; - else if (info.free < kModerateFreeMemoryKB) + } else if (info.free.InKiB() < kModerateFreeMemoryKB) { level = base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE; + } } UpdateMemoryPressureLevel(level);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index d6845ec..ce728d50 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -16370.0.0-1070738 \ No newline at end of file +16373.0.0-1070779 \ No newline at end of file
diff --git a/chromeos/ash/components/dbus/resourced/resourced_client.cc b/chromeos/ash/components/dbus/resourced/resourced_client.cc index 2ccfdf5..e14df4ae 100644 --- a/chromeos/ash/components/dbus/resourced/resourced_client.cc +++ b/chromeos/ash/components/dbus/resourced/resourced_client.cc
@@ -129,9 +129,9 @@ }; ResourcedClientImpl::ResourcedClientImpl() { - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; if (base::GetSystemMemoryInfo(&info)) { - total_memory_kb_ = static_cast<uint64_t>(info.total); + total_memory_kb_ = static_cast<uint64_t>(info.total.InKiB()); } else { PLOG(ERROR) << "Error reading total memory."; }
diff --git a/chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.cc b/chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.cc index b2159c2..f1b7444 100644 --- a/chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.cc +++ b/chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.cc
@@ -4,6 +4,8 @@ #include "chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.h" +#include <utility> + #include "ash/public/cpp/arc_compat_mode_util.h" #include "ash/public/cpp/style/color_provider.h" #include "ash/public/cpp/window_properties.h" @@ -29,12 +31,15 @@ #include "ui/color/color_id.h" #include "ui/color/color_provider.h" #include "ui/compositor/layer.h" +#include "ui/compositor/layer_type.h" #include "ui/gfx/geometry/insets.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/text_constants.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/background.h" #include "ui/views/border.h" +#include "ui/views/bubble/bubble_border.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/controls/highlight_path_generator.h" #include "ui/views/controls/image_view.h" @@ -50,39 +55,39 @@ constexpr int kButtonRadius = 12; constexpr int kBorderThicknessDp = 1; +constexpr int kBubbleCornerRadius = 12; } // namespace -class RoundedCornerBubbleDialogDelegateView - : public views::BubbleDialogDelegateView { - METADATA_HEADER(RoundedCornerBubbleDialogDelegateView, - views::BubbleDialogDelegateView) - +class ResizeToggleMenuBubbleDialogDelegate + : public views::BubbleDialogDelegate { public: - explicit RoundedCornerBubbleDialogDelegateView(int corner_radius) - : corner_radius_(corner_radius) {} - - // views::View: - void AddedToWidget() override { - auto* const frame = GetBubbleFrameView(); - if (frame) { - frame->SetRoundedCorners(gfx::RoundedCornersF(corner_radius_)); - } + ResizeToggleMenuBubbleDialogDelegate(aura::Window* parent, + const gfx::Rect& anchor_rect) + : views::BubbleDialogDelegate(nullptr, views::BubbleBorder::Arrow::NONE) { + set_layer_type(ui::LAYER_NOT_DRAWN); + set_corner_radius(kBubbleCornerRadius); + SetArrow(views::BubbleBorder::Arrow::TOP_CENTER); + SetButtons(static_cast<int>(ui::mojom::DialogButton::kNone)); + set_parent_window(parent); + set_title_margins(gfx::Insets()); + set_margins(gfx::Insets()); + SetAnchorRect(anchor_rect); + SetTitle(l10n_util::GetStringUTF16( + IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TITLE)); + SetShowTitle(false); + SetAccessibleWindowRole(ax::mojom::Role::kMenu); } - base::WeakPtr<RoundedCornerBubbleDialogDelegateView> GetWeakPtr() { + base::WeakPtr<ResizeToggleMenuBubbleDialogDelegate> GetWeakPtr() { return weak_factory_.GetWeakPtr(); } private: - const int corner_radius_; - base::WeakPtrFactory<RoundedCornerBubbleDialogDelegateView> weak_factory_{ + base::WeakPtrFactory<ResizeToggleMenuBubbleDialogDelegate> weak_factory_{ this}; }; -BEGIN_METADATA(RoundedCornerBubbleDialogDelegateView) -END_METADATA - ResizeToggleMenu::MenuButtonView::MenuButtonView(PressedCallback callback, const gfx::VectorIcon& icon, int title_string_id) @@ -192,11 +197,10 @@ window_observation_.Observe(window); - bubble_widget_ = - views::BubbleDialogDelegateView::CreateBubble(MakeBubbleDelegateView( - widget_, GetAnchorRect(), - base::BindRepeating(&ResizeToggleMenu::ApplyResizeCompatMode, - base::Unretained(this)))); + bubble_widget_ = views::BubbleDialogDelegate::CreateBubble(MakeBubbleDelegate( + widget_, GetAnchorRect(), + base::BindRepeating(&ResizeToggleMenu::ApplyResizeCompatMode, + base::Unretained(this)))); widget_observations_.AddObservation(widget_.get()); widget_observations_.AddObservation(bubble_widget_.get()); OverlayDialog::Show(widget_->GetNativeWindow(), @@ -265,74 +269,51 @@ client_view_rect.width(), 0); } -std::unique_ptr<views::BubbleDialogDelegateView> -ResizeToggleMenu::MakeBubbleDelegateView( +std::unique_ptr<views::BubbleDialogDelegate> +ResizeToggleMenu::MakeBubbleDelegate( views::Widget* parent, gfx::Rect anchor_rect, base::RepeatingCallback<void(ash::ResizeCompatMode)> command_handler) { - const int kCornerRadius = 12; + auto bubble_delegate = std::make_unique<ResizeToggleMenuBubbleDialogDelegate>( + parent->GetNativeView(), GetAnchorRect()); + bubble_delegate_ = bubble_delegate->GetWeakPtr(); - auto delegate_view = - std::make_unique<RoundedCornerBubbleDialogDelegateView>(kCornerRadius); - bubble_view_ = delegate_view->GetWeakPtr(); + auto* contents_view = + bubble_delegate->SetContentsView(std::make_unique<views::View>()); + contents_view->SetUseDefaultFillLayout(true); - // Setup delegate. - delegate_view->SetArrow(views::BubbleBorder::Arrow::TOP_CENTER); - delegate_view->SetButtons(static_cast<int>(ui::mojom::DialogButton::kNone)); - delegate_view->set_parent_window(parent->GetNativeView()); - delegate_view->set_title_margins(gfx::Insets()); - delegate_view->set_margins(gfx::Insets()); - delegate_view->SetAnchorRect(anchor_rect); - delegate_view->SetTitle( - l10n_util::GetStringUTF16(IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_TITLE)); - delegate_view->SetShowTitle(false); - delegate_view->SetAccessibleWindowRole(ax::mojom::Role::kMenu); - // Clear root view's background color. We use the color in - // `background_view`. - delegate_view->SetBackgroundColor(SK_ColorTRANSPARENT); + contents_view->SetBorder(std::make_unique<views::HighlightBorder>( + kBubbleCornerRadius, + views::HighlightBorder::Type::kHighlightBorderNoShadow)); - // Setup view. - delegate_view->SetUseDefaultFillLayout(true); + contents_view->SetPaintToLayer(); + ui::Layer* contents_layer = contents_view->layer(); + contents_layer->SetRoundedCornerRadius( + gfx::RoundedCornersF(kBubbleCornerRadius)); + contents_layer->SetIsFastRoundedCorner(true); + if (chromeos::features::IsSystemBlurEnabled()) { + contents_layer->SetBackgroundBlur(ash::ColorProvider::kBackgroundBlurSigma); + contents_layer->SetBackdropFilterQuality( + ash::ColorProvider::kBackgroundBlurQuality); + contents_layer->SetFillsBoundsOpaquely(false); + } - delegate_view->SetBorder(std::make_unique<views::HighlightBorder>( - kCornerRadius, views::HighlightBorder::Type::kHighlightBorderNoShadow)); - - // Add empty view for background blur. const ui::ColorId background_color_id = chromeos::features::IsSystemBlurEnabled() ? cros_tokens::kCrosSysSystemBaseElevated : cros_tokens::kCrosSysSystemBaseElevatedOpaque; - views::View* background_view = nullptr; - delegate_view->AddChildView( - views::Builder<views::View>() - .CopyAddressTo(&background_view) - .SetUseDefaultFillLayout(true) - .SetBackground(views::CreateSolidBackground(background_color_id)) - .Build()); - - background_view->SetPaintToLayer(); - if (chromeos::features::IsSystemBlurEnabled()) { - background_view->layer()->SetBackgroundBlur( - ash::ColorProvider::kBackgroundBlurSigma); - background_view->layer()->SetBackdropFilterQuality( - ash::ColorProvider::kBackgroundBlurQuality); - background_view->layer()->SetFillsBoundsOpaquely(false); - } - background_view->layer()->SetRoundedCornerRadius( - gfx::RoundedCornersF(kCornerRadius)); - - auto* const container_view = - delegate_view->AddChildView(std::make_unique<views::View>()); + contents_view->SetBackground( + views::CreateSolidBackground(background_color_id)); auto* const provider = views::LayoutProvider::Get(); - container_view->SetLayoutManager(std::make_unique<views::BoxLayout>( + contents_view->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets(16), provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL))); - const auto add_menu_button = [&container_view, &command_handler]( + const auto add_menu_button = [&contents_view, &command_handler]( ash::ResizeCompatMode command_id, const gfx::VectorIcon& icon, int string_id) { - return container_view->AddChildView(std::make_unique<MenuButtonView>( + return contents_view->AddChildView(std::make_unique<MenuButtonView>( base::BindRepeating(command_handler, command_id), icon, string_id)); }; phone_button_ = @@ -346,17 +327,7 @@ IDS_ARC_COMPAT_MODE_RESIZE_TOGGLE_MENU_RESIZABLE); UpdateSelectedButton(); - - // We need to ensure that the layer is non-opaque for popup animation. - delegate_view->SetPaintToLayer(); - delegate_view->layer()->SetFillsBoundsOpaquely(false); - - // Note this view needs to be set to paint to layer so other view won't - // paint over it. - container_view->SetPaintToLayer(); - container_view->layer()->SetFillsBoundsOpaquely(false); - - return delegate_view; + return bubble_delegate; } void ResizeToggleMenu::UpdateSelectedButton() { @@ -393,7 +364,7 @@ } bool ResizeToggleMenu::IsBubbleShown() const { - return bubble_view_ && bubble_view_->GetWidget(); + return bubble_delegate_ && bubble_delegate_->GetWidget(); } void ResizeToggleMenu::CloseBubble() {
diff --git a/chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.h b/chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.h index 9b7e4af..25b6bf2 100644 --- a/chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.h +++ b/chromeos/ash/experiences/arc/compat_mode/resize_toggle_menu.h
@@ -26,7 +26,7 @@ } // namespace gfx namespace views { -class BubbleDialogDelegateView; +class BubbleDialogDelegate; class ImageView; class Label; } // namespace views @@ -98,9 +98,9 @@ gfx::Rect GetAnchorRect() const; - base::WeakPtr<views::BubbleDialogDelegateView> bubble_view_; + base::WeakPtr<views::BubbleDialogDelegate> bubble_delegate_; - std::unique_ptr<views::BubbleDialogDelegateView> MakeBubbleDelegateView( + std::unique_ptr<views::BubbleDialogDelegate> MakeBubbleDelegate( views::Widget* parent, gfx::Rect anchor_rect, base::RepeatingCallback<void(ash::ResizeCompatMode)> command_handler);
diff --git a/chromeos/ash/experiences/arc/session/arc_session_impl.cc b/chromeos/ash/experiences/arc/session/arc_session_impl.cc index fe86d24d4..5ad81ec 100644 --- a/chromeos/ash/experiences/arc/session/arc_session_impl.cc +++ b/chromeos/ash/experiences/arc/session/arc_session_impl.cc
@@ -90,20 +90,20 @@ void ApplyDalvikMemoryProfile( ArcSessionImpl::SystemMemoryInfoCallback system_memory_info_callback, StartParams* params) { - base::SystemMemoryInfoKB mem_info; + base::SystemMemoryInfo mem_info; if (!system_memory_info_callback.Run(&mem_info)) { LOG(ERROR) << "Failed to get system memory info"; return; } std::string log_profile_name; - if (mem_info.total >= kClassify16GbDeviceInKb) { + if (mem_info.total.InKiB() >= kClassify16GbDeviceInKb) { params->dalvik_memory_profile = StartParams::DalvikMemoryProfile::M16G; log_profile_name = "high-memory 16G"; - } else if (mem_info.total >= kClassify8GbDeviceInKb) { + } else if (mem_info.total.InKiB() >= kClassify8GbDeviceInKb) { params->dalvik_memory_profile = StartParams::DalvikMemoryProfile::M8G; log_profile_name = "high-memory 8G"; - } else if (mem_info.total >= kClassify4GbDeviceInKb) { + } else if (mem_info.total.InKiB() >= kClassify4GbDeviceInKb) { params->dalvik_memory_profile = StartParams::DalvikMemoryProfile::M4G; log_profile_name = "high-memory 4G"; } else { @@ -111,7 +111,7 @@ log_profile_name = "default low-memory"; } VLOG(1) << "Applied " << log_profile_name << " profile for the " - << (mem_info.total / 1024) << "Mb device."; + << mem_info.total.InMiB() << "Mb device."; } void ApplyHostUreadaheadMode(StartParams* params) {
diff --git a/chromeos/ash/experiences/arc/session/arc_session_impl.h b/chromeos/ash/experiences/arc/session/arc_session_impl.h index f9e2c7f..97435c83 100644 --- a/chromeos/ash/experiences/arc/session/arc_session_impl.h +++ b/chromeos/ash/experiences/arc/session/arc_session_impl.h
@@ -20,7 +20,7 @@ #include "chromeos/ash/experiences/arc/session/mojo_invitation_manager.h" namespace base { -struct SystemMemoryInfoKB; +struct SystemMemoryInfo; } namespace cryptohome { @@ -164,7 +164,7 @@ }; using SystemMemoryInfoCallback = - base::RepeatingCallback<bool(base::SystemMemoryInfoKB*)>; + base::RepeatingCallback<bool(base::SystemMemoryInfo*)>; ArcSessionImpl( std::unique_ptr<Delegate> delegate,
diff --git a/chromeos/ash/experiences/arc/session/arc_vm_client_adapter.cc b/chromeos/ash/experiences/arc/session/arc_vm_client_adapter.cc index 3493698..d8ba0a7 100644 --- a/chromeos/ash/experiences/arc/session/arc_vm_client_adapter.cc +++ b/chromeos/ash/experiences/arc/session/arc_vm_client_adapter.cc
@@ -221,11 +221,11 @@ } int GetDefaultVmMemoryMiB(ArcVmClientAdapterDelegate* delegate) { - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; if (!delegate->GetSystemMemoryInfo(&info)) { return 0; } - const int sys_memory_mb = info.total / 1024; + const int sys_memory_mb = info.total.InMiB(); int vm_memory_mb; if (sys_memory_mb >= 4096) { // On devices with >=4GB RAM, reserve 1GB for other processes. @@ -399,9 +399,9 @@ // Specify VM Memory. if (base::FeatureList::IsEnabled(kVmMemorySize)) { - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; if (delegate->GetSystemMemoryInfo(&info)) { - const int ram_mib = info.total / 1024; + const int ram_mib = info.total.InMiB(); const int shift_mib = kVmMemorySizeShiftMiB.Get(); const int max_mib = kVmMemorySizeMaxMiB.Get(); const int ram_percentage = kVmMemorySizePercentage.Get(); @@ -636,7 +636,7 @@ } // namespace bool ArcVmClientAdapterDelegate::GetSystemMemoryInfo( - base::SystemMemoryInfoKB* info) { + base::SystemMemoryInfo* info) { // Call the base function by default. return base::GetSystemMemoryInfo(info); }
diff --git a/chromeos/ash/experiences/arc/session/arc_vm_client_adapter.h b/chromeos/ash/experiences/arc/session/arc_vm_client_adapter.h index e953ebc..64d2c67d 100644 --- a/chromeos/ash/experiences/arc/session/arc_vm_client_adapter.h +++ b/chromeos/ash/experiences/arc/session/arc_vm_client_adapter.h
@@ -15,7 +15,7 @@ #include "chromeos/ash/experiences/arc/session/file_system_status.h" namespace base { -struct SystemMemoryInfoKB; +struct SystemMemoryInfo; class TimeDelta; } // namespace base @@ -62,7 +62,7 @@ ArcVmClientAdapterDelegate& operator=(const ArcVmClientAdapterDelegate&) = delete; virtual ~ArcVmClientAdapterDelegate() = default; - virtual bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* info); + virtual bool GetSystemMemoryInfo(base::SystemMemoryInfo* info); // Returns if crosvm is a 32-bit process. virtual bool IsCrosvm32bit();
diff --git a/chromeos/ash/experiences/arc/session/arc_vm_client_adapter_unittest.cc b/chromeos/ash/experiences/arc/session/arc_vm_client_adapter_unittest.cc index f938b24c..bc0e020 100644 --- a/chromeos/ash/experiences/arc/session/arc_vm_client_adapter_unittest.cc +++ b/chromeos/ash/experiences/arc/session/arc_vm_client_adapter_unittest.cc
@@ -17,6 +17,7 @@ #include <vector> #include "ash/constants/ash_features.h" +#include "base/byte_count.h" #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/containers/contains.h" @@ -2144,9 +2145,9 @@ base::FieldTrialParams params; params["shift_mib"] = "0"; feature_list.InitAndEnableFeatureWithParameters(kVmMemorySize, params); - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; ASSERT_TRUE(base::GetSystemMemoryInfo(&info)); - const uint32_t total_mib = info.total / 1024; + const int64_t total_mib = info.total.InMiB(); StartParams start_params(GetPopulatedStartParams()); StartMiniArcWithParams(true, std::move(start_params)); const auto& request = GetTestConciergeClient()->start_arc_vm_request(); @@ -2160,9 +2161,9 @@ base::FieldTrialParams params; params["shift_mib"] = "-1024"; feature_list.InitAndEnableFeatureWithParameters(kVmMemorySize, params); - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; ASSERT_TRUE(base::GetSystemMemoryInfo(&info)); - const uint32_t total_mib = info.total / 1024; + const int64_t total_mib = info.total.InMiB(); StartParams start_params(GetPopulatedStartParams()); StartMiniArcWithParams(true, std::move(start_params)); const auto& request = GetTestConciergeClient()->start_arc_vm_request(); @@ -2207,9 +2208,9 @@ base::FieldTrialParams params; params["ram_percentage"] = "25"; feature_list.InitAndEnableFeatureWithParameters(kVmMemorySize, params); - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; ASSERT_TRUE(base::GetSystemMemoryInfo(&info)); - const uint32_t total_mib = info.total / 1024; + const int64_t total_mib = info.total.InMiB(); StartParams start_params(GetPopulatedStartParams()); StartMiniArcWithParams(true, std::move(start_params)); const auto& request = GetTestConciergeClient()->start_arc_vm_request(); @@ -2224,9 +2225,9 @@ params["ram_percentage"] = "25"; params["shift_mib"] = "-512"; feature_list.InitAndEnableFeatureWithParameters(kVmMemorySize, params); - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; ASSERT_TRUE(base::GetSystemMemoryInfo(&info)); - const uint32_t total_mib = info.total / 1024; + const int64_t total_mib = info.total.InMiB(); StartParams start_params(GetPopulatedStartParams()); StartMiniArcWithParams(true, std::move(start_params)); const auto& request = GetTestConciergeClient()->start_arc_vm_request(); @@ -2238,7 +2239,7 @@ TEST_F(ArcVmClientAdapterTest, ArcVmMemorySizeEnabledNoSystemMemoryInfo) { // Inject the failure. class TestDelegate : public ArcVmClientAdapterDelegate { - bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* info) override { + bool GetSystemMemoryInfo(base::SystemMemoryInfo* info) override { return false; } }; @@ -2260,10 +2261,10 @@ // TODO(khmel): Remove this once crosvm becomes 64 bit binary on ARM. TEST_F(ArcVmClientAdapterTest, ArcVmMemorySizeEnabledOn32Bit) { class TestDelegate : public ArcVmClientAdapterDelegate { - bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* info) override { + bool GetSystemMemoryInfo(base::SystemMemoryInfo* info) override { // Return a value larger than k32bitVmRamMaxMib to verify that the VM // memory size is actually limited. - info->total = (k32bitVmRamMaxMib + 1000) * 1024; + info->total = base::MiB(k32bitVmRamMaxMib + 1000); return true; } bool IsCrosvm32bit() override { return true; } @@ -2546,8 +2547,8 @@ TEST_F(ArcVmClientAdapterTest, ArcGuestZramSizeByPercentage_5GbSystem) { class TestDelegate : public ArcVmClientAdapterDelegate { - bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* info) override { - info->total = 5 * 1024 * 1024; + bool GetSystemMemoryInfo(base::SystemMemoryInfo* info) override { + info->total = base::GiB(5); return true; } bool IsCrosvm32bit() override { return false; } @@ -2571,8 +2572,8 @@ TEST_F(ArcVmClientAdapterTest, ArcGuestZramSizeByPercentage_4GbSystem) { class TestDelegate : public ArcVmClientAdapterDelegate { - bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* info) override { - info->total = 4 * 1024 * 1024; + bool GetSystemMemoryInfo(base::SystemMemoryInfo* info) override { + info->total = base::GiB(4); return true; } bool IsCrosvm32bit() override { return false; } @@ -2596,8 +2597,8 @@ TEST_F(ArcVmClientAdapterTest, ArcGuestZramSizeByPercentage_CustomMem) { class TestDelegate : public ArcVmClientAdapterDelegate { - bool GetSystemMemoryInfo(base::SystemMemoryInfoKB* info) override { - info->total = 6 * 1024 * 1024; + bool GetSystemMemoryInfo(base::SystemMemoryInfo* info) override { + info->total = base::GiB(6); return true; } bool IsCrosvm32bit() override { return false; }
diff --git a/chromeos/ash/experiences/arc/test/arc_util_test_support.cc b/chromeos/ash/experiences/arc/test/arc_util_test_support.cc index e104c334..77cd9a3 100644 --- a/chromeos/ash/experiences/arc/test/arc_util_test_support.cc +++ b/chromeos/ash/experiences/arc/test/arc_util_test_support.cc
@@ -33,7 +33,7 @@ } bool GetSystemMemoryInfoForTesting(const std::string& file_name, - base::SystemMemoryInfoKB* mem_info) { + base::SystemMemoryInfo* mem_info) { base::FilePath base_path; base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &base_path); const base::FilePath test_path = base_path.Append("chromeos")
diff --git a/chromeos/ash/experiences/arc/test/arc_util_test_support.h b/chromeos/ash/experiences/arc/test/arc_util_test_support.h index 236f19d..8faae29b 100644 --- a/chromeos/ash/experiences/arc/test/arc_util_test_support.h +++ b/chromeos/ash/experiences/arc/test/arc_util_test_support.h
@@ -9,7 +9,7 @@ namespace base { class CommandLine; -struct SystemMemoryInfoKB; +struct SystemMemoryInfo; } // namespace base namespace arc { @@ -27,7 +27,7 @@ // Gets a system memory profile based on file name. bool GetSystemMemoryInfoForTesting(const std::string& file_name, - base::SystemMemoryInfoKB* mem_info); + base::SystemMemoryInfo* mem_info); } // namespace arc
diff --git a/clank b/clank index 1629330..da266c8 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 1629330ef8eb9d5030577c64fb7121ed7c12aa23 +Subproject commit da266c809240f37f6b564ad0034021f70c44ae52
diff --git a/components/BUILD.gn b/components/BUILD.gn index f598cd4d..10b3c34c 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -727,6 +727,7 @@ if (!is_android && !is_ios) { deps += [ "//components/access_code_cast/common:unit_tests", + "//components/headless/console_message_logger:unit_tests", "//components/headless/screen_info:unit_tests", "//components/live_caption:unit_tests", "//components/soda:unit_tests",
diff --git a/components/autofill/core/browser/autofill_ai_form_rationalization.cc b/components/autofill/core/browser/autofill_ai_form_rationalization.cc index 4534794f..cc72cf96 100644 --- a/components/autofill/core/browser/autofill_ai_form_rationalization.cc +++ b/components/autofill/core/browser/autofill_ai_form_rationalization.cc
@@ -17,21 +17,64 @@ // Checks whether `fields` matches `entity_of_interst`'s required fields, // returns an empty vector if not. +void EnforceRequiredFieldsConstraints( + std::vector<AutofillFieldWithAttributeType>& fields, + EntityType entity_of_interest) { + DenseSet<AttributeType> types = + DenseSet<AttributeType>(fields, &AutofillFieldWithAttributeType::type); + bool attributes_satisfy_required_fields = + std::ranges::any_of(entity_of_interest.required_fields(), + [&](DenseSet<AttributeType> constraint) { + return types.contains_all(constraint); + }); + if (!attributes_satisfy_required_fields) { + fields.clear(); + } +} + +// Looks for adjacent kVehicleLicensePlate fields. Since we don't have +// heuristics to split license plates reliably, we do not want to fill them. +void RemoveAdjacentLicensePlateNumbers( + std::vector<AutofillFieldWithAttributeType>& fields, + EntityType entity_of_interest) { + if (entity_of_interest != EntityType(EntityTypeName::kVehicle)) { + return; + } + + // The rank is the field's index in the form. Since `fields` only contains + // fields that belong to `entity_of_interest` and they appear in the same + // order as in the form, their std::distance() in `fields` is less than or + // equal to their rank_distance(). + auto rank_distance = [](auto begin, auto end) { + CHECK(begin != end); + ptrdiff_t lo = begin->field->rank(); + ptrdiff_t hi = std::prev(end)->field->rank(); + return hi - lo + 1; + }; + + // Erases all subranges where all fields `pred`, provided that these subranges + // have more than one field and the ranks of the fields are reasonably close + // (i.e., there aren't too many fields in between those). + auto pred = [](const AutofillFieldWithAttributeType& f) { + return f.type == AttributeType(AttributeTypeName::kVehiclePlateNumber); + }; + auto begin = fields.begin(); + auto end = fields.begin(); + while ((begin = std::find_if(end, fields.end(), pred)) != fields.end()) { + end = std::find_if_not(std::next(begin), fields.end(), pred); + if (std::distance(begin, end) > 1 && + std::distance(begin, end) * 3 / 2 >= rank_distance(begin, end)) { + end = fields.erase(begin, end); + } + } +} + std::vector<AutofillFieldWithAttributeType> RationalizeAttributeTypes( std::vector<AutofillFieldWithAttributeType> fields, EntityType entity_of_interest) { - bool attributes_satisfy_required_fields = [&]() { - DenseSet<AttributeType> types = - DenseSet<AttributeType>(fields, &AutofillFieldWithAttributeType::type); - return std::ranges::any_of(entity_of_interest.required_fields(), - [&](DenseSet<AttributeType> constraint) { - return types.contains_all(constraint); - }); - }(); - if (attributes_satisfy_required_fields) { - return fields; - } - return std::vector<AutofillFieldWithAttributeType>(); + EnforceRequiredFieldsConstraints(fields, entity_of_interest); + RemoveAdjacentLicensePlateNumbers(fields, entity_of_interest); + return fields; } } // namespace
diff --git a/components/autofill/core/browser/autofill_ai_form_rationalization_unittest.cc b/components/autofill/core/browser/autofill_ai_form_rationalization_unittest.cc index 9397cbbb..74782cb 100644 --- a/components/autofill/core/browser/autofill_ai_form_rationalization_unittest.cc +++ b/components/autofill/core/browser/autofill_ai_form_rationalization_unittest.cc
@@ -20,7 +20,20 @@ namespace { +using ::testing::AllOf; using ::testing::Field; +using ::testing::Truly; + +testing::Matcher<AutofillFieldWithAttributeType> FieldAndType( + const std::unique_ptr<AutofillField>& field, + AttributeType type) { + return AllOf( + Field(&AutofillFieldWithAttributeType::field, + Truly([ptr = field.get()](raw_ref<const AutofillField> field) { + return &*field == ptr; + })), + Field(&AutofillFieldWithAttributeType::type, type)); +} std::string GetEntityAttributesStringRepresentation( DenseSet<AttributeType> attributes) { @@ -38,6 +51,11 @@ return field; }); + size_t rank = 0; + for (auto& field : fields) { + field->set_rank(rank++); + } + base::flat_map<LocalFrameToken, size_t> frame_tokens; for (auto& field : fields) { field->set_section( @@ -159,6 +177,52 @@ EXPECT_TRUE(GetRelevantEntityTypesForFields(fields).empty()); } +// Tests that adjacent vehicle license plate numbers are erased. +TEST_F(AutofillAiFormRationalizationTest, ClearAdjacentVehiclePlateNumbers) { + std::vector<std::unique_ptr<AutofillField>> fields = CreateFields( + {// 1x: OK. + VEHICLE_LICENSE_PLATE, + // Separator. + VEHICLE_MAKE, + // 1x: OK. + VEHICLE_LICENSE_PLATE, + // Separator. + VEHICLE_MODEL, + // 2x: Rationalized. + VEHICLE_LICENSE_PLATE, VEHICLE_LICENSE_PLATE, + // Separator. + VEHICLE_VIN, + // 3x: Rationalized. + VEHICLE_LICENSE_PLATE, VEHICLE_LICENSE_PLATE, VEHICLE_LICENSE_PLATE, + // Separator. + NAME_FIRST, + // 2x: Rationalized. + VEHICLE_LICENSE_PLATE, UNKNOWN_TYPE, VEHICLE_LICENSE_PLATE, + // Separator. + NAME_MIDDLE, + // 2x: Rationalized, . + VEHICLE_LICENSE_PLATE, UNKNOWN_TYPE, UNKNOWN_TYPE, VEHICLE_LICENSE_PLATE, + // Separator. + NAME_LAST, + // 2x: Rationalized. + VEHICLE_LICENSE_PLATE, VEHICLE_LICENSE_PLATE}); + + using enum AttributeTypeName; + EXPECT_THAT( + RationalizeAndDetermineAttributeTypes( + fields, fields[0]->section(), EntityType(EntityTypeName::kVehicle)), + ElementsAre(FieldAndType(fields[0], AttributeType(kVehiclePlateNumber)), + FieldAndType(fields[1], AttributeType(kVehicleMake)), + FieldAndType(fields[2], AttributeType(kVehiclePlateNumber)), + FieldAndType(fields[3], AttributeType(kVehicleModel)), + FieldAndType(fields[6], AttributeType(kVehicleVin)), + FieldAndType(fields[10], AttributeType(kVehicleOwner)), + FieldAndType(fields[14], AttributeType(kVehicleOwner)), + FieldAndType(fields[15], AttributeType(kVehiclePlateNumber)), + FieldAndType(fields[18], AttributeType(kVehiclePlateNumber)), + FieldAndType(fields[19], AttributeType(kVehicleOwner)))); +} + } // namespace } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc index c17ed841..d6a763bc 100644 --- a/components/autofill/core/browser/autofill_field.cc +++ b/components/autofill/core/browser/autofill_field.cc
@@ -197,9 +197,8 @@ return true; } // Until we gain confidence in the precision of AutofillAI predictions, they - // should not overrule local heuristics. The AutofillAI prediction itself can - // always be retrieved via `GetAutofillAiServerTypePredictions`. The - // killswitch below is meant to experiment with removing this logic. + // should not overrule local heuristics. The kill switch below is meant to + // experiment with removing this logic. return base::Contains(kAutofillHeuristicsVsServerOverrides, std::make_pair(heuristic_type, server_type)) || (heuristic_type != UNKNOWN_TYPE &&
diff --git a/components/autofill/core/browser/data_model/addresses/address_unittest.cc b/components/autofill/core/browser/data_model/addresses/address_unittest.cc index fdb01dfc..6c10ad0 100644 --- a/components/autofill/core/browser/data_model/addresses/address_unittest.cc +++ b/components/autofill/core/browser/data_model/addresses/address_unittest.cc
@@ -34,65 +34,63 @@ // localized country name. TEST_F(AddressTest, GetCountry) { Address address(kLegacyHierarchyCountryCode); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u""); // Make sure that nothing breaks when the country code is missing. - std::u16string country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(std::u16string(), country); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u""); address.SetInfo(ADDRESS_HOME_COUNTRY, u"US", "en-US"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"United States", country); - country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US"); - EXPECT_EQ(u"United States", country); - country = address.GetInfo( - AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), "en-US"); - EXPECT_EQ(u"US", country); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"United States"); + EXPECT_EQ(address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US"), + u"United States"); + EXPECT_EQ(address.GetInfo( + AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), + "en-US"), + u"US"); address.SetRawInfo(ADDRESS_HOME_COUNTRY, u"CA"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"Canada", country); - country = address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US"); - EXPECT_EQ(u"Canada", country); - country = address.GetInfo( - AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), "en-US"); - EXPECT_EQ(u"CA", country); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"Canada"); + EXPECT_EQ(address.GetInfo(AutofillType(ADDRESS_HOME_COUNTRY), "en-US"), + u"Canada"); + EXPECT_EQ(address.GetInfo( + AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), + "en-US"), + u"CA"); } // Test that country data can be properly returned as either a country code or a // full country name that can even be localized. TEST_F(AddressTest, SetHtmlCountryCodeTypeWithFullCountryName) { Address address(kLegacyHierarchyCountryCode); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u""); AutofillType autofill_type(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true); // Test that the country value can be set and retrieved if it is not // a country code but a full country name. address.SetInfo(autofill_type, u"Germany", "en-US"); - std::u16string actual_country = - address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - std::u16string actual_country_code = address.GetInfo( - AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), "en-US"); - EXPECT_EQ(u"Germany", actual_country); - EXPECT_EQ(u"DE", actual_country_code); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"Germany"); + EXPECT_EQ(address.GetInfo( + AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), + "en-US"), + u"DE"); // Reset the country and verify that the reset works as expected. address.SetInfo(autofill_type, u"", "en-US"); - actual_country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - actual_country_code = address.GetInfo( - AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), "en-US"); - EXPECT_EQ(u"", actual_country); - EXPECT_EQ(u"", actual_country_code); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u""); + EXPECT_EQ(address.GetInfo( + AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), + "en-US"), + u""); // Test that the country value can be set and retrieved if it is not // a country code but a full country name with a non-standard locale. address.SetInfo(autofill_type, u"deutschland", "de"); - actual_country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - actual_country_code = address.GetInfo( - AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), "en-US"); - EXPECT_EQ(u"Germany", actual_country); - EXPECT_EQ(u"DE", actual_country_code); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"Germany"); + EXPECT_EQ(address.GetInfo( + AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), + "en-US"), + u"DE"); // Reset the country. address.SetInfo(autofill_type, u"", "en-US"); @@ -100,75 +98,66 @@ // Test that the country is still stored correctly with a supplied // country code. address.SetInfo(autofill_type, u"DE", "en-US"); - actual_country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - actual_country_code = address.GetInfo( - AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), "en-US"); - EXPECT_EQ(u"DE", actual_country_code); - EXPECT_EQ(u"Germany", actual_country); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"Germany"); + EXPECT_EQ(address.GetInfo( + AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true), + "en-US"), + u"DE"); } // Test that we properly detect country codes appropriate for each country. TEST_F(AddressTest, SetCountry) { Address address(kLegacyHierarchyCountryCode); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u""); // Test basic conversion. address.SetInfo(ADDRESS_HOME_COUNTRY, u"United States", "en-US"); - std::u16string country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"US", address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(u"United States", country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u"US"); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"United States"); // Test basic synonym detection. address.SetInfo(ADDRESS_HOME_COUNTRY, u"USA", "en-US"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"US", address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(u"United States", country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u"US"); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"United States"); // Test case-insensitivity. address.SetInfo(ADDRESS_HOME_COUNTRY, u"canADA", "en-US"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"CA", address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(u"Canada", country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u"CA"); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"Canada"); // Test country code detection. address.SetInfo(ADDRESS_HOME_COUNTRY, u"JP", "en-US"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"JP", address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(u"Japan", country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u"JP"); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"Japan"); // Test that we ignore unknown countries. address.SetInfo(ADDRESS_HOME_COUNTRY, u"Unknown", "en-US"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(std::u16string(), country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u""); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u""); // Test setting the country based on an HTML field type. AutofillType html_type_country_code = AutofillType(ADDRESS_HOME_COUNTRY, /*is_country_code=*/true); address.SetInfo(html_type_country_code, u"US", "en-US"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"US", address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(u"United States", country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u"US"); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"United States"); // Test case-insensitivity when setting the country based on an HTML field // type. address.SetInfo(html_type_country_code, u"cA", "en-US"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"CA", address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(u"Canada", country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u"CA"); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"Canada"); // Test setting the country based on invalid data with an HTML field type. address.SetInfo(html_type_country_code, u"unknown", "en-US"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(std::u16string(), country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u""); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u""); // Test incorrect use of country codes (when a country name is passed // as a country code). address.SetInfo(html_type_country_code, u"日本", "ja-JP"); - country = address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"); - EXPECT_EQ(u"JP", address.GetRawInfo(ADDRESS_HOME_COUNTRY)); - EXPECT_EQ(u"Japan", country); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u"JP"); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_COUNTRY, "en-US"), u"Japan"); } // Test setting and getting the new structured address tokens @@ -211,7 +200,7 @@ // Make sure that garbage values don't match when the country code is empty. address.SetRawInfo(ADDRESS_HOME_COUNTRY, std::u16string()); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_COUNTRY)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_COUNTRY), u""); FieldTypeSet matching_types; address.GetMatchingTypes(u"Garbage", "US", &matching_types); EXPECT_EQ(0U, matching_types.size()); @@ -224,16 +213,15 @@ EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty()); EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty()); EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE3).empty()); - EXPECT_EQ(std::u16string(), - address.GetInfo(ADDRESS_HOME_STREET_ADDRESS, "en-US")); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_STREET_ADDRESS, "en-US"), u""); // Address has only line 1. address.SetRawInfo(ADDRESS_HOME_LINE1, u"123 Example Ave."); EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty()); EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty()); EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE3).empty()); - EXPECT_EQ(u"123 Example Ave.", - address.GetInfo(ADDRESS_HOME_STREET_ADDRESS, "en-US")); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_STREET_ADDRESS, "en-US"), + u"123 Example Ave."); // Address has only line 2. address.SetRawInfo(ADDRESS_HOME_LINE1, std::u16string()); @@ -241,8 +229,8 @@ EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty()); EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty()); EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE3).empty()); - EXPECT_EQ(u"\nApt 42.", - address.GetInfo(ADDRESS_HOME_STREET_ADDRESS, "en-US")); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_STREET_ADDRESS, "en-US"), + u"\nApt 42."); // Address has lines 1 and 2. address.SetRawInfo(ADDRESS_HOME_LINE1, u"123 Example Ave."); @@ -250,34 +238,30 @@ EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty()); EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty()); EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE3).empty()); - EXPECT_EQ( - u"123 Example Ave.\n" - u"Apt. 42", - address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); - EXPECT_EQ( - u"123 Example Ave.\n" - u"Apt. 42", - address.GetInfo(ADDRESS_HOME_STREET_ADDRESS, "en-US")); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), + u"123 Example Ave.\n" + u"Apt. 42"); + EXPECT_EQ(address.GetInfo(ADDRESS_HOME_STREET_ADDRESS, "en-US"), + u"123 Example Ave.\n" + u"Apt. 42"); // A wild third line appears. address.SetRawInfo(ADDRESS_HOME_LINE3, u"Living room couch"); - EXPECT_EQ(u"Living room couch", address.GetRawInfo(ADDRESS_HOME_LINE3)); - EXPECT_EQ( - u"123 Example Ave.\n" - u"Apt. 42\n" - u"Living room couch", - address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE3), u"Living room couch"); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), + u"123 Example Ave.\n" + u"Apt. 42\n" + u"Living room couch"); // The second line vanishes. address.SetRawInfo(ADDRESS_HOME_LINE2, std::u16string()); EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE1).empty()); EXPECT_TRUE(address.GetRawInfo(ADDRESS_HOME_LINE2).empty()); EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE3).empty()); - EXPECT_EQ( - u"123 Example Ave.\n" - u"\n" - u"Living room couch", - address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), + u"123 Example Ave.\n" + u"\n" + u"Living room couch"); } // Verifies that overwriting an address with N lines with one that has fewer @@ -290,12 +274,12 @@ // Now clear out the second address line. address.SetRawInfo(ADDRESS_HOME_LINE2, std::u16string()); - EXPECT_EQ(u"123 Example Ave.", - address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), + u"123 Example Ave."); // Now clear out the first address line as well. address.SetRawInfo(ADDRESS_HOME_LINE1, std::u16string()); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), u""); } // Verifies that Address::SetRawInfo() is able to split address lines correctly. @@ -308,25 +292,25 @@ u"(The one with the blue door)"; Address address(kLegacyHierarchyCountryCode); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u""); address.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, long_street_address); - EXPECT_EQ(u"123 Example Ave.", address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(u"Apt. 42", address.GetRawInfo(ADDRESS_HOME_LINE2)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u"123 Example Ave."); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u"Apt. 42"); EXPECT_EQ(long_street_address, address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); // A short address should clear out unused address lines. address.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, short_street_address); - EXPECT_EQ(u"456 Nowhere Ln.", address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u"456 Nowhere Ln."); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u""); // An empty address should clear out all address lines. address.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, long_street_address); address.SetRawInfo(ADDRESS_HOME_STREET_ADDRESS, empty_street_address); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u""); } // Street addresses should be set properly. @@ -350,16 +334,16 @@ // Attempting to set a multi-line address should succeed. EXPECT_TRUE(address.SetInfo(ADDRESS_HOME_STREET_ADDRESS, multi_line_street_address, "en-US")); - EXPECT_EQ(u"789 Fancy Pkwy.", address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(u"Unit 3.14", address.GetRawInfo(ADDRESS_HOME_LINE2)); - EXPECT_EQ(u"Box 9", address.GetRawInfo(ADDRESS_HOME_LINE3)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u"789 Fancy Pkwy."); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u"Unit 3.14"); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE3), u"Box 9"); // Setting a single line street address should clear out subsequent lines. EXPECT_TRUE(address.SetInfo(ADDRESS_HOME_STREET_ADDRESS, single_line_street_address, "en-US")); EXPECT_EQ(single_line_street_address, address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE3)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE3), u""); // Attempting to set an empty address should also succeed, and clear out the // previously stored data. @@ -370,9 +354,9 @@ EXPECT_FALSE(address.GetRawInfo(ADDRESS_HOME_LINE3).empty()); EXPECT_TRUE(address.SetInfo(ADDRESS_HOME_STREET_ADDRESS, empty_street_address, "en-US")); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE3)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE3), u""); } // Verifies that Address::SetInfio() rejects setting data for @@ -393,9 +377,9 @@ u"\n" u"Address line 3", "en-US")); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), u""); } // Verifies that Address::SetInfio() rejects setting data for @@ -416,9 +400,9 @@ u"Address line 2" u"Address line 3", "en-US")); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), u""); } // Verifies that Address::SetInfio() rejects setting data for @@ -439,9 +423,9 @@ u"Address line 2" u"\n", "en-US")); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE1)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_LINE2)); - EXPECT_EQ(std::u16string(), address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS)); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE1), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_LINE2), u""); + EXPECT_EQ(address.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), u""); } // Verifies that the merging-related methods for structured addresses are @@ -761,8 +745,8 @@ EXPECT_EQ(address2.GetRawInfo(ADDRESS_HOME_STREET_LOCATION_AND_LOCALITY), u"12/110, Flat no. 504, Raja Apartments, Kondapur"); EXPECT_EQ(address2.GetRawInfo(ADDRESS_HOME_STREET_ADDRESS), - u"12/110, Flat no. 504, Raja Apartments, Kondapur\nOpp to Ayyappa " - u"Swamy temple"); + u"12/110, Flat no. 504, Raja Apartments, Kondapur\n" + u"Opp to Ayyappa Swamy temple"); } } // namespace
diff --git a/components/autofill/core/browser/foundations/browser_autofill_manager.cc b/components/autofill/core/browser/foundations/browser_autofill_manager.cc index 3017db4..32d3854 100644 --- a/components/autofill/core/browser/foundations/browser_autofill_manager.cc +++ b/components/autofill/core/browser/foundations/browser_autofill_manager.cc
@@ -3002,16 +3002,18 @@ } std::vector<Suggestion> BrowserAutofillManager::GetLoyaltyCardSuggestions( - const GURL& url, - const FormFieldData& trigger_field) { + const FormData& form, + const FormStructure* form_structure, + const FormFieldData& field, + const AutofillField* autofill_field) { ValuablesDataManager* valuables_manager = client().GetValuablesDataManager(); if (!valuables_manager) { return {}; } metrics_->loyalty_card_form_event_logger.OnDidPollSuggestions( - trigger_field.global_id()); - return GetSuggestionsForLoyaltyCards(*valuables_manager, url, - trigger_field.is_autofilled()); + field.global_id()); + return GetSuggestionsForLoyaltyCards(form, form_structure, field, + autofill_field, client()); } // TODO(crbug.com/40219607) Eliminate and replace with a listener? @@ -3235,8 +3237,8 @@ if (ValuablesDataManager* valuables_manager = client().GetValuablesDataManager()) { if (suggestions.empty()) { - suggestions = GetLoyaltyCardSuggestions( - client().GetLastCommittedPrimaryMainFrameURL(), field); + suggestions = GetLoyaltyCardSuggestions(form, form_structure, field, + autofill_field); } else { ExtendEmailSuggestionsWithLoyaltyCardSuggestions( *valuables_manager, @@ -3256,8 +3258,8 @@ // Only loyalty card numbers filling is supported. if (autofill_field->Type().GetLoyaltyCardType() == LOYALTY_MEMBERSHIP_ID) { - suggestions = GetLoyaltyCardSuggestions( - client().GetLastCommittedPrimaryMainFrameURL(), field); + suggestions = GetLoyaltyCardSuggestions(form, form_structure, field, + autofill_field); } } break;
diff --git a/components/autofill/core/browser/foundations/browser_autofill_manager.h b/components/autofill/core/browser/foundations/browser_autofill_manager.h index d95cddfc..b400dea 100644 --- a/components/autofill/core/browser/foundations/browser_autofill_manager.h +++ b/components/autofill/core/browser/foundations/browser_autofill_manager.h
@@ -419,10 +419,15 @@ autofill_metrics::SuggestionRankingContext& ranking_context); // Returns a list of suggestions from the stored loyalty cards for the given - // `url` and value of `trigger_field` + // last committed primary main frame URL obtained from `client()` and the + // value of the trigger `field`. + // TODO(crbug.com/409962888): Remove after new suggestion generation logic is + // launched. std::vector<Suggestion> GetLoyaltyCardSuggestions( - const GURL& url, - const FormFieldData& trigger_field); + const FormData& form, + const FormStructure* form_structure, + const FormFieldData& field, + const AutofillField* autofill_field); // Fills or previews `form` with the information in `credit_card`. // `autofill_field` is the field that triggered the filling operation.
diff --git a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_import_utils_unittest.cc b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_import_utils_unittest.cc index f65bf33..64896d7 100644 --- a/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_import_utils_unittest.cc +++ b/components/autofill/core/browser/integrators/autofill_ai/autofill_ai_import_utils_unittest.cc
@@ -11,6 +11,7 @@ #include "base/containers/to_vector.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/icu_test_util.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" @@ -281,6 +282,8 @@ TEST_F(AutofillAiImportUtilsTest, MaybeGetLocalizedDate) { using enum AttributeTypeName; + base::test::ScopedRestoreICUDefaultLocale restore_default_locale; + EntityInstance entity = test::GetPassportEntityInstance({.expiry_date = u"2025-12-30"}); {
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h index 94f07e8f..f5a0cc0 100644 --- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h +++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h
@@ -29,6 +29,8 @@ class CreditCardFormEventLogger : public FormEventLoggerBase { public: + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. enum class UnmaskAuthFlowEvent { // Authentication prompt is shown. kPromptShown = 0,
diff --git a/components/autofill/core/browser/metrics/payments/amount_extraction_metrics.h b/components/autofill/core/browser/metrics/payments/amount_extraction_metrics.h index c378e50..235c04e 100644 --- a/components/autofill/core/browser/metrics/payments/amount_extraction_metrics.h +++ b/components/autofill/core/browser/metrics/payments/amount_extraction_metrics.h
@@ -13,6 +13,8 @@ namespace autofill::autofill_metrics { +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class AmountExtractionComponentInstallationResult { // The component installation was successful. kSuccessful = 0, @@ -29,6 +31,8 @@ kMaxValue = kEmptyGenericDetails, }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class AmountExtractionResult { // The amount extraction was successful. kSuccessful = 0,
diff --git a/components/autofill/core/browser/metrics/payments/better_auth_metrics.h b/components/autofill/core/browser/metrics/payments/better_auth_metrics.h index faf7253..b9b60a5 100644 --- a/components/autofill/core/browser/metrics/payments/better_auth_metrics.h +++ b/components/autofill/core/browser/metrics/payments/better_auth_metrics.h
@@ -12,10 +12,10 @@ // Metric for tracking which authentication method was used for a user with // FIDO authentication enabled. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class CardUnmaskTypeDecisionMetric { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Only WebAuthn prompt was shown. kFidoOnly = 0, // CVC authentication was required in addition to WebAuthn. @@ -25,10 +25,10 @@ // Events related to user-perceived latency due to GetDetailsForGetRealPan // call. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class PreflightCallEvent { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Returned before card chosen. kPreflightCallReturnedBeforeCardChosen = 0, // Did not return before card was chosen. When opted-in, this means @@ -41,10 +41,10 @@ }; // Possible scenarios where a WebAuthn prompt may show. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class WebauthnFlowEvent { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // WebAuthn is immediately prompted for unmasking. kImmediateAuthentication = 0, // WebAuthn is prompted after a CVC check. @@ -58,10 +58,10 @@ }; // The parameters with which opt change was called. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class WebauthnOptInParameters { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Call made to fetch a challenge. kFetchingChallenge = 0, // Call made with signature of creation challenge. @@ -74,10 +74,10 @@ // On Desktop, this enum represents the reason that the FIDO opt-in dialog was // not offered to the user. On Android, it represents whether the checkbox // was shown to the user. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class WebauthnOptInPromoNotOfferedReason { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Default value, should never be used. kUnknown = 0, // Not offered because we authenticated a virtual card, and we do not offer @@ -99,10 +99,10 @@ }; // The user decision for the WebAuthn opt-in promo. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class WebauthnOptInPromoUserDecisionMetric { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // User accepted promo. kAccepted = 0, // User immediately declined promo. @@ -115,10 +115,10 @@ }; // The result of a WebAuthn user-verification prompt. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class WebauthnResultMetric { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // User-verification succeeded. kSuccess = 0, // Other checks failed (e.g. invalid domain, algorithm unsupported, etc.)
diff --git a/components/autofill/core/browser/metrics/payments/bnpl_metrics.h b/components/autofill/core/browser/metrics/payments/bnpl_metrics.h index f822a0c0..64d8770 100644 --- a/components/autofill/core/browser/metrics/payments/bnpl_metrics.h +++ b/components/autofill/core/browser/metrics/payments/bnpl_metrics.h
@@ -28,7 +28,12 @@ // available BNPL issuers. kCheckoutAmountNotSupported = 1, - kMaxValue = kCheckoutAmountNotSupported, + // Amount extraction timed out while running on the page and the checkout + // amount was not retrieved. This value is necessary to determine BNPL + // eligibility for the purchase. + kAmountExtractionTimeout = 2, + + kMaxValue = kAmountExtractionTimeout, }; // Enum to track the result of a corresponding BnplTosDialog that was shown. @@ -45,6 +50,7 @@ // LINT.ThenChange(/tools/metrics/histograms/metadata/autofill/enums.xml:BnplTosDialogResult) // The dialog close reason of select BNPL issuer dialog. +// // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. //
diff --git a/components/autofill/core/browser/metrics/payments/bnpl_metrics_unittest.cc b/components/autofill/core/browser/metrics/payments/bnpl_metrics_unittest.cc index bff68ba..3608c98 100644 --- a/components/autofill/core/browser/metrics/payments/bnpl_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/payments/bnpl_metrics_unittest.cc
@@ -115,6 +115,18 @@ BnplSuggestionNotShownReason::kCheckoutAmountNotSupported, 1); } +TEST_F(BnplMetricsTest, + LogBnplSuggestionNotShownReason_AmountExtractionTimeout) { + base::HistogramTester histogram_tester; + + LogBnplSuggestionNotShownReason( + BnplSuggestionNotShownReason::kAmountExtractionTimeout); + + histogram_tester.ExpectUniqueSample( + "Autofill.Bnpl.SuggestionNotShownReason", + BnplSuggestionNotShownReason::kAmountExtractionTimeout, 1); +} + TEST_F(BnplMetricsTest, LogSelectBnplIssuerDialogResult_Cancelled) { base::HistogramTester histogram_tester; LogSelectBnplIssuerDialogResult(
diff --git a/components/autofill/core/browser/metrics/payments/card_info_retrieval_enrolled_metrics.h b/components/autofill/core/browser/metrics/payments/card_info_retrieval_enrolled_metrics.h index 0f53f60..4e07859e 100644 --- a/components/autofill/core/browser/metrics/payments/card_info_retrieval_enrolled_metrics.h +++ b/components/autofill/core/browser/metrics/payments/card_info_retrieval_enrolled_metrics.h
@@ -8,6 +8,9 @@ namespace autofill::autofill_metrics { // Enum for different types of form events. Used for metrics logging. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class CardInfoRetrievalEnrolledLoggingEvent { // A dropdown with suggestions was shown. kSuggestionShown = 0, @@ -29,6 +32,7 @@ }; // Enum for different types of unmask results. Used for metrics logging. +// // These values are used in enums.xml; do not reorder or renumber entries! // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused.
diff --git a/components/autofill/core/browser/metrics/payments/card_metadata_metrics.h b/components/autofill/core/browser/metrics/payments/card_metadata_metrics.h index 984cc78..6b045ffc 100644 --- a/components/autofill/core/browser/metrics/payments/card_metadata_metrics.h +++ b/components/autofill/core/browser/metrics/payments/card_metadata_metrics.h
@@ -40,6 +40,9 @@ "MetadataNotShown"; // Enum for different types of form events. Used for metrics logging. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class CardMetadataLoggingEvent { // Suggestions were shown. kShown = 0, @@ -57,8 +60,10 @@ // LINT.IfChange(CardBenefitFormEvent) // All server cards with card benefit available Form Events are logged once per -// page load. These values are persisted to logs. Entries should not be -// renumbered and numeric values should never be reused. +// page load. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class CardBenefitFormEvent { // Suggestions containing cards with a benefit available were shown. kSuggestionWithBenefitShown = 0,
diff --git a/components/autofill/core/browser/metrics/payments/card_unmask_authentication_metrics.h b/components/autofill/core/browser/metrics/payments/card_unmask_authentication_metrics.h index 097d73f..e540cc2d 100644 --- a/components/autofill/core/browser/metrics/payments/card_unmask_authentication_metrics.h +++ b/components/autofill/core/browser/metrics/payments/card_unmask_authentication_metrics.h
@@ -12,10 +12,10 @@ // Card unmasking CVC authentication-related metrics. // CVC authentication-related events. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class CvcAuthEvent { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Unknown result. Should not happen. kUnknown = 0, // The CVC auth succeeded. @@ -52,10 +52,10 @@ // Card unmasking OTP authentication-related metrics. // OTP authentication-related events. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class OtpAuthEvent { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Unknown results. Should not happen. kUnknown = 0, // The OTP auth succeeded. @@ -84,12 +84,10 @@ // The result of how the OTP input dialog was closed. This dialog is used for // users to type in the received OTP value for card verification. +// // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class OtpInputDialogResult { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Unknown event, should not happen. kUnknown = 0, // The dialog was closed before the user entered any OTP and clicked the OK @@ -107,12 +105,10 @@ }; // The type of error message shown in the card unmask OTP input dialog. +// // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class OtpInputDialogError { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Unknown type, should not be used. kUnknown = 0, // The error indicating that the OTP is expired. @@ -177,10 +173,10 @@ // Card unmasking risk-based authentication-related metrics. // Risk-based authentication-related events. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class RiskBasedAuthEvent { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // No further authentication is required. kNoAuthenticationRequired = 0, // The user needs to complete further authentication to retrieve the card.
diff --git a/components/autofill/core/browser/metrics/payments/card_unmask_flow_metrics.h b/components/autofill/core/browser/metrics/payments/card_unmask_flow_metrics.h index 5f9d37c..f1651f1 100644 --- a/components/autofill/core/browser/metrics/payments/card_unmask_flow_metrics.h +++ b/components/autofill/core/browser/metrics/payments/card_unmask_flow_metrics.h
@@ -14,10 +14,10 @@ namespace autofill::autofill_metrics { // All possible results of the card unmask flow. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class ServerCardUnmaskResult { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Default value, should never be used in logging. kUnknown = 0, // Card unmask completed successfully because the data had already been @@ -55,10 +55,9 @@ kMaxValue = kMandatoryReauth, }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class ServerCardUnmaskFlowType { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Flow type was unknown at time of logging. kUnspecified = 0, // Only FIDO auth was offered.
diff --git a/components/autofill/core/browser/metrics/payments/credit_card_save_metrics.h b/components/autofill/core/browser/metrics/payments/credit_card_save_metrics.h index 5ed6f24..a21bf43 100644 --- a/components/autofill/core/browser/metrics/payments/credit_card_save_metrics.h +++ b/components/autofill/core/browser/metrics/payments/credit_card_save_metrics.h
@@ -14,10 +14,9 @@ // updated each time a new value is added. const int kNumCardUploadDecisionMetrics = 19; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum CardUploadDecision { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // All the required conditions were satisfied using either the form fields // or we prompted the user to fix one or more conditions in the card upload // prompt. @@ -78,10 +77,10 @@ // Log all the scenarios that contribute to the decision of whether card // upload is enabled or not. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class CardUploadEnabled { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - kSyncServiceNull = 0, kSyncServicePaused = 1, kSyncServiceMissingAutofillWalletDataActiveType = 2, @@ -104,10 +103,10 @@ // platforms. // Metrics to track event when the save card prompt is offered. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class SaveCardPromptOffer { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // The prompt is actually shown. kShown = 0, // The prompt is not shown because the prompt has been declined by the user @@ -122,10 +121,9 @@ kMaxValue = kCvcMissingForPotentialUpdate, }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class SaveCardPromptResult { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // The user explicitly accepted the prompt by clicking the ok button. kAccepted = 0, // The user explicitly cancelled the prompt by clicking the cancel button. @@ -143,10 +141,10 @@ }; // Represents requesting expiration date reason. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class SaveCardRequestExpirationDateReason { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Submitted card has empty month. kMonthMissingOnly = 0, // Submitted card has empty year. @@ -159,10 +157,10 @@ }; // Clank-specific metrics. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class SaveCreditCardPromptResult { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // User accepted save. kAccepted = 0, // User declined to save card.
diff --git a/components/autofill/core/browser/metrics/payments/filled_card_information_bubble_metrics.h b/components/autofill/core/browser/metrics/payments/filled_card_information_bubble_metrics.h index 0f5ebd7..e731662 100644 --- a/components/autofill/core/browser/metrics/payments/filled_card_information_bubble_metrics.h +++ b/components/autofill/core/browser/metrics/payments/filled_card_information_bubble_metrics.h
@@ -9,10 +9,10 @@ // Metrics to measure user interaction with the filled card information // bubble after it has appeared upon unmasking and filling a virtual card. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class FilledCardInformationBubbleResult { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // The reason why the bubble is closed is not clear. Possible reason is the // logging function is invoked before the closed reason is correctly set. kUnknown = 0, @@ -26,10 +26,10 @@ // Metric to measure which field in the filled card information bubble // was selected by the user. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class FilledCardInformationBubbleFieldClicked { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - kCardNumber = 0, kExpirationMonth = 1, kExpirationYear = 2,
diff --git a/components/autofill/core/browser/metrics/payments/iban_metrics.h b/components/autofill/core/browser/metrics/payments/iban_metrics.h index 740ebd3..3f4cdc83 100644 --- a/components/autofill/core/browser/metrics/payments/iban_metrics.h +++ b/components/autofill/core/browser/metrics/payments/iban_metrics.h
@@ -13,8 +13,10 @@ namespace autofill::autofill_metrics { // This includes all possible results. +// // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. +// // A java IntDef@ is generated from this. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill enum class SaveIbanPromptResult { @@ -35,8 +37,10 @@ }; // Metrics to track event when the IBAN prompt is offered. +// // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. +// // A java IntDef@ is generated from this. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill enum class SaveIbanPromptOffer { @@ -50,6 +54,7 @@ // Metrics to track events related to individual IBAN suggestions in the // IBANs suggestions popup. +// // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class IbanSuggestionsEvent { @@ -68,7 +73,6 @@ // suggestion for the same field, or if the user alternates between this IBAN // field and the other non-IBAN fields and then click on IBAN suggestion. kLocalIbanSuggestionSelectedOnce = 3, - // An individual server IBAN suggestion was selected. kServerIbanSuggestionSelected = 4, // An individual server IBAN suggestion was selected. Logged only once per @@ -80,6 +84,9 @@ }; // Metrics to track the site blocklist status when showing IBAN suggestions. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class IbanSuggestionBlockListStatus { // IBAN suggestions were allowed. kAllowed = 0, @@ -93,6 +100,7 @@ // Log all the scenarios that contribute to the decision of whether IBAN // upload is enabled or not. +// // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class IbanUploadEnabledStatus { @@ -108,6 +116,9 @@ // Metric to measure if an IBAN for which an upload action was taken (offered, // accepted, declined, ignored) is already stored as a local IBAN on the device // or if it's a new IBAN. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class UploadIbanOriginMetric { // IBAN upload action happened for a local IBAN already on the device. kLocalIban = 0, @@ -117,6 +128,9 @@ }; // Metric to track the metrics for an IBAN upload offer. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class UploadIbanActionMetric { kOffered = 0, kAccepted = 1,
diff --git a/components/autofill/core/browser/metrics/payments/manage_cards_prompt_metrics.h b/components/autofill/core/browser/metrics/payments/manage_cards_prompt_metrics.h index 381fbce..9be5b59 100644 --- a/components/autofill/core/browser/metrics/payments/manage_cards_prompt_metrics.h +++ b/components/autofill/core/browser/metrics/payments/manage_cards_prompt_metrics.h
@@ -9,10 +9,10 @@ // Metrics to measure user interaction with the Manage Cards view shown when the // user clicks on the save card icon after saving a local card. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class ManageCardsPromptMetric { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // The manage cards promo was shown. kManageCardsShown = 0, // The user clicked on [Done].
diff --git a/components/autofill/core/browser/metrics/payments/mandatory_reauth_metrics.h b/components/autofill/core/browser/metrics/payments/mandatory_reauth_metrics.h index 8354ce11..1164355 100644 --- a/components/autofill/core/browser/metrics/payments/mandatory_reauth_metrics.h +++ b/components/autofill/core/browser/metrics/payments/mandatory_reauth_metrics.h
@@ -78,6 +78,8 @@ kMaxValue = kLostFocus, }; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class MandatoryReauthOptInConfirmationBubbleMetric { // The user is shown the opt-in confirmation bubble. kShown = 0, @@ -87,8 +89,11 @@ }; // Enum class to include all the possible auth flows that can occur for -// mandatory reauth. These values are persisted to logs. -// Entries should not be renumbered and numeric values should never be reused. +// mandatory reauth. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill enum class MandatoryReauthAuthenticationFlowEvent { kUnknown = 0, @@ -105,6 +110,9 @@ // All the sources that can trigger the OptIn or OptOut flow for mandatory // reauth. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class MandatoryReauthOptInOrOutSource { kUnknown = 0, // The OptIn or OptOut process is triggered from the settings page.
diff --git a/components/autofill/core/browser/metrics/payments/virtual_card_enrollment_metrics.h b/components/autofill/core/browser/metrics/payments/virtual_card_enrollment_metrics.h index 60b94e7..9e760417 100644 --- a/components/autofill/core/browser/metrics/payments/virtual_card_enrollment_metrics.h +++ b/components/autofill/core/browser/metrics/payments/virtual_card_enrollment_metrics.h
@@ -18,10 +18,10 @@ // Metrics to record user interaction with the virtual card enrollment // bubble/infobar/bottomsheet. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class VirtualCardEnrollmentBubbleResult { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // The reason why the bubble is closed is not clear. Possible reason is the // logging function is invoked before the closed reason is correctly set. VIRTUAL_CARD_ENROLLMENT_BUBBLE_RESULT_UNKNOWN = 0, @@ -40,10 +40,10 @@ // Metrics to record the source that prompted the virtual card enrollment // bubble/infobar/bottomsheet. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class VirtualCardEnrollmentBubbleSource { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // The source of the bubble is unknown. VIRTUAL_CARD_ENROLLMENT_UNKNOWN_SOURCE = 0, // Bubble began after an unenrolled VCN-eligible card was saved via credit @@ -58,13 +58,14 @@ kMaxValue = VIRTUAL_CARD_ENROLLMENT_SETTINGS_PAGE_SOURCE, }; -// Used to determine the type of link that was clicked for logging purposes. A -// java IntDef@ is generated from this. +// Used to determine the type of link that was clicked for logging purposes. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// +// A java IntDef@ is generated from this. // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill enum class VirtualCardEnrollmentLinkType { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // User selected the Google Payments terms of service link. VIRTUAL_CARD_ENROLLMENT_GOOGLE_PAYMENTS_TOS_LINK = 0, // User selected the issuer terms of service link. @@ -85,10 +86,10 @@ bool previous_declined); // Metrics to measure strikes logged or cleared in strike database. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. enum class VirtualCardEnrollmentStrikeDatabaseEvent { - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // Strike logged as enrollment bubble/infobar/bottomsheet was not accepted. VIRTUAL_CARD_ENROLLMENT_STRIKE_DATABASE_STRIKE_LOGGED = 0, // All strikes cleared as user accepted virtual card enrollment.
diff --git a/components/autofill/core/browser/metrics/payments/virtual_card_standalone_cvc_suggestion_metrics.h b/components/autofill/core/browser/metrics/payments/virtual_card_standalone_cvc_suggestion_metrics.h index ce326379..1654db1 100644 --- a/components/autofill/core/browser/metrics/payments/virtual_card_standalone_cvc_suggestion_metrics.h +++ b/components/autofill/core/browser/metrics/payments/virtual_card_standalone_cvc_suggestion_metrics.h
@@ -11,6 +11,7 @@ // Enum for different types of virtual card standalone CVC suggestion form // events. Used for metrics logging. +// // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class VirtualCardStandaloneCvcSuggestionFormEvent {
diff --git a/components/autofill/core/browser/payments/amount_extraction_manager.cc b/components/autofill/core/browser/payments/amount_extraction_manager.cc index 4f5b265..ff3b54a 100644 --- a/components/autofill/core/browser/payments/amount_extraction_manager.cc +++ b/components/autofill/core/browser/payments/amount_extraction_manager.cc
@@ -5,6 +5,7 @@ #include "components/autofill/core/browser/payments/amount_extraction_manager.h" #include <memory> +#include <optional> #include <string> #include "base/check_deref.h" @@ -204,7 +205,10 @@ GetMainFrameDriver()->GetPageUkmSourceId()); has_logged_amount_extraction_result_ = true; } - // TODO(crbug.com/378517983): Add BNPL flow action logic here. + if (BnplManager* bnpl_manager = autofill_manager_->GetPaymentsBnplManager()) { + bnpl_manager->OnAmountExtractionReturned(/*extracted_amount=*/std::nullopt, + /*timeout_reached=*/true); + } if constexpr (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)) { if (base::FeatureList::IsEnabled(
diff --git a/components/autofill/core/browser/payments/amount_extraction_manager_unittest.cc b/components/autofill/core/browser/payments/amount_extraction_manager_unittest.cc index 7a824b6..6da60d20 100644 --- a/components/autofill/core/browser/payments/amount_extraction_manager_unittest.cc +++ b/components/autofill/core/browser/payments/amount_extraction_manager_unittest.cc
@@ -107,6 +107,11 @@ extracted_amount); } + void FakeAmountExtractionTimeout() { + amount_extraction_manager_->SetSearchRequestPendingForTesting(true); + amount_extraction_manager_->OnTimeoutReached(); + } + void SetUpCheckoutAmountExtractionCall(const std::string& extracted_amount, int latency_ms = 0) { auto extract_action = @@ -688,7 +693,7 @@ TEST_F(AmountExtractionManagerTest, OnCheckoutAmountReceived_EmptyResult_BnplManagerNotified) { EXPECT_CALL(*autofill_manager_->GetPaymentsBnplManager(), - OnAmountExtractionReturned(std::optional<uint64_t>())) + OnAmountExtractionReturned(std::optional<uint64_t>(), false)) .Times(1); FakeCheckoutAmountReceived(""); @@ -698,13 +703,24 @@ // extraction receives a result with correct format. TEST_F(AmountExtractionManagerTest, OnCheckoutAmountReceived_AmountInCorrectFormat_BnplManagerNotified) { - EXPECT_CALL( - *autofill_manager_->GetPaymentsBnplManager(), - OnAmountExtractionReturned(std::optional<uint64_t>(123'450'000ULL))) + EXPECT_CALL(*autofill_manager_->GetPaymentsBnplManager(), + OnAmountExtractionReturned( + std::optional<uint64_t>(123'450'000ULL), false)) .Times(1); FakeCheckoutAmountReceived("$ 123.45"); } + +// This test checks that the BNPL manager will be notified when the amount +// extraction times out. +TEST_F(AmountExtractionManagerTest, + OnCheckoutAmountReceived_AmountExtractionTimeout_BnplManagerNotified) { + EXPECT_CALL(*autofill_manager_->GetPaymentsBnplManager(), + OnAmountExtractionReturned(Eq(std::nullopt), true)) + .Times(1); + + FakeAmountExtractionTimeout(); +} #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || // BUILDFLAG(IS_CHROMEOS)
diff --git a/components/autofill/core/browser/payments/bnpl_manager.cc b/components/autofill/core/browser/payments/bnpl_manager.cc index ada0771b..6cc34bf 100644 --- a/components/autofill/core/browser/payments/bnpl_manager.cc +++ b/components/autofill/core/browser/payments/bnpl_manager.cc
@@ -141,7 +141,8 @@ } void BnplManager::OnAmountExtractionReturned( - const std::optional<uint64_t>& extracted_amount) { + const std::optional<uint64_t>& extracted_amount, + bool timeout_reached) { if (!update_suggestions_barrier_callback_.has_value()) { return; } @@ -150,6 +151,14 @@ update_suggestions_barrier_callback_->Run(extracted_amount); } + if (timeout_reached && !has_logged_bnpl_suggestion_not_shown_reason_) { + LogBnplSuggestionNotShownReason( + autofill_metrics::BnplSuggestionNotShownReason:: + kAmountExtractionTimeout); + has_logged_bnpl_suggestion_not_shown_reason_ = true; + return; + } + if (!extracted_amount && !has_logged_bnpl_suggestion_not_shown_reason_) { LogBnplSuggestionNotShownReason( autofill_metrics::BnplSuggestionNotShownReason::
diff --git a/components/autofill/core/browser/payments/bnpl_manager.h b/components/autofill/core/browser/payments/bnpl_manager.h index 4b524b4..3c3de13 100644 --- a/components/autofill/core/browser/payments/bnpl_manager.h +++ b/components/autofill/core/browser/payments/bnpl_manager.h
@@ -78,7 +78,8 @@ // result. This must be called after `NotifyOfSuggestionGeneration()`, so // that the manager can update suggestions for buy-now-pay-later. virtual void OnAmountExtractionReturned( - const std::optional<uint64_t>& extracted_amount); + const std::optional<uint64_t>& extracted_amount, + bool timeout_reached = false); // Determines if autofill BNPL is supported. // Returns true if:
diff --git a/components/autofill/core/browser/payments/bnpl_manager_unittest.cc b/components/autofill/core/browser/payments/bnpl_manager_unittest.cc index 2c72d53..ddd5935b 100644 --- a/components/autofill/core/browser/payments/bnpl_manager_unittest.cc +++ b/components/autofill/core/browser/payments/bnpl_manager_unittest.cc
@@ -259,7 +259,8 @@ void TriggerBnplUpdateSuggestionsFlow( bool expect_suggestions_are_updated, - std::optional<uint64_t> extracted_amount) { + std::optional<uint64_t> extracted_amount, + bool timeout_reached = false) { std::vector<Suggestion> suggestions = { Suggestion(SuggestionType::kCreditCardEntry), Suggestion(SuggestionType::kManageCreditCard)}; @@ -269,7 +270,8 @@ bnpl_manager_->NotifyOfSuggestionGeneration( AutofillSuggestionTriggerSource::kUnspecified); - bnpl_manager_->OnAmountExtractionReturned(extracted_amount); + bnpl_manager_->OnAmountExtractionReturned(extracted_amount, + timeout_reached); bnpl_manager_->OnSuggestionsShown(suggestions, callback.Get()); } @@ -1485,6 +1487,38 @@ 1); } +// Tests that BnplSuggestionNotShownReason will be logged once if the amount +// extraction engine times out. +TEST_F( + BnplManagerTest, + AddBnplSuggestion_AmountExtractionTimeout_BnplSuggestionNotShownReasonLogged) { + base::HistogramTester histogram_tester; + + // Add one linked issuer to payments data manager. + SetUpLinkedBnplIssuer( + /*price_lower_bound_in_micros=*/40, + /*price_higher_bound_in_micros=*/1000, IssuerId::kBnplAffirm, + /*instrument_id=*/1234); + + TriggerBnplUpdateSuggestionsFlow(/*expect_suggestions_are_updated=*/false, + /*extracted_amount=*/std::nullopt, + /*timeout_reached=*/true); + histogram_tester.ExpectUniqueSample( + "Autofill.Bnpl.SuggestionNotShownReason", + autofill_metrics::BnplSuggestionNotShownReason::kAmountExtractionTimeout, + 1); + + // Test that BnplSuggestionNotShownReason is logged only once even if BNPL + // flow is triggered and not shown more than once on the same page. + TriggerBnplUpdateSuggestionsFlow(/*expect_suggestions_are_updated=*/false, + /*extracted_amount=*/std::nullopt, + /*timeout_reached=*/true); + histogram_tester.ExpectUniqueSample( + "Autofill.Bnpl.SuggestionNotShownReason", + autofill_metrics::BnplSuggestionNotShownReason::kAmountExtractionTimeout, + 1); +} + // Tests that BnplSuggestionNotShownReason will not be logged if BNPL feature // flag is disabled and the extracted amount is not supported by available // BNPL issuers.
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.cc b/components/autofill/core/browser/payments/credit_card_save_manager.cc index 2813981..fe6f944e 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager.cc +++ b/components/autofill/core/browser/payments/credit_card_save_manager.cc
@@ -510,9 +510,9 @@ ClientBehaviorConstants::kShowAccountEmailInLegalMessage); #endif - // Check if the CVC is being uploaded and CVC storage is enabled on the - // client. - if (!upload_request_.card.cvc().empty() && + // Check if we should request the CVC-inclusive legal message and if the user + // has enabled CVC storage. + if (ShouldRequestCvcInclusiveLegalMessage() && payments_data_manager().IsPaymentCvcStorageEnabled()) { upload_request_.client_behavior_signals.push_back( ClientBehaviorConstants::kOfferingToSaveCvc); @@ -664,7 +664,7 @@ } CreditCardSaveStrikeDatabase* -CreditCardSaveManager::GetCreditCardSaveStrikeDatabase() { +CreditCardSaveManager::GetCreditCardSaveStrikeDatabase() const { if (credit_card_save_strike_database_.get() == nullptr) { credit_card_save_strike_database_ = std::make_unique<CreditCardSaveStrikeDatabase>( @@ -1399,6 +1399,14 @@ client_->GetAppLocale()); } +// On iOS, the user can add a CVC on the save card details page. This CVC is +// then passed here and set on the card to be uploaded. For other platforms, +// this is a no-op as `user_provided_card_details.cvc` will be empty. +#if BUILDFLAG(IS_IOS) + if (!user_provided_card_details.cvc.empty()) { + upload_request_.card.set_cvc(user_provided_card_details.cvc); + } +#endif // Virtual card enrollment manager may not be set of CWV clients. if (auto* virtual_card_enrollment_manager = client_->GetPaymentsAutofillClient()->GetVirtualCardEnrollmentManager()) { @@ -1605,6 +1613,36 @@ } } +bool CreditCardSaveManager::ShouldRequestCvcInclusiveLegalMessage() const { + // If the main CVC storage feature is disabled, we should never request the + // CVC-inclusive legal message. + if (!base::FeatureList::IsEnabled( + features::kAutofillEnableCvcStorageAndFilling)) { + return false; + } +#if BUILDFLAG(IS_IOS) + // On iOS, we request the CVC-inclusive message if a CVC is already present, + // or if the save prompt will be the infobar and detail page flow, where a CVC + // can be added by the user. + if (!upload_request_.card.cvc().empty()) { + return true; + } + + int num_strikes = GetCreditCardSaveStrikeDatabase()->GetStrikes( + base::UTF16ToUTF8(upload_request_.card.LastFourDigits())); + bool will_show_bottom_sheet = + num_strikes == 0 && !should_request_name_from_user_ && + !should_request_expiration_date_from_user_ && + base::FeatureList::IsEnabled(features::kAutofillSaveCardBottomSheet); + + return !will_show_bottom_sheet; +#else + // For other platforms, we only request the CVC-inclusive message if a CVC + // was present in the form. + return !upload_request_.card.cvc().empty(); +#endif // BUILDFLAG(IS_IOS) +} + PaymentsDataManager& CreditCardSaveManager::payments_data_manager() { return const_cast<PaymentsDataManager&>( const_cast<const CreditCardSaveManager*>(this)->payments_data_manager());
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager.h b/components/autofill/core/browser/payments/credit_card_save_manager.h index 79a9ff7f..8d91896b 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager.h +++ b/components/autofill/core/browser/payments/credit_card_save_manager.h
@@ -202,7 +202,7 @@ get_details_for_enrollment_response_details); // Returns the CreditCardSaveStrikeDatabase for |client_|. - CreditCardSaveStrikeDatabase* GetCreditCardSaveStrikeDatabase(); + CreditCardSaveStrikeDatabase* GetCreditCardSaveStrikeDatabase() const; // Returns the CvcStorageStrikeDatabase for `client_`. CvcStorageStrikeDatabase* GetCvcStorageStrikeDatabase(); @@ -351,6 +351,10 @@ observer_for_testing_ = observer; } + // Returns true if the CVC-inclusive legal message should be requested from + // the server. + bool ShouldRequestCvcInclusiveLegalMessage() const; + PaymentsDataManager& payments_data_manager(); const PaymentsDataManager& payments_data_manager() const; @@ -404,7 +408,7 @@ // The parsed lines from the legal message returned from GetUploadDetails. LegalMessageLines legal_message_lines_; - std::unique_ptr<CreditCardSaveStrikeDatabase> + mutable std::unique_ptr<CreditCardSaveStrikeDatabase> credit_card_save_strike_database_; std::unique_ptr<CvcStorageStrikeDatabase> cvc_storage_strike_database_;
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc index 7f52889..4d6fe13 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -2082,6 +2082,7 @@ testing::Contains(ClientBehaviorConstants::kOfferingToSaveCvc)); } +#if !BUILDFLAG(IS_IOS) TEST_F(CreditCardSaveManagerTest, AttemptToOfferCardUploadSave_DoNotSendSaveCvcSignalIfCvcEmpty) { // Set up the flags to enable the Tos for Save Card CVC UI. @@ -2113,6 +2114,7 @@ testing::Not(testing::Contains( ClientBehaviorConstants::kOfferingToSaveCvc))); } +#endif // !BUILDFLAG(IS_IOS) TEST_F( CreditCardSaveManagerTest, @@ -2301,6 +2303,118 @@ } #endif +#if BUILDFLAG(IS_IOS) +// Tests that for the iOS bottom sheet, the kOfferingToSaveCvc signal is NOT +// sent if the CVC is missing from the form. +TEST_F(CreditCardSaveManagerTest, + IOS_BottomSheet_DoNotSendSaveCvcSignalIfCvcEmpty) { + // Enable the bottom sheet feature. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kAutofillEnableCvcStorageAndFilling, + features::kAutofillSaveCardBottomSheet}, + /*disabled_features=*/{}); + prefs::SetPaymentCvcStorage(autofill_client_.GetPrefs(), true); + + // Set up form data with no strikes and no fix flows required. + FormData credit_card_form = CreateTestCreditCardFormData(); + FormsSeen({credit_card_form}); + test_api(credit_card_form).field(0).set_value(u"Jane Doe"); + test_api(credit_card_form).field(1).set_value(u"4111111111111111"); + test_api(credit_card_form) + .field(2) + .set_value(ASCIIToUTF16(test::NextMonth())); + test_api(credit_card_form).field(3).set_value(ASCIIToUTF16(test::NextYear())); + test_api(credit_card_form).field(4).set_value(u""); // CVC is empty. + + FormSubmitted(credit_card_form); + + // For the bottom sheet, the signal should NOT be sent if the CVC is empty. + EXPECT_THAT(payments_network_interface().client_behavior_signals_in_request(), + testing::Not(testing::Contains( + ClientBehaviorConstants::kOfferingToSaveCvc))); +} + +// Tests that for the iOS infobar/detail page flow (triggered by disabling +// the bottom sheet feature), the kOfferingToSaveCvc signal IS sent, even if +// the CVC is missing from the form. +TEST_F(CreditCardSaveManagerTest, + IOS_Infobar_SendSaveCvcSignalIfCvcEmpty_FeatureDisabled) { + // Disable the bottom sheet feature to force the infobar flow. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kAutofillEnableCvcStorageAndFilling}, + /*disabled_features=*/{features::kAutofillSaveCardBottomSheet}); + prefs::SetPaymentCvcStorage(autofill_client_.GetPrefs(), true); + + // Set up form data. + FormData credit_card_form = CreateTestCreditCardFormData(); + FormsSeen({credit_card_form}); + test_api(credit_card_form).field(1).set_value(u"4111111111111111"); + test_api(credit_card_form).field(4).set_value(u""); // CVC is empty. + + FormSubmitted(credit_card_form); + + // For the infobar flow, the signal SHOULD be sent even if the CVC is empty. + EXPECT_THAT(payments_network_interface().client_behavior_signals_in_request(), + testing::Contains(ClientBehaviorConstants::kOfferingToSaveCvc)); +} + +// Tests that for the iOS infobar/detail page flow (triggered by strikes), +// the kOfferingToSaveCvc signal IS sent, even if the CVC is missing. +TEST_F(CreditCardSaveManagerTest, + IOS_Infobar_SendSaveCvcSignalIfCvcEmpty_WithStrikes) { + // Enable the bottom sheet feature. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kAutofillEnableCvcStorageAndFilling, + features::kAutofillSaveCardBottomSheet}, + /*disabled_features=*/{}); + prefs::SetPaymentCvcStorage(autofill_client_.GetPrefs(), true); + + // Add one strike to the card to force the infobar flow. + TestCreditCardSaveStrikeDatabase(&strike_database()).AddStrike("1111"); + + // Set up form data. + FormData credit_card_form = CreateTestCreditCardFormData(); + FormsSeen({credit_card_form}); + test_api(credit_card_form).field(1).set_value(u"4111111111111111"); + test_api(credit_card_form).field(4).set_value(u""); // CVC is empty. + + FormSubmitted(credit_card_form); + + // For the infobar flow (due to strikes), the signal SHOULD be sent. + EXPECT_THAT(payments_network_interface().client_behavior_signals_in_request(), + testing::Contains(ClientBehaviorConstants::kOfferingToSaveCvc)); +} + +// Tests that for the iOS infobar/detail page flow (triggered by a name fix +// flow), the kOfferingToSaveCvc signal IS sent, even if the CVC is missing. +TEST_F(CreditCardSaveManagerTest, + IOS_Infobar_SendSaveCvcSignalIfCvcEmpty_NameFixFlow) { + // Enable the bottom sheet feature. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{features::kAutofillEnableCvcStorageAndFilling, + features::kAutofillSaveCardBottomSheet}, + /*disabled_features=*/{}); + prefs::SetPaymentCvcStorage(autofill_client_.GetPrefs(), true); + + // Set up form data to trigger a name fix flow (name is missing). + FormData credit_card_form = CreateTestCreditCardFormData(); + FormsSeen({credit_card_form}); + test_api(credit_card_form).field(0).set_value(u""); + test_api(credit_card_form).field(1).set_value(u"4111111111111111"); + test_api(credit_card_form).field(4).set_value(u""); // CVC is empty. + + FormSubmitted(credit_card_form); + + // For the infobar flow (due to fix flow), the signal SHOULD be sent. + EXPECT_THAT(payments_network_interface().client_behavior_signals_in_request(), + testing::Contains(ClientBehaviorConstants::kOfferingToSaveCvc)); +} +#endif // BUILDFLAG(IS_IOS) + // TODO(crbug.com/40710040): Create an equivalent test for iOS, or skip // permanently if the test doesn't apply to iOS flow. #if !BUILDFLAG(IS_IOS)
diff --git a/components/autofill/core/browser/payments/test/mock_bnpl_manager.h b/components/autofill/core/browser/payments/test/mock_bnpl_manager.h index fe543b57..63870cb 100644 --- a/components/autofill/core/browser/payments/test/mock_bnpl_manager.h +++ b/components/autofill/core/browser/payments/test/mock_bnpl_manager.h
@@ -32,7 +32,7 @@ MOCK_METHOD(void, OnAmountExtractionReturned, - (const std::optional<uint64_t>&), + (const std::optional<uint64_t>&, bool), (override)); MOCK_METHOD(void,
diff --git a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.cc b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.cc index 92b82c7..2862a00 100644 --- a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.cc +++ b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.cc
@@ -135,18 +135,26 @@ } // namespace std::vector<Suggestion> GetSuggestionsForLoyaltyCards( - const ValuablesDataManager& valuables_manager, - const GURL& url, - bool trigger_field_is_autofilled) { + const FormData& form, + const FormStructure* form_structure, + const FormFieldData& field, + const AutofillField* autofill_field, + const AutofillClient& client) { + const ValuablesDataManager* valuables_manager = + client.GetValuablesDataManager(); + if (!valuables_manager) { + return {}; + } std::vector<LoyaltyCard> all_loyalty_cards = - valuables_manager.GetLoyaltyCardsToSuggest(); + valuables_manager->GetLoyaltyCardsToSuggest(); if (all_loyalty_cards.empty()) { return {}; } auto non_affiliated_cards = std::ranges::stable_partition( all_loyalty_cards, [&](const LoyaltyCard& card) { - return card.GetAffiliationCategory(url) == + return card.GetAffiliationCategory( + client.GetLastCommittedPrimaryMainFrameURL()) == LoyaltyCard::AffiliationCategory::kAffiliated; }); // SAFETY: Bounds information contained in vector iterators. @@ -162,17 +170,17 @@ #endif if (generate_flat_suggestions) { - std::vector<Suggestion> suggestions = - CreateSuggestionsFromLoyaltyCards(all_loyalty_cards, valuables_manager); + std::vector<Suggestion> suggestions = CreateSuggestionsFromLoyaltyCards( + all_loyalty_cards, *valuables_manager); std::ranges::move( - GetLoyaltyCardsFooterSuggestions(trigger_field_is_autofilled), + GetLoyaltyCardsFooterSuggestions(field.is_autofilled()), std::back_inserter(suggestions)); return suggestions; } // Build suggestions with 'all loyalty cards' submenu. std::vector<Suggestion> suggestions = - CreateSuggestionsFromLoyaltyCards(affiliated_cards, valuables_manager); + CreateSuggestionsFromLoyaltyCards(affiliated_cards, *valuables_manager); suggestions.emplace_back(SuggestionType::kSeparator); // Build 'all loyalty cards' submenu. @@ -185,9 +193,9 @@ submenu_suggestion.icon = Suggestion::Icon::kGoogleWalletMonochrome; #endif submenu_suggestion.children = CreateSuggestionsFromLoyaltyCards( - valuables_manager.GetLoyaltyCardsToSuggest(), valuables_manager); + valuables_manager->GetLoyaltyCardsToSuggest(), *valuables_manager); std::ranges::move( - GetLoyaltyCardsFooterSuggestions(trigger_field_is_autofilled), + GetLoyaltyCardsFooterSuggestions(field.is_autofilled()), std::back_inserter(suggestions)); return suggestions; }
diff --git a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.h b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.h index a70a860..76b64a2 100644 --- a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.h +++ b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.h
@@ -7,6 +7,7 @@ #include <vector> +#include "components/autofill/core/browser/foundations/autofill_client.h" #include "components/autofill/core/browser/suggestions/suggestion.h" class GURL; @@ -15,12 +16,17 @@ class ValuablesDataManager; -// Generates loyalty card suggestions for a given `url`. Loyalty cards are -// extracted from the `valuables_manager`. +// Generates loyalty card suggestions for the value of trigger `field` and the +// last committed primary main frame URL obtained from `client`. Loyalty cards +// are extracted from the `ValuablesDataManager` using `client`. +// TODO(crbug.com/409962888): Remove after new suggestion generation logic is +// launched. std::vector<Suggestion> GetSuggestionsForLoyaltyCards( - const ValuablesDataManager& valuables_manager, - const GURL& url, - bool trigger_field_is_autofilled); + const FormData& form, + const FormStructure* form_structure, + const FormFieldData& field, + const AutofillField* autofill_field, + const AutofillClient& client); // Extends `email_suggestions` with loyalty cards suggestions. void ExtendEmailSuggestionsWithLoyaltyCardSuggestions(
diff --git a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator_unittest.cc b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator_unittest.cc index 0dd2a8a..5bba354 100644 --- a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator_unittest.cc +++ b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator_unittest.cc
@@ -7,12 +7,17 @@ #include <variant> #include <vector> +#include "base/test/task_environment.h" #include "components/autofill/core/browser/data_manager/valuables/test_valuables_data_manager.h" #include "components/autofill/core/browser/data_manager/valuables/valuables_data_manager_test_api.h" #include "components/autofill/core/browser/data_model/valuables/loyalty_card.h" +#include "components/autofill/core/browser/form_structure.h" +#include "components/autofill/core/browser/form_structure_test_api.h" +#include "components/autofill/core/browser/foundations/test_autofill_client.h" #include "components/autofill/core/browser/suggestions/suggestion.h" #include "components/autofill/core/browser/suggestions/suggestion_test_helpers.h" #include "components/autofill/core/browser/suggestions/suggestion_type.h" +#include "components/autofill/core/common/autofill_test_utils.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/strings/grit/components_strings.h" #include "testing/gmock/include/gmock/gmock.h" @@ -69,15 +74,14 @@ Suggestion::Icon::kSettings); } +class MockAutofillClient : public TestAutofillClient { + public: + MOCK_METHOD(ValuablesDataManager*, GetValuablesDataManager, (), (override)); +}; + class ValuableSuggestionGeneratorTest : public testing::Test { public: - ValuableSuggestionGeneratorTest() = default; - - TestValuablesDataManager& valuables_data_manager() { - return valuables_data_manager_; - } - - void SetUp() override { + ValuableSuggestionGeneratorTest() { const std::vector<LoyaltyCard> loyalty_cards = { LoyaltyCard( /*loyalty_card_id=*/ValuableId("loyalty_card_id_1"), @@ -102,21 +106,39 @@ {GURL("https://domain2.example"), GURL("https://common-domain.example")})}; test_api(valuables_data_manager()).SetLoyaltyCards(loyalty_cards); + ON_CALL(autofill_client_, GetValuablesDataManager()) + .WillByDefault(testing::Return(&valuables_data_manager_)); + form_structure_ = + std::make_unique<FormStructure>(test::CreateTestLoyaltyCardFormData()); + test_api(*form_structure_).SetFieldTypes({LOYALTY_MEMBERSHIP_ID}); } + TestAutofillClient& test_autofill_client() { return autofill_client_; } + AutofillClient& client() { return autofill_client_; } + FormStructure& form() { return *form_structure_; } + AutofillField& field() { return *form_structure_->fields().front(); } gfx::Image CustomIconForTest() { return gfx::test::CreateImage(32, 32); } + TestValuablesDataManager& valuables_data_manager() { + return valuables_data_manager_; + } + private: TestValuablesDataManager valuables_data_manager_; + base::test::SingleThreadTaskEnvironment task_environment_; + test::AutofillUnitTestEnvironment autofill_test_environment_; + MockAutofillClient autofill_client_; + std::unique_ptr<FormStructure> form_structure_; }; TEST_F(ValuableSuggestionGeneratorTest, GetSuggestionsForLoyaltyCards_NoMatchingDomain) { + test_autofill_client().set_last_committed_primary_main_frame_url( + GURL("https://not-existing-domain.example/test")); + field().set_is_autofilled(false); EXPECT_THAT( - GetSuggestionsForLoyaltyCards( - valuables_data_manager(), - GURL("https://not-existing-domain.example/test"), - /*trigger_field_is_autofilled=*/false), + GetSuggestionsForLoyaltyCards(form().ToFormData(), &form(), field(), + &field(), client()), testing::ElementsAre( EqualsLoyaltyCardSuggestion(u"987654321987654321", u"CVS Pharmacy", "loyalty_card_id_1"), @@ -130,11 +152,12 @@ TEST_F(ValuableSuggestionGeneratorTest, GetSuggestionsForLoyaltyCards_NoMatchingDomainAndFieldAutofilled) { + test_autofill_client().set_last_committed_primary_main_frame_url( + GURL("https://not-existing-domain.example/test")); + field().set_is_autofilled(true); EXPECT_THAT( - GetSuggestionsForLoyaltyCards( - valuables_data_manager(), - GURL("https://not-existing-domain.example/test"), - /*trigger_field_is_autofilled=*/true), + GetSuggestionsForLoyaltyCards(form().ToFormData(), &form(), field(), + &field(), client()), testing::ElementsAre( EqualsLoyaltyCardSuggestion(u"987654321987654321", u"CVS Pharmacy", "loyalty_card_id_1"), @@ -149,10 +172,12 @@ TEST_F(ValuableSuggestionGeneratorTest, GetSuggestionsForLoyaltyCards_WithMatchingDomain) { + test_autofill_client().set_last_committed_primary_main_frame_url( + GURL("https://domain2.example/test")); + field().set_is_autofilled(false); std::vector<Suggestion> suggestions_with_matching_domain = - GetSuggestionsForLoyaltyCards(valuables_data_manager(), - GURL("https://domain2.example/test"), - /*trigger_field_is_autofilled=*/false); + GetSuggestionsForLoyaltyCards(form().ToFormData(), &form(), field(), + &field(), client()); EXPECT_THAT( suggestions_with_matching_domain, testing::ElementsAre( @@ -195,10 +220,12 @@ TEST_F(ValuableSuggestionGeneratorTest, GetSuggestionsForLoyaltyCards_WithMatchingDomainAndFieldAutofilled) { + test_autofill_client().set_last_committed_primary_main_frame_url( + GURL("https://domain2.example/test")); + field().set_is_autofilled(true); std::vector<Suggestion> suggestions_with_matching_domain = - GetSuggestionsForLoyaltyCards(valuables_data_manager(), - GURL("https://domain2.example/test"), - /*trigger_field_is_autofilled=*/true); + GetSuggestionsForLoyaltyCards(form().ToFormData(), &form(), field(), + &field(), client()); EXPECT_THAT( suggestions_with_matching_domain, testing::ElementsAre( @@ -242,10 +269,12 @@ TEST_F(ValuableSuggestionGeneratorTest, GetSuggestionsForLoyaltyCards_AllMatchDomain) { + test_autofill_client().set_last_committed_primary_main_frame_url( + GURL("https://common-domain.example/test")); + field().set_is_autofilled(false); EXPECT_THAT( - GetSuggestionsForLoyaltyCards(valuables_data_manager(), - GURL("https://common-domain.example/test"), - /*trigger_field_is_autofilled=*/false), + GetSuggestionsForLoyaltyCards(form().ToFormData(), &form(), field(), + &field(), client()), testing::ElementsAre( EqualsLoyaltyCardSuggestion(u"987654321987654321", u"CVS Pharmacy", "loyalty_card_id_1"), @@ -273,10 +302,12 @@ valuables_data_manager().CacheImage(program_logo, fake_image); test_api(valuables_data_manager()).NotifyObservers(); - std::vector<Suggestion> suggestions = GetSuggestionsForLoyaltyCards( - valuables_data_manager(), GURL("https://common-domain.example/test"), - /*trigger_field_is_autofilled=*/false); + test_autofill_client().set_last_committed_primary_main_frame_url( + GURL("https://common-domain.example/test")); + field().set_is_autofilled(false); + std::vector<Suggestion> suggestions = GetSuggestionsForLoyaltyCards( + form().ToFormData(), &form(), field(), &field(), client()); EXPECT_THAT(suggestions, testing::ElementsAre(EqualsLoyaltyCardSuggestion( u"987654321987654321", u"CVS Pharmacy", @@ -506,12 +537,13 @@ raw_ptr<const base::Feature> kIphFeature = &feature_engagement::kIPHAutofillEnableLoyaltyCardsFeature; - EXPECT_THAT( - GetSuggestionsForLoyaltyCards(valuables_data_manager(), - GURL("https://common-domain.example/test"), - /*trigger_field_is_autofilled=*/false), - testing::ElementsAre(HasIphFeature(kIphFeature), HasNoIphFeature(), - HasNoIphFeature())); + test_autofill_client().set_last_committed_primary_main_frame_url( + GURL("https://common-domain.example/test")); + field().set_is_autofilled(false); + EXPECT_THAT(GetSuggestionsForLoyaltyCards(form().ToFormData(), &form(), + field(), &field(), client()), + testing::ElementsAre(HasIphFeature(kIphFeature), + HasNoIphFeature(), HasNoIphFeature())); } } // namespace } // namespace autofill
diff --git a/components/autofill/core/browser/ui/addresses/autofill_address_util_unittest.cc b/components/autofill/core/browser/ui/addresses/autofill_address_util_unittest.cc index 034430a..9dbc464 100644 --- a/components/autofill/core/browser/ui/addresses/autofill_address_util_unittest.cc +++ b/components/autofill/core/browser/ui/addresses/autofill_address_util_unittest.cc
@@ -63,8 +63,7 @@ i18n::TypeForField(::i18n::addressinput::AddressField::POSTAL_CODE)); } -// TODO(crbug.com/433964259): Test is flaky. -TEST_F(AddressFormattingTest, FLAKY_GetEnvelopeStyleAddressSanity) { +TEST_F(AddressFormattingTest, GetEnvelopeStyleAddressSanity) { AutofillProfile profile = test::GetFullProfile(); std::u16string address = GetEnvelopeStyleAddress(profile, GetLocale(), /*include_recipient=*/true,
diff --git a/components/autofill/core/common/autofill_prefs.cc b/components/autofill/core/common/autofill_prefs.cc index 0842c53..6c8f935 100644 --- a/components/autofill/core/common/autofill_prefs.cc +++ b/components/autofill/core/common/autofill_prefs.cc
@@ -92,6 +92,10 @@ registry->RegisterStringPref(kAutofillAblationSeedPref, ""); registry->RegisterBooleanPref(kAutofillRanQuasiDuplicateExtraDeduplication, false); +#if BUILDFLAG(IS_ANDROID) + registry->RegisterBooleanPref(kFacilitatedPaymentsPixAccountLinkingDeprecated, + /*default_value=*/true); +#endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID) registry->RegisterBooleanPref(kAutofillUsingVirtualViewStructure, false); @@ -103,9 +107,11 @@ registry->RegisterBooleanPref( kFacilitatedPaymentsPix, /*default_value=*/true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); - registry->RegisterBooleanPref( - kFacilitatedPaymentsPixAccountLinking, /*default_value=*/true, - user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); + // The Pix account linking pref is a profile pref but not synced across + // devices since users may prefer to have a different value for it on + // different devices. + registry->RegisterBooleanPref(kFacilitatedPaymentsPixAccountLinking, + /*default_value=*/true); registry->RegisterBooleanPref( kFacilitatedPaymentsA2AEnabled, /*default_value=*/true, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); @@ -145,6 +151,10 @@ pref_service->ClearPref(kAutofillRanQuasiDuplicateExtraDeduplication); // Added 03/2025 pref_service->ClearPref(kAutofillEnabledDeprecated); +#if BUILDFLAG(IS_ANDROID) + // Added 08/2025 + pref_service->ClearPref(kFacilitatedPaymentsPixAccountLinkingDeprecated); +#endif // BUILDFLAG(IS_ANDROID) } void RegisterLocalStatePrefs(PrefRegistrySimple* registry) {
diff --git a/components/autofill/core/common/autofill_prefs.h b/components/autofill/core/common/autofill_prefs.h index e8c2011..da0d68b 100644 --- a/components/autofill/core/common/autofill_prefs.h +++ b/components/autofill/core/common/autofill_prefs.h
@@ -149,6 +149,8 @@ "facilitated_payments.ewallet"; inline constexpr char kFacilitatedPaymentsPix[] = "facilitated_payments.pix"; inline constexpr char kFacilitatedPaymentsPixAccountLinking[] = + "facilitated_payments.pix_account_linking_enabled"; +inline constexpr char kFacilitatedPaymentsPixAccountLinkingDeprecated[] = "facilitated_payments.pix_account_linking"; inline constexpr char kFacilitatedPaymentsA2AEnabled[] = "facilitated_payments.a2a_enabled";
diff --git a/components/bookmarks/browser/titled_url_index_unittest.cc b/components/bookmarks/browser/titled_url_index_unittest.cc index ec3c201d..e74a1bdb 100644 --- a/components/bookmarks/browser/titled_url_index_unittest.cc +++ b/components/bookmarks/browser/titled_url_index_unittest.cc
@@ -11,7 +11,7 @@ #include <utility> #include <vector> -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -155,11 +155,11 @@ } void ExpectMatches(const std::string& query, - const char** expected_titles, - size_t expected_count) { + base::span<const char*> expected_titles) { std::vector<std::string> title_vector; - for (size_t i = 0; i < expected_count; ++i) - title_vector.push_back(UNSAFE_TODO(expected_titles[i])); + for (const char* expected_title : expected_titles) { + title_vector.push_back(expected_title); + } ExpectMatches(query, query_parser::MatchingAlgorithm::DEFAULT, title_vector); }
diff --git a/components/browser_ui/site_settings/android/java/res/xml/grouped_websites_preferences.xml b/components/browser_ui/site_settings/android/java/res/xml/grouped_websites_preferences.xml index a9f020f..07decdd 100644 --- a/components/browser_ui/site_settings/android/java/res/xml/grouped_websites_preferences.xml +++ b/components/browser_ui/site_settings/android/java/res/xml/grouped_websites_preferences.xml
@@ -25,11 +25,6 @@ <PreferenceCategory android:key="related_sites" android:title="@string/website_settings_related_sites" /> - <org.chromium.components.browser_ui.settings.ButtonPreference - android:key="related_sites_delete_data_button" - android:title="@string/site_settings_rws_delete_button_label" - app:allowDividerAbove="false" - app:allowDividerBelow="true" /> <PreferenceCategory android:key="sites_in_group" /> <org.chromium.components.browser_ui.settings.ButtonPreference
diff --git a/components/browser_ui/site_settings/android/java/res/xml/single_website_preferences.xml b/components/browser_ui/site_settings/android/java/res/xml/single_website_preferences.xml index c4c0e35..68a151d 100644 --- a/components/browser_ui/site_settings/android/java/res/xml/single_website_preferences.xml +++ b/components/browser_ui/site_settings/android/java/res/xml/single_website_preferences.xml
@@ -47,11 +47,6 @@ <PreferenceCategory android:key="related_sites_header" android:title="@string/website_settings_related_sites" /> - <org.chromium.components.browser_ui.settings.ButtonPreference - android:key="related_sites_delete_data_button" - android:title="@string/site_settings_rws_delete_button_label" - app:allowDividerAbove="false" - app:allowDividerBelow="true" /> <PreferenceCategory android:key="site_permissions" android:title="@string/website_settings_permissions_category" />
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java index 554129a..1938fa2d 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java
@@ -501,7 +501,6 @@ getSiteSettingsDelegate(), entry, getActivity().getLayoutInflater(), - /* showRwsMembershipLabels= */ true, /* isClickable= */ true); preference.setOnDeleteCallback( () -> {
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java index cf9791b..e427af8 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java
@@ -25,14 +25,11 @@ import org.chromium.build.annotations.Initializer; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.components.browser_ui.settings.ButtonPreference; import org.chromium.components.browser_ui.settings.CustomDividerFragment; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.settings.TextMessagePreference; import org.chromium.components.browsing_data.DeleteBrowsingDataAction; -import org.chromium.ui.text.ChromeClickableSpan; -import org.chromium.ui.text.SpanApplier; /** Shows the permissions and other settings for a group of websites. */ @NullMarked @@ -47,12 +44,9 @@ public static final String PREF_CLEAR_DATA = "clear_data"; public static final String PREF_USAGE = "site_usage"; public static final String PREF_RELATED_SITES = "related_sites"; - public static final String PREF_RELATED_SITES_CLEAR_DATA = "related_sites_delete_data_button"; public static final String PREF_SITES_IN_GROUP = "sites_in_group"; public static final String PREF_RESET_GROUP = "reset_group_button"; - public static final int RWS_ROW_ID = View.generateViewId(); - private static @Nullable GroupedWebsitesSettings sPausedInstance; private WebsiteGroup mSiteGroup; @@ -255,52 +249,6 @@ preference.setOnPreferenceClickListener(this); } - @VisibleForTesting - public void resetRwsData() { - if (getActivity() == null) return; - RwsCookieInfo rwsInfo = mSiteGroup.getRwsInfo(); - assumeNonNull(rwsInfo); - WebsiteGroup group = new WebsiteGroup(rwsInfo.getOwner(), rwsInfo.getMembers()); - SiteDataCleaner.clearData(getSiteSettingsDelegate(), group, mDataClearedCallback); - RecordHistogram.recordEnumeratedHistogram( - "Privacy.DeleteBrowsingData.Action", - DeleteBrowsingDataAction.RWS_DELETE_ALL_DATA, - DeleteBrowsingDataAction.MAX_VALUE); - } - - public boolean onDeleteRwsDataPreferenceClick(Preference preference) { - View dialogView = - getActivity().getLayoutInflater().inflate(R.layout.clear_reset_dialog, null); - TextView mainMessage = dialogView.findViewById(R.id.main_message); - RwsCookieInfo rwsInfo = mSiteGroup.getRwsInfo(); - assumeNonNull(rwsInfo); - mainMessage.setText( - getString( - R.string.site_settings_delete_rws_storage_confirmation_android, - rwsInfo.getOwner())); - TextView signedOutText = dialogView.findViewById(R.id.signed_out_text); - signedOutText.setText(R.string.site_settings_delete_rws_storage_sign_out); - TextView offlineText = dialogView.findViewById(R.id.offline_text); - offlineText.setText(R.string.webstorage_delete_data_dialog_offline_message); - mConfirmationDialog = - new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog) - .setView(dialogView) - .setTitle(R.string.site_settings_delete_rws_storage_dialog_title) - .setPositiveButton( - R.string.storage_delete_dialog_clear_storage_option, - (dialog, which) -> { - resetRwsData(); - }) - .setNegativeButton( - R.string.cancel, (dialog, which) -> mConfirmationDialog = null) - .show(); - return true; - } - - private boolean isCurrentSite(WebsiteEntry entry) { - return mSiteGroup.getDomainAndRegistry().equals(entry.getDomainAndRegistry()); - } - private void setUpRelatedSitesPreferences() { PreferenceCategory relatedSitesSection = findPreference(PREF_RELATED_SITES); TextMessagePreference relatedSitesText = new TextMessagePreference(getContext(), null); @@ -310,12 +258,6 @@ && rwsInfo != null; relatedSitesText.setVisible(shouldRelatedSitesPrefBeVisible); relatedSitesSection.setVisible(shouldRelatedSitesPrefBeVisible); - ButtonPreference relatedSitesClearDataButton = - findPreference(PREF_RELATED_SITES_CLEAR_DATA); - relatedSitesClearDataButton - .setVisible( - shouldRelatedSitesPrefBeVisible - && getSiteSettingsDelegate().shouldShowPrivacySandboxRwsUi()); if (shouldRelatedSitesPrefBeVisible) { assumeNonNull(rwsInfo); @@ -335,63 +277,15 @@ } }); - if (getSiteSettingsDelegate().shouldShowPrivacySandboxRwsUi()) { - relatedSitesText.setSummary( - SpanApplier.applySpans( - getContext() - .getString(R.string.site_settings_rws_description_android), - new SpanApplier.SpanInfo( - "<link>", - "</link>", - new ChromeClickableSpan( - getContext(), - (unused) -> { - getSiteSettingsDelegate() - .launchUrlInCustomTab( - getActivity(), - WebsiteSettingsConstants - .RWS_LEARN_MORE_URL); - })))); - relatedSitesSection.addPreference(relatedSitesText); - for (WebsiteEntry entry : rwsInfo.getMembersGroupedByDomain()) { - WebsiteRowPreference preference = - new WebsiteRowPreference( - relatedSitesSection.getContext(), - getSiteSettingsDelegate(), - entry, - getActivity().getLayoutInflater(), - /* showRwsMembershipLabels= */ false, - /* isClickable= */ false); - preference.setViewId(RWS_ROW_ID); - // If the row is for the current site, deleting the data will bounce back to the - // previous page to refresh - preference.setOnDeleteCallback( - isCurrentSite(entry) - // If deleting data for the current site, pop back to refresh - ? mDataClearedCallback - : () -> { - relatedSitesSection.removePreference(preference); - }); - relatedSitesSection.addPreference(preference); - } - relatedSitesClearDataButton.setOnPreferenceClickListener( - new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - return onDeleteRwsDataPreferenceClick(preference); - } - }); - } else { - relatedSitesText.setTitle( - getContext() - .getResources() - .getQuantityString( - R.plurals.allsites_rws_summary, - rwsInfo.getMembersCount(), - Integer.toString(rwsInfo.getMembersCount()), - rwsInfo.getOwner())); - relatedSitesSection.addPreference(relatedSitesText); - } + relatedSitesText.setTitle( + getContext() + .getResources() + .getQuantityString( + R.plurals.allsites_rws_summary, + rwsInfo.getMembersCount(), + Integer.toString(rwsInfo.getMembersCount()), + rwsInfo.getOwner())); + relatedSitesSection.addPreference(relatedSitesText); } } @@ -405,7 +299,6 @@ getSiteSettingsDelegate(), site, getActivity().getLayoutInflater(), - /* showRwsMembershipLabels= */ false, /* isClickable= */ true); preference.setOnDeleteCallback( () -> {
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java index a25be50..6902299 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -35,7 +35,6 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.build.annotations.RequiresNonNull; -import org.chromium.components.browser_ui.settings.ButtonPreference; import org.chromium.components.browser_ui.settings.ChromeImageViewPreference; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.CustomDividerFragment; @@ -51,8 +50,6 @@ import org.chromium.components.permissions.PermissionsAndroidFeatureList; import org.chromium.components.permissions.PermissionsAndroidFeatureMap; import org.chromium.content_public.browser.BrowserContextHandle; -import org.chromium.ui.text.ChromeClickableSpan; -import org.chromium.ui.text.SpanApplier; import java.util.ArrayList; import java.util.Collection; @@ -102,7 +99,6 @@ public static final String PREF_USAGE = "site_usage"; public static final String PREF_RELATED_SITES_HEADER = "related_sites_header"; public static final String PREF_RELATED_SITES = "related_sites"; - public static final String PREF_RELATED_SITES_CLEAR_DATA = "related_sites_delete_data_button"; public static final String PREF_PERMISSIONS_HEADER = "site_permissions"; public static final String PREF_OS_PERMISSIONS_WARNING = "os_permissions_warning"; public static final String PREF_OS_PERMISSIONS_WARNING_EXTRA = "os_permissions_warning_extra"; @@ -117,7 +113,6 @@ public static final String PREF_RESET_SITE = "reset_site_button"; public static final int REQUEST_CODE_NOTIFICATION_CHANNEL_SETTINGS = 1; - public static final int RWS_ROW_ID = View.generateViewId(); private static boolean arrayContains(int[] array, int element) { for (int e : array) { @@ -216,7 +211,6 @@ PREF_USAGE, PREF_RELATED_SITES_HEADER, PREF_RELATED_SITES, - PREF_RELATED_SITES_CLEAR_DATA, PREF_PERMISSIONS_HEADER, PREF_CLEAR_DATA, }; @@ -289,15 +283,6 @@ popBackIfNoSettings(); }; - private final Runnable mRwsDataClearedCallback = - () -> { - Activity activity = getActivity(); - if (activity == null || activity.isFinishing()) { - return; - } - popBackToPreviousPage(); - }; - /** * Creates a Bundle with the correct arguments for opening this fragment for the website with * the given url. @@ -1025,52 +1010,6 @@ } } - public void resetRwsData() { - if (getActivity() == null) return; - RwsCookieInfo rwsInfo = assumeNonNull(mSite).getRwsCookieInfo(); - assumeNonNull(rwsInfo); - WebsiteGroup group = new WebsiteGroup(rwsInfo.getOwner(), rwsInfo.getMembers()); - SiteDataCleaner.clearData(getSiteSettingsDelegate(), group, mRwsDataClearedCallback); - RecordHistogram.recordEnumeratedHistogram( - "Privacy.DeleteBrowsingData.Action", - DeleteBrowsingDataAction.RWS_DELETE_ALL_DATA, - DeleteBrowsingDataAction.MAX_VALUE); - } - - public boolean onDeleteRwsDataPreferenceClick(Preference preference) { - View dialogView = - getActivity().getLayoutInflater().inflate(R.layout.clear_reset_dialog, null); - TextView mainMessage = dialogView.findViewById(R.id.main_message); - RwsCookieInfo rwsInfo = assumeNonNull(mSite).getRwsCookieInfo(); - assumeNonNull(rwsInfo); - mainMessage.setText( - getString( - R.string.site_settings_delete_rws_storage_confirmation_android, - rwsInfo.getOwner())); - TextView signedOutText = dialogView.findViewById(R.id.signed_out_text); - signedOutText.setText(R.string.site_settings_delete_rws_storage_sign_out); - TextView offlineText = dialogView.findViewById(R.id.offline_text); - offlineText.setText(R.string.webstorage_delete_data_dialog_offline_message); - mConfirmationDialog = - new AlertDialog.Builder(getContext(), R.style.ThemeOverlay_BrowserUI_AlertDialog) - .setView(dialogView) - .setTitle(R.string.site_settings_delete_rws_storage_dialog_title) - .setPositiveButton( - R.string.storage_delete_dialog_clear_storage_option, - (dialog, which) -> { - resetRwsData(); - }) - .setNegativeButton( - R.string.cancel, (dialog, which) -> mConfirmationDialog = null) - .show(); - return true; - } - - private boolean isCurrentSite(WebsiteEntry entry) { - assumeNonNull(mSite); - return mSite.getDomainAndRegistry().equals(entry.getDomainAndRegistry()); - } - private void setUpRelatedSitesPreferences() { PreferenceCategory relatedSitesSection = findPreference(PREF_RELATED_SITES_HEADER); TextMessagePreference relatedSitesText = new TextMessagePreference(getContext(), null); @@ -1080,12 +1019,6 @@ && rwsInfo != null; relatedSitesSection.setVisible(shouldRelatedSitesPrefBeVisible); relatedSitesText.setVisible(shouldRelatedSitesPrefBeVisible); - ButtonPreference relatedSitesClearDataButton = - findPreference(PREF_RELATED_SITES_CLEAR_DATA); - relatedSitesClearDataButton - .setVisible( - shouldRelatedSitesPrefBeVisible - && getSiteSettingsDelegate().shouldShowPrivacySandboxRwsUi()); if (shouldRelatedSitesPrefBeVisible) { assumeNonNull(rwsInfo); @@ -1100,61 +1033,15 @@ } }); - if (getSiteSettingsDelegate().shouldShowPrivacySandboxRwsUi()) { - relatedSitesText.setSummary( - SpanApplier.applySpans( - getContext() - .getString(R.string.site_settings_rws_description_android), - new SpanApplier.SpanInfo( - "<link>", - "</link>", - new ChromeClickableSpan( - getContext(), - (unused) -> { - getSiteSettingsDelegate() - .launchUrlInCustomTab( - getActivity(), - WebsiteSettingsConstants - .RWS_LEARN_MORE_URL); - })))); - relatedSitesSection.addPreference(relatedSitesText); - for (WebsiteEntry entry : rwsInfo.getMembersGroupedByDomain()) { - WebsiteRowPreference preference = - new WebsiteRowPreference( - relatedSitesSection.getContext(), - getSiteSettingsDelegate(), - entry, - getActivity().getLayoutInflater(), - /* showRwsMembershipLabels= */ false, - /* isClickable= */ false); - preference.setViewId(RWS_ROW_ID); - preference.setOnDeleteCallback( - isCurrentSite(entry) - // If deleting data for the current site, pop back to refresh - ? mRwsDataClearedCallback - : () -> { - relatedSitesSection.removePreference(preference); - }); - relatedSitesSection.addPreference(preference); - } - relatedSitesClearDataButton.setOnPreferenceClickListener( - new Preference.OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - return onDeleteRwsDataPreferenceClick(preference); - } - }); - } else { - relatedSitesText.setTitle( - getContext() - .getResources() - .getQuantityString( - R.plurals.allsites_rws_summary, - rwsInfo.getMembersCount(), - Integer.toString(rwsInfo.getMembersCount()), - rwsInfo.getOwner())); - relatedSitesSection.addPreference(relatedSitesText); - } + relatedSitesText.setTitle( + getContext() + .getResources() + .getQuantityString( + R.plurals.allsites_rws_summary, + rwsInfo.getMembersCount(), + Integer.toString(rwsInfo.getMembersCount()), + rwsInfo.getOwner())); + relatedSitesSection.addPreference(relatedSitesText); } }
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java index ffd431b..71e6f79 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java
@@ -231,11 +231,6 @@ void getBrowsingDataModel(Callback<BrowsingDataModel> callback); /** - * @return whether the Privacy Sandbox Rws UI should be shown in the Settings. - */ - boolean shouldShowPrivacySandboxRwsUi(); - - /** * @return whether the Safety Hub is enabled. */ boolean isSafetyHubEnabled();
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java index 355cb51..943735a 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
@@ -721,12 +721,7 @@ Set<String> originToWebsite = new HashSet<>(); Map<String, List<Website>> rwsOwnerToMember = new HashMap<>(); for (Website site : mSites.values()) { - // Use the origin when RWS UI feature is enabled to include - // subdomain variations in the members - String rwsMemberHostname = - mSiteSettingsDelegate.shouldShowPrivacySandboxRwsUi() - ? site.getAddress().getOrigin() - : site.getAddress().getDomainAndRegistry(); + String rwsMemberHostname = site.getAddress().getDomainAndRegistry(); String rwsOwnerHostname = mSiteSettingsDelegate.getRelatedWebsiteSetOwner( site.getAddress().getOrigin());
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java index 12cbf25..d390e15 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java
@@ -44,8 +44,6 @@ private Runnable mOnDeleteCallback; - private final boolean mShowRwsMembershipLabels; - private final boolean mIsClickable; WebsiteRowPreference( @@ -53,7 +51,6 @@ SiteSettingsDelegate siteSettingsDelegate, WebsiteEntry siteEntry, LayoutInflater layoutInflater, - boolean showRwsMembershipLabels, boolean isClickable) { super(context); mSiteSettingsDelegate = siteSettingsDelegate; @@ -61,7 +58,6 @@ mLayoutInflater = layoutInflater; // Initialize with an empty callback. mOnDeleteCallback = CallbackUtils.emptyRunnable(); - mShowRwsMembershipLabels = showRwsMembershipLabels; mIsClickable = isClickable; // To make sure the layout stays stable throughout, we assign a @@ -209,19 +205,6 @@ } } - if (mSiteSettingsDelegate.shouldShowPrivacySandboxRwsUi() - && mSiteEntry.isPartOfRws() - && mShowRwsMembershipLabels) { - String rwsSummary = getContext().getString(R.string.all_sites_rws_label); - if (summary.isEmpty()) { - summary = rwsSummary; - } else { - summary = - getContext() - .getString(R.string.summary_with_one_bullet, summary, rwsSummary); - } - } - if (!summary.isEmpty()) { setSummary(summary); }
diff --git a/components/browser_ui/site_settings/android/javatests/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreferenceTest.java b/components/browser_ui/site_settings/android/javatests/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreferenceTest.java index efcc574..3c6b375 100644 --- a/components/browser_ui/site_settings/android/javatests/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreferenceTest.java +++ b/components/browser_ui/site_settings/android/javatests/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreferenceTest.java
@@ -4,7 +4,6 @@ package org.chromium.components.browser_ui.site_settings; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.verify; import android.app.Activity; @@ -18,7 +17,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.chromium.base.library_loader.LibraryLoader; @@ -29,7 +27,6 @@ import org.chromium.components.browser_ui.settings.PlaceholderSettingsForTest; import java.util.Arrays; -import java.util.List; /** Tests for WebsiteRowPreference. */ @RunWith(BaseJUnit4ClassRunner.class) @@ -60,7 +57,6 @@ WebsitePreferenceBridgeJni.setInstanceForTesting(mBridgeMock); mSettingsRule.launchPreference(PlaceholderSettingsForTest.class); mActivity = mSettingsRule.getActivity(); - Mockito.doReturn(true).when(mDelegate).shouldShowPrivacySandboxRwsUi(); } @Test @@ -73,7 +69,6 @@ mDelegate, website, LayoutInflater.from(mActivity), - /* showRwsMembershipLabels= */ false, /* isClickable= */ true); mPreference.setOnDeleteCallback(mOnDeleteCallback); mPreference.resetEntry(); @@ -95,31 +90,9 @@ mDelegate, group, LayoutInflater.from(mActivity), - /* showRwsMembershipLabels= */ false, /* isClickable= */ true); mPreference.setOnDeleteCallback(mOnDeleteCallback); mPreference.resetEntry(); verify(mOnDeleteCallback).run(); } - - @Test - @SmallTest - public void showRwsMembershipLabels() { - Website origin1 = new Website(WebsiteAddress.create("https://one.test.com"), null); - Website origin2 = new Website(WebsiteAddress.create("https://two.test.com"), null); - RwsCookieInfo rwsInfo = - new RwsCookieInfo( - origin1.getAddress().getDomainAndRegistry(), List.of(origin1, origin2)); - origin1.setRwsCookieInfo(rwsInfo); - origin1.setCookiesInfo(new CookiesInfo(5)); - mPreference = - new WebsiteRowPreference( - mActivity, - mDelegate, - origin1, - LayoutInflater.from(mActivity), - /* showRwsMembershipLabels= */ true, - /* isClickable= */ true); - assertEquals("5 cookies • Has related sites", mPreference.getSummary().toString()); - } }
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd index 700b8cf..b22504c35 100644 --- a/components/browser_ui/strings/android/browser_ui_strings.grd +++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -1031,7 +1031,6 @@ </message> <!-- Text Size Contrast --> - <!-- TODO(crbug.com/40064612): Add descriptions and make the strings translateable. --> <message name="IDS_TEXT_SIZE_CONTRAST_TITLE" translateable="false" desc="Title of the preference that allows the user to update the accessibility smart zoom feature that applies to the web contents."> Text size contrast </message>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java index dfe0d2e..f3f669cb 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java
@@ -784,6 +784,17 @@ } /** + * @return Is any normal content is available in the adapter + */ + public boolean isNormalContentAvailable() { + for (ItemGroup group : mGroups) { + if (group.priority() != GroupPriority.NORMAL_CONTENT) continue; + if (group.size() > 0) return true; + } + return false; + } + + /** * Utility method to traverse all groups and find the {@link ItemGroup} for the given position. */ protected Pair<ItemGroup, Integer> getGroupAt(int position) {
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java index babe8f8c..4ba05e2 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java
@@ -568,7 +568,7 @@ return true; } - if (mToolbar.isSearching()) { + if (mToolbar.isSearching() && !mToolbar.isLargeScreenWithKeyboard()) { mToolbar.hideSearchView(); return true; }
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListToolbar.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListToolbar.java index 98a2002..fb32590 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListToolbar.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListToolbar.java
@@ -172,6 +172,7 @@ // current view type that SelectableListToolbar is showing private int mViewType; + private boolean mIsLargeScreenWithKeyboard; /** Constructor for inflating from XML. */ public SelectableListToolbar(Context context, AttributeSet attrs) { @@ -287,6 +288,7 @@ mShowInfoIcon = true; mShowInfoStringId = R.string.show_info; mHideInfoStringId = R.string.hide_info; + mIsLargeScreenWithKeyboard = false; if (showBackInNormalView) { mShowBackInNormalView = true; @@ -446,7 +448,7 @@ * search view will be hidden. */ public void onSearchNavigationBack() { - if (!mHasSearchView || !isSearching()) return; + if (!mHasSearchView || !isSearching() || mIsLargeScreenWithKeyboard) return; hideSearchView(); } @@ -473,6 +475,7 @@ case NavigationButton.NONE: break; case NavigationButton.SEARCH_BACK: + if (mIsLargeScreenWithKeyboard) break; // Create a LayerDrawable to hold the search box icon highlight background as well // as the navigation icon drawable. var navigationBackgroundDrawable = @@ -582,7 +585,7 @@ if (mIsDestroyed) return; if (mSelectionDelegate != null) mSelectionDelegate.clearSelection(); - if (isSearching()) hideSearchView(); + if (isSearching() && !mIsLargeScreenWithKeyboard) hideSearchView(); } /** @@ -839,4 +842,12 @@ public @ViewType int getCurrentViewType() { return mViewType; } + + public void setIsLargeScreenWithKeyboard(boolean isLargeScreenWithKeyboard) { + mIsLargeScreenWithKeyboard = isLargeScreenWithKeyboard; + } + + public boolean isLargeScreenWithKeyboard() { + return mIsLargeScreenWithKeyboard; + } }
diff --git a/components/compose_strings.grdp b/components/compose_strings.grdp index fe78370..de35e1d 100644 --- a/components/compose_strings.grdp +++ b/components/compose_strings.grdp
@@ -49,6 +49,9 @@ <message name="IDS_COMPOSE_FRE_MAIN_MID" desc="The middle main text of the Help me write disclaimer dialog."> Your text and the content and URL of the page you're writing on will be sent to Google, reviewed by humans, and used to improve this feature. Avoid entering personal information (like medical or financial details) or using this tool on sites that contain private or sensitive information. </message> + <message name="IDS_COMPOSE_FRE_MAIN_MID_ENTERPRISE" desc="The middle main text of the Help me write disclaimer dialog for enterprise users with logging turned off."> + Your text and the content and URL of the page you're writing on will be sent to Google. Your content will not be used by human reviewers to improve AI. Your organization may change these settings at any time. + </message> <message name="IDS_COMPOSE_FRE_OK_BUTTON" desc="The button to acknowledge the Help me write disclaimer message."> OK </message> @@ -102,6 +105,10 @@ Your text and page content are sent to Google and may be used to improve this feature. <ph name="BEGIN_LINK"><a href=""></ph>Learn more<ph name="END_LINK"></a></ph> </message> + <message name="IDS_COMPOSE_INPUT_FOOTER_ENTERPRISE" desc="Privacy disclaimer in the input dialog for enterprise users with logging turned off."> + Your text and page content are sent to Google, but will not be used to improve AI. + <ph name="BEGIN_LINK"><a href="#" id="enterpriseLearnMore" role="button"></ph>Learn more<ph name="END_LINK"></a></ph> + </message> <message name="IDS_COMPOSE_INPUT_MODE_POLISH" desc="The chip title used to select the Polish mode for a Help me write request."> Polish </message>
diff --git a/components/compose_strings_grdp/IDS_COMPOSE_FRE_MAIN_MID_ENTERPRISE.png.sha1 b/components/compose_strings_grdp/IDS_COMPOSE_FRE_MAIN_MID_ENTERPRISE.png.sha1 new file mode 100644 index 0000000..b960307 --- /dev/null +++ b/components/compose_strings_grdp/IDS_COMPOSE_FRE_MAIN_MID_ENTERPRISE.png.sha1
@@ -0,0 +1 @@ +fd934a33641aa700807d9f00fcd3f143f1c17201 \ No newline at end of file
diff --git a/components/compose_strings_grdp/IDS_COMPOSE_INPUT_FOOTER_ENTERPRISE.png.sha1 b/components/compose_strings_grdp/IDS_COMPOSE_INPUT_FOOTER_ENTERPRISE.png.sha1 new file mode 100644 index 0000000..7d5a806 --- /dev/null +++ b/components/compose_strings_grdp/IDS_COMPOSE_INPUT_FOOTER_ENTERPRISE.png.sha1
@@ -0,0 +1 @@ +aa5420b2589b1fa1fdd6a0d2c509ee4df1bccbc3 \ No newline at end of file
diff --git a/components/content_settings/browser/ui/cookie_controls_controller.cc b/components/content_settings/browser/ui/cookie_controls_controller.cc index 2c519147..56b28cf 100644 --- a/components/content_settings/browser/ui/cookie_controls_controller.cc +++ b/components/content_settings/browser/ui/cookie_controls_controller.cc
@@ -578,7 +578,6 @@ const GURL& url = GetWebContents()->GetLastCommittedURL(); // Metrics, related to confidence signals: - // TODO(crbug.com/40064612): Add CookieControlsActivated.FedCmInitiated base::UmaHistogramBoolean( "Privacy.CookieControlsActivated.SaaRequested", cookie_settings_->HasAnyFrameRequestedStorageAccess(url)); @@ -597,7 +596,6 @@ site_data_access_type); // Record activation UKM. - // TODO(crbug.com/40064612): Include FedCM information. DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto ukm_source_id = GetWebContents()->GetPrimaryMainFrame()->GetPageUkmSourceId(); @@ -614,8 +612,6 @@ .SetThirdPartySiteDataAccessType( static_cast<uint64_t>(site_data_access_type)) .Record(ukm::UkmRecorder::Get()); - - // TODO(crbug.com/40064612): Add metrics, related to repeated activations. } bool CookieControlsController::ShouldHighlightUserBypass( @@ -635,7 +631,6 @@ return false; } - // TODO(crbug.com/40064612): Check if FedCM was requested. const GURL& url = web_contents->GetLastCommittedURL(); if (cookie_settings_->HasAnyFrameRequestedStorageAccess(url)) { return false;
diff --git a/components/content_settings/core/browser/content_settings_info.cc b/components/content_settings/core/browser/content_settings_info.cc index 7361bb0..d6e78df 100644 --- a/components/content_settings/core/browser/content_settings_info.cc +++ b/components/content_settings/core/browser/content_settings_info.cc
@@ -98,13 +98,18 @@ } bool ContentSettingsInfo::Delegate::IsAnyPermissionAllowed( - PermissionSetting setting) const { - return std::get<ContentSetting>(setting) == CONTENT_SETTING_ALLOW; + const PermissionSetting& permission_setting) const { + auto& setting = std::get<ContentSetting>(permission_setting); + return setting == CONTENT_SETTING_ALLOW || + setting == CONTENT_SETTING_SESSION_ONLY; } bool ContentSettingsInfo::Delegate::IsUndecided( - PermissionSetting setting) const { - return std::get<ContentSetting>(setting) == CONTENT_SETTING_ASK; + const PermissionSetting& permission_setting) const { + auto& setting = std::get<ContentSetting>(permission_setting); + // DEFAULT should be represented as an empty optional PermissionSetting. + DCHECK(setting != CONTENT_SETTING_DEFAULT); + return setting == CONTENT_SETTING_ASK; } bool ContentSettingsInfo::Delegate::CanTrackLastVisit() const {
diff --git a/components/content_settings/core/browser/content_settings_info.h b/components/content_settings/core/browser/content_settings_info.h index d740529..447aec3 100644 --- a/components/content_settings/core/browser/content_settings_info.h +++ b/components/content_settings/core/browser/content_settings_info.h
@@ -43,8 +43,9 @@ PermissionSetting InheritInIncognito( const PermissionSetting& setting) const override; bool ShouldCoalesceEphemeralState() const override; - bool IsAnyPermissionAllowed(PermissionSetting setting) const override; - bool IsUndecided(PermissionSetting setting) const override; + bool IsAnyPermissionAllowed( + const PermissionSetting& setting) const override; + bool IsUndecided(const PermissionSetting& setting) const override; bool CanTrackLastVisit() const override; base::Value ToValue(const PermissionSetting& setting) const override; std::optional<PermissionSetting> FromValue(
diff --git a/components/content_settings/core/browser/content_settings_registry_unittest.cc b/components/content_settings/core/browser/content_settings_registry_unittest.cc index 62c608e..0e75c262 100644 --- a/components/content_settings/core/browser/content_settings_registry_unittest.cc +++ b/components/content_settings/core/browser/content_settings_registry_unittest.cc
@@ -248,4 +248,26 @@ EXPECT_EQ(count, values.size()); } +TEST_F(ContentSettingsRegistryTest, DelegateStateChecks) { + auto* info = registry() + ->Get(ContentSettingsType::MEDIASTREAM_MIC) + ->permission_settings_info(); + + EXPECT_FALSE(info->delegate().IsAnyPermissionAllowed(CONTENT_SETTING_ASK)); + EXPECT_TRUE(info->delegate().IsAnyPermissionAllowed(CONTENT_SETTING_ALLOW)); + EXPECT_FALSE(info->delegate().IsAnyPermissionAllowed(CONTENT_SETTING_BLOCK)); + EXPECT_TRUE( + info->delegate().IsAnyPermissionAllowed(CONTENT_SETTING_SESSION_ONLY)); + + EXPECT_TRUE(info->delegate().IsUndecided(CONTENT_SETTING_ASK)); + EXPECT_FALSE(info->delegate().IsUndecided(CONTENT_SETTING_ALLOW)); + EXPECT_FALSE(info->delegate().IsUndecided(CONTENT_SETTING_BLOCK)); + EXPECT_FALSE(info->delegate().IsUndecided(CONTENT_SETTING_SESSION_ONLY)); + + EXPECT_FALSE(info->delegate().IsBlocked(CONTENT_SETTING_ASK)); + EXPECT_FALSE(info->delegate().IsBlocked(CONTENT_SETTING_ALLOW)); + EXPECT_TRUE(info->delegate().IsBlocked(CONTENT_SETTING_BLOCK)); + EXPECT_FALSE(info->delegate().IsBlocked(CONTENT_SETTING_SESSION_ONLY)); +} + } // namespace content_settings
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc index f556735..64c9fc9 100644 --- a/components/content_settings/core/browser/cookie_settings.cc +++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -245,8 +245,6 @@ // created manually, or through the previous UI. Resetting should support // both of these. - // TODO(crbug.com/40064612): Log metrics when there is pattern that has domain - // as wildcard. auto pattern = ContentSettingsPattern::FromURLToSchemefulSitePattern(first_party_url);
diff --git a/components/content_settings/core/browser/geolocation_setting_delegate.cc b/components/content_settings/core/browser/geolocation_setting_delegate.cc index 25aa721..8f57b24 100644 --- a/components/content_settings/core/browser/geolocation_setting_delegate.cc +++ b/components/content_settings/core/browser/geolocation_setting_delegate.cc
@@ -86,14 +86,15 @@ } bool GeolocationSettingDelegate::IsAnyPermissionAllowed( - PermissionSetting setting) const { + const PermissionSetting& setting) const { // When precise is allowed, then approximate must be allowed too so we only // need to check approximate here. return std::get<GeolocationSetting>(setting).approximate == PermissionOption::kAllowed; } -bool GeolocationSettingDelegate::IsUndecided(PermissionSetting setting) const { +bool GeolocationSettingDelegate::IsUndecided( + const PermissionSetting& setting) const { const auto& geo_setting = std::get<GeolocationSetting>(setting); return geo_setting.approximate == PermissionOption::kAsk && geo_setting.precise == PermissionOption::kAsk;
diff --git a/components/content_settings/core/browser/geolocation_setting_delegate.h b/components/content_settings/core/browser/geolocation_setting_delegate.h index 3c95b57eb..01ad425 100644 --- a/components/content_settings/core/browser/geolocation_setting_delegate.h +++ b/components/content_settings/core/browser/geolocation_setting_delegate.h
@@ -21,8 +21,8 @@ PermissionSetting InheritInIncognito( const PermissionSetting& setting) const override; - bool IsAnyPermissionAllowed(PermissionSetting setting) const override; - bool IsUndecided(PermissionSetting setting) const override; + bool IsAnyPermissionAllowed(const PermissionSetting& setting) const override; + bool IsUndecided(const PermissionSetting& setting) const override; bool CanTrackLastVisit() const override; bool ShouldCoalesceEphemeralState() const override;
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc index 56e6b6c..be1fe24 100644 --- a/components/content_settings/core/browser/host_content_settings_map.cc +++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -601,7 +601,7 @@ const GURL& primary_url, const GURL& secondary_url, ContentSettingsType type, - PermissionSetting setting, + std::optional<PermissionSetting> setting, const content_settings::ContentSettingConstraints& constraints) { content_settings::PatternPair patterns = GetNarrowestPatterns(primary_url, secondary_url, type);
diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h index 2f92bea..4bf8840 100644 --- a/components/content_settings/core/browser/host_content_settings_map.h +++ b/components/content_settings/core/browser/host_content_settings_map.h
@@ -309,7 +309,7 @@ const GURL& primary_url, const GURL& secondary_url, ContentSettingsType type, - PermissionSetting setting, + std::optional<PermissionSetting> setting, const content_settings::ContentSettingConstraints& constraints = {}); // Updates the last used time to a recent timestamp.
diff --git a/components/content_settings/core/browser/permission_settings_info.cc b/components/content_settings/core/browser/permission_settings_info.cc index 608a165..cce1809 100644 --- a/components/content_settings/core/browser/permission_settings_info.cc +++ b/components/content_settings/core/browser/permission_settings_info.cc
@@ -35,6 +35,11 @@ return *default_setting; } +bool PermissionSettingsInfo::Delegate::IsBlocked( + const PermissionSetting& setting) const { + return !IsAnyPermissionAllowed(setting) && !IsUndecided(setting); +} + PermissionSetting PermissionSettingsInfo::Delegate::CoalesceEphemeralState( const PermissionSetting& persistent_permission_setting, const PermissionSetting& ephemeral_permission_setting) const {
diff --git a/components/content_settings/core/browser/permission_settings_info.h b/components/content_settings/core/browser/permission_settings_info.h index cfb2be8..063a299 100644 --- a/components/content_settings/core/browser/permission_settings_info.h +++ b/components/content_settings/core/browser/permission_settings_info.h
@@ -39,10 +39,15 @@ // Returns if at least some of the permission setting is allowed. Used e.g. // to decide whether the permission setting can be auto-revoked by // SafetyHub. - virtual bool IsAnyPermissionAllowed(PermissionSetting setting) const = 0; + virtual bool IsAnyPermissionAllowed( + const PermissionSetting& setting) const = 0; // Returns true when no permission has been allowed or blocked yet. - virtual bool IsUndecided(PermissionSetting setting) const = 0; + virtual bool IsUndecided(const PermissionSetting& setting) const = 0; + + // Returns whether the permission is fully blocked. This is usually the case + // when nothing is allowed and the permission is not undecided. + virtual bool IsBlocked(const PermissionSetting& setting) const; // Returns whether the permission setting supports expiration tracking. virtual bool CanTrackLastVisit() const = 0;
diff --git a/components/content_settings/core/common/third_party_site_data_access_type.h b/components/content_settings/core/common/third_party_site_data_access_type.h index fcd424f..6a5624d 100644 --- a/components/content_settings/core/common/third_party_site_data_access_type.h +++ b/components/content_settings/core/common/third_party_site_data_access_type.h
@@ -9,8 +9,6 @@ // Keep in sync with CookieControlsSiteDataAccessType in enums.xml. // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. -// TODO(crbug.com/40064612): Extend this to capture sites which only accessed -// partitioned cookies and storage. enum class ThirdPartySiteDataAccessType { kAnyBlockedThirdPartySiteAccesses = 0, kAnyAllowedThirdPartySiteAccesses = 1,
diff --git a/components/crash/content/browser/crash_metrics_reporter_android.cc b/components/crash/content/browser/crash_metrics_reporter_android.cc index 0b90123..2d97651 100644 --- a/components/crash/content/browser/crash_metrics_reporter_android.cc +++ b/components/crash/content/browser/crash_metrics_reporter_android.cc
@@ -184,17 +184,17 @@ base::RecordAction( base::UserMetricsAction("RendererForegroundMainFrameOOM")); } - base::SystemMemoryInfoKB meminfo; + base::SystemMemoryInfo meminfo; base::GetSystemMemoryInfo(&meminfo); base::UmaHistogramMemoryLargeMB( "Memory.Experimental.Renderer.TotalMemoryAfterOOM", - meminfo.total / 1024); + meminfo.total.InMiB()); base::UmaHistogramMemoryLargeMB( "Memory.Experimental.Renderer.AvailableMemoryAfterOOM", - meminfo.available / 1024); + meminfo.available.InMiB()); base::UmaHistogramMemoryLargeMB( "Memory.Experimental.Renderer.SwapFreeAfterOOM", - meminfo.swap_free / 1024); + meminfo.swap_free.InMiB()); base::UmaHistogramMemoryLargeMB( "Memory.Experimental.Renderer.AvailableMemoryBeforeOOM", available_memory_kb / 1024);
diff --git a/components/crash/core/app/BUILD.gn b/components/crash/core/app/BUILD.gn index 915c62be..3b42ebe 100644 --- a/components/crash/core/app/BUILD.gn +++ b/components/crash/core/app/BUILD.gn
@@ -35,20 +35,6 @@ "//third_party/crashpad/crashpad/handler", ] - if (is_mac) { - # TODO(crbug.com/40064248): Remove this once sufficient information is - # collected. - sources += [ - "command_output_user_stream.cc", - "command_output_user_stream.h", - ] - - deps += [ - "//third_party/crashpad/crashpad/minidump", - "//third_party/crashpad/crashpad/snapshot", - ] - } - if (is_linux || is_chromeos || is_mac) { deps += [ "//components/stability_report" ] }
diff --git a/components/crash/core/app/DEPS b/components/crash/core/app/DEPS index 1c6c4eec..8790b901 100644 --- a/components/crash/core/app/DEPS +++ b/components/crash/core/app/DEPS
@@ -11,5 +11,4 @@ "+third_party/crashpad", "+third_party/cros_system_api/constants/crash_reporter.h", "+third_party/lss/linux_syscall_support.h", - "+third_party/zlib", ]
diff --git a/components/crash/core/app/command_output_user_stream.cc b/components/crash/core/app/command_output_user_stream.cc deleted file mode 100644 index fa09591..0000000 --- a/components/crash/core/app/command_output_user_stream.cc +++ /dev/null
@@ -1,198 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/crash/core/app/command_output_user_stream.h" - -#include <optional> -#include <string> -#include <type_traits> -#include <vector> - -#include "base/process/launch.h" -#include "base/strings/stringprintf.h" -#include "third_party/crashpad/crashpad/client/annotation.h" -#include "third_party/crashpad/crashpad/minidump/minidump_user_extension_stream_data_source.h" -#include "third_party/crashpad/crashpad/snapshot/annotation_snapshot.h" -#include "third_party/crashpad/crashpad/snapshot/module_snapshot.h" -#include "third_party/crashpad/crashpad/snapshot/process_snapshot.h" -#include "third_party/zlib/zlib.h" - -namespace crash_reporter { - -namespace { - -// Some commands produce a lot of output, but it’s text, so it compresses fairly -// well. Use zlib to compress it to not produce extra-large minidumps. -std::optional<std::string> ZlibCompress(const std::string& uncompressed) { - if (uncompressed.empty()) { - return std::nullopt; - } - - uLongf compressed_size = compressBound(uncompressed.size()); - std::string compressed(compressed_size, '\0'); - int compress_result = compress2( - reinterpret_cast<unsigned char*>(compressed.data()), &compressed_size, - reinterpret_cast<const unsigned char*>(uncompressed.data()), - uncompressed.size(), Z_DEFAULT_COMPRESSION); - if (compress_result != Z_OK) { - return std::nullopt; - } - - compressed.resize(compressed_size); - return compressed; -} - -class CommandOutputUserStreamDataSource final - : public crashpad::MinidumpUserExtensionStreamDataSource { - public: - CommandOutputUserStreamDataSource( - const std::vector<std::vector<std::string>>& commands) - : MinidumpUserExtensionStreamDataSource(kStreamType) { - // This is a simple serialization format that encodes a sequence of - // (commands), where each command in (commands) is a sequence of (args, - // exit_status, stdout). args is a sequence created from each command’s - // argv, and exit_status is an int, or 'x' if the command could not be run. - // stdout is preceded by a number indicating whether it’s presented - // uncompressed (0) or zlib-compressed (1). sequences are preceded by the - // number of contained elements, and strings such as arguments and (possibly - // compressed) stdout are preceded by their encoded byte length. - // - // This format can be decoded by - // https://chromium-review.googlesource.com/c/6791935. - data_ = base::StringPrintf("%u ", commands.size()); - for (const std::vector<std::string>& command : commands) { - base::StringAppendF(&data_, "%u ", command.size()); - for (const std::string& arg : command) { - base::StringAppendF(&data_, "%u ", arg.size()); - data_ += arg; - } - - int status; - std::string uncompressed_stdout; - if (!base::GetAppOutputWithExitCode(command, &uncompressed_stdout, - &status)) { - data_ += "x "; - } else { - base::StringAppendF(&data_, "%d ", status); - } - - std::optional<std::string> compressed_stdout = - ZlibCompress(uncompressed_stdout); - int stdout_format; - const std::string* which_stdout; - if (compressed_stdout && - compressed_stdout->size() < uncompressed_stdout.size()) { - stdout_format = 1; - which_stdout = &compressed_stdout.value(); - } else { - stdout_format = 0; - which_stdout = &uncompressed_stdout; - } - base::StringAppendF(&data_, "%d %u ", stdout_format, - which_stdout->size()); - data_ += *which_stdout; - } - } - - CommandOutputUserStreamDataSource(const CommandOutputUserStreamDataSource&) = - delete; - CommandOutputUserStreamDataSource& operator=( - const CommandOutputUserStreamDataSource&) = delete; - - ~CommandOutputUserStreamDataSource() final = default; - - size_t StreamDataSize() final { return data_.size(); } - - bool ReadStreamData(Delegate* delegate) final { - return delegate->ExtensionStreamDataSourceRead(data_.data(), data_.size()); - } - - private: - static constexpr uint32_t kStreamType = 0x4b6b0005; - - std::string data_; -}; - -} // namespace - -std::unique_ptr<crashpad::MinidumpUserExtensionStreamDataSource> -CommandOutputUserStream::ProduceStreamData( - crashpad::ProcessSnapshot* process_snapshot) { - DCHECK(process_snapshot); - - // Look for the magic crash key that says that the CommandOutputUserStream - // stream should be created. - bool found = false; - for (const crashpad::ModuleSnapshot* module_snapshot : - process_snapshot->Modules()) { - for (const crashpad::AnnotationSnapshot& annotation_snapshot : - module_snapshot->AnnotationObjects()) { - if (annotation_snapshot.name == "net-crbug_40064248" && - annotation_snapshot.type == - static_cast<std::underlying_type_t<crashpad::Annotation::Type>>( - crashpad::Annotation::Type::kString)) { - std::string value( - reinterpret_cast<const char*>(annotation_snapshot.value.data()), - annotation_snapshot.value.size()); - if (value == "1") { - found = true; - break; - } - } - } - if (found) { - break; - } - } - - if (!found) { - // The magic crash key wasn’t present. Don’t include a - // CommandOutputUserStream in the minidump. - return nullptr; - } - - std::vector<std::vector<std::string>> commands{ - // Network interface configuration. - {"/sbin/ifconfig", "-aLmrv"}, - - // Per-interface statistics. - {"/usr/sbin/netstat", "-abdilnvW"}, - - // Routing table. - {"/usr/sbin/netstat", "-alllnr"}, - - // BPF statistics (not supported on all OS versions). - {"/usr/sbin/netstat", "-Bn"}, - - // Network stack memory management. - {"/usr/sbin/netstat", "-mmn"}, - - // System extensions (not to be confused with kernel extensions). - {"/usr/bin/systemextensionsctl", "list"}, - - // Kernel extensions. - {"/usr/bin/kmutil", "showloaded"}, - - // Files opened by the crashing process. - {"/usr/sbin/lsof", "-lnPR", "+f", "cg", "-g", "+L", "-T", "fqs", "-p", - base::StringPrintf("%d", process_snapshot->ProcessID())}, - }; - - static int count; - if (count++ == 0) { - // The system profile. - // - // This can take a long time (~9s on a M1 MacBookPro18,2 running macOS 15.5 - // 24F74), so only do it once per chrome_crashpad_handler process. - // - // The use of the static is thread-safe because this runs exclusively on the - // single handler thread in chrome_crashpad_handler. - commands.push_back( - {"/usr/sbin/system_profiler", "-xml", "-detailLevel", "full"}); - } - - return std::make_unique<CommandOutputUserStreamDataSource>(commands); -} - -} // namespace crash_reporter
diff --git a/components/crash/core/app/command_output_user_stream.h b/components/crash/core/app/command_output_user_stream.h deleted file mode 100644 index 9502061..0000000 --- a/components/crash/core/app/command_output_user_stream.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_CRASH_CORE_APP_COMMAND_OUTPUT_USER_STREAM_H_ -#define COMPONENTS_CRASH_CORE_APP_COMMAND_OUTPUT_USER_STREAM_H_ - -#include "third_party/crashpad/crashpad/handler/user_stream_data_source.h" - -namespace crash_reporter { - -// A custom minidump stream source that, when evidence of -// https://crbug.com/40064248 is observed, produces output from various commands -// that might be useful for troubleshooting. -// -// TODO(crbug.com/40064248): Remove this once sufficient information is -// collected. -class CommandOutputUserStream final : public crashpad::UserStreamDataSource { - public: - CommandOutputUserStream() = default; - ~CommandOutputUserStream() final = default; - - CommandOutputUserStream(const CommandOutputUserStream&) = delete; - CommandOutputUserStream& operator=(const CommandOutputUserStream&) = delete; - - std::unique_ptr<crashpad::MinidumpUserExtensionStreamDataSource> - ProduceStreamData(crashpad::ProcessSnapshot* process_snapshot) final; -}; - -} // namespace crash_reporter - -#endif // COMPONENTS_CRASH_CORE_APP_COMMAND_OUTPUT_USER_STREAM_H_
diff --git a/components/crash/core/app/crashpad_handler_main.cc b/components/crash/core/app/crashpad_handler_main.cc index 1daec4c..6f98f331 100644 --- a/components/crash/core/app/crashpad_handler_main.cc +++ b/components/crash/core/app/crashpad_handler_main.cc
@@ -14,12 +14,6 @@ #include "components/stability_report/user_stream_data_source_posix.h" #endif -#if BUILDFLAG(IS_MAC) -// TODO(crbug.com/40064248): Remove this once sufficient information is -// collected. -#include "components/crash/core/app/command_output_user_stream.h" -#endif - #if BUILDFLAG(ENABLE_GWP_ASAN) #include "components/gwp_asan/crash_handler/crash_handler.h" // nogncheck #endif @@ -42,13 +36,6 @@ std::make_unique<stability_report::UserStreamDataSourcePosix>()); #endif -#if BUILDFLAG(IS_MAC) - // TODO(crbug.com/40064248): Remove this once sufficient information is - // collected. - user_stream_data_sources.push_back( - std::make_unique<crash_reporter::CommandOutputUserStream>()); -#endif - #if BUILDFLAG(ENABLE_GWP_ASAN) user_stream_data_sources.push_back( std::make_unique<gwp_asan::UserStreamDataSource>()); @@ -58,8 +45,8 @@ user_stream_data_sources.push_back( std::make_unique<allocation_recorder::crash_handler:: AllocationRecorderStreamDataSource>( - base::MakeRefCounted< - allocation_recorder::crash_handler::AllocationRecorderHolder>(), + base::MakeRefCounted<allocation_recorder::crash_handler:: + AllocationRecorderHolder>(), base::MakeRefCounted< allocation_recorder::crash_handler::StreamDataSourceFactory>())); #endif
diff --git a/components/dom_distiller/content/browser/distiller_page_web_contents.cc b/components/dom_distiller/content/browser/distiller_page_web_contents.cc index b0230a7..7a86b787 100644 --- a/components/dom_distiller/content/browser/distiller_page_web_contents.cc +++ b/components/dom_distiller/content/browser/distiller_page_web_contents.cc
@@ -14,6 +14,7 @@ #include "components/dom_distiller/content/browser/distiller_javascript_utils.h" #include "components/dom_distiller/core/distiller_page.h" #include "components/dom_distiller/core/dom_distiller_constants.h" +#include "components/dom_distiller/core/dom_distiller_features.h" #include "components/dom_distiller/core/dom_distiller_service.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_controller.h" @@ -127,6 +128,11 @@ return false; } +DistillerType DistillerPageWebContents::GetDistillerType() { + return ShouldUseReadabilityDistiller() ? DistillerType::kReadability + : DistillerType::kDOMDistiller; +} + void DistillerPageWebContents::DistillPageImpl(const GURL& url, const std::string& script) { DCHECK(browser_context_);
diff --git a/components/dom_distiller/content/browser/distiller_page_web_contents.h b/components/dom_distiller/content/browser/distiller_page_web_contents.h index f3cf904c6..dfe18d6 100644 --- a/components/dom_distiller/content/browser/distiller_page_web_contents.h +++ b/components/dom_distiller/content/browser/distiller_page_web_contents.h
@@ -11,6 +11,7 @@ #include "base/memory/raw_ptr.h" #include "base/supports_user_data.h" #include "components/dom_distiller/core/distiller_page.h" +#include "components/dom_distiller/core/dom_distiller_constants.h" #include "content/public/browser/navigation_throttle_registry.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" @@ -66,6 +67,7 @@ // DistillerPage implementation. bool ShouldFetchOfflineData() override; + DistillerType GetDistillerType() override; // content::WebContentsDelegate implementation. gfx::Size GetSizeForNewRenderView(
diff --git a/components/dom_distiller/core/css/distilledpage.css b/components/dom_distiller/core/css/distilledpage.css index bda7674d..cf2c713 100644 --- a/components/dom_distiller/core/css/distilledpage.css +++ b/components/dom_distiller/core/css/distilledpage.css
@@ -1,80 +1,14 @@ -/* Copyright 2014 The Chromium Authors +/* 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. */ -/* This file contains style used across ALL platforms. Platform-specific styling - * should be placed in the corresponding file (e.g. desktop style goes in - * distilledpage_desktop.css).*/ - -/* Set the global 'box-sizing' state to 'border-box'. - * *::after and *::before used to select pseudo-elements not selectable by *. */ - -:root { - --google-blue-300: 138, 180, 248; - --google-blue-600: 26, 115, 232; - --google-blue-700: 25, 103, 210; - --google-brown-900: 62, 39, 35; - --google-grey-50: 248, 249, 250; - --google-grey-900: 32, 33, 36; - --google-purple-300: 197, 138, 249; - --google-purple-700: 132, 48, 206; - --google-yellow-50: 254, 247, 224; - --google-yellow-100: 254, 239, 195; -} - -*, -*::after, -*::before { - box-sizing: border-box; -} - -/* Remove all margins and padding from certain element and add word wrap. */ - -blockquote, -body, -caption, -dd, -dl, -fieldset, -figure, -form, -h1, -h2, -h3, -h4, -h5, -h6, -hr, -legend, -ol, -p, -pre, -ul, -table, -td, -th { - margin: 0; - padding: 0; - word-wrap: break-word; -} - -/* Prevent 'sub' and 'sup' affecting 'line-height'. */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} + /* + * This file contains style used across ALL platforms. It contains the legacy + * styling to A/B test against a new set of styles. Common styling has been + * refactored into distilledpage_common.css. + * Platform-specific styling should be placed in the corresponding file (e.g. + * desktop style goes in distilledpage_desktop.css). + */ /* Remove most spacing between table cells. */ @@ -98,153 +32,9 @@ } body { -<if expr="is_ios"> - padding-left: env(safe-area-inset-left); - padding-right: env(safe-area-inset-right); - padding-top: env(safe-area-inset-top); - padding-bottom: env(safe-area-inset-bottom); -</if> - -webkit-overflow-scrolling: touch; - display: flex; - flex-direction: column; line-height: 1.714; - margin: 0 auto; - min-height: 100vh; - overflow-x: hidden; - text-rendering: optimizeLegibility; - transition-duration: 500ms; - transition-property: color, background-color; - transition-timing-function: ease; } -/* Classes for light, dark and sepia themes. - * Must agree with classes returned by useTheme() in dom_distiller_viewer.js - * and with CSS class constants in viewer.cc */ - -.light { - background-color: #FFF; - color: rgb(var(--google-grey-900)); -} - -.dark { - background-color: rgb(var(--google-grey-900)); - color: #FFF; -} - -.sepia { - background-color: rgb(var(--google-yellow-50)); - color: rgb(var(--google-brown-900)); -} - -.light a:link { - color: rgb(var(--google-blue-600)); -} - -.sepia a:link { - color: rgb(var(--google-blue-700)); -} - -.dark a:link { - color: rgb(var(--google-blue-300)); -} - -.light a:visited { - color: rgb(var(--google-purple-700)); -} - -.sepia a:visited { - color: rgb(var(--google-purple-700)); -} - -.dark a:visited { - color: rgb(var(--google-purple-300)); -} - -.light code, -.light pre { - background-color: rgb(var(--google-grey-50)); - border-color: rgb(var(--google-grey-900)); -} - -.sepia code, -.sepia pre { - background-color: rgb(var(--google-yellow-100)); - border-color: rgba(var(--google-brown-900), 0.5); -} - -.dark code, -.dark pre { - background-color: #000; - border-color: rgba(255, 255, 255, 0.5); -} - -.light tbody tr:nth-child(odd) { - background-color: #EEE; -} - -.light th, -.light td { - border-inline-start: 2px solid #AAA; -} - -.sepia tbody tr:nth-child(odd) { - background-color: rgb(217, 196, 175); -} - -.sepia th, -.sepia td { - border-inline-start: 1px solid rgb(147, 125, 102); -} - -.dark tbody tr:nth-child(odd) { - background-color: #333; -} - -.dark th, -.dark td { - border-inline-start: 1px solid #555; -} - -/* #content-wrap is added to be more specific than the color theme rules */ -#content-wrap th:first-child { - border-inline-start: none; -} - -#content-wrap td:first-child { - border-inline-start: none; -} - - -/* Font settings */ - -<if expr="not(is_ios)"> -.serif { - font-family: serif; -} - -.sans-serif { - font-family: 'Roboto', sans-serif; -} - -.monospace { - font-family: monospace; -} -</if> - -<if expr="is_ios"> -.serif { - font-family: -apple-system-ui-serif, ui-serif, 'Georgia', serif; -} - -.sans-serif { - font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - -.monospace { - font-family: ui-monospace, SFMono-Regular, ui-monospace, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; -} -</if> - /* Define vertical rhythm (baseline grid of 4px). */ blockquote, @@ -278,26 +68,7 @@ margin: 1em 0; } -/* Content. */ - -#loading-indicator { - padding-bottom: 2em; - width: 100%; -} - -#loading-indicator > img, -#loading-indicator > svg { - display: block; - height: 2.5em; - margin: auto; - width: 2.5em; -} - -/* Margins for Show Original link. */ - -video::-webkit-media-controls-fullscreen-button { - display: none; -} +/* Margin and styling rules for various elements. */ #content { margin: 24px 16px 24px 16px; @@ -419,9 +190,3 @@ top: 0; width: 100%; } - -<if expr="is_ios or is_android"> -.desktop-only { - display: none; -} -</if>
diff --git a/components/dom_distiller/core/css/distilledpage_common.css b/components/dom_distiller/core/css/distilledpage_common.css new file mode 100644 index 0000000..3de76ba --- /dev/null +++ b/components/dom_distiller/core/css/distilledpage_common.css
@@ -0,0 +1,251 @@ +/* Copyright 2014 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* Common CSS used for every platform. */ + +/* Set the global 'box-sizing' state to 'border-box'. + * *::after and *::before used to select pseudo-elements not selectable by *. */ + +:root { + --google-blue-300: 138, 180, 248; + --google-blue-600: 26, 115, 232; + --google-blue-700: 25, 103, 210; + --google-brown-900: 62, 39, 35; + --google-grey-50: 248, 249, 250; + --google-grey-900: 32, 33, 36; + --google-purple-300: 197, 138, 249; + --google-purple-700: 132, 48, 206; + --google-yellow-50: 254, 247, 224; + --google-yellow-100: 254, 239, 195; +} + +*, +*::after, +*::before { + box-sizing: border-box; +} + +/* Remove all margins and padding from certain element and add word wrap. */ + +blockquote, +body, +caption, +dd, +dl, +fieldset, +figure, +form, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +legend, +ol, +p, +pre, +ul, +table, +td, +th { + margin: 0; + padding: 0; + word-wrap: break-word; +} + +/* Prevent 'sub' and 'sup' affecting 'line-height'. */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Base styling. */ + +body { +<if expr="is_ios"> + padding-left: env(safe-area-inset-left); + padding-right: env(safe-area-inset-right); + padding-top: env(safe-area-inset-top); + padding-bottom: env(safe-area-inset-bottom); +</if> + -webkit-overflow-scrolling: touch; + display: flex; + flex-direction: column; + margin: 0 auto; + min-height: 100vh; + overflow-x: hidden; + text-rendering: optimizeLegibility; + transition-duration: 500ms; + transition-property: color, background-color; + transition-timing-function: ease; +} + +/* Classes for light, dark and sepia themes. + * Must agree with classes returned by useTheme() in dom_distiller_viewer.js + * and with CSS class constants in viewer.cc */ + +.light { + background-color: #FFF; + color: rgb(var(--google-grey-900)); +} + +.dark { + background-color: rgb(var(--google-grey-900)); + color: #FFF; +} + +.sepia { + background-color: rgb(var(--google-yellow-50)); + color: rgb(var(--google-brown-900)); +} + +.light a:link { + color: rgb(var(--google-blue-600)); +} + +.sepia a:link { + color: rgb(var(--google-blue-700)); +} + +.dark a:link { + color: rgb(var(--google-blue-300)); +} + +.light a:visited { + color: rgb(var(--google-purple-700)); +} + +.sepia a:visited { + color: rgb(var(--google-purple-700)); +} + +.dark a:visited { + color: rgb(var(--google-purple-300)); +} + +.light code, +.light pre { + background-color: rgb(var(--google-grey-50)); + border-color: rgb(var(--google-grey-900)); +} + +.sepia code, +.sepia pre { + background-color: rgb(var(--google-yellow-100)); + border-color: rgba(var(--google-brown-900), 0.5); +} + +.dark code, +.dark pre { + background-color: #000; + border-color: rgba(255, 255, 255, 0.5); +} + +.light tbody tr:nth-child(odd) { + background-color: #EEE; +} + +.light th, +.light td { + border-inline-start: 2px solid #AAA; +} + +.sepia tbody tr:nth-child(odd) { + background-color: rgb(217, 196, 175); +} + +.sepia th, +.sepia td { + border-inline-start: 1px solid rgb(147, 125, 102); +} + +.dark tbody tr:nth-child(odd) { + background-color: #333; +} + +.dark th, +.dark td { + border-inline-start: 1px solid #555; +} + +/* #content-wrap is added to be more specific than the color theme rules */ +#content-wrap th:first-child { + border-inline-start: none; +} + +#content-wrap td:first-child { + border-inline-start: none; +} + + +/* Font settings */ + +<if expr="not(is_ios)"> +.serif { + font-family: serif; +} + +.sans-serif { + font-family: 'Roboto', sans-serif; +} + +.monospace { + font-family: monospace; +} +</if> + +<if expr="is_ios"> +.serif { + font-family: -apple-system-ui-serif, ui-serif, 'Georgia', serif; +} + +.sans-serif { + font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Arial, sans-serif; +} + +.monospace { + font-family: ui-monospace, SFMono-Regular, ui-monospace, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; +} +</if> + +/* Content. */ + +#loading-indicator { + padding-bottom: 2em; + width: 100%; +} + +#loading-indicator > img, +#loading-indicator > svg { + display: block; + height: 2.5em; + margin: auto; + width: 2.5em; +} + +/* Video styling. */ + +video::-webkit-media-controls-fullscreen-button { + display: none; +} + +<if expr="is_ios or is_android"> +.desktop-only { + display: none; +} +</if>
diff --git a/components/dom_distiller/core/distiller_page.cc b/components/dom_distiller/core/distiller_page.cc index ea24d4c..c1157f0 100644 --- a/components/dom_distiller/core/distiller_page.cc +++ b/components/dom_distiller/core/distiller_page.cc
@@ -120,9 +120,17 @@ ready_ = false; distiller_page_callback_ = std::move(callback); - DistillPageImpl(gurl, ShouldUseReadabilityDistiller() - ? GetReadabilityDistillerScript() - : GetDistillerScriptWithOptions(options)); + std::string script; + switch (GetDistillerType()) { + case DistillerType::kReadability: + script = GetReadabilityDistillerScript(); + break; + case DistillerType::kDOMDistiller: + script = GetDistillerScriptWithOptions(options); + break; + } + + DistillPageImpl(gurl, script); } void DistillerPage::OnDistillationDone(const GURL& page_url, @@ -139,12 +147,17 @@ found_content = false; result = DistillationParseResult::kNoData; } else { - found_content = - ShouldUseReadabilityDistiller() - ? ReadabilityDistillerResultToDomDistillerResult( - *value, distiller_result.get()) - : dom_distiller::proto::json::DomDistillerResult::ReadFromValue( - *value, distiller_result.get()); + switch (GetDistillerType()) { + case DistillerType::kReadability: + found_content = ReadabilityDistillerResultToDomDistillerResult( + *value, distiller_result.get()); + break; + case DistillerType::kDOMDistiller: + found_content = + dom_distiller::proto::json::DomDistillerResult::ReadFromValue( + *value, distiller_result.get()); + } + if (found_content) { result = DistillationParseResult::kSuccess; } else {
diff --git a/components/dom_distiller/core/distiller_page.h b/components/dom_distiller/core/distiller_page.h index aa044a1..de2327e4 100644 --- a/components/dom_distiller/core/distiller_page.h +++ b/components/dom_distiller/core/distiller_page.h
@@ -10,6 +10,7 @@ #include "base/functional/callback.h" #include "base/values.h" +#include "components/dom_distiller/core/dom_distiller_constants.h" #include "third_party/dom_distiller_js/dom_distiller.pb.h" #include "ui/gfx/geometry/size.h" #include "url/gurl.h" @@ -52,6 +53,9 @@ // offline consumption. virtual bool ShouldFetchOfflineData() = 0; + // Returns the distillation type to use to retrieve simplified page content. + virtual DistillerType GetDistillerType() = 0; + DistillerPage(const DistillerPage&) = delete; DistillerPage& operator=(const DistillerPage&) = delete;
diff --git a/components/dom_distiller/core/distiller_page_unittest.cc b/components/dom_distiller/core/distiller_page_unittest.cc index 2ca6350..aba25f9 100644 --- a/components/dom_distiller/core/distiller_page_unittest.cc +++ b/components/dom_distiller/core/distiller_page_unittest.cc
@@ -13,6 +13,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/values.h" +#include "components/dom_distiller/core/dom_distiller_constants.h" #include "components/dom_distiller/core/dom_distiller_features.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/dom_distiller_js/dom_distiller.pb.h" @@ -59,6 +60,11 @@ bool ShouldFetchOfflineData() override { return false; } + DistillerType GetDistillerType() override { + return ShouldUseReadabilityDistiller() ? DistillerType::kReadability + : DistillerType::kDOMDistiller; + } + // The overridden implementation now simulates one of three outcomes based on // the configuration set by SetNextResult(). void DistillPageImpl(const GURL& url, const std::string& script) override {
diff --git a/components/dom_distiller/core/distiller_unittest.cc b/components/dom_distiller/core/distiller_unittest.cc index 0af0c815c..177b66f 100644 --- a/components/dom_distiller/core/distiller_unittest.cc +++ b/components/dom_distiller/core/distiller_unittest.cc
@@ -341,6 +341,8 @@ .WillOnce(DistillerPageOnDistillationDone(distiller_page, url, result)); EXPECT_CALL(*distiller_page, ShouldFetchOfflineData()) .WillRepeatedly(Return(use_offline_data)); + EXPECT_CALL(*distiller_page, GetDistillerType()) + .WillRepeatedly(Return(dom_distiller::DistillerType::kDOMDistiller)); return std::unique_ptr<DistillerPage>(distiller_page); } @@ -359,6 +361,8 @@ EXPECT_CALL(*distiller_page, DistillPageImpl(url, _)); EXPECT_CALL(*distiller_page, ShouldFetchOfflineData()) .WillRepeatedly(Return(false)); + EXPECT_CALL(*distiller_page, GetDistillerType()) + .WillRepeatedly(Return(dom_distiller::DistillerType::kDOMDistiller)); return std::unique_ptr<DistillerPage>(distiller_page); } @@ -369,6 +373,8 @@ MockDistillerPage* distiller_page = new MockDistillerPage(); EXPECT_CALL(*distiller_page, ShouldFetchOfflineData()) .WillRepeatedly(Return(use_offline_data)); + EXPECT_CALL(*distiller_page, GetDistillerType()) + .WillRepeatedly(Return(dom_distiller::DistillerType::kDOMDistiller)); { testing::InSequence s; for (int page : page_num_sequence) {
diff --git a/components/dom_distiller/core/dom_distiller_constants.h b/components/dom_distiller/core/dom_distiller_constants.h index 1d01eda5..e645e2e 100644 --- a/components/dom_distiller/core/dom_distiller_constants.h +++ b/components/dom_distiller/core/dom_distiller_constants.h
@@ -7,6 +7,13 @@ namespace dom_distiller { +// The distillation technique used for distilling web page content. +enum class DistillerType { + kReadability = 0, + kDOMDistiller = 1, + kMaxValue = kDOMDistiller, +}; + extern const char kChromeUIDomDistillerURL[]; extern const char kChromeUIDomDistillerHost[];
diff --git a/components/dom_distiller/core/fake_distiller_page.h b/components/dom_distiller/core/fake_distiller_page.h index 2276a71e..ea043c3 100644 --- a/components/dom_distiller/core/fake_distiller_page.h +++ b/components/dom_distiller/core/fake_distiller_page.h
@@ -6,6 +6,7 @@ #define COMPONENTS_DOM_DISTILLER_CORE_FAKE_DISTILLER_PAGE_H_ #include "components/dom_distiller/core/distiller_page.h" +#include "components/dom_distiller/core/dom_distiller_constants.h" #include "testing/gmock/include/gmock/gmock.h" namespace dom_distiller { @@ -31,6 +32,7 @@ MockDistillerPage(); ~MockDistillerPage() override; MOCK_METHOD0(ShouldFetchOfflineData, bool()); + MOCK_METHOD0(GetDistillerType, DistillerType()); MOCK_METHOD2(DistillPageImpl, void(const GURL& gurl, const std::string& script)); };
diff --git a/components/dom_distiller/core/javascript/dom_distiller_viewer.js b/components/dom_distiller/core/javascript/dom_distiller_viewer.js index d9babc0..120b08a 100644 --- a/components/dom_distiller/core/javascript/dom_distiller_viewer.js +++ b/components/dom_distiller/core/javascript/dom_distiller_viewer.js
@@ -2,6 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// LINT.IfChange(JSThemesAndFonts) + +// These classes must agree with the font classes in distilledpage.css. +const themeClasses = ['light', 'dark', 'sepia']; +const fontFamilyClasses = ['sans-serif', 'serif', 'monospace']; + +// LINT.ThenChange(//components/dom_distiller/core/viewer.cc:JSThemesAndFonts) + // On iOS, |distillerOnIos| was set to true before this script. // eslint-disable-next-line no-var var distillerOnIos; @@ -112,10 +120,6 @@ document.body.setAttribute('dir', direction); } -// These classes must agree with the font classes in distilledpage.css. -const themeClasses = ['light', 'dark', 'sepia']; -const fontFamilyClasses = ['sans-serif', 'serif', 'monospace']; - // Get the currently applied appearance setting. function getAppearanceSetting(settingClasses) { const cls = Array.from(document.body.classList)
diff --git a/components/dom_distiller/core/viewer.cc b/components/dom_distiller/core/viewer.cc index a92b462fc..6ed9841 100644 --- a/components/dom_distiller/core/viewer.cc +++ b/components/dom_distiller/core/viewer.cc
@@ -36,26 +36,40 @@ namespace { -// JS Themes. Must agree with useTheme() in dom_distiller_viewer.js. +// LINT.IfChange(JSThemesAndFonts) + +// JS Themes. Must agree with themeClasses in dom_distiller_viewer.js. const char kDarkJsTheme[] = "dark"; const char kLightJsTheme[] = "light"; const char kSepiaJsTheme[] = "sepia"; -// CSS Theme classes. Must agree with classes in distilledpage.css. -const char kDarkCssClass[] = "dark"; -const char kLightCssClass[] = "light"; -const char kSepiaCssClass[] = "sepia"; - -// JS FontFamilies. Must agree with useFontFamily() in dom_distiller_viewer.js. +// JS FontFamilies. Must agree with fontFamilyClasses in +// dom_distiller_viewer.js. const char kSerifJsFontFamily[] = "serif"; const char kSansSerifJsFontFamily[] = "sans-serif"; const char kMonospaceJsFontFamily[] = "monospace"; -// CSS FontFamily classes. Must agree with classes in distilledpage.css. +// LINT.ThenChange(//components/dom_distiller/core/javascript/dom_distiller_viewer.js:JSThemesAndFonts) + +// LINT.IfChange + +// CSS Theme classes. Must agree with classes in distilledpage_common.css. +const char kDarkCssClass[] = "dark"; +const char kLightCssClass[] = "light"; +const char kSepiaCssClass[] = "sepia"; + +// CSS FontFamily classes. Must agree with classes in distilledpage_common.css. const char kSerifCssClass[] = "serif"; const char kSansSerifCssClass[] = "sans-serif"; const char kMonospaceCssClass[] = "monospace"; +// LINT.ThenChange(//components/dom_distiller/core/css/distilledpage_common.css) + +std::string GetVersionedCss() { + return ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( + IDR_DISTILLER_CSS); +} + std::string GetPlatformSpecificCss() { #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) return ""; @@ -281,8 +295,8 @@ const std::string GetCss() { return base::StrCat( {ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_DISTILLER_CSS), - GetPlatformSpecificCss()}); + IDR_DISTILLER_COMMON_CSS), + GetVersionedCss(), GetPlatformSpecificCss()}); } const std::string GetLoadingImage() {
diff --git a/components/download/internal/common/base_file.cc b/components/download/internal/common/base_file.cc index d21dc75..26c67e3 100644 --- a/components/download/internal/common/base_file.cc +++ b/components/download/internal/common/base_file.cc
@@ -221,16 +221,6 @@ return DOWNLOAD_INTERRUPT_REASON_NONE; } -DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset, - const char* data, - size_t data_len) { - UNSAFE_BUFFERS( - // SAFETY TODO(https://crbug.com/435230896): get rid of this. - return WriteDataToFile( - offset, - base::span(reinterpret_cast<const uint8_t*>(data), data_len));) -} - bool BaseFile::ValidateDataInFile(int64_t offset, base::span<const uint8_t> data) { if (!file_.IsValid())
diff --git a/components/download/internal/common/base_file_unittest.cc b/components/download/internal/common/base_file_unittest.cc index c803570b..280112d 100644 --- a/components/download/internal/common/base_file_unittest.cc +++ b/components/download/internal/common/base_file_unittest.cc
@@ -797,8 +797,8 @@ ASSERT_TRUE(base_file_->ValidateDataInFile(0, "Let's", 5)); ASSERT_TRUE(base_file_->ValidateDataInFile(1, "et's ", 5)); - ASSERT_TRUE(base_file_->ValidateDataInFile( - 0, "Let's write some data to the file!\n", kTestData1.size())); + ASSERT_TRUE( + base_file_->ValidateDataInFile(0, base::as_byte_span(kTestData1))); ASSERT_TRUE(base_file_->ValidateDataInFile(kTestData1.size() - 1, "\n", 1)); ASSERT_FALSE(base_file_->ValidateDataInFile(kTestData1.size(), "\n", 1)); ASSERT_FALSE(base_file_->ValidateDataInFile(kTestData1.size() - 1, "y\n", 2));
diff --git a/components/download/internal/common/download_file_impl.cc b/components/download/internal/common/download_file_impl.cc index a64f424..35d6d77 100644 --- a/components/download/internal/common/download_file_impl.cc +++ b/components/download/internal/common/download_file_impl.cc
@@ -310,34 +310,30 @@ DownloadInterruptReason DownloadFileImpl::ValidateAndWriteDataToFile( int64_t offset, - const char* data, - size_t bytes_to_validate, - size_t bytes_to_write) { + base::span<const uint8_t> to_validate, + base::span<const uint8_t> to_write) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Check if some of the data is for validation purpose. - bool should_validate = bytes_to_validate > 0; + bool should_validate = to_validate.size() > 0; #if BUILDFLAG(ENTERPRISE_CONTENT_ANALYSIS) should_validate = should_validate && !obfuscator_; #endif - if (should_validate && - !file_.ValidateDataInFile(offset, data, bytes_to_validate)) { + if (should_validate && !file_.ValidateDataInFile(offset, to_validate)) { return DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH; } // If there is no data to write, just return DOWNLOAD_INTERRUPT_REASON_NONE // and read the next chunk. - if (bytes_to_write <= 0) + if (to_write.size() <= 0) { return DOWNLOAD_INTERRUPT_REASON_NONE; + } #if BUILDFLAG(ENTERPRISE_CONTENT_ANALYSIS) if (obfuscator_) { bool is_last_chunk = save_info_->total_bytes > 0 && - static_cast<int64_t>(offset + bytes_to_validate + bytes_to_write) == + static_cast<int64_t>(offset + to_validate.size() + to_write.size()) == save_info_->total_bytes; - auto obfuscated_data = obfuscator_->ObfuscateChunk( - base::span(reinterpret_cast<const uint8_t*>(data + bytes_to_validate), - bytes_to_write), - is_last_chunk); + auto obfuscated_data = obfuscator_->ObfuscateChunk(to_write, is_last_chunk); // TODO(b/367259664): Add better error handling for file obfuscation. if (!obfuscated_data.has_value()) { @@ -345,17 +341,13 @@ } WillWriteToDisk(obfuscated_data.value().size()); - return file_.WriteDataToFile( - file_.bytes_so_far(), - reinterpret_cast<const char*>(obfuscated_data.value().data()), - obfuscated_data.value().size()); + return file_.WriteDataToFile(file_.bytes_so_far(), obfuscated_data.value()); } #endif // Write the remaining data to disk. - WillWriteToDisk(bytes_to_write); - return file_.WriteDataToFile(offset + bytes_to_validate, - data + bytes_to_validate, bytes_to_write); + WillWriteToDisk(to_write.size()); + return file_.WriteDataToFile(offset + to_validate.size(), to_write); } bool DownloadFileImpl::CalculateBytesToWrite(SourceStream* source_stream, @@ -667,7 +659,8 @@ DCHECK_GE(incoming_data_size, bytes_to_write); reason = ValidateAndWriteDataToFile( source_stream->offset() + source_stream->bytes_read(), - incoming_data->data(), bytes_to_validate, bytes_to_write); + incoming_data->span().first(bytes_to_validate), + incoming_data->span().subspan(bytes_to_validate, bytes_to_write)); bytes_seen_ += bytes_to_write; total_incoming_data_size += incoming_data_size; if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) { @@ -789,9 +782,7 @@ } DownloadInterruptReason reason = file_.WriteDataToFile( - file_.bytes_so_far(), - reinterpret_cast<const char*>(obfuscated_empty_data.value().data()), - obfuscated_empty_data.value().size()); + file_.bytes_so_far(), obfuscated_empty_data.value()); if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { SendErrorUpdateIfFinished(reason);
diff --git a/components/download/public/common/base_file.h b/components/download/public/common/base_file.h index 659c4f6..cfbf896 100644 --- a/components/download/public/common/base_file.h +++ b/components/download/public/common/base_file.h
@@ -126,9 +126,6 @@ // indicating the result of the operation. DownloadInterruptReason WriteDataToFile(int64_t offset, base::span<const uint8_t> data); - DownloadInterruptReason WriteDataToFile(int64_t offset, - const char* data, - size_t data_len); // Validates that the content starting from |offset| matches that of |data| // with the given length.
diff --git a/components/download/public/common/download_features.cc b/components/download/public/common/download_features.cc index ff40299..ff2bf2c 100644 --- a/components/download/public/common/download_features.cc +++ b/components/download/public/common/download_features.cc
@@ -92,10 +92,6 @@ "AllowedMixedContentInlinePdf", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kCopyImageFilenameToClipboard, - "CopyImageFilenameToClipboard", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kEnableAsyncNotificationManagerForDownload, "EnableAsyncNotificationManagerForDownload", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/download/public/common/download_features.h b/components/download/public/common/download_features.h index d83e825d..d22cf1c8a 100644 --- a/components/download/public/common/download_features.h +++ b/components/download/public/common/download_features.h
@@ -67,9 +67,6 @@ // Whether mixed-content PDF links can be downloaded if opening inline. COMPONENTS_DOWNLOAD_EXPORT BASE_DECLARE_FEATURE(kAllowedMixedContentInlinePdf); -// Whether to write filename to the clipboard when copying image downloads. -COMPONENTS_DOWNLOAD_EXPORT BASE_DECLARE_FEATURE(kCopyImageFilenameToClipboard); - // Whether to enable async notification manager for downloads. COMPONENTS_DOWNLOAD_EXPORT BASE_DECLARE_FEATURE( kEnableAsyncNotificationManagerForDownload);
diff --git a/components/download/public/common/download_file_impl.h b/components/download/public/common/download_file_impl.h index 6f6a4835..79c4b83 100644 --- a/components/download/public/common/download_file_impl.h +++ b/components/download/public/common/download_file_impl.h
@@ -207,13 +207,12 @@ protected: // For test class overrides. - // Validate the first |bytes_to_validate| bytes and write the next - // |bytes_to_write| bytes of data from the offset to the file. + // Validate that |to_validate| exists at |offset| in the file, then write + // |to_write| after it. virtual DownloadInterruptReason ValidateAndWriteDataToFile( int64_t offset, - const char* data, - size_t bytes_to_validate, - size_t bytes_to_write); + base::span<const uint8_t> to_validate, + base::span<const uint8_t> to_write); virtual base::TimeDelta GetRetryDelayForFailedRename(int attempt_number);
diff --git a/components/error_page/common/localized_error.cc b/components/error_page/common/localized_error.cc index b2866908..96dedda 100644 --- a/components/error_page/common/localized_error.cc +++ b/components/error_page/common/localized_error.cc
@@ -18,6 +18,7 @@ #include "base/check_op.h" #include "base/command_line.h" +#include "base/containers/span.h" #include "base/i18n/rtl.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" @@ -547,10 +548,15 @@ } } -const LocalizedErrorMap* FindErrorMapInArray(const LocalizedErrorMap* maps, - size_t num_maps, - int error_code) { - for (size_t i = 0; i < num_maps; ++i) { +const LocalizedErrorMap* FindErrorMapInArray( + base::span<const LocalizedErrorMap> maps, + size_t spanification_suspected_redundant_num_maps, + int error_code) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK(spanification_suspected_redundant_num_maps == maps.size(), + base::NotFatalUntil::M143); + for (size_t i = 0; i < spanification_suspected_redundant_num_maps; ++i) { if (maps[i].error_code == error_code) return &maps[i]; }
diff --git a/components/facilitated_payments_strings.grdp b/components/facilitated_payments_strings.grdp index 9e34aae9..16c4798 100644 --- a/components/facilitated_payments_strings.grdp +++ b/components/facilitated_payments_strings.grdp
@@ -78,6 +78,9 @@ <message name="IDS_FACILITATED_PAYMENTS_PAYMENT_METHODS_BOTTOM_SHEET_GENERIC_TITLE" desc="Title for the bottom sheet displaying user's accounts linked to their GPay wallet. It is shown to prompt the user to pay directly on Chrome when it receives signal of intention to pay, and the user has eligible payment accounts." formatter_data="android_java"> Pay without switching apps </message> + <message name="IDS_FACILITATED_PAYMENTS_NON_CARD_PAYMENT_METHODS_BOTTOM_SHEET_TITLE" desc="Title for the bottom sheet displaying user's available non-card payment methods. It is displayed when user has at least 1 supported payment app installed." formatter_data="android_java"> + Pay instantly without QR upload + </message> <message name="IDS_PIX_PAYMENT_METHODS_BOTTOM_SHEET_DESCRIPTION" desc="Explanation text for the bottom sheet displaying user's PIX bank accounts linked to their GPay wallet. It is shown to prompt the user to pay directly on Chrome when a PIX payment page is detected." formatter_data="android_java"> Account info is encrypted and kept private </message>
diff --git a/components/facilitated_payments_strings_grdp/IDS_FACILITATED_PAYMENTS_NON_CARD_PAYMENT_METHODS_BOTTOM_SHEET_TITLE.png.sha1 b/components/facilitated_payments_strings_grdp/IDS_FACILITATED_PAYMENTS_NON_CARD_PAYMENT_METHODS_BOTTOM_SHEET_TITLE.png.sha1 new file mode 100644 index 0000000..94c32a76 --- /dev/null +++ b/components/facilitated_payments_strings_grdp/IDS_FACILITATED_PAYMENTS_NON_CARD_PAYMENT_METHODS_BOTTOM_SHEET_TITLE.png.sha1
@@ -0,0 +1 @@ +580cbf4bf0e63dfea40f273ef6a1a86653c412a5 \ No newline at end of file
diff --git a/components/feedback/redaction_tool/ip_address.cc b/components/feedback/redaction_tool/ip_address.cc index edafc65..9f7476a 100644 --- a/components/feedback/redaction_tool/ip_address.cc +++ b/components/feedback/redaction_tool/ip_address.cc
@@ -15,6 +15,7 @@ #include "base/check_op.h" #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/notreached.h" #include "base/strings/strcat.h" #include "base/strings/string_split.h" @@ -37,12 +38,12 @@ // * |ip_address| is at least |prefix_length_in_bits| (bits) long; // * |ip_prefix| is at least |prefix_length_in_bits| (bits) long. bool IPAddressPrefixCheck(const IPAddressBytes& ip_address, - const uint8_t* ip_prefix, + base::span<const uint8_t> ip_prefix, size_t prefix_length_in_bits) { // Compare all the bytes that fall entirely within the prefix. size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8; for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) { - if (ip_address[i] != UNSAFE_TODO(ip_prefix[i])) { + if (ip_address[i] != ip_prefix[i]) { return false; } } @@ -53,7 +54,7 @@ if (remaining_bits != 0) { uint8_t mask = 0xFF << (8 - remaining_bits); size_t i = num_entire_bytes_in_prefix; - if ((ip_address[i] & mask) != (UNSAFE_TODO(ip_prefix[i]) & mask)) { + if ((ip_address[i] & mask) != (ip_prefix[i] & mask)) { return false; } } @@ -276,7 +277,7 @@ 96 + prefix_length_in_bits); } - return IPAddressPrefixCheck(ip_address.bytes(), ip_prefix.bytes().data(), + return IPAddressPrefixCheck(ip_address.bytes(), ip_prefix.bytes(), prefix_length_in_bits); }
diff --git a/components/feedback/redaction_tool/redaction_tool.cc b/components/feedback/redaction_tool/redaction_tool.cc index ba2bc91..b712fd14 100644 --- a/components/feedback/redaction_tool/redaction_tool.cc +++ b/components/feedback/redaction_tool/redaction_tool.cc
@@ -15,6 +15,7 @@ #include <utility> #include <vector> +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/no_destructor.h" #include "base/strings/strcat.h" @@ -521,19 +522,28 @@ bool FindAndConsumeAndGetSkippedN(std::string_view* input, const re2::RE2& pattern, std::string_view* skipped_input, - std::string_view* args[], - int argc) { + base::span<std::string_view*> args, + int spanification_suspected_redundant_argc) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK(spanification_suspected_redundant_argc == static_cast<int>(args.size()), + base::NotFatalUntil::M143); std::string_view old_input = *input; - CHECK_GE(argc, 1); - re2::RE2::Arg a0(argc > 0 ? args[0] : nullptr); - re2::RE2::Arg a1(argc > 1 ? args[1] : nullptr); - re2::RE2::Arg a2(argc > 2 ? args[2] : nullptr); - re2::RE2::Arg a3(argc > 3 ? args[3] : nullptr); + CHECK_GE(spanification_suspected_redundant_argc, 1); + re2::RE2::Arg a0(spanification_suspected_redundant_argc > 0 ? args[0] + : nullptr); + re2::RE2::Arg a1(spanification_suspected_redundant_argc > 1 ? args[1] + : nullptr); + re2::RE2::Arg a2(spanification_suspected_redundant_argc > 2 ? args[2] + : nullptr); + re2::RE2::Arg a3(spanification_suspected_redundant_argc > 3 ? args[3] + : nullptr); const re2::RE2::Arg* const wrapped_args[] = {&a0, &a1, &a2, &a3}; - CHECK_LE(argc, 4); + CHECK_LE(spanification_suspected_redundant_argc, 4); - bool result = re2::RE2::FindAndConsumeN(input, pattern, wrapped_args, argc); + bool result = re2::RE2::FindAndConsumeN( + input, pattern, wrapped_args, spanification_suspected_redundant_argc); if (skipped_input && result) { size_t bytes_skipped = args[0]->data() - old_input.data();
diff --git a/components/global_media_controls/public/views/media_progress_view.cc b/components/global_media_controls/public/views/media_progress_view.cc index 9bf74e0..368f6c6 100644 --- a/components/global_media_controls/public/views/media_progress_view.cc +++ b/components/global_media_controls/public/views/media_progress_view.cc
@@ -12,6 +12,7 @@ #include "services/media_session/public/mojom/media_session.mojom.h" #include "third_party/skia/include/core/SkPath.h" #include "ui/accessibility/ax_action_data.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/gfx/canvas.h"
diff --git a/components/global_media_controls/public/views/media_progress_view_unittest.cc b/components/global_media_controls/public/views/media_progress_view_unittest.cc index ab7a474f..9bdbc3da 100644 --- a/components/global_media_controls/public/views/media_progress_view_unittest.cc +++ b/components/global_media_controls/public/views/media_progress_view_unittest.cc
@@ -5,6 +5,7 @@ #include "components/global_media_controls/public/views/media_progress_view.h" #include "base/i18n/rtl.h" +#include "base/test/icu_test_util.h" #include "base/timer/mock_timer.h" #include "components/strings/grit/components_strings.h" #include "services/media_session/public/mojom/media_session.mojom.h" @@ -65,8 +66,6 @@ progress_drag_started_delay_timer_ = mock_timer.get(); view_->set_progress_drag_started_delay_timer_for_testing( std::move(mock_timer)); - - default_locale_ = base::i18n::GetConfiguredLocale(); } void TearDown() override { @@ -75,7 +74,6 @@ progress_drag_started_delay_timer_ = nullptr; view_ = nullptr; widget_->Close(); - base::i18n::SetICUDefaultLocale(default_locale_); ViewsTestBase::TearDown(); } @@ -97,12 +95,12 @@ MOCK_METHOD1(OnProgressUpdated, void(base::TimeDelta)); private: + base::test::ScopedRestoreICUDefaultLocale restore_default_locale_; std::unique_ptr<views::Widget> widget_; raw_ptr<MediaProgressView> view_ = nullptr; raw_ptr<base::MockOneShotTimer> update_progress_timer_ = nullptr; raw_ptr<base::MockOneShotTimer> switch_progress_colors_delay_timer_ = nullptr; raw_ptr<base::MockOneShotTimer> progress_drag_started_delay_timer_ = nullptr; - std::string default_locale_; }; TEST_F(MediaProgressViewTest, MediaPlaying) {
diff --git a/components/headless/console_message_logger/BUILD.gn b/components/headless/console_message_logger/BUILD.gn new file mode 100644 index 0000000..491620d --- /dev/null +++ b/components/headless/console_message_logger/BUILD.gn
@@ -0,0 +1,30 @@ +# 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. + +source_set("console_message_logger") { + sources = [ + "headless_console_message_logger.cc", + "headless_console_message_logger.h", + ] + + deps = [ + "//base", + "//content/public/browser", + "//content/public/common", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "headless_console_message_logger_unittest.cc" ] + + deps = [ + ":console_message_logger", + "//base/test:test_support", + "//content/public/browser", + "//content/public/common", + "//testing/gmock", + "//testing/gtest", + ] +}
diff --git a/components/headless/console_message_logger/DEPS b/components/headless/console_message_logger/DEPS new file mode 100644 index 0000000..c24130e --- /dev/null +++ b/components/headless/console_message_logger/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+content/public/browser", + "+content/public/common", +]
diff --git a/components/headless/console_message_logger/headless_console_message_logger.cc b/components/headless/console_message_logger/headless_console_message_logger.cc new file mode 100644 index 0000000..39b74c1 --- /dev/null +++ b/components/headless/console_message_logger/headless_console_message_logger.cc
@@ -0,0 +1,52 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/headless/console_message_logger/headless_console_message_logger.h" + +#include "base/feature_list.h" +#include "base/logging.h" +#include "content/public/browser/console_message.h" +#include "content/public/common/content_features.h" + +namespace headless { + +namespace { + +const std::u16string TruncateDataUrl(const std::u16string& data_url) { + DCHECK(data_url.starts_with(u"data:")); + // data:[<media-type>][;base64],<data> + size_t data_index = data_url.find(u','); + if (data_index == std::string::npos) { + data_index = sizeof("data:") - 1; + } + return data_url.substr(0, data_index) + u"..."; +} + +} // namespace + +void LogConsoleMessage(blink::mojom::ConsoleMessageLevel log_level, + const std::u16string& message, + int32_t line_number, + bool is_builtin_component, + const std::u16string& source_id) { + const int32_t resolved_level = + is_builtin_component + ? content::ConsoleMessageLevelToLogSeverity(log_level) + : ::logging::LOGGING_INFO; + if (resolved_level < ::logging::GetMinLogLevel()) { + return; + } + + if (!base::FeatureList::IsEnabled(features::kLogJsConsoleMessages)) { + return; + } + + logging::LogMessage("CONSOLE", line_number, resolved_level).stream() + << "\"" << message << "\", source: " + << (source_id.starts_with(u"data:") ? TruncateDataUrl(source_id) + : source_id) + << " (" << line_number << ")"; +} + +} // namespace headless
diff --git a/components/headless/console_message_logger/headless_console_message_logger.h b/components/headless/console_message_logger/headless_console_message_logger.h new file mode 100644 index 0000000..3ea1cff --- /dev/null +++ b/components/headless/console_message_logger/headless_console_message_logger.h
@@ -0,0 +1,22 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_HEADLESS_CONSOLE_MESSAGE_LOGGER_HEADLESS_CONSOLE_MESSAGE_LOGGER_H_ +#define COMPONENTS_HEADLESS_CONSOLE_MESSAGE_LOGGER_HEADLESS_CONSOLE_MESSAGE_LOGGER_H_ + +#include "content/public/browser/console_message.h" + +namespace headless { + +// Alternate console message logger that logs JS messages while in incognito +// mode which is how headless runs most of the time. +void LogConsoleMessage(blink::mojom::ConsoleMessageLevel log_level, + const std::u16string& message, + int32_t line_number, + bool is_builtin_component, + const std::u16string& source_id); + +} // namespace headless + +#endif // COMPONENTS_HEADLESS_CONSOLE_MESSAGE_LOGGER_HEADLESS_CONSOLE_MESSAGE_LOGGER_H_
diff --git a/components/headless/console_message_logger/headless_console_message_logger_unittest.cc b/components/headless/console_message_logger/headless_console_message_logger_unittest.cc new file mode 100644 index 0000000..aec3b2f --- /dev/null +++ b/components/headless/console_message_logger/headless_console_message_logger_unittest.cc
@@ -0,0 +1,94 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/headless/console_message_logger/headless_console_message_logger.h" + +#include "base/logging.h" +#include "base/no_destructor.h" +#include "base/test/scoped_logging_settings.h" +#include "build/build_config.h" +#include "content/public/browser/console_message.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace headless { +namespace { + +class HeadlessConsoleMessageLoggerTest : public testing::Test { + public: + void SetUp() override { + logging::SetLogMessageHandler([](int severity, const char* file, int line, + size_t start, + const std::string& str) -> bool { + *log_string_ = str; + return true; + }); + + logging::SetLogItems(/*enable_process_id=*/false, + /*enable_thread_id=*/false, + /*enable_timestamp=*/false, + /*enable_tickcount=*/false); + } + + void TearDown() override { + logging::SetLogMessageHandler(nullptr); + log_string_->clear(); + } + + protected: + const std::string& log_string() const { return *log_string_; } + + private: + logging::ScopedLoggingSettings scoped_logging_settings_; + static base::NoDestructor<std::string> log_string_; +}; + +base::NoDestructor<std::string> HeadlessConsoleMessageLoggerTest::log_string_; + +TEST_F(HeadlessConsoleMessageLoggerTest, Basics) { + headless::LogConsoleMessage(blink::mojom::ConsoleMessageLevel::kError, + u"foobar", 42, /*is_builtin_component=*/false, + u"test.js"); + + const char kExpected[] = +#if BUILDFLAG(IS_CHROMEOS) + R"(INFO components_unittests: [CONSOLE:42] "foobar", source: test.js (42) +)"; +#else + R"([INFO:CONSOLE:42] "foobar", source: test.js (42) +)"; +#endif + EXPECT_THAT(log_string(), testing::StrEq(kExpected)); +} + +TEST_F(HeadlessConsoleMessageLoggerTest, BuiltInComponentLogLevel) { + // Log level for built-in components is respected. + headless::LogConsoleMessage(blink::mojom::ConsoleMessageLevel::kError, + u"foobar", 42, /*is_builtin_component=*/true, + u"test.js"); + EXPECT_THAT(log_string(), testing::HasSubstr("ERROR")); +} + +TEST_F(HeadlessConsoleMessageLoggerTest, DataUrl) { + // Data URL is logged with data portion truncated. + headless::LogConsoleMessage(blink::mojom::ConsoleMessageLevel::kError, + u"foobar", 42, /*is_builtin_component=*/false, + u"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///" + u"yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); + EXPECT_THAT(log_string(), + testing::HasSubstr( + R"(] "foobar", source: data:image/gif;base64... (42))")); +} + +TEST_F(HeadlessConsoleMessageLoggerTest, MalformedDataUrl) { + // Incomplete data URL is shortened to a minimum. + headless::LogConsoleMessage(blink::mojom::ConsoleMessageLevel::kError, + u"foobar", 42, /*is_builtin_component=*/false, + u"data:image/gif;base64"); + EXPECT_THAT(log_string(), + testing::HasSubstr(R"(] "foobar", source: data:... (42))")); +} + +} // namespace +} // namespace headless
diff --git a/components/history/core/browser/expire_history_backend_unittest.cc b/components/history/core/browser/expire_history_backend_unittest.cc index c16f6d1..03efb20 100644 --- a/components/history/core/browser/expire_history_backend_unittest.cc +++ b/components/history/core/browser/expire_history_backend_unittest.cc
@@ -12,7 +12,7 @@ #include <string> #include <utility> -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -85,8 +85,8 @@ protected: // Called by individual tests when they want data populated. - void AddExampleData(URLID url_ids[3], - base::Time visit_times[4], + void AddExampleData(base::span<URLID, 3> url_ids, + base::span<base::Time, 4> visit_times, bool set_app_id = false); // Returns true if the given favicon has an entry in the DB. @@ -225,18 +225,18 @@ // The IDs of the added URLs, and the times of the four added visits will be // added to the given arrays. If set_app_id is true, set the app_id to the // 2nd/3rd row for testing. -void ExpireHistoryTest::AddExampleData(URLID url_ids[3], - base::Time visit_times[4], +void ExpireHistoryTest::AddExampleData(base::span<URLID, 3> url_ids, + base::span<base::Time, 4> visit_times, bool set_app_id) { if (!main_db_) { return; } // Four times for each visit. - UNSAFE_TODO(visit_times[3]) = PretendNow(); - UNSAFE_TODO(visit_times[2]) = UNSAFE_TODO(visit_times[3]) - base::Days(1); - UNSAFE_TODO(visit_times[1]) = UNSAFE_TODO(visit_times[3]) - base::Days(2); - visit_times[0] = UNSAFE_TODO(visit_times[3]) - base::Days(3); + visit_times[3] = PretendNow(); + visit_times[2] = visit_times[3] - base::Days(1); + visit_times[1] = visit_times[3] - base::Days(2); + visit_times[0] = visit_times[3] - base::Days(3); // Two favicons. The first two URLs will share the same one, while the last // one will have a unique favicon. @@ -254,17 +254,17 @@ favicon::PageUrlType::kRegular); URLRow url_row2(GURL("http://www.google.com/2")); - url_row2.set_last_visit(UNSAFE_TODO(visit_times[2])); + url_row2.set_last_visit(visit_times[2]); url_row2.set_visit_count(2); url_row2.set_typed_count(1); - UNSAFE_TODO(url_ids[1]) = main_db_->AddURL(url_row2); + url_ids[1] = main_db_->AddURL(url_row2); thumb_db_->AddIconMapping(url_row2.url(), favicon1, favicon::PageUrlType::kRegular); URLRow url_row3(GURL("http://www.google.com/3")); - url_row3.set_last_visit(UNSAFE_TODO(visit_times[3])); + url_row3.set_last_visit(visit_times[3]); url_row3.set_visit_count(1); - UNSAFE_TODO(url_ids[2]) = main_db_->AddURL(url_row3); + url_ids[2] = main_db_->AddURL(url_row3); thumb_db_->AddIconMapping(url_row3.url(), favicon2, favicon::PageUrlType::kRegular); @@ -275,16 +275,16 @@ main_db_->AddVisit(&visit_row1, SOURCE_BROWSED); VisitRow visit_row2; - visit_row2.url_id = UNSAFE_TODO(url_ids[1]); - visit_row2.visit_time = UNSAFE_TODO(visit_times[1]); + visit_row2.url_id = url_ids[1]; + visit_row2.visit_time = visit_times[1]; if (set_app_id) { visit_row2.app_id = kTestAppId; } main_db_->AddVisit(&visit_row2, SOURCE_BROWSED); VisitRow visit_row3; - visit_row3.url_id = UNSAFE_TODO(url_ids[1]); - visit_row3.visit_time = UNSAFE_TODO(visit_times[2]); + visit_row3.url_id = url_ids[1]; + visit_row3.visit_time = visit_times[2]; visit_row3.transition = ui::PAGE_TRANSITION_TYPED; visit_row3.incremented_omnibox_typed_score = true; if (set_app_id) { @@ -293,8 +293,8 @@ main_db_->AddVisit(&visit_row3, SOURCE_BROWSED); VisitRow visit_row4; - visit_row4.url_id = UNSAFE_TODO(url_ids[2]); - visit_row4.visit_time = UNSAFE_TODO(visit_times[3]); + visit_row4.url_id = url_ids[2]; + visit_row4.visit_time = visit_times[3]; main_db_->AddVisit(&visit_row4, SOURCE_BROWSED); } @@ -598,7 +598,7 @@ // Deletes multiple URLs at once. The favicon for the third one but // not the first two should be deleted. TEST_F(ExpireHistoryTest, DeleteURLs) { - URLID url_ids[3]; + std::array<URLID, 3> url_ids; base::Time visit_times[4]; AddExampleData(url_ids, visit_times); @@ -609,7 +609,7 @@ // Push back a bogus URL (which shouldn't change anything). urls.push_back(GURL()); for (size_t i = 0; i < std::size(rows); ++i) { - UNSAFE_TODO(ASSERT_TRUE(main_db_->GetURLRow(url_ids[i], &rows[i]))); + ASSERT_TRUE(main_db_->GetURLRow(url_ids[i], &rows[i])); favicon_ids[i] = GetFavicon(rows[i].url(), favicon_base::IconType::kFavicon); EXPECT_TRUE(HasFavicon(favicon_ids[i]));
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc index c1ff2ba1..f8d09c5 100644 --- a/components/history/core/browser/history_backend_unittest.cc +++ b/components/history/core/browser/history_backend_unittest.cc
@@ -21,6 +21,7 @@ #include <utility> #include <vector> +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/bind.h" @@ -493,12 +494,12 @@ : nullptr; } - void AddRedirectChain(const char* sequence[], int nav_entry_id) { + void AddRedirectChain(base::span<const char*> sequence, int nav_entry_id) { AddRedirectChainWithTransitionAndTime( sequence, nav_entry_id, ui::PAGE_TRANSITION_LINK, base::Time::Now()); } - void AddRedirectChainWithTransitionAndTime(const char* sequence[], + void AddRedirectChainWithTransitionAndTime(base::span<const char*> sequence, int nav_entry_id, ui::PageTransition transition, base::Time time) {
diff --git a/components/history/core/browser/history_querying_unittest.cc b/components/history/core/browser/history_querying_unittest.cc index 5dc8ca4..992d8b4 100644 --- a/components/history/core/browser/history_querying_unittest.cc +++ b/components/history/core/browser/history_querying_unittest.cc
@@ -7,7 +7,7 @@ #include <array> #include <memory> -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -117,19 +117,18 @@ // Defined here so code can be shared for the text search and the non-text // seach versions. void TestPaging(const std::string& query_text, - const int* expected_results, - int results_length) { + base::span<const int> expected_results) { ASSERT_TRUE(history_.get()); QueryOptions options; QueryResults results; options.max_count = 1; - for (int i = 0; i < results_length; i++) { + for (size_t i = 0; i < expected_results.size(); i++) { SCOPED_TRACE(testing::Message() << "i = " << i); QueryHistory(query_text, options, &results); ASSERT_EQ(1U, results.size()); - UNSAFE_TODO(EXPECT_TRUE(NthResultIs(results, 0, expected_results[i]))); + EXPECT_TRUE(NthResultIs(results, 0, expected_results[i])); options.end_time = results.back().visit_time(); } QueryHistory(query_text, options, &results); @@ -138,14 +137,12 @@ // Try with a max_count > 1. options.max_count = 2; options.end_time = base::Time(); - for (int i = 0; i < results_length / 2; i++) { + for (size_t i = 0; i < expected_results.size() / 2; i++) { SCOPED_TRACE(testing::Message() << "i = " << i); QueryHistory(query_text, options, &results); ASSERT_EQ(2U, results.size()); - UNSAFE_TODO( - EXPECT_TRUE(NthResultIs(results, 0, expected_results[i * 2]))); - UNSAFE_TODO( - EXPECT_TRUE(NthResultIs(results, 1, expected_results[i * 2 + 1]))); + EXPECT_TRUE(NthResultIs(results, 0, expected_results[i * 2])); + EXPECT_TRUE(NthResultIs(results, 1, expected_results[i * 2 + 1])); options.end_time = results.back().visit_time(); } @@ -478,15 +475,15 @@ // Since results are fetched 1 and 2 at a time, entry #0 and #6 will not // be de-duplicated. int expected_results[] = {4, 2, 3, 1, 7, 6, 5, 8, 9, 10, 11, 12, 13, 14, 0}; - TestPaging(std::string(), expected_results, std::size(expected_results)); + TestPaging(std::string(), expected_results); } TEST_F(HistoryQueryTest, TextSearchPaging) { // Since results are fetched 1 and 2 at a time, entry #0 and #6 will not // be de-duplicated. Entry #4 does not contain the text "title", so it // shouldn't appear. - int expected_results[] = { 2, 3, 1, 7, 6, 5 }; - TestPaging("title", expected_results, std::size(expected_results)); + int expected_results[] = {2, 3, 1, 7, 6, 5}; + TestPaging("title", expected_results); } } // namespace history
diff --git a/components/history/core/browser/visit_tracker_unittest.cc b/components/history/core/browser/visit_tracker_unittest.cc index 700127c..4aa9023d 100644 --- a/components/history/core/browser/visit_tracker_unittest.cc +++ b/components/history/core/browser/visit_tracker_unittest.cc
@@ -4,7 +4,7 @@ #include "components/history/core/browser/visit_tracker.h" -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "testing/gtest/include/gtest/gtest.h" namespace history { @@ -41,9 +41,10 @@ test_data.visit_id); } -void RunTest(VisitTracker* tracker, VisitToTest* test, int test_count) { - for (int i = 0; i < test_count; i++) - AddVisitToTracker(UNSAFE_TODO(test[i]), tracker); +void RunTest(VisitTracker* tracker, base::span<VisitToTest> test) { + for (size_t i = 0; i < test.size(); i++) { + AddVisitToTracker(test[i], tracker); + } } } // namespace @@ -61,7 +62,7 @@ }; VisitTracker tracker; - RunTest(&tracker, test_simple, std::size(test_simple)); + RunTest(&tracker, test_simple); } // Test that referrer is properly computed when there are different frame @@ -83,7 +84,7 @@ }; VisitTracker tracker; - RunTest(&tracker, test_frames, std::size(test_frames)); + RunTest(&tracker, test_frames); } // Test frame navigation to make sure that the referrer is properly computed @@ -105,7 +106,7 @@ }; VisitTracker tracker; - RunTest(&tracker, test_processes, std::size(test_processes)); + RunTest(&tracker, test_processes); } // Test that processes get removed properly. @@ -117,7 +118,7 @@ }; VisitTracker tracker; - RunTest(&tracker, part1, std::size(part1)); + RunTest(&tracker, part1); // Say that context has been invalidated. tracker.ClearCachedDataForContextID(1); @@ -127,7 +128,7 @@ VisitToTest part2[] = { {1, 1, "http://images.google.com/", 2, "http://www.google.com/", 0}, }; - RunTest(&tracker, part2, std::size(part2)); + RunTest(&tracker, part2); } TEST(VisitTracker, RemoveVisitById) { @@ -138,7 +139,7 @@ }; VisitTracker tracker; - RunTest(&tracker, test_simple, std::size(test_simple)); + RunTest(&tracker, test_simple); // Remove the first visit. const VisitToTest& removed = test_simple[0]; @@ -185,7 +186,7 @@ }; VisitTracker tracker; - RunTest(&tracker, test_simple, std::size(test_simple)); + RunTest(&tracker, test_simple); EXPECT_FALSE(tracker.IsEmpty()); tracker.Clear(); EXPECT_TRUE(tracker.IsEmpty());
diff --git a/components/live_caption/views/caption_bubble.cc b/components/live_caption/views/caption_bubble.cc index e67bf5f1..97ca397 100644 --- a/components/live_caption/views/caption_bubble.cc +++ b/components/live_caption/views/caption_bubble.cc
@@ -35,6 +35,7 @@ #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/platform/ax_mode_observer.h" #include "ui/base/buildflags.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/hit_test.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h"
diff --git a/components/live_caption/views/translation_view_wrapper_base.cc b/components/live_caption/views/translation_view_wrapper_base.cc index f26ca9ad..96aa15d7 100644 --- a/components/live_caption/views/translation_view_wrapper_base.cc +++ b/components/live_caption/views/translation_view_wrapper_base.cc
@@ -18,6 +18,7 @@ #include "components/translate/core/browser/translate_ui_languages_manager.h" #include "components/vector_icons/vector_icons.h" #include "media/base/media_switches.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h"
diff --git a/components/manta/base_provider.cc b/components/manta/base_provider.cc index 3c48254..9c98029 100644 --- a/components/manta/base_provider.cc +++ b/components/manta/base_provider.cc
@@ -14,7 +14,6 @@ namespace { constexpr endpoint_fetcher::HttpMethod kHttpMethod = endpoint_fetcher::HttpMethod::kPost; -constexpr char kHttpMethodString[] = "POST"; constexpr char kHttpContentType[] = "application/x-protobuf"; constexpr char kOAuthScope[] = "https://www.googleapis.com/auth/mdi.aratea"; constexpr char kAutopushEndpointUrl[] = @@ -136,16 +135,18 @@ const std::vector<std::string>& scopes{kOAuthScope}; return std::make_unique<EndpointFetcher>( /*url_loader_factory=*/url_loader_factory_, - /*oauth_consumer_name=*/oauth_consumer_name, - /*url=*/url, - /*http_method=*/kHttpMethodString, - /*content_type=*/kHttpContentType, - /*scopes=*/scopes, - /*timeout=*/timeout, - /*post_data=*/post_data, - /*annotation_tag=*/annotation_tag, /*identity_manager=*/identity_manager_observation_.GetSource(), - /*consent_level=*/signin::ConsentLevel::kSignin); + EndpointFetcher::RequestParams::Builder(/*method=*/kHttpMethod, + /*annotation_tag=*/annotation_tag) + .SetAuthType(endpoint_fetcher::OAUTH) + .SetConsentLevel(signin::ConsentLevel::kSignin) + .SetContentType(kHttpContentType) + .SetTimeout(timeout) + .SetUrl(url) + .SetOauthScopes(scopes) + .SetOauthConsumerName(oauth_consumer_name) + .SetPostData(post_data) + .Build()); } std::unique_ptr<EndpointFetcher> BaseProvider::CreateEndpointFetcherForDemoMode(
diff --git a/components/manta/base_provider_test_helper.cc b/components/manta/base_provider_test_helper.cc index 284bff33..fe4dd84 100644 --- a/components/manta/base_provider_test_helper.cc +++ b/components/manta/base_provider_test_helper.cc
@@ -21,7 +21,8 @@ constexpr char kMockOAuthConsumerName[] = "mock_oauth_consumer_name"; constexpr char kMockScope[] = "mock_scope"; constexpr char kMockEndpoint[] = "https://my-endpoint.com"; -constexpr char kHttpMethod[] = "POST"; +constexpr endpoint_fetcher::HttpMethod kHttpMethod = + endpoint_fetcher::HttpMethod::kPost; constexpr char kMockContentType[] = "mock_content_type"; constexpr char kEmail[] = "mock_email@gmail.com"; } // namespace @@ -46,17 +47,18 @@ .Run(nullptr, {MantaStatusCode::kNoIdentityManager}); return; } - auto fetcher = std::make_unique<EndpointFetcher>( /*url_loader_factory=*/url_loader_factory_, - /*oauth_consumer_name=*/kMockOAuthConsumerName, - /*url=*/GURL{kMockEndpoint}, - /*http_method=*/kHttpMethod, /*content_type=*/kMockContentType, - /*scopes=*/std::vector<std::string>{kMockScope}, - /*timeout=*/kMockTimeout, /*post_data=*/request.SerializeAsString(), - /*annotation_tag=*/TRAFFIC_ANNOTATION_FOR_TESTS, - /*identity_manager=*/identity_manager_observation_.GetSource(), - /*consent_level=*/signin::ConsentLevel::kSync); + identity_manager_observation_.GetSource(), + EndpointFetcher::RequestParams::Builder(kHttpMethod, annotation_tag) + .SetConsentLevel(signin::ConsentLevel::kSync) + .SetContentType(kMockContentType) + .SetTimeout(kMockTimeout) + .SetUrl(GURL{kMockEndpoint}) + .SetOauthScopes(std::vector<std::string>{kMockScope}) + .SetOauthConsumerName(kMockOAuthConsumerName) + .SetPostData(request.SerializeAsString()) + .Build()); EndpointFetcher* const fetcher_ptr = fetcher.get(); fetcher_ptr->Fetch(base::BindOnce(&OnEndpointFetcherComplete,
diff --git a/components/media_router/common/providers/cast/certificate/net_trust_store.cc b/components/media_router/common/providers/cast/certificate/net_trust_store.cc index c412155..41c22ba 100644 --- a/components/media_router/common/providers/cast/certificate/net_trust_store.cc +++ b/components/media_router/common/providers/cast/certificate/net_trust_store.cc
@@ -7,7 +7,7 @@ #include <string_view> #include "base/check.h" -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/logging.h" @@ -61,8 +61,7 @@ // TODO(issuetracker.google.com/222145200): We need to allow linking this // implementation into `openscreen_unittests` when in the chromium waterfall. auto result = std::make_unique<cast_certificate::NetTrustStore>(); - result->AddAnchor(UNSAFE_TODO( - base::span(trust_anchor_der.cbegin(), trust_anchor_der.cend()))); + result->AddAnchor(trust_anchor_der); return result; } @@ -77,9 +76,7 @@ auto result = std::make_unique<cast_certificate::NetTrustStore>(); while (tokenizer.GetNext()) { const std::string& data = tokenizer.data(); - auto* data_ptr = reinterpret_cast<const uint8_t*>(data.data()); - result->AddAnchor(UNSAFE_TODO( - base::span<const uint8_t>(data_ptr, data_ptr + data.size()))); + result->AddAnchor(base::as_byte_span(data)); } return result; }
diff --git a/components/omnibox/browser/actions/omnibox_action.cc b/components/omnibox/browser/actions/omnibox_action.cc index 9ceeb9a..77300b1 100644 --- a/components/omnibox/browser/actions/omnibox_action.cc +++ b/components/omnibox/browser/actions/omnibox_action.cc
@@ -77,8 +77,12 @@ // ============================================================================= -OmniboxAction::OmniboxAction(LabelStrings strings, GURL url) - : strings_(strings), url_(url) {} +OmniboxAction::OmniboxAction(LabelStrings strings, + GURL url, + bool show_as_action_button) + : strings_(strings), + url_(url), + show_as_action_button_(show_as_action_button) {} OmniboxAction::~OmniboxAction() { #if BUILDFLAG(IS_ANDROID)
diff --git a/components/omnibox/browser/actions/omnibox_action.h b/components/omnibox/browser/actions/omnibox_action.h index cae1cef..bb6c049c 100644 --- a/components/omnibox/browser/actions/omnibox_action.h +++ b/components/omnibox/browser/actions/omnibox_action.h
@@ -157,7 +157,9 @@ int enter_starter_pack_id_; }; - OmniboxAction(LabelStrings strings, GURL url); + OmniboxAction(LabelStrings strings, + GURL url, + bool show_as_action_button = false); // Provides read access to labels associated with this Action. const LabelStrings& GetLabelStrings() const; @@ -215,6 +217,9 @@ // For navigation Actions, this holds the destination URL. Otherwise, empty. GURL url_; + // Whether to show as action button. + bool show_as_action_button_; + #if BUILDFLAG(IS_ANDROID) mutable base::android::ScopedJavaGlobalRef<jobject> j_omnibox_action_; #endif
diff --git a/components/omnibox/browser/actions/omnibox_action_factory_android.cc b/components/omnibox/browser/actions/omnibox_action_factory_android.cc index eb857f77..7b19bea 100644 --- a/components/omnibox/browser/actions/omnibox_action_factory_android.cc +++ b/components/omnibox/browser/actions/omnibox_action_factory_android.cc
@@ -52,14 +52,15 @@ const std::u16string& hint, const std::u16string& accessibility_hint, int action_type, - const std::string& action_uri) { + const std::string& action_uri, + bool show_as_action_button) { return base::android::ScopedJavaGlobalRef<jobject>( Java_OmniboxActionFactory_buildActionInSuggest( env, g_java_factory.Get(), instance, base::android::ConvertUTF16ToJavaString(env, hint), base::android::ConvertUTF16ToJavaString(env, accessibility_hint), - action_type, - base::android::ConvertUTF8ToJavaString(env, action_uri))); + action_type, base::android::ConvertUTF8ToJavaString(env, action_uri), + show_as_action_button)); } base::android::ScopedJavaGlobalRef<jobject> BuildOmniboxAnswerAction(
diff --git a/components/omnibox/browser/actions/omnibox_action_factory_android.h b/components/omnibox/browser/actions/omnibox_action_factory_android.h index 5019cbbe..84ec281 100644 --- a/components/omnibox/browser/actions/omnibox_action_factory_android.h +++ b/components/omnibox/browser/actions/omnibox_action_factory_android.h
@@ -32,7 +32,8 @@ const std::u16string& hint, const std::u16string& accessibility_hint, int action_type, - const std::string& action_uri); + const std::string& action_uri, + bool show_as_action_button); base::android::ScopedJavaGlobalRef<jobject> BuildOmniboxAnswerAction( JNIEnv* env,
diff --git a/components/omnibox/browser/actions/omnibox_action_in_suggest.cc b/components/omnibox/browser/actions/omnibox_action_in_suggest.cc index e74c0ab4..2130fe1 100644 --- a/components/omnibox/browser/actions/omnibox_action_in_suggest.cc +++ b/components/omnibox/browser/actions/omnibox_action_in_suggest.cc
@@ -100,6 +100,12 @@ } NOTREACHED() << "Unrecognized action type: " << action_type; } + +constexpr bool AllowAsActionButton( + const omnibox::SuggestTemplateInfo::TemplateAction& action) { + return action.action_type() == + omnibox::SuggestTemplateInfo_TemplateAction_ActionType_CHROME_AIM; +} } // namespace OmniboxActionInSuggest::OmniboxActionInSuggest( @@ -110,7 +116,8 @@ ToActionContents(template_action.action_type()), IDS_ACC_OMNIBOX_ACTION_IN_SUGGEST_SUFFIX, ToActionContents(template_action.action_type())), - {}), + {}, + AllowAsActionButton(template_action)), template_action{std::move(template_action)}, search_terms_args{std::move(search_terms_args)} {} @@ -123,7 +130,7 @@ j_omnibox_action_.Reset(BuildOmniboxActionInSuggest( env, reinterpret_cast<intptr_t>(this), strings_.hint, strings_.accessibility_hint, template_action.action_type(), - template_action.action_uri())); + template_action.action_uri(), show_as_action_button_)); } return base::android::ScopedJavaLocalRef<jobject>(j_omnibox_action_); }
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java index ecf89f2..5e28a5b 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java
@@ -60,6 +60,9 @@ public final int primaryTextAppearance; + /** Whether to show it as action button. */ + public final boolean showAsActionButton; + /** The corresponding native instance, or 0 if the native instance is not available. */ private long mNativeInstance; @@ -69,13 +72,15 @@ String hint, String accessibilityHint, ChipIcon icon, - int primaryTextAppearance) { + int primaryTextAppearance, + boolean showAsActionButton) { assert !TextUtils.isEmpty(hint); this.actionId = actionId; this.hint = hint; this.accessibilityHint = accessibilityHint; this.icon = icon; this.primaryTextAppearance = primaryTextAppearance; + this.showAsActionButton = showAsActionButton; mNativeInstance = nativeInstance; }
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java index 929a29b..36e9cde 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java
@@ -33,6 +33,7 @@ * @param actionType the specific type of an action matching the {@link * SuggestTemplateInfo.TemplateAction.ActionType} * @param actionUri the corresponding action URI/URL (serialized intent) + * @param showAsActionButton whether to show it as action button * @return new instance of an OmniboxActionInSuggest */ @CalledByNative @@ -41,7 +42,8 @@ String hint, String accessibilityHint, /* SuggestTemplateInfo.TemplateAction.ActionType */ int actionType, - String actionUri); + String actionUri, + boolean showAsActionButton); /** * Construct a new OmniboxAnswerAction.
diff --git a/components/omnibox/browser/autocomplete_provider_client.cc b/components/omnibox/browser/autocomplete_provider_client.cc index dfea44da..7b34d90e 100644 --- a/components/omnibox/browser/autocomplete_provider_client.cc +++ b/components/omnibox/browser/autocomplete_provider_client.cc
@@ -61,6 +61,10 @@ return false; } +bool AutocompleteProviderClient::IsAimEligible() const { + return false; +} + base::WeakPtr<AutocompleteProviderClient> AutocompleteProviderClient::GetWeakPtr() { return nullptr;
diff --git a/components/omnibox/browser/autocomplete_provider_client.h b/components/omnibox/browser/autocomplete_provider_client.h index db47e6e..88f3163 100644 --- a/components/omnibox/browser/autocomplete_provider_client.h +++ b/components/omnibox/browser/autocomplete_provider_client.h
@@ -37,6 +37,7 @@ class ZeroSuggestCacheService; struct AutocompleteMatch; struct ProviderStateService; +class AimEligibilityService; namespace bookmarks { class BookmarkModel; @@ -116,6 +117,7 @@ virtual base::CallbackListSubscription GetLensSuggestInputsWhenReady( LensOverlaySuggestInputsCallback callback) const = 0; virtual tab_groups::TabGroupSyncService* GetTabGroupSyncService() const = 0; + virtual AimEligibilityService* GetAimEligibilityService() const = 0; // The value to use for Accept-Languages HTTP header when making an HTTP // request. @@ -248,6 +250,9 @@ virtual void set_in_background_state(bool in_background_state) {} + // Returns true if AI mode is enabled. + virtual bool IsAimEligible() const; + // Gets a weak pointer to the client. Used when providers need to use the // client when the client may no longer be around. virtual base::WeakPtr<AutocompleteProviderClient> GetWeakPtr();
diff --git a/components/omnibox/browser/contextual_search_provider.cc b/components/omnibox/browser/contextual_search_provider.cc index 8d6c5fb..f916efee 100644 --- a/components/omnibox/browser/contextual_search_provider.cc +++ b/components/omnibox/browser/contextual_search_provider.cc
@@ -41,7 +41,6 @@ #include "components/omnibox/browser/suggestion_group_util.h" #include "components/omnibox/browser/zero_suggest_provider.h" #include "components/omnibox/common/omnibox_feature_configs.h" -#include "components/search/search.h" #include "components/search_engines/search_engine_type.h" #include "components/search_engines/search_terms_data.h" #include "components/search_engines/template_url.h" @@ -147,15 +146,13 @@ // - Restricted to when `kAiModeOmniboxEntryPoint` is disabled // - Restricted to DSE google - // - Restricted to locale EN + // - Restricted to country US + // - Restricted to locale en-US // - Restricted to when `kAIModeSettings` policy is enabled toolbelt_ai_mode = toolbelt && !base::FeatureList::IsEnabled(omnibox::kAiModeOmniboxEntryPoint) && - search::DefaultSearchProviderIsGoogle( - client->GetTemplateURLService()) && - l10n_util::GetLanguage(client->GetApplicationLocale()) == "en" && - omnibox::IsAimAllowedByPolicy(client->GetPrefs()) && + client->IsAimEligible() && ToolbeltActionEligible( input, client, toolbelt_config.show_ai_mode_action_on_non_ntp, toolbelt_config.show_ai_mode_action_on_ntp,
diff --git a/components/omnibox/browser/featured_search_provider.cc b/components/omnibox/browser/featured_search_provider.cc index ad7cb33..0f553dc8 100644 --- a/components/omnibox/browser/featured_search_provider.cc +++ b/components/omnibox/browser/featured_search_provider.cc
@@ -289,27 +289,34 @@ for (TemplateURL* turl : turls) { if (turl->starter_pack_id() > 0 && turl->is_active() == TemplateURLData::ActiveStatus::kTrue) { - // Don't add the expanded set of starter pack engines unless the feature - // is enabled. - if ((turl->starter_pack_id() == template_url_starter_pack_data::kGemini && - !OmniboxFieldTrial::IsStarterPackExpansionEnabled()) || - (turl->starter_pack_id() == template_url_starter_pack_data::kPage && - !omnibox_feature_configs::ContextualSearch::Get() - .starter_pack_page)) { + // Skip @gemini if feature disabled. + if (turl->starter_pack_id() == template_url_starter_pack_data::kGemini && + !OmniboxFieldTrial::IsStarterPackExpansionEnabled()) { + continue; + } + // Skip @page if feature disabled. + if (turl->starter_pack_id() == template_url_starter_pack_data::kPage && + !omnibox_feature_configs::ContextualSearch::Get().starter_pack_page) { + continue; + } + // Skip @aimode if feature disabled. + if (turl->starter_pack_id() == template_url_starter_pack_data::kAiMode && + (!omnibox_feature_configs::Toolbelt::Get().enabled || + !client_->IsAimEligible())) { continue; } // The history starter pack engine is disabled in incognito mode. - if (client_->IsOffTheRecord() && - turl->starter_pack_id() == template_url_starter_pack_data::kHistory) { + if (turl->starter_pack_id() == template_url_starter_pack_data::kHistory && + client_->IsOffTheRecord()) { continue; } AddStarterPackMatch(*turl, input); - // Don't add enterprise search aggregator engines in incognito mode. } else if (turl->featured_by_policy() && IsEnterpriseSearchAggregatorTemplateURLEnabled( *turl, client_->IsOffTheRecord()) && turl->is_active() == TemplateURLData::ActiveStatus::kTrue && enterprise_count < kMaxEnterpriseSuggestions) { + // Don't add enterprise search aggregator engines in incognito mode. AddFeaturedEnterpriseSearchMatch(*turl, input); enterprise_count++; }
diff --git a/components/omnibox/browser/featured_search_provider_unittest.cc b/components/omnibox/browser/featured_search_provider_unittest.cc index a8ceef9..1e5336d1 100644 --- a/components/omnibox/browser/featured_search_provider_unittest.cc +++ b/components/omnibox/browser/featured_search_provider_unittest.cc
@@ -91,7 +91,9 @@ ~FeaturedSearchProviderTest() override = default; void SetUp() override { + toolbelt_scoped_config_.Get().enabled = true; client_ = std::make_unique<FakeAutocompleteProviderClient>(); + ON_CALL(*client_, IsAimEligible()).WillByDefault(testing::Return(true)); provider_ = new FeaturedSearchProvider(client_.get()); omnibox::RegisterProfilePrefs( static_cast<sync_preferences::TestingPrefServiceSyncable*>( @@ -179,6 +181,9 @@ std::make_unique<TemplateURL>(template_url_data)); } + omnibox_feature_configs::ScopedConfigForTesting< + omnibox_feature_configs::Toolbelt> + toolbelt_scoped_config_; std::unique_ptr<MockAutocompleteProviderClient> client_; scoped_refptr<FeaturedSearchProvider> provider_; };
diff --git a/components/omnibox/browser/mock_autocomplete_provider_client.h b/components/omnibox/browser/mock_autocomplete_provider_client.h index a6b4f39..4541d90 100644 --- a/components/omnibox/browser/mock_autocomplete_provider_client.h +++ b/components/omnibox/browser/mock_autocomplete_provider_client.h
@@ -138,6 +138,10 @@ return mock_tab_group_sync_service_.get(); } + AimEligibilityService* GetAimEligibilityService() const override { + return nullptr; + } + MOCK_CONST_METHOD0(GetAcceptLanguages, std::string()); MOCK_CONST_METHOD0(GetEmbedderRepresentationOfAboutScheme, std::string()); MOCK_METHOD0(GetBuiltinURLs, std::vector<std::u16string>()); @@ -158,6 +162,7 @@ MOCK_CONST_METHOD1(GetLensSuggestInputsWhenReady, base::CallbackListSubscription( LensOverlaySuggestInputsCallback callback)); + MOCK_METHOD(bool, IsAimEligible, (), (const)); MOCK_METHOD6( Classify,
diff --git a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java index 794f2f8..02d202c 100644 --- a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java +++ b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java
@@ -8,7 +8,6 @@ import android.text.format.DateUtils; import androidx.annotation.IntDef; -import androidx.annotation.VisibleForTesting; import com.google.android.gms.location.Priority; @@ -127,16 +126,11 @@ public static final CachedFlag sJumpStartOmnibox = newFlag(OmniboxFeatureList.JUMP_START_OMNIBOX, FeatureState.ENABLED_IN_TEST); - /** See {@link #shouldRetainOmniboxOnFocus()}. */ - @VisibleForTesting - public static final CachedFlag sRetainOmniboxOnFocus = - newFlag(OmniboxFeatureList.RETAIN_OMNIBOX_ON_FOCUS, FeatureState.ENABLED_IN_TEST); - public static final CachedFlag sPostDelayedTaskFocusTab = newFlag(OmniboxFeatureList.POST_DELAYED_TASK_FOCUS_TAB, FeatureState.ENABLED_IN_PROD); public static final CachedFlag sOmniboxMobileParityUpdate = - newFlag(OmniboxFeatureList.OMNIBOX_MOBILE_PARITY_UPDATE, FeatureState.ENABLED_IN_TEST); + newFlag(OmniboxFeatureList.OMNIBOX_MOBILE_PARITY_UPDATE, FeatureState.ENABLED_IN_PROD); public static final CachedFlag sOmniboxMobileParityUpdateV2 = newFlag( @@ -398,8 +392,7 @@ if (sShouldRetainOmniboxOnFocusForTesting != null) { return sShouldRetainOmniboxOnFocusForTesting; } - return sRetainOmniboxOnFocus.isEnabled() - && DeviceFormFactor.isTablet() + return DeviceFormFactor.isTablet() && DeviceInput.supportsAlphabeticKeyboard() && DeviceInput.supportsPrecisionPointer(); }
diff --git a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeaturesTest.java b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeaturesTest.java index 7cafe57d..ca7bbe7 100644 --- a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeaturesTest.java +++ b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeaturesTest.java
@@ -17,8 +17,6 @@ import org.robolectric.ParameterizedRobolectricTestRunner.Parameters; import org.chromium.base.test.BaseRobolectricTestRule; -import org.chromium.base.test.util.Features.DisableFeatures; -import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.base.DeviceInput; @@ -78,25 +76,9 @@ @Test @SmallTest - @DisableFeatures(OmniboxFeatureList.RETAIN_OMNIBOX_ON_FOCUS) - public void testShouldRetainOmniboxOnFocus_withFeatureExplicitlyDisabled() { - testShouldRetainOmniboxOnFocus(/* expectFeatureEnabled= */ false); - } - - @Test - @SmallTest - @EnableFeatures(OmniboxFeatureList.RETAIN_OMNIBOX_ON_FOCUS) - public void testShouldRetainOmniboxOnFocus_withFeatureExplicitlyEnabled() { - testShouldRetainOmniboxOnFocus(/* expectFeatureEnabled= */ true); - } - - private void testShouldRetainOmniboxOnFocus(boolean expectFeatureEnabled) { - boolean featureEnabled = OmniboxFeatures.sRetainOmniboxOnFocus.isEnabled(); - Assert.assertEquals(expectFeatureEnabled, featureEnabled); - - boolean expectRetainOmniboxOnFocus = - featureEnabled - && mDeviceFormFactorIsTablet + public void testShouldRetainOmniboxOnFocus() { + final boolean expectRetainOmniboxOnFocus = + mDeviceFormFactorIsTablet && mDeviceInputSupportsAlphabeticKeyboard && mDeviceInputSupportsPrecisionPointer;
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index 4ebda5f..324bf324 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -315,7 +315,7 @@ // Updates various NTP/Omnibox assets and descriptions for visual alignment on // Android and iOS. -BASE_FEATURE(kOmniboxMobileParityUpdate, "OmniboxMobileParityUpdate", DISABLED); +BASE_FEATURE(kOmniboxMobileParityUpdate, "OmniboxMobileParityUpdate", ENABLED); // Updates various NTP/Omnibox assets and descriptions for visual alignment on // Android and iOS, V2. @@ -397,14 +397,6 @@ // scripts (e.g. Burmese). BASE_FEATURE(kOmniboxElegantTextHeight, "OmniboxElegantTextHeight", ENABLED); -// Whether the contents of the omnibox should be retained on focus as opposed to -// being cleared. When this feature flag is enabled and the omnibox contents are -// retained, focus events will also result in the omnibox contents being fully -// selected so as to allow for easy replacement by the user. Note that even with -// this feature flag enabled, only large screen devices with an attached -// keyboard and precision pointer will exhibit a change in behavior. -BASE_FEATURE(kRetainOmniboxOnFocus, "RetainOmniboxOnFocus", ENABLED); - // Accelerates time from cold start to focused Omnibox on low-end devices, // prioritizing Omnibox focus and background initialization. BASE_FEATURE(kJumpStartOmnibox, "JumpStartOmnibox", DISABLED); @@ -438,7 +430,6 @@ &kRichAutocompletion, &kUseFusedLocationProvider, &kOmniboxElegantTextHeight, - &kRetainOmniboxOnFocus, &kJumpStartOmnibox, &kAndroidHubSearchTabGroups, &kPostDelayedTaskFocusTab,
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h index 4530555..18e0642 100644 --- a/components/omnibox/common/omnibox_features.h +++ b/components/omnibox/common/omnibox_features.h
@@ -155,7 +155,6 @@ #if BUILDFLAG(IS_ANDROID) BASE_DECLARE_FEATURE(kDiagnostics); -BASE_DECLARE_FEATURE(kRetainOmniboxOnFocus); BASE_DECLARE_FEATURE(kJumpStartOmnibox); BASE_DECLARE_FEATURE(kSuppressIntermediateACUpdatesOnLowEndDevices); // Delay focusTab to prioritize navigation (https://crbug.com/374852568).
diff --git a/components/omnibox/composebox/composebox_metrics_recorder.cc b/components/omnibox/composebox/composebox_metrics_recorder.cc index 5743756..451cec4b 100644 --- a/components/omnibox/composebox/composebox_metrics_recorder.cc +++ b/components/omnibox/composebox/composebox_metrics_recorder.cc
@@ -9,6 +9,9 @@ #include "components/omnibox/composebox/composebox_query.mojom.h" #include "components/omnibox/composebox/composebox_query_controller.h" +using composebox::SessionMetrics; +using composebox::SessionState; + namespace { const char kComposeboxFileDeleted[] = "Composebox.Session.File.DeletedCount"; const char kComposeboxSessionDuration[] = "Composebox.Session.Duration.Total";
diff --git a/components/omnibox/composebox/composebox_metrics_recorder.h b/components/omnibox/composebox/composebox_metrics_recorder.h index aa4e971..33d1f58 100644 --- a/components/omnibox/composebox/composebox_metrics_recorder.h +++ b/components/omnibox/composebox/composebox_metrics_recorder.h
@@ -14,14 +14,6 @@ #include "components/omnibox/composebox/composebox_query.mojom.h" #include "components/omnibox/composebox/composebox_query_controller.h" -enum class SessionState { - kNone = 0, - kSessionStarted = 1, - kSessionAbandoned = 2, - kQuerySubmitted = 3, - kNavigationOccurred = 4, -}; - // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. // Describes the query submission details. @@ -34,6 +26,16 @@ using FileUploadStatus = composebox_query::mojom::FileUploadStatus; +namespace composebox { + +enum class SessionState { + kNone = 0, + kSessionStarted = 1, + kSessionAbandoned = 2, + kQuerySubmitted = 3, + kNavigationOccurred = 4, +}; + struct SessionMetrics { SessionMetrics(); ~SessionMetrics(); @@ -54,6 +56,8 @@ int num_query_submissions = 0; }; +} // namespace composebox + class ComposeboxMetricsRecorder { public: explicit ComposeboxMetricsRecorder(std::string metric_component_name); @@ -61,7 +65,8 @@ // Should be called when there are session state changes to keep track of // session state metrics. Virtual for testing. - virtual void NotifySessionStateChanged(SessionState session_state); + virtual void NotifySessionStateChanged( + composebox::SessionState session_state); void OnFileUploadStatusChanged( lens::MimeType file_mime_type, @@ -104,8 +109,8 @@ // Resets all session metrics at the end of a session. void ResetSessionMetrics(); std::string metric_category_name_; - std::unique_ptr<SessionMetrics> session_metrics_; - SessionState session_state_ = SessionState::kNone; + std::unique_ptr<composebox::SessionMetrics> session_metrics_; + composebox::SessionState session_state_ = composebox::SessionState::kNone; }; #endif // COMPONENTS_OMNIBOX_COMPOSEBOX_COMPOSEBOX_METRICS_RECORDER_H_
diff --git a/components/omnibox/composebox/composebox_metrics_recorder_unittest.cc b/components/omnibox/composebox/composebox_metrics_recorder_unittest.cc index 56eb3e0..2ad0c2d7 100644 --- a/components/omnibox/composebox/composebox_metrics_recorder_unittest.cc +++ b/components/omnibox/composebox/composebox_metrics_recorder_unittest.cc
@@ -10,6 +10,8 @@ #include "components/omnibox/composebox/composebox_query_controller.h" #include "testing/gtest/include/gtest/gtest.h" +using composebox::SessionState; + namespace { const char kTestMetricName[] = "Test."; const char kComposeboxFileDeleted[] =
diff --git a/components/openscreen_platform/tls_connection_factory.cc b/components/openscreen_platform/tls_connection_factory.cc index 99b20a3..0f1e06f 100644 --- a/components/openscreen_platform/tls_connection_factory.cc +++ b/components/openscreen_platform/tls_connection_factory.cc
@@ -8,7 +8,8 @@ #include <utility> -#include "base/compiler_specific.h" +#include "base/containers/auto_spanification_helper.h" +#include "base/containers/span.h" #include "base/notimplemented.h" #include "components/openscreen_platform/network_context.h" #include "components/openscreen_platform/network_util.h" @@ -208,9 +209,8 @@ std::move(request.tls_socket)); CRYPTO_BUFFER* der_buffer = ssl_info.value().unverified_cert->cert_buffer(); - const uint8_t* data = CRYPTO_BUFFER_data(der_buffer); - std::vector<uint8_t> der_x509_certificate( - data, UNSAFE_TODO(data + CRYPTO_BUFFER_len(der_buffer))); + base::span<const uint8_t> data = UNSAFE_CRYPTO_BUFFER_DATA(der_buffer); + std::vector<uint8_t> der_x509_certificate(data.begin(), data.end()); client_->OnConnected(this, std::move(der_x509_certificate), std::move(tls_connection)); }
diff --git a/components/optimization_guide/proto/model_quality_service.proto b/components/optimization_guide/proto/model_quality_service.proto index 2dc883a..e7b5e02 100644 --- a/components/optimization_guide/proto/model_quality_service.proto +++ b/components/optimization_guide/proto/model_quality_service.proto
@@ -19,8 +19,10 @@ import "components/optimization_guide/proto/features/password_change_submission.proto"; import "components/optimization_guide/proto/features/permissions_ai.proto"; import "components/optimization_guide/proto/features/product_specifications.proto"; +import "components/optimization_guide/proto/features/prompt_api.proto"; import "components/optimization_guide/proto/features/proofreader_api.proto"; import "components/optimization_guide/proto/features/scam_detection.proto"; +import "components/optimization_guide/proto/features/summarize.proto"; import "components/optimization_guide/proto/features/tab_organization.proto"; import "components/optimization_guide/proto/features/wallpaper_search.proto"; import "components/optimization_guide/proto/features/writing_assistance_api.proto"; @@ -85,6 +87,10 @@ ProofreaderApiLoggingData proofreader_api = 25; + PromptApiLoggingData prompt_api = 26; + + SummarizeLoggingData summarize = 27; + DefaultLoggingData default = 1000; } }
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc index 6abb3e9..4798360 100644 --- a/components/page_info/page_info.cc +++ b/components/page_info/page_info.cc
@@ -1425,13 +1425,6 @@ return true; } -#if !BUILDFLAG(IS_ANDROID) - if (info.type == ContentSettingsType::WEB_APP_INSTALLATION && - base::FeatureList::IsEnabled(blink::features::kWebAppInstallation)) { - return true; - } -#endif // !BUILDFLAG(IS_ANDROID) - return false; }
diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc index 213cafa..d164ce50 100644 --- a/components/page_info/page_info_ui.cc +++ b/components/page_info/page_info_ui.cc
@@ -675,7 +675,7 @@ bool is_one_time) { ContentSetting effective_setting = GetEffectiveSetting(type, setting, default_setting); - const int* button_text_ids = nullptr; + base::span<const int> button_text_ids; switch (source) { case SettingSource::kUser: if (setting == CONTENT_SETTING_DEFAULT) {
diff --git a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc index 00df2863..1e71625 100644 --- a/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc +++ b/components/page_load_metrics/browser/observers/use_counter/ukm_features.cc
@@ -113,12 +113,6 @@ WebFeature::kLazyLoadFrameLoadingAttributeEager, WebFeature::kLazyLoadImageLoadingAttributeLazy, WebFeature::kLazyLoadImageLoadingAttributeEager, - WebFeature::kDOMSubtreeModifiedEvent, - WebFeature::kDOMNodeInsertedEvent, - WebFeature::kDOMNodeRemovedEvent, - WebFeature::kDOMNodeRemovedFromDocumentEvent, - WebFeature::kDOMNodeInsertedIntoDocumentEvent, - WebFeature::kDOMCharacterDataModifiedEvent, WebFeature::kWebOTP, WebFeature::kBaseWithCrossOriginHref, WebFeature::kWakeLockAcquireScreenLock, @@ -471,6 +465,7 @@ WebFeature::kClearSiteData, WebFeature::kXSLProcessingInstruction, WebFeature::kXSLTProcessor, + WebFeature::kXMLExternalResourceLoad, // NOTE: before adding new use counters here, verify in UMA that their // emissions are very rare, e.g. <1% of page loads. }));
diff --git a/components/page_load_metrics/browser/page_load_metrics_util.cc b/components/page_load_metrics/browser/page_load_metrics_util.cc index e124931..fc49be47 100644 --- a/components/page_load_metrics/browser/page_load_metrics_util.cc +++ b/components/page_load_metrics/browser/page_load_metrics_util.cc
@@ -361,4 +361,11 @@ return std::nullopt; } +bool IsServiceWorkerControlled( + const PageLoadMetricsObserverDelegate& delegate) { + return (delegate.GetMainFrameMetadata().behavior_flags & + blink::LoadingBehaviorFlag:: + kLoadingBehaviorServiceWorkerControlled) != 0; +} + } // namespace page_load_metrics
diff --git a/components/page_load_metrics/browser/page_load_metrics_util.h b/components/page_load_metrics/browser/page_load_metrics_util.h index 05d737b2..fb3b842 100644 --- a/components/page_load_metrics/browser/page_load_metrics_util.h +++ b/components/page_load_metrics/browser/page_load_metrics_util.h
@@ -266,6 +266,9 @@ // https://docs.google.com/document/d/1TSbtp5I5Bc1pbAKrrEHfmZlAwgeh6AlgAH7GbDMNPRQ/edit?disco=AAABe5h90jQ std::optional<uint32_t> GetCategoryIdFromUrl(const GURL& url); +// Returns true if the page is controlled by a service worker. +bool IsServiceWorkerControlled(const PageLoadMetricsObserverDelegate& delegate); + } // namespace page_load_metrics #endif // COMPONENTS_PAGE_LOAD_METRICS_BROWSER_PAGE_LOAD_METRICS_UTIL_H_
diff --git a/components/password_manager/core/browser/actor_login/actor_login_types.h b/components/password_manager/core/browser/actor_login/actor_login_types.h index b0bef5e6..54134cb 100644 --- a/components/password_manager/core/browser/actor_login/actor_login_types.h +++ b/components/password_manager/core/browser/actor_login/actor_login_types.h
@@ -67,6 +67,7 @@ enum class LoginStatusResult { kSuccessUsernameAndPasswordFilled, kErrorNoSigninForm, + kErrorInvalidCredential, }; using LoginStatusResultOrError =
diff --git a/components/password_manager/core/browser/actor_login/internal/BUILD.gn b/components/password_manager/core/browser/actor_login/internal/BUILD.gn index f0a2223..5dfb472d6 100644 --- a/components/password_manager/core/browser/actor_login/internal/BUILD.gn +++ b/components/password_manager/core/browser/actor_login/internal/BUILD.gn
@@ -13,6 +13,8 @@ "actor_login_delegate.h", "actor_login_get_credentials_helper.cc", "actor_login_get_credentials_helper.h", + "actor_login_util.cc", + "actor_login_util.h", ] visibility = [
diff --git a/components/password_manager/core/browser/actor_login/internal/actor_login_credential_filler.cc b/components/password_manager/core/browser/actor_login/internal/actor_login_credential_filler.cc index 3ae81dfd..3174028 100644 --- a/components/password_manager/core/browser/actor_login/internal/actor_login_credential_filler.cc +++ b/components/password_manager/core/browser/actor_login/internal/actor_login_credential_filler.cc
@@ -10,6 +10,7 @@ #include "base/task/single_thread_task_runner.h" #include "base/types/expected.h" #include "components/password_manager/core/browser/actor_login/actor_login_types.h" +#include "components/password_manager/core/browser/actor_login/internal/actor_login_util.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_form_cache.h" #include "components/password_manager/core/browser/password_form_manager.h" @@ -34,7 +35,7 @@ password_manager::PasswordFormCache* form_cache = password_manager->GetPasswordFormCache(); CHECK(form_cache); - bool has_signin_form = false; + password_manager::PasswordFormManager* signin_form_manager = nullptr; for (const auto& manager : form_cache->GetFormManagers()) { if (manager->GetDriver()->GetLastCommittedOrigin().IsSameOriginWith( origin_)) { @@ -43,21 +44,38 @@ // TODO(crbug.com/427170499): Check if this is the right condition to // check for a signin form. if (parsed_form && parsed_form->IsLikelyLoginForm()) { - has_signin_form = true; + signin_form_manager = manager.get(); break; } } } - if (!has_signin_form) { + if (!signin_form_manager) { base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(std::move(callback_), LoginStatusResult::kErrorNoSigninForm)); return; } - // TODO(crbug.com/427170499): Check if the credential matches a saved - // credential and fill the form if it does. + bool credential_is_saved_for_origin = false; + for (const password_manager::PasswordForm& stored_credential_form : + signin_form_manager->GetBestMatches()) { + if (stored_credential_form.username_value == credential_.username && + GetSourceSiteOrAppFromUrl(stored_credential_form.url) == + credential_.source_site_or_app) { + credential_is_saved_for_origin = true; + break; + } + } + + if (!credential_is_saved_for_origin) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback_), + LoginStatusResult::kErrorInvalidCredential)); + return; + } + + // TODO(crbug.com/427170499): Fill the form. } } // namespace actor_login
diff --git a/components/password_manager/core/browser/actor_login/internal/actor_login_credential_filler_unittest.cc b/components/password_manager/core/browser/actor_login/internal/actor_login_credential_filler_unittest.cc index fd238c5d..13c8a74 100644 --- a/components/password_manager/core/browser/actor_login/internal/actor_login_credential_filler_unittest.cc +++ b/components/password_manager/core/browser/actor_login/internal/actor_login_credential_filler_unittest.cc
@@ -54,6 +54,19 @@ (const, override)); }; +password_manager::PasswordForm CreateSavedPasswordForm( + const GURL& url, + const std::u16string& username, + const std::u16string& password = u"") { + password_manager::PasswordForm form; + form.url = url; + form.signon_realm = password_manager::GetSignonRealm(url); + form.username_value = username; + form.password_value = password; + form.match_type = PasswordForm::MatchType::kExact; + return form; +} + } // namespace class ActorLoginCredentialFillerTest : public ::testing::Test { @@ -81,6 +94,7 @@ std::make_unique<PasswordSaveManagerImpl>(&stub_client_), /*metrics_recorder=*/nullptr); // Force form parsing, otherwise there will be no parsed observed form. + form_manager->DisableFillingServerPredictionsForTesting(); form_fetcher_.NotifyFetchCompleted(); return form_manager; } @@ -177,4 +191,78 @@ EXPECT_EQ(future.Get().value(), LoginStatusResult::kErrorNoSigninForm); } +TEST_F(ActorLoginCredentialFillerTest, + CredentialNotSavedForOrigin_MultipleCredentials) { + const url::Origin origin = + url::Origin::Create(GURL("https://example.com/login")); + const std::u16string username_to_find = u"targetuser"; + const Credential credential = + CreateTestCredential(username_to_find, origin.GetURL()); + const FormData form_data = CreateSigninFormData(origin.GetURL()); + std::vector<password_manager::PasswordForm> saved_forms; + saved_forms.push_back(CreateSavedPasswordForm(origin.GetURL(), u"user1")); + saved_forms.push_back(CreateSavedPasswordForm(origin.GetURL(), u"user2")); + form_fetcher_.SetBestMatches(saved_forms); // No matching username + + std::vector<std::unique_ptr<PasswordFormManager>> form_managers; + form_managers.push_back(CreateFormManagerWithParsedForm(origin, form_data)); + + base::test::TestFuture<LoginStatusResultOrError> future; + ActorLoginCredentialFiller filler(origin, credential, future.GetCallback()); + EXPECT_CALL(mock_form_cache_, GetFormManagers()) + .WillOnce(Return(base::span(form_managers))); + filler.AttemptLogin(&mock_password_manager_); + ASSERT_TRUE(future.Get().has_value()); + EXPECT_EQ(future.Get().value(), LoginStatusResult::kErrorInvalidCredential); +} + +TEST_F(ActorLoginCredentialFillerTest, + CredentialNotSavedForOrigin_NoSavedCredentialsForOrigin) { + const url::Origin origin = + url::Origin::Create(GURL("https://example.com/login")); + const std::u16string username = u"testuser"; + const Credential credential = CreateTestCredential(username, origin.GetURL()); + const FormData form_data = CreateSigninFormData(origin.GetURL()); + // No saved forms for this origin (empty vector) + std::vector<password_manager::PasswordForm> saved_forms; + form_fetcher_.SetBestMatches(saved_forms); + + std::vector<std::unique_ptr<PasswordFormManager>> form_managers; + form_managers.push_back(CreateFormManagerWithParsedForm(origin, form_data)); + + base::test::TestFuture<LoginStatusResultOrError> future; + ActorLoginCredentialFiller filler(origin, credential, future.GetCallback()); + EXPECT_CALL(mock_form_cache_, GetFormManagers()) + .WillOnce(Return(base::span(form_managers))); + filler.AttemptLogin(&mock_password_manager_); + ASSERT_TRUE(future.Get().has_value()); + EXPECT_EQ(future.Get().value(), LoginStatusResult::kErrorInvalidCredential); +} + +TEST_F(ActorLoginCredentialFillerTest, + CredentialNotSavedForOrigin_SuppliedAndStoredCredentialOriginDiffers) { + const url::Origin origin = + url::Origin::Create(GURL("https://example.com/login")); + const std::u16string username = u"testuser"; + const Credential credential = + CreateTestCredential(username, GURL("https://otherexample.com")); + const FormData form_data = CreateSigninFormData(origin.GetURL()); + // Prepare a saved credential that does match the requested username, but not + // the origin + std::vector<password_manager::PasswordForm> saved_forms; + saved_forms.push_back(CreateSavedPasswordForm(origin.GetURL(), username)); + form_fetcher_.SetBestMatches(saved_forms); + + std::vector<std::unique_ptr<PasswordFormManager>> form_managers; + form_managers.push_back(CreateFormManagerWithParsedForm(origin, form_data)); + + base::test::TestFuture<LoginStatusResultOrError> future; + ActorLoginCredentialFiller filler(origin, credential, future.GetCallback()); + EXPECT_CALL(mock_form_cache_, GetFormManagers()) + .WillOnce(Return(base::span(form_managers))); + filler.AttemptLogin(&mock_password_manager_); + ASSERT_TRUE(future.Get().has_value()); + EXPECT_EQ(future.Get().value(), LoginStatusResult::kErrorInvalidCredential); +} + } // namespace actor_login
diff --git a/components/password_manager/core/browser/actor_login/internal/actor_login_get_credentials_helper.cc b/components/password_manager/core/browser/actor_login/internal/actor_login_get_credentials_helper.cc index 47ecd93..58b5f76 100644 --- a/components/password_manager/core/browser/actor_login/internal/actor_login_get_credentials_helper.cc +++ b/components/password_manager/core/browser/actor_login/internal/actor_login_get_credentials_helper.cc
@@ -7,6 +7,7 @@ #include <ranges> #include "base/strings/utf_string_conversions.h" +#include "components/password_manager/core/browser/actor_login/internal/actor_login_util.h" #include "components/password_manager/core/browser/form_fetcher_impl.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_manager_client.h" @@ -24,8 +25,7 @@ Credential credential; credential.username = form.username_value; // TODO(crbug.com/427171031): Clarify the format. - credential.source_site_or_app = - base::UTF8ToUTF16(form.url.GetWithEmptyPath().spec()); + credential.source_site_or_app = GetSourceSiteOrAppFromUrl(form.url); // TODO(crbug.com/427171031): Use PasswordManager to set the real value here. credential.immediatelyAvailableToLogin = true; return credential;
diff --git a/components/password_manager/core/browser/actor_login/internal/actor_login_util.cc b/components/password_manager/core/browser/actor_login/internal/actor_login_util.cc new file mode 100644 index 0000000..015cbfb8 --- /dev/null +++ b/components/password_manager/core/browser/actor_login/internal/actor_login_util.cc
@@ -0,0 +1,15 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/core/browser/actor_login/internal/actor_login_util.h" + +#include "base/strings/utf_string_conversions.h" + +namespace actor_login { + +std::u16string GetSourceSiteOrAppFromUrl(const GURL& url) { + return base::UTF8ToUTF16(url.GetWithEmptyPath().spec()); +} + +} // namespace actor_login
diff --git a/components/password_manager/core/browser/actor_login/internal/actor_login_util.h b/components/password_manager/core/browser/actor_login/internal/actor_login_util.h new file mode 100644 index 0000000..a95e0bf1 --- /dev/null +++ b/components/password_manager/core/browser/actor_login/internal/actor_login_util.h
@@ -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. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ACTOR_LOGIN_INTERNAL_ACTOR_LOGIN_UTIL_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ACTOR_LOGIN_INTERNAL_ACTOR_LOGIN_UTIL_H_ + +#include <string> + +#include "url/gurl.h" + +namespace actor_login { + +// Transforms `url` into `Credential.source_site_or_app` +std::u16string GetSourceSiteOrAppFromUrl(const GURL& url); + +} // namespace actor_login + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ACTOR_LOGIN_INTERNAL_ACTOR_LOGIN_UTIL_H_
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index fe493dc0..ad2c4d5 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -429,12 +429,8 @@ kExplicitlyTriggeredInSettings = 1, // The user explicitly asked to move multiple passwords at once in Settings. kExplicitlyTriggeredForMultiplePasswordsInSettings = 2, - // After saving a password locally, the user opted in to saving this and - // future passwords in the account. - kUserOptedInAfterSavingLocally = 3, - // The user explicitly asked to move a password to account store from password - // details page. - kExplicitlyTriggeredForSinglePasswordInDetailsInSettings = 4, + // Deprecated: kUserOptedInAfterSavingLocally = 3, + // Deprecated: kExplicitlyTriggeredForSinglePasswordInDetailsInSettings = 4, // The user clicked a link in a footer of the manage passwords bubble. kExplicitlyTriggeredInPasswordsManagementBubble = 5, kMaxValue = kExplicitlyTriggeredInPasswordsManagementBubble,
diff --git a/components/password_manager/core/browser/password_session_durations_metrics_recorder.h b/components/password_manager/core/browser/password_session_durations_metrics_recorder.h index 46a2599..2767f13 100644 --- a/components/password_manager/core/browser/password_session_durations_metrics_recorder.h +++ b/components/password_manager/core/browser/password_session_durations_metrics_recorder.h
@@ -20,8 +20,8 @@ namespace password_manager { -// Tracks the active browsing time that the user spends in each state related to -// the account-scoped password storage, i.e. signed in or not, opted in or not. +// Tracks the active browsing time that the user spends in each +// features_util::PasswordAccountStorageUserState. class PasswordSessionDurationsMetricsRecorder : public syncer::SyncServiceObserver { public:
diff --git a/components/performance_manager/freezing/freezing_policy.cc b/components/performance_manager/freezing/freezing_policy.cc index 28c7c7b..eabb50af 100644 --- a/components/performance_manager/freezing/freezing_policy.cc +++ b/components/performance_manager/freezing/freezing_policy.cc
@@ -1410,7 +1410,7 @@ void FreezingPolicy::CheckMemoryPressureForFreezing() { #if BUILDFLAG(IS_WIN) - base::SystemMemoryInfoKB info; + base::SystemMemoryInfo info; if (!base::GetSystemMemoryInfo(&info)) { // Cannot get system memory info, do nothing. return; @@ -1423,8 +1423,8 @@ const int kPressureThresholdPercent = features::kInfiniteTabsFreezingOnMemoryPressurePercent.Get(); - uint64_t total_kb = info.total; - uint64_t avail_kb = info.avail_phys; + uint64_t total_kb = info.total.InKiB(); + uint64_t avail_kb = info.avail_phys.InKiB(); int available_percent = 0; if (total_kb > 0) {
diff --git a/components/performance_manager/graph/policies/bfcache_policy.cc b/components/performance_manager/graph/policies/bfcache_policy.cc index 1bf40296..924a944 100644 --- a/components/performance_manager/graph/policies/bfcache_policy.cc +++ b/components/performance_manager/graph/policies/bfcache_policy.cc
@@ -131,6 +131,18 @@ } // namespace +BFCachePolicy::BFCachePolicy() + : memory_pressure_listener_( + FROM_HERE, + base::BindRepeating(&BFCachePolicy::OnMemoryPressure, + base::Unretained(this))) {} + +BFCachePolicy::~BFCachePolicy() = default; + +void BFCachePolicy::OnPassedToGraph(Graph* graph) {} + +void BFCachePolicy::OnTakenFromGraph(Graph* graph) {} + void BFCachePolicy::MaybeFlushBFCache( const PageNode* page_node, MemoryPressureLevel memory_pressure_level) { @@ -139,15 +151,6 @@ memory_pressure_level); } -void BFCachePolicy::OnPassedToGraph(Graph* graph) { - DCHECK(graph->HasOnlySystemNode()); - graph->AddSystemNodeObserver(this); -} - -void BFCachePolicy::OnTakenFromGraph(Graph* graph) { - graph->RemoveSystemNodeObserver(this); -} - void BFCachePolicy::OnMemoryPressure(MemoryPressureLevel new_level) { // This shouldn't happen but add the check anyway in case the API changes. if (new_level == MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE) {
diff --git a/components/performance_manager/graph/policies/bfcache_policy.h b/components/performance_manager/graph/policies/bfcache_policy.h index 130cd2b29..e4ffe200 100644 --- a/components/performance_manager/graph/policies/bfcache_policy.h +++ b/components/performance_manager/graph/policies/bfcache_policy.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_PERFORMANCE_MANAGER_GRAPH_POLICIES_BFCACHE_POLICY_H_ #define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_POLICIES_BFCACHE_POLICY_H_ +#include "base/memory/memory_pressure_listener.h" #include "base/time/time.h" #include "base/timer/timer.h" #include "components/performance_manager/public/graph/graph.h" @@ -14,14 +15,18 @@ // Policies that automatically flush the BFCache of pages when the system is // under memory pressure. -class BFCachePolicy : public GraphOwned, public SystemNodeObserver { +class BFCachePolicy : public GraphOwned { public: - BFCachePolicy() = default; + BFCachePolicy(); BFCachePolicy(const BFCachePolicy&) = delete; BFCachePolicy(BFCachePolicy&&) = delete; BFCachePolicy& operator=(const BFCachePolicy&) = delete; BFCachePolicy& operator=(BFCachePolicy&&) = delete; - ~BFCachePolicy() override = default; + ~BFCachePolicy() override; + + // GraphOwned: + void OnPassedToGraph(Graph* graph) override; + void OnTakenFromGraph(Graph* graph) override; protected: using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; @@ -32,12 +37,9 @@ MemoryPressureLevel memory_pressure_level); private: - // GraphOwned implementation: - void OnPassedToGraph(Graph* graph) override; - void OnTakenFromGraph(Graph* graph) override; + void OnMemoryPressure(MemoryPressureLevel new_level); - // SystemNodeObserver: - void OnMemoryPressure(MemoryPressureLevel new_level) override; + base::MemoryPressureListener memory_pressure_listener_; }; } // namespace performance_manager::policies
diff --git a/components/performance_manager/graph/policies/bfcache_policy_unittest.cc b/components/performance_manager/graph/policies/bfcache_policy_unittest.cc index bdade9c4..5e286e8 100644 --- a/components/performance_manager/graph/policies/bfcache_policy_unittest.cc +++ b/components/performance_manager/graph/policies/bfcache_policy_unittest.cc
@@ -5,6 +5,7 @@ #include "components/performance_manager/graph/policies/bfcache_policy.h" #include "base/memory/raw_ptr.h" +#include "base/run_loop.h" #include "base/time/time.h" #include "components/performance_manager/graph/frame_node_impl.h" #include "components/performance_manager/graph/graph_impl.h" @@ -80,21 +81,33 @@ page_node_->SetLoadingState(PageNode::LoadingState::kLoadedBusy); ::testing::Mock::VerifyAndClearExpectations(policy_); - EXPECT_CALL( - *policy_, - MaybeFlushBFCache(page_node_.get(), - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE)); - GetSystemNode()->OnMemoryPressureForTesting( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE); - ::testing::Mock::VerifyAndClearExpectations(policy_); + { + base::RunLoop run_loop; + EXPECT_CALL( + *policy_, + MaybeFlushBFCache(page_node_.get(), + MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE)) + .WillOnce(testing::Invoke( + ::testing::Invoke(&run_loop, &base::RunLoop::Quit))); + base::MemoryPressureListener::SimulatePressureNotification( + MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE); + run_loop.Run(); + ::testing::Mock::VerifyAndClearExpectations(policy_); + } - EXPECT_CALL( - *policy_, - MaybeFlushBFCache(page_node_.get(), - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL)); - GetSystemNode()->OnMemoryPressureForTesting( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL); - ::testing::Mock::VerifyAndClearExpectations(policy_); + { + base::RunLoop run_loop; + EXPECT_CALL( + *policy_, + MaybeFlushBFCache(page_node_.get(), + MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL)) + .WillOnce(testing::Invoke( + ::testing::Invoke(&run_loop, &base::RunLoop::Quit))); + base::MemoryPressureListener::SimulatePressureNotification( + MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL); + run_loop.Run(); + ::testing::Mock::VerifyAndClearExpectations(policy_); + } } } // namespace performance_manager::policies
diff --git a/components/performance_manager/graph/system_node_impl.cc b/components/performance_manager/graph/system_node_impl.cc index b2acf9a..a04702f 100644 --- a/components/performance_manager/graph/system_node_impl.cc +++ b/components/performance_manager/graph/system_node_impl.cc
@@ -17,11 +17,7 @@ namespace performance_manager { -SystemNodeImpl::SystemNodeImpl() { - memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>( - FROM_HERE, base::BindRepeating(&SystemNodeImpl::OnMemoryPressure, - base::Unretained(this))); -} +SystemNodeImpl::SystemNodeImpl() = default; SystemNodeImpl::~SystemNodeImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -36,15 +32,4 @@ } } -void SystemNodeImpl::OnMemoryPressure(MemoryPressureLevel new_level) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - for (auto& observer : GetObservers()) { - observer.OnBeforeMemoryPressure(new_level); - } - for (auto& observer : GetObservers()) { - observer.OnMemoryPressure(new_level); - } -} - } // namespace performance_manager
diff --git a/components/performance_manager/graph/system_node_impl.h b/components/performance_manager/graph/system_node_impl.h index a02ea13a..d3cdc0f 100644 --- a/components/performance_manager/graph/system_node_impl.h +++ b/components/performance_manager/graph/system_node_impl.h
@@ -5,9 +5,6 @@ #ifndef COMPONENTS_PERFORMANCE_MANAGER_GRAPH_SYSTEM_NODE_IMPL_H_ #define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_SYSTEM_NODE_IMPL_H_ -#include <cstdint> -#include <memory> - #include "base/memory/memory_pressure_listener.h" #include "base/memory/weak_ptr.h" #include "base/process/process_handle.h" @@ -37,21 +34,12 @@ // nodes. void OnProcessMemoryMetricsAvailable(); - void OnMemoryPressureForTesting(MemoryPressureLevel new_level) { - OnMemoryPressure(new_level); - } - base::WeakPtr<SystemNodeImpl> GetWeakPtr() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return weak_factory_.GetWeakPtr(); } private: - void OnMemoryPressure(MemoryPressureLevel new_level); - - // The memory pressure listener. - std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; - base::WeakPtrFactory<SystemNodeImpl> weak_factory_ GUARDED_BY_CONTEXT(sequence_checker_){this}; };
diff --git a/components/performance_manager/graph/system_node_impl_unittest.cc b/components/performance_manager/graph/system_node_impl_unittest.cc index 5742bdc..38c4bad 100644 --- a/components/performance_manager/graph/system_node_impl_unittest.cc +++ b/components/performance_manager/graph/system_node_impl_unittest.cc
@@ -101,65 +101,7 @@ SystemNodeImpl::FromNode(system_node)->OnProcessMemoryMetricsAvailable(); EXPECT_EQ(system_node, obs.TakeNotifiedSystemNode()); - EXPECT_CALL(obs, OnBeforeMemoryPressure( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL)); - EXPECT_CALL(obs, OnMemoryPressure( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL)); - SystemNodeImpl::FromNode(system_node) - ->OnMemoryPressureForTesting( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL); - - // Re-entrant iteration should work. - EXPECT_CALL(obs, OnProcessMemoryMetricsAvailable(system_node)) - .WillOnce(InvokeWithoutArgs([&] { - SystemNodeImpl::FromNode(system_node) - ->OnMemoryPressureForTesting( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE); - })); - EXPECT_CALL(obs, OnBeforeMemoryPressure( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE)); - EXPECT_CALL(obs, OnMemoryPressure( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE)); - SystemNodeImpl::FromNode(system_node)->OnProcessMemoryMetricsAvailable(); - graph()->RemoveSystemNodeObserver(&obs); } -TEST_F(SystemNodeImplTest, MemoryPressureNotification) { - MockObserver obs(graph()); - memory_pressure::test::FakeMemoryPressureMonitor mem_pressure_monitor; - - { - base::RunLoop run_loop; - auto quit_closure = run_loop.QuitClosure(); - EXPECT_CALL(obs, OnBeforeMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel:: - MEMORY_PRESSURE_LEVEL_CRITICAL)) - .WillOnce(InvokeWithoutArgs([&]() { std::move(quit_closure).Run(); })); - EXPECT_CALL(obs, OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel:: - MEMORY_PRESSURE_LEVEL_CRITICAL)); - mem_pressure_monitor.SetAndNotifyMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel:: - MEMORY_PRESSURE_LEVEL_CRITICAL); - run_loop.Run(); - } - - { - base::RunLoop run_loop; - auto quit_closure = run_loop.QuitClosure(); - EXPECT_CALL(obs, OnBeforeMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel:: - MEMORY_PRESSURE_LEVEL_MODERATE)) - .WillOnce(InvokeWithoutArgs([&]() { std::move(quit_closure).Run(); })); - EXPECT_CALL(obs, OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel:: - MEMORY_PRESSURE_LEVEL_MODERATE)); - mem_pressure_monitor.SetAndNotifyMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel:: - MEMORY_PRESSURE_LEVEL_MODERATE); - run_loop.Run(); - } -} - } // namespace performance_manager
diff --git a/components/performance_manager/public/graph/system_node.h b/components/performance_manager/public/graph/system_node.h index 3dc7e1a3..a66cbb4 100644 --- a/components/performance_manager/public/graph/system_node.h +++ b/components/performance_manager/public/graph/system_node.h
@@ -45,24 +45,6 @@ // for process memory metrics by calling // ProcessMetricsDecorator::RegisterInterestForProcessMetrics. virtual void OnProcessMemoryMetricsAvailable(const SystemNode* system_node) {} - - // Called before OnMemoryPressure(). This can be used to track state before - // memory start being released in response to memory pressure. - // - // Note: This is guaranteed to be invoked before OnMemoryPressure(), but - // will not necessarily be called before base::MemoryPressureListeners - // are notified. - virtual void OnBeforeMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel new_level) {} - - // Called when the system is under memory pressure. Observers may start - // releasing memory in response to memory pressure. - // - // NOTE: This isn't called for a transition to the MEMORY_PRESSURE_LEVEL_NONE - // level. For this reason there's no corresponding property in this node and - // the response to these notifications should be stateless. - virtual void OnMemoryPressure( - base::MemoryPressureListener::MemoryPressureLevel new_level) {} }; } // namespace performance_manager
diff --git a/components/performance_manager/scenario_api/performance_scenario_memory.cc b/components/performance_manager/scenario_api/performance_scenario_memory.cc index f3c5863..dea157d 100644 --- a/components/performance_manager/scenario_api/performance_scenario_memory.cc +++ b/components/performance_manager/scenario_api/performance_scenario_memory.cc
@@ -7,9 +7,11 @@ #include <optional> #include <utility> +#include "base/logging.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/scoped_refptr.h" #include "base/memory/structured_shared_memory.h" +#include "base/metrics/histogram_functions.h" #include "base/no_destructor.h" #include "base/notreached.h" #include "components/performance_manager/scenario_api/performance_scenario_observer.h" @@ -35,6 +37,30 @@ NOTREACHED(); } +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// +// LINT.IfChange(ChildScenarioMappingResult) +enum class MappingResult { + kSuccess = 0, + kInvalidHandle = 1, + kSystemError = 2, + kMaxValue = kSystemError, +}; +// LINT.ThenChange(//tools/metrics/histograms/metadata/performance_manager/enums.xml:ChildScenarioMappingResult) + +void LogMappingResult( + MappingResult result, + std::optional<logging::SystemErrorCode> system_error = std::nullopt) { + base::UmaHistogramEnumeration("PerformanceManager.ChildScenarioMappingResult", + result); + if (system_error.has_value()) { + base::UmaHistogramSparse( + "PerformanceManager.ChildScenarioMappingSystemError", + system_error.value()); + } +} + } // namespace // TODO(crbug.com/365586676): Currently these are only mapped into browser and @@ -46,12 +72,17 @@ base::ReadOnlySharedMemoryRegion region) : scope_(scope) { using SharedScenarioState = base::StructuredSharedMemory<ScenarioState>; - std::optional<SharedScenarioState::ReadOnlyMapping> mapping = - SharedScenarioState::MapReadOnlyRegion(std::move(region)); - if (mapping.has_value()) { + if (!region.IsValid()) { + LogMappingResult(MappingResult::kInvalidHandle); + } else if (std::optional<SharedScenarioState::ReadOnlyMapping> mapping = + SharedScenarioState::MapReadOnlyRegion(std::move(region))) { MappingPtrForScope(scope_) = base::MakeRefCounted<RefCountedScenarioMapping>( std::move(mapping.value())); + LogMappingResult(MappingResult::kSuccess); + } else { + LogMappingResult(MappingResult::kSystemError, + logging::GetLastSystemErrorCode()); } // The ObserverList must be created after mapping the memory, because it reads
diff --git a/components/performance_manager/scenarios/performance_scenario_data.cc b/components/performance_manager/scenarios/performance_scenario_data.cc index 1a383776..acc7151 100644 --- a/components/performance_manager/scenarios/performance_scenario_data.cc +++ b/components/performance_manager/scenarios/performance_scenario_data.cc
@@ -5,10 +5,13 @@ #include "components/performance_manager/scenarios/performance_scenario_data.h" #include <memory> +#include <optional> #include <utility> +#include "base/logging.h" #include "base/memory/shared_memory_mapper.h" #include "base/memory/structured_shared_memory.h" +#include "base/metrics/histogram_functions.h" #include "base/types/optional_util.h" #include "components/performance_manager/graph/process_node_impl.h" #include "components/performance_manager/public/tracing_support.h" @@ -19,6 +22,29 @@ namespace { +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// +// LINT.IfChange(CreateScenarioMemoryResult) +enum class CreateScenarioMemoryResult { + kSuccess = 0, + kSystemError = 1, + kMaxValue = kSystemError, +}; +// LINT.ThenChange(//tools/metrics/histograms/metadata/performance_manager/enums.xml:CreateScenarioMemoryResult) + +void LogCreateScenarioMemoryResult( + CreateScenarioMemoryResult result, + std::optional<logging::SystemErrorCode> system_error = std::nullopt) { + base::UmaHistogramEnumeration("PerformanceManager.CreateScenarioMemoryResult", + result); + if (system_error.has_value()) { + base::UmaHistogramSparse( + "PerformanceManager.CreateScenarioMemorySystemError", + system_error.value()); + } +} + perfetto::NamedTrack CreateTracingTrack(const ProcessNode* process_node, perfetto::StaticString name, uint64_t track_id) { @@ -45,7 +71,14 @@ PerformanceScenarioData::PerformanceScenarioData( base::SharedMemoryMapper* mapper) : shared_state_(mapper ? SharedScenarioState::CreateWithCustomMapper(mapper) - : SharedScenarioState::Create()) {} + : SharedScenarioState::Create()) { + if (shared_state_.has_value()) { + LogCreateScenarioMemoryResult(CreateScenarioMemoryResult::kSuccess); + } else { + LogCreateScenarioMemoryResult(CreateScenarioMemoryResult::kSystemError, + logging::GetLastSystemErrorCode()); + } +} PerformanceScenarioData::~PerformanceScenarioData() = default;
diff --git a/components/performance_manager/test_support/graph/mock_system_node_observer.h b/components/performance_manager/test_support/graph/mock_system_node_observer.h index c129f9d..13c6fc5 100644 --- a/components/performance_manager/test_support/graph/mock_system_node_observer.h +++ b/components/performance_manager/test_support/graph/mock_system_node_observer.h
@@ -19,14 +19,6 @@ OnProcessMemoryMetricsAvailable, (const SystemNode*), (override)); - MOCK_METHOD(void, - OnMemoryPressure, - (base::MemoryPressureListener::MemoryPressureLevel), - (override)); - MOCK_METHOD(void, - OnBeforeMemoryPressure, - (base::MemoryPressureListener::MemoryPressureLevel), - (override)); }; using MockSystemNodeObserver =
diff --git a/components/permissions/add_new_permission.md b/components/permissions/add_new_permission.md index 2a3ead9..42eef4b 100644 --- a/components/permissions/add_new_permission.md +++ b/components/permissions/add_new_permission.md
@@ -205,8 +205,7 @@ [permissions::PermissionContextBase](https://source.chromium.org/chromium/chromium/src/+/main:components/permissions/permission_context_base.h). 2. Put it in `components/permissions/contexts/` or in a feature folder. 3. In [permission_manager_factory.cc](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/permissions/permission_manager_factory.cc) update [CreatePermissionContexts()](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/permissions/permission_manager_factory.cc;l=50;drc=c970b8647281cc3fc7ffe1288ce7c5f2e5f7acf6) -4. In [permission_manager_factory.cc](https://source.chromium.org/chromium/chromium/src/+/main:weblayer/browser/permissions/permission_manager_factory.cc) update [CreatePermissionContexts()](https://source.chromium.org/chromium/chromium/src/+/main:weblayer/browser/permissions/permission_manager_factory.cc;l=61;drc=0e1f7e00e6ee851f977f5f37d711ee5d4e9b28eb) -5. In [permission_test_util.cc](https://source.chromium.org/chromium/chromium/src/+/main:components/permissions/test/permission_test_util.cc) update [CreatePermissionContexts()](https://source.chromium.org/chromium/chromium/src/+/main:components/permissions/test/permission_test_util.cc;l=46;drc=0e1f7e00e6ee851f977f5f37d711ee5d4e9b28eb) +4. In [permission_test_util.cc](https://source.chromium.org/chromium/chromium/src/+/main:components/permissions/test/permission_test_util.cc) update [CreatePermissionContexts()](https://source.chromium.org/chromium/chromium/src/+/main:components/permissions/test/permission_test_util.cc;l=46;drc=0e1f7e00e6ee851f977f5f37d711ee5d4e9b28eb) ### DevTools Add new permissions for browser automation (e2e testing).
diff --git a/components/permissions/android/BUILD.gn b/components/permissions/android/BUILD.gn index 41e495f..5919f82d 100644 --- a/components/permissions/android/BUILD.gn +++ b/components/permissions/android/BUILD.gn
@@ -32,6 +32,8 @@ "res/drawable-mdpi/infobar_protected_media_identifier.png", "res/drawable-mdpi/infobar_warning.png", "res/drawable-mdpi/permission_cookie.png", + "res/drawable-night/location_approximate.xml", + "res/drawable-night/location_precise.xml", "res/drawable-xhdpi/exclamation_triangle.png", "res/drawable-xhdpi/infobar_downloading.png", "res/drawable-xhdpi/infobar_protected_media_identifier.png",
diff --git a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCoordinator.java b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCoordinator.java index 1497617..35ac3e7d 100644 --- a/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCoordinator.java +++ b/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogCoordinator.java
@@ -239,7 +239,7 @@ Context context = mDialogDelegate.getWindow().getContext().get(); assert context != null; // Use the context to access resources instead of the activity because the activity may not - // have the correct resources in some cases (e.g. WebLayer). + // have the correct resources in some cases. return context; }
diff --git a/components/permissions/android/res/drawable-night/location_approximate.xml b/components/permissions/android/res/drawable-night/location_approximate.xml new file mode 100644 index 0000000..81b91ed --- /dev/null +++ b/components/permissions/android/res/drawable-night/location_approximate.xml
@@ -0,0 +1,92 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="80dp" + android:height="80dp" + android:viewportWidth="80" + android:viewportHeight="80"> + <group> + <clip-path + android:pathData="M0,0h80v80h-80z"/> + <path + android:pathData="M0,0h80v80h-80z" + android:fillColor="#202124"/> + <path + android:pathData="M81.5,21.5L42.344,17.202C41.122,17.068 39.887,17.123 38.681,17.364L19.509,21.198C15.459,22.008 12.11,24.844 10.644,28.705L-2,62" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M-6,9L86,72" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M20.169,53.776L-2,46.5L-8.5,80.5L26.824,103L32.001,73.612L20.169,53.776Z" + android:fillColor="#188038"/> + <path + android:pathData="M30,86L36.198,44.382C36.704,40.99 38.762,38.028 41.764,36.371L49.776,31.951C50.916,31.322 51.936,30.495 52.787,29.51L61,20L78.5,-4" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M50.486,72.296a5.5,4.5 105.673,1 0,8.665 2.431a5.5,4.5 105.673,1 0,-8.665 -2.431z" + android:strokeWidth="2" + android:fillColor="#188038" + android:strokeColor="#80868B"/> + <path + android:pathData="M62.077,18.699m-2.888,-0.81a3,3 57.086,1 1,5.777 1.621a3,3 60.818,1 1,-5.777 -1.621" + android:strokeWidth="2" + android:fillColor="#202124" + android:strokeColor="#80868B"/> + <path + android:pathData="M57,68.5L61.682,59.136C62.548,57.404 63.82,55.908 65.389,54.775L71.051,50.685C71.682,50.229 72.267,49.714 72.798,49.145L86,35" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M50,71.5L33.5,66.5" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M59.5,75.5L83,83.5" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M53,79L49.5,89L82.5,96" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M-7.5,44.5L13.801,51.471C17.792,52.777 21.158,55.514 23.251,59.154L28.58,68.421C30.472,71.712 31.208,75.542 30.671,79.299L29.5,87.5" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M15,-7L38.743,16.531L86,63" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M25,30.5L17.5,53" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M89,12L75,20.5L63.5,40.5L53.5,49.5L43,69L40,88" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M5.447,18.308L-7.294,27.116C-9.392,28.567 -12.293,27.474 -12.913,25C-13.193,23.886 -12.932,22.706 -12.209,21.813L1.566,4.805C3.066,2.953 5.099,1.608 7.391,0.952L9.355,0.39C12.007,-0.369 14.862,0.302 16.898,2.163C18.244,3.392 19.126,5.047 19.396,6.849L19.986,10.779C20.065,11.311 19.99,11.854 19.767,12.344C19.432,13.083 18.791,13.64 18.012,13.868L9.585,16.335C8.109,16.767 6.712,17.433 5.447,18.308Z" + android:strokeWidth="2" + android:fillColor="#12B5CB" + android:strokeColor="#80868B"/> + <path + android:pathData="M40,8.75L40,8.75A31.25,31.25 0,0 1,71.25 40L71.25,40A31.25,31.25 0,0 1,40 71.25L40,71.25A31.25,31.25 0,0 1,8.75 40L8.75,40A31.25,31.25 0,0 1,40 8.75z" + android:strokeWidth="1.5" + android:fillColor="#AECBFA" + android:fillAlpha="0.4" + android:strokeColor="#AECBFA"/> + </group> +</vector>
diff --git a/components/permissions/android/res/drawable-night/location_precise.xml b/components/permissions/android/res/drawable-night/location_precise.xml new file mode 100644 index 0000000..a8f28af --- /dev/null +++ b/components/permissions/android/res/drawable-night/location_precise.xml
@@ -0,0 +1,92 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="80dp" + android:height="80dp" + android:viewportWidth="80" + android:viewportHeight="80"> + <group> + <clip-path + android:pathData="M0,0h80v80h-80z"/> + <path + android:pathData="M0,0h80v80h-80z" + android:fillColor="#202124"/> + <path + android:pathData="M81.5,21.5L42.344,17.202C41.122,17.068 39.887,17.123 38.681,17.364L19.509,21.198C15.459,22.008 12.11,24.844 10.644,28.705L-2,62" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M-6,9L86,72" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M20.169,53.776L-2,46.5L-8.5,80.5L26.824,103L32.001,73.612L20.169,53.776Z" + android:fillColor="#188038"/> + <path + android:pathData="M30,86L36.198,44.382C36.704,40.99 38.762,38.028 41.764,36.371L49.776,31.951C50.916,31.322 51.936,30.495 52.787,29.51L61,20L78.5,-4" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M50.486,72.296a5.5,4.5 105.673,1 0,8.665 2.431a5.5,4.5 105.673,1 0,-8.665 -2.431z" + android:strokeWidth="2" + android:fillColor="#188038" + android:strokeColor="#80868B"/> + <path + android:pathData="M62.077,18.699m-2.888,-0.81a3,3 57.086,1 1,5.777 1.621a3,3 60.818,1 1,-5.777 -1.621" + android:strokeWidth="2" + android:fillColor="#202124" + android:strokeColor="#80868B"/> + <path + android:pathData="M57,68.5L61.682,59.136C62.548,57.404 63.82,55.908 65.389,54.775L71.051,50.685C71.682,50.229 72.267,49.714 72.798,49.145L86,35" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M50,71.5L33.5,66.5" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M59.5,75.5L83,83.5" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M53,79L49.5,89L82.5,96" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M-7.5,44.5L13.801,51.471C17.792,52.777 21.158,55.514 23.251,59.154L28.58,68.421C30.472,71.712 31.208,75.542 30.671,79.299L29.5,87.5" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M15,-7L38.743,16.531L86,63" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M25,30.5L17.5,53" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M89,12L75,20.5L63.5,40.5L53.5,49.5L43,69L40,88" + android:strokeWidth="2" + android:fillColor="#00000000" + android:strokeColor="#80868B"/> + <path + android:pathData="M5.447,18.308L-7.294,27.116C-9.392,28.567 -12.293,27.474 -12.913,25C-13.193,23.886 -12.932,22.706 -12.209,21.813L1.566,4.805C3.066,2.953 5.099,1.608 7.391,0.952L9.355,0.39C12.007,-0.369 14.862,0.302 16.898,2.163C18.244,3.392 19.126,5.047 19.396,6.849L19.986,10.779C20.065,11.311 19.99,11.854 19.767,12.344C19.432,13.083 18.791,13.64 18.012,13.868L9.585,16.335C8.109,16.767 6.712,17.433 5.447,18.308Z" + android:strokeWidth="2" + android:fillColor="#12B5CB" + android:strokeColor="#80868B"/> + <path + android:pathData="M39.228,39.683m-5.956,-0.727a6,6 74.012,1 1,11.912 1.455a6,6 74.012,1 1,-11.912 -1.455" + android:fillColor="#ffffff"/> + <path + android:pathData="M35.059,39.174a4.2,4.2 51.963,1 0,8.338 1.018a4.2,4.2 51.963,1 0,-8.338 -1.018z" + android:fillColor="#1967D2"/> + </group> +</vector>
diff --git a/components/persistent_cache/backend_params_manager.cc b/components/persistent_cache/backend_params_manager.cc index 1fcaef1..1090d90 100644 --- a/components/persistent_cache/backend_params_manager.cc +++ b/components/persistent_cache/backend_params_manager.cc
@@ -7,9 +7,9 @@ #include <algorithm> #include <array> #include <cstdint> +#include <queue> #include <string> #include <string_view> -#include <vector> #include "base/files/file.h" #include "base/files/file_enumerator.h" @@ -37,16 +37,29 @@ base::File::Info info; }; +// Comparator to be used with priority_queue to make sure that smallest times +// representing the oldest files are at the top. +class FilePathWithInfoComparator { + public: + bool operator()(const FilePathWithInfo& a, const FilePathWithInfo& b) { + return a.info.last_modified > b.info.last_modified; + } +}; + const base::FilePath::CharType kDbFile[] = FILE_PATH_LITERAL(".db_file"); const base::FilePath::CharType kJournalFile[] = FILE_PATH_LITERAL(".journal_file"); constexpr size_t kLruCacheCapacity = 100; +// Character not allowed in keys or filenames (by itself). Used to mark the +// start of a replacement token. +constexpr char kTokenMarker = '`'; + // All characters allowed in filenames. constexpr std::string_view kAllowedCharsInFilenames = "abcdefghijklmnopqrstuvwxyz0123456789-._~" - "#[]@!$&'()+,;="; + "#[]@!$&'()+,;= "; // Use to translate a character `c` viable for a filename into another arbitrary // but equally viable character. To reverse the process the function is called @@ -81,20 +94,20 @@ // Mapping of characters illegal in filenames to a unique token to represent // them in filenames. This prevents collisions by avoiding two characters get // mapped to the same value. Ex: -// "*/" --> " 9 2" -// "><" --> " 5 4" +// "*/" --> "`9`2" +// "><" --> "`5`4" // -// Mapping both strings to " 1 1" for example would result in a valid filename +// Mapping both strings to "`1`1" for example would result in a valid filename // but in backing files being shared for two keys which is not correct. -static_assert(kAllowedCharsInFilenames.find(' ') == std::string::npos, +static_assert(kAllowedCharsInFilenames.find(kTokenMarker) == std::string::npos, "Space is not allowed in filenames by itself."); using ConstStringPair = std::pair<char, const char*>; std::array<ConstStringPair, 10> kCharacterToTokenMap{ - ConstStringPair{'\\', " 1"}, ConstStringPair{'/', " 2"}, - ConstStringPair{'|', " 3"}, ConstStringPair{'<', " 4"}, - ConstStringPair{'>', " 5"}, ConstStringPair{':', " 6"}, - ConstStringPair{'\"', " 7"}, ConstStringPair{'?', " 8"}, - ConstStringPair{'*', " 9"}, ConstStringPair{'\n', " 0"}}; + ConstStringPair{'\\', "`1"}, ConstStringPair{'/', "`2"}, + ConstStringPair{'|', "`3"}, ConstStringPair{'<', "`4"}, + ConstStringPair{'>', "`5"}, ConstStringPair{':', "`6"}, + ConstStringPair{'\"', "`7"}, ConstStringPair{'?', "`8"}, + ConstStringPair{'*', "`9"}, ConstStringPair{'\n', "`0"}}; // Use to get a token to insert in a filename if `c` is a character // illegal in filenames and an empty string if it's not. @@ -157,7 +170,7 @@ FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&BackendParamsManager::CreateParamsSync, top_directory_, - backend_type, key, access_rights), + backend_type, filename, access_rights), base::BindOnce(&BackendParamsManager::SaveParams, weak_factory_.GetWeakPtr(), key, std::move(callback))); } @@ -212,18 +225,21 @@ backend_params_map_.Clear(); int64_t total_footprint = 0; - std::vector<FilePathWithInfo> filepaths_with_info; + + std::priority_queue<FilePathWithInfo, std::vector<FilePathWithInfo>, + FilePathWithInfoComparator> + file_paths_with_info; base::FileEnumerator file_enumerator(top_directory_, /*recursive=*/false, base::FileEnumerator::FILES); - file_enumerator.ForEach([&total_footprint, &filepaths_with_info]( + file_enumerator.ForEach([&total_footprint, &file_paths_with_info]( const base::FilePath& file_path) { base::File::Info info; base::GetFileInfo(file_path, &info); // Only target database files for deletion. if (file_path.MatchesFinalExtension(kDbFile)) { - filepaths_with_info.emplace_back(file_path, info); + file_paths_with_info.emplace(file_path, info); } // All files count towards measured footprint. @@ -236,21 +252,16 @@ .number_of_bytes_deleted = 0}; } - // Order files from least to most recently modified to prioritize deleting - // older staler files. - std::sort(filepaths_with_info.begin(), filepaths_with_info.end(), - [](const FilePathWithInfo& left, const FilePathWithInfo& right) { - return left.info.last_modified < right.info.last_modified; - }); - int64_t size_of_necessary_deletes = total_footprint - target_footprint; int64_t deleted_size = 0; - for (const FilePathWithInfo& file_path_with_info : filepaths_with_info) { + while (!file_paths_with_info.empty()) { if (size_of_necessary_deletes <= deleted_size) { break; } + const FilePathWithInfo& file_path_with_info = file_paths_with_info.top(); + bool db_file_delete_success = base::DeleteFile(file_path_with_info.file_path); base::UmaHistogramBoolean( @@ -276,6 +287,8 @@ deleted_size += journal_file_info.size; } }; + + file_paths_with_info.pop(); } return FootprintReductionResult{ @@ -313,10 +326,10 @@ key.reserve(filename.size()); for (auto it = filename.begin(); it != filename.end(); ++it) { - if (*it == ' ') { - // Spaces cannot be by themselves in filenames. Return an empty string - // instead of CHECKing here because it's not advisable to have a crash - // because something renamed a file. + if (*it == kTokenMarker) { + // Token markers cannot be by themselves in filenames. Return an empty + // string instead of CHECKing here because it's not advisable to have a + // crash because something renamed a file. if (it + 1 == filename.end()) { return ""; } @@ -331,8 +344,9 @@ continue; } - // If executiion gets here it's that a space was followed by a character - // that didn't resolve to anything. This means the file name is invalid. + // If execution gets here it's that a token marker was followed by a + // character that didn't resolve to anything. This means the file name is + // invalid. return ""; } else { std::optional<char> rotated_char = RotateChar(*it, false);
diff --git a/components/persistent_cache/backend_params_manager_unittest.cc b/components/persistent_cache/backend_params_manager_unittest.cc index 6771089..b8b659c2 100644 --- a/components/persistent_cache/backend_params_manager_unittest.cc +++ b/components/persistent_cache/backend_params_manager_unittest.cc
@@ -309,8 +309,8 @@ TEST(BackendParamsManager, KeyToFileName) { // Invalid tokens results in empty string and not a crash. - EXPECT_EQ(BackendParamsManager::KeyFromFileName(" "), ""); - EXPECT_EQ(BackendParamsManager::KeyFromFileName(" "), ""); + EXPECT_EQ(BackendParamsManager::KeyFromFileName("`"), ""); + EXPECT_EQ(BackendParamsManager::KeyFromFileName("``"), ""); // Invalid characters result in an empty string and not a crash. EXPECT_EQ(BackendParamsManager::KeyFromFileName("/"), "");
diff --git a/components/privacy_sandbox_strings.grd b/components/privacy_sandbox_strings.grd index 8260376..0aec73bd 100644 --- a/components/privacy_sandbox_strings.grd +++ b/components/privacy_sandbox_strings.grd
@@ -1005,46 +1005,6 @@ When you're in Incognito mode, sites can't use third-party cookies. If a site that relies on these cookies isn't working, you can <ph name="BEGIN_LINK"><link></ph>try giving that site temporary access to third-party cookies<ph name="END_LINK"></link></ph>. </message> - <!-- RWS - All Sites --> - <message name="IDS_ALL_SITES_RWS_LABEL" desc="A specific indication that this website has a list of related websites associated with it." formatter_data="android_java"> - Has related sites - </message> - <message name="IDS_ALL_SITES_SHOW_RWS_BUTTON" desc="Title for a button that allows the user to go to the related website sets settings page to view all of the related sites associated with this website."> - Show related sites - </message> - <message name="IDS_ALL_SITES_RWS_FILTER_VIEW_TITLE" desc="Header for the related website sets settings page view. Includes the URL for the website that owns the related website set."> - Related sites defined by <ph name="RWS_OWNER">$1<ex>google.com</ex></ph> - </message> - <message name="IDS_ALL_SITES_RWS_FILTER_VIEW_DESCRIPTION" desc="Description explaining what related website sets are and how they relate to third-party cookies. Includes a Learn More link that takes the user to a Help Center article about managing settings for third-party cookies and related website sets."> - Related sites can share third-party cookies with each other to help sites work as expected, such as keeping you signed in or remembering your site settings. Sites are responsible for explaining why they need access to this data. Learn more about <ph name="START_LINK"><a target="_blank" href="$1" aria-description="$2"></ph>related sites and third-party cookies<ph name="END_LINK"></a></ph> - </message> - <message name="IDS_ALL_SITES_RWS_FILTER_VIEW_STORAGE_DESCRIPTION" desc="Describes how much storage is being used by all sites in the displayed list of related websites."> - Total storage used by sites in the list: <ph name="TOTAL_USAGE">$1<ex>8 GB</ex></ph> - </message> - <message name="IDS_ALL_SITES_RWS_DELETE_DATA_BUTTON_LABEL" desc="Label of a button to delete all site data for sites in a related website set."> - Delete data - </message> - <message name="IDS_ALL_SITES_RWS_DELETE_DATA_DIALOG_TITLE" desc="Title of the dialog that warns about deleting all site data for sites in a related website set."> - Delete data? - </message> - - <!-- RWS - Site Settings --> - <message name="IDS_SITE_SETTINGS_RWS_DESCRIPTION_ANDROID" desc="Description explaining what related website sets are and how they relate to third-party cookies. Includes a Learn More link that takes the user to a Help Center article about managing settings for third-party cookies and related website sets." formatter_data="android_java"> - Related sites can share third-party cookies with each other to help sites work as expected, such as keeping you signed in or remembering your site settings. Sites are responsible for explaining why they need access to this data. <ph name="BEGIN_LINK"><link></ph>Learn more<ph name="END_LINK"></link></ph> - </message> - <message name="IDS_SITE_SETTINGS_RWS_DELETE_BUTTON_LABEL" desc="Title for a button that allows the user to delete all stored data for sites in the related website set associated with this website." formatter_data="android_java"> - Delete all data - </message> - <message name="IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_CONFIRMATION_ANDROID" desc="Text for the dialog that warns about deleting storage used by a site and its related sites." formatter_data="android_java"> - This action will delete all data and cookies stored by <ph name="SITE_NAME">%1$s<ex>www.example.com</ex></ph> and related sites - </message> - <message name="IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_SIGN_OUT" desc="Text for the dialog that warns about potentially being signed out of sites in the related website set." formatter_data="android_java"> - You'll be signed out of these sites - </message> - <message name="IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_DIALOG_TITLE" desc="Title for the dialog that prompts the user to confirm if they would like to delete all data for sites in the related website set." formatter_data="android_java"> - Delete all data? - </message> - <!-- ACT - Incognito Tracking Protections Settings Page --> <message name="IDS_INCOGNITO_TRACKING_PROTECTIONS_PAGE_TITLE" desc="Title for the 'Incognito tracking protections' settings page." formatter_data="android_java"> Incognito tracking protections
diff --git a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_DELETE_DATA_BUTTON_LABEL.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_DELETE_DATA_BUTTON_LABEL.png.sha1 deleted file mode 100644 index 6ebf5bf..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_DELETE_DATA_BUTTON_LABEL.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -3c1883e31b8faed8ea70c19df50048f3697a7bc9 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_DELETE_DATA_DIALOG_TITLE.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_DELETE_DATA_DIALOG_TITLE.png.sha1 deleted file mode 100644 index b6d3b4a..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_DELETE_DATA_DIALOG_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -4edebdead9018ae150affaab8dd278fe2efb0635 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_DESCRIPTION.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_DESCRIPTION.png.sha1 deleted file mode 100644 index 983873376..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_DESCRIPTION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -4f6197b39c2d85b393ba8c06658f492fbcf92812 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_STORAGE_DESCRIPTION.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_STORAGE_DESCRIPTION.png.sha1 deleted file mode 100644 index cb4ac0e9..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_STORAGE_DESCRIPTION.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -c6cc2cd345b40723b878997ee4ff2a5ba8f4d7d8 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_TITLE.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_TITLE.png.sha1 deleted file mode 100644 index 0e9c5e3..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_FILTER_VIEW_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -fcc7199a0077fcb34abe7b6be674ad22b4e3188b \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_LABEL.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_LABEL.png.sha1 deleted file mode 100644 index 815a7d6..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_RWS_LABEL.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -ed20499e7e9d266df5197128dc2aedc3c8b8e5a0 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_SHOW_RWS_BUTTON.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_SHOW_RWS_BUTTON.png.sha1 deleted file mode 100644 index e4c54c6ea..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_ALL_SITES_SHOW_RWS_BUTTON.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -d264fbf364b0c58b2646464b366319f8f9e5529f \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_CONFIRMATION_ANDROID.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_CONFIRMATION_ANDROID.png.sha1 deleted file mode 100644 index ffe90b0b..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_CONFIRMATION_ANDROID.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -5fa2bf9a248000bbda0a7fb8b5bf5c6452e36edf \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_DIALOG_TITLE.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_DIALOG_TITLE.png.sha1 deleted file mode 100644 index 1d2aa18..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_DIALOG_TITLE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -b7607d0c1de505f0695c7c671ea2eb3070fd621c \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_SIGN_OUT.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_SIGN_OUT.png.sha1 deleted file mode 100644 index 3c718cf7..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_DELETE_RWS_STORAGE_SIGN_OUT.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -8c44fb9fd6dd3c261adba78768d1ec6157b00bb2 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_RWS_DELETE_BUTTON_LABEL.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_RWS_DELETE_BUTTON_LABEL.png.sha1 deleted file mode 100644 index 59beceb..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_RWS_DELETE_BUTTON_LABEL.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -ab92e155743656678a896366b15deb12fe6bba09 \ No newline at end of file
diff --git a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_RWS_DESCRIPTION_ANDROID.png.sha1 b/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_RWS_DESCRIPTION_ANDROID.png.sha1 deleted file mode 100644 index 9527ea5..0000000 --- a/components/privacy_sandbox_strings_grd/IDS_SITE_SETTINGS_RWS_DESCRIPTION_ANDROID.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -7fbbdb9e7b15359452aa83093fd3e6fa6de8bda8 \ No newline at end of file
diff --git a/components/qr_code_generator/bitmap_generator.cc b/components/qr_code_generator/bitmap_generator.cc index 557ebb53..0bfb6e12 100644 --- a/components/qr_code_generator/bitmap_generator.cc +++ b/components/qr_code_generator/bitmap_generator.cc
@@ -9,7 +9,9 @@ #include "components/qr_code_generator/bitmap_generator.h" -#include "base/notreached.h" +#include <cstdint> + +#include "base/containers/span.h" #include "base/types/expected.h" #include "build/build_config.h" #include "components/qr_code_generator/dino_image.h" @@ -54,13 +56,13 @@ // Helper: Copies |src_num_rows| of dino data from |src_array| to // canvas (obtained via closure), starting at |dest_row|. - auto copyPixelBitData = [&](const unsigned char* src_array, int src_num_rows, - int dest_row) { + auto copyPixelBitData = [&](base::span<const unsigned char> src_array, + int src_num_rows, int dest_row) { for (int row = 0; row < src_num_rows; row++) { int which_byte = (row * bytes_per_row); unsigned char mask = 0b10000000; for (int col = 0; col < dino_image::kDinoWidth; col++) { - if (*(src_array + which_byte) & mask) { + if (src_array[which_byte] & mask) { canvas.drawIRect({col, dest_row + row, col + 1, dest_row + row + 1}, paint); }
diff --git a/components/reporting/util/file_unittest.cc b/components/reporting/util/file_unittest.cc index eab9a1a..469ff42 100644 --- a/components/reporting/util/file_unittest.cc +++ b/components/reporting/util/file_unittest.cc
@@ -10,6 +10,7 @@ #include "components/reporting/util/file.h" #include <string> +#include <string_view> #include "base/files/file.h" #include "base/files/scoped_temp_dir.h" @@ -23,10 +24,10 @@ namespace reporting { namespace { -constexpr char kNewFile[] = "to_create.txt"; -constexpr char kWriteDataOne[] = "hello world!"; -constexpr char kWriteDataTwo[] = "bye world!"; -constexpr char kMultiLineData[] = "12\n34\n56\n78\n"; +constexpr std::string_view kNewFile = "to_create.txt"; +constexpr std::string_view kWriteDataOne = "hello world!"; +constexpr std::string_view kWriteDataTwo = "bye world!"; +constexpr std::string_view kMultiLineData = "12\n34\n56\n78\n"; constexpr size_t kMultiLineDataLineLength = 3; constexpr size_t kMultiLineDataLines = 4; constexpr size_t kOverFlowPos = 256; @@ -38,10 +39,9 @@ ASSERT_TRUE(remove_status.has_value()) << remove_status.error(); const auto read_status = MaybeReadFile(file_path, 0); ASSERT_TRUE(read_status.has_value()) << read_status.error(); - ASSERT_THAT( - read_status.value(), - StrEq( - &kMultiLineData[expected_lines_removed * kMultiLineDataLineLength])); + ASSERT_THAT(read_status.value(), + StrEq(kMultiLineData.substr(expected_lines_removed * + kMultiLineDataLineLength))); } TEST(FileTest, DeleteFileWarnIfFailed) {
diff --git a/components/resources/dom_distiller_resources.grdp b/components/resources/dom_distiller_resources.grdp index e879e78d..68c2654 100644 --- a/components/resources/dom_distiller_resources.grdp +++ b/components/resources/dom_distiller_resources.grdp
@@ -4,6 +4,7 @@ <include name="IDR_DOM_DISTILLER_VIEWER_JS" file="../dom_distiller/core/javascript/dom_distiller_viewer.js" type="BINDATA" /> <include name="IDR_DISTILLER_JS" file="../dom_distiller/core/javascript/domdistiller.js" flattenhtml="true" type="BINDATA" /> <include name="IDR_DISTILLER_CSS" file="../dom_distiller/core/css/distilledpage.css" type="BINDATA" preprocess="true"/> + <include name="IDR_DISTILLER_COMMON_CSS" file="../dom_distiller/core/css/distilledpage_common.css" type="BINDATA" preprocess="true"/> <include name="IDR_DISTILLER_DESKTOP_CSS" file="../dom_distiller/core/css/distilledpage_desktop.css" type="BINDATA" /> <include name="IDR_DISTILLER_LOADING_IMAGE" file="../dom_distiller/core/images/dom_distiller_material_spinner.svg" type="BINDATA" /> <include name="IDR_EXTRACT_PAGE_FEATURES_JS" file="../dom_distiller/core/javascript/extract_features.js" type="BINDATA" />
diff --git a/components/saved_tab_groups/internal/BUILD.gn b/components/saved_tab_groups/internal/BUILD.gn index 9e9fd419..831b116 100644 --- a/components/saved_tab_groups/internal/BUILD.gn +++ b/components/saved_tab_groups/internal/BUILD.gn
@@ -227,10 +227,9 @@ # This is allowed until usage of SavedTabGroupKeyedService has been migrated # to TabGroupSyncService. "//chrome/android:browser_test_support", - "//chrome/browser", "//chrome/browser/sync/test/integration:*", - "//chrome/browser/ui", "//chrome/browser/ui/tabs:tab_group_impl", + "//chrome/browser/ui/tabs/saved_tab_groups:impl", "//chrome/test:*", "//ios/chrome/browser/saved_tab_groups/model", "//ios/chrome/test/app:test_support",
diff --git a/components/saved_tab_groups/internal/saved_tab_group_model.cc b/components/saved_tab_groups/internal/saved_tab_group_model.cc index 4c3991a..4a21b93 100644 --- a/components/saved_tab_groups/internal/saved_tab_group_model.cc +++ b/components/saved_tab_groups/internal/saved_tab_group_model.cc
@@ -219,6 +219,12 @@ group->SetCollaborationId(std::move(collaboration_id)); } +void SavedTabGroupModel::MakeTabGroupUnsharedForTesting( + const LocalTabGroupID& local_group_id) { + SavedTabGroup* const group = GetMutableGroup(local_group_id); + group->SetCollaborationId(std::nullopt); +} + void SavedTabGroupModel::SetIsTransitioningToSaved( const LocalTabGroupID& local_group_id, bool is_transitioning_to_saved) {
diff --git a/components/saved_tab_groups/internal/saved_tab_group_model.h b/components/saved_tab_groups/internal/saved_tab_group_model.h index 8ecbdea..6668fb41 100644 --- a/components/saved_tab_groups/internal/saved_tab_group_model.h +++ b/components/saved_tab_groups/internal/saved_tab_group_model.h
@@ -97,6 +97,7 @@ // updated group is retrieved from the service before use. void MakeTabGroupSharedForTesting(const LocalTabGroupID& local_group_id, CollaborationId collaboration_id); + void MakeTabGroupUnsharedForTesting(const LocalTabGroupID& local_group_id); // Mark whether the tab group identified by `local_group_id` is transitioning // to a saved group.
diff --git a/components/saved_tab_groups/internal/tab_group_sync_service_impl.cc b/components/saved_tab_groups/internal/tab_group_sync_service_impl.cc index 9b3d70d..47f2523a 100644 --- a/components/saved_tab_groups/internal/tab_group_sync_service_impl.cc +++ b/components/saved_tab_groups/internal/tab_group_sync_service_impl.cc
@@ -874,6 +874,12 @@ model_->MakeTabGroupSharedForTesting(local_group_id, collaboration_id); } +void TabGroupSyncServiceImpl::MakeTabGroupUnsharedForTesting( + const LocalTabGroupID& local_group_id) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + model_->MakeTabGroupUnsharedForTesting(local_group_id); +} + bool TabGroupSyncServiceImpl::ShouldExposeSavedTabGroupInList( const SavedTabGroup& group) const { // TODO(crbug.com/395160538): Simplify the logic of filtering out groups
diff --git a/components/saved_tab_groups/internal/tab_group_sync_service_impl.h b/components/saved_tab_groups/internal/tab_group_sync_service_impl.h index acf0a2d..3d43c1fe 100644 --- a/components/saved_tab_groups/internal/tab_group_sync_service_impl.h +++ b/components/saved_tab_groups/internal/tab_group_sync_service_impl.h
@@ -122,6 +122,8 @@ void MakeTabGroupSharedForTesting( const LocalTabGroupID& local_group_id, const syncer::CollaborationId& collaboration_id) override; + void MakeTabGroupUnsharedForTesting( + const LocalTabGroupID& local_group_id) override; void AboutToUnShareTabGroup(const LocalTabGroupID& local_group_id, base::OnceClosure on_complete_callback) override;
diff --git a/components/saved_tab_groups/public/features.cc b/components/saved_tab_groups/public/features.cc index 32b35ac6..b3e73834 100644 --- a/components/saved_tab_groups/public/features.cc +++ b/components/saved_tab_groups/public/features.cc
@@ -18,12 +18,6 @@ constexpr char kGroupCleanUpTimeIntervalInSecondsFinchKey[] = "group_clean_up_time_internal_seconds"; -// Feature flag used to determine whether the network layer is disabled for -// tab group sync. -BASE_FEATURE(kTabGroupSyncDisableNetworkLayer, - "TabGroupSyncDisableNetworkLayer", - base::FEATURE_DISABLED_BY_DEFAULT); - // Feature flag specific to Desktop platforms. When enabled, desktop platforms // will use the TabGroupSyncService. When disabled, desktop platforms will // continue to use SavedTabGroupKeyedService.
diff --git a/components/saved_tab_groups/public/tab_group_sync_service.h b/components/saved_tab_groups/public/tab_group_sync_service.h index c920ad8..3714dcda 100644 --- a/components/saved_tab_groups/public/tab_group_sync_service.h +++ b/components/saved_tab_groups/public/tab_group_sync_service.h
@@ -243,6 +243,8 @@ virtual void MakeTabGroupSharedForTesting( const LocalTabGroupID& local_group_id, const syncer::CollaborationId& collaboration_id) = 0; + virtual void MakeTabGroupUnsharedForTesting( + const LocalTabGroupID& local_group_id) = 0; // Mutator methods for shared tab groups. // Starts the process of converting a shared tab group to saved tab group. Due
diff --git a/components/saved_tab_groups/test_support/fake_tab_group_sync_service.cc b/components/saved_tab_groups/test_support/fake_tab_group_sync_service.cc index edea4792..2e4e689 100644 --- a/components/saved_tab_groups/test_support/fake_tab_group_sync_service.cc +++ b/components/saved_tab_groups/test_support/fake_tab_group_sync_service.cc
@@ -246,6 +246,11 @@ // No op. } +void FakeTabGroupSyncService::MakeTabGroupUnsharedForTesting( + const LocalTabGroupID& local_group_id) { + // No op. +} + void FakeTabGroupSyncService::AboutToUnShareTabGroup( const LocalTabGroupID& local_group_id, base::OnceClosure on_complete_callback) {
diff --git a/components/saved_tab_groups/test_support/fake_tab_group_sync_service.h b/components/saved_tab_groups/test_support/fake_tab_group_sync_service.h index 3323cb2..8ce08d41 100644 --- a/components/saved_tab_groups/test_support/fake_tab_group_sync_service.h +++ b/components/saved_tab_groups/test_support/fake_tab_group_sync_service.h
@@ -66,6 +66,8 @@ void MakeTabGroupSharedForTesting( const LocalTabGroupID& local_group_id, const syncer::CollaborationId& collaboration_id) override; + void MakeTabGroupUnsharedForTesting( + const LocalTabGroupID& local_group_id) override; void AboutToUnShareTabGroup(const LocalTabGroupID& local_group_id, base::OnceClosure on_complete_callback) override; void OnTabGroupUnShareComplete(const LocalTabGroupID& local_group_id,
diff --git a/components/saved_tab_groups/test_support/mock_tab_group_sync_service.h b/components/saved_tab_groups/test_support/mock_tab_group_sync_service.h index 5c10805..c8d65f1 100644 --- a/components/saved_tab_groups/test_support/mock_tab_group_sync_service.h +++ b/components/saved_tab_groups/test_support/mock_tab_group_sync_service.h
@@ -71,6 +71,7 @@ MOCK_METHOD(void, MakeTabGroupSharedForTesting, (const LocalTabGroupID&, const syncer::CollaborationId&)); + MOCK_METHOD(void, MakeTabGroupUnsharedForTesting, (const LocalTabGroupID&)); MOCK_METHOD(void, AboutToUnShareTabGroup, (const LocalTabGroupID&, base::OnceClosure));
diff --git a/components/sessions/core/command_storage_backend_unittest.cc b/components/sessions/core/command_storage_backend_unittest.cc index a002e48..daee44d 100644 --- a/components/sessions/core/command_storage_backend_unittest.cc +++ b/components/sessions/core/command_storage_backend_unittest.cc
@@ -11,6 +11,7 @@ #include <utility> #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/functional/bind.h" @@ -75,13 +76,13 @@ } void AssertCommandsEqualsData( - const TestData* data, - size_t data_length, + base::span<const TestData> data, const std::vector<std::unique_ptr<SessionCommand>>& commands) { - ASSERT_EQ(data_length, commands.size()); - for (size_t i = 0; i < data_length; ++i) - UNSAFE_TODO(EXPECT_NO_FATAL_FAILURE( - AssertCommandEqualsData(data[i], commands[i].get()))); + ASSERT_EQ(data.size(), commands.size()); + for (size_t i = 0; i < data.size(); ++i) { + EXPECT_NO_FATAL_FAILURE( + AssertCommandEqualsData(data[i], commands[i].get())); + } } scoped_refptr<CommandStorageBackend> CreateBackend( @@ -743,8 +744,7 @@ ASSERT_TRUE(base::CopyFile( test_data_path, restore_path().Append(kLegacyCurrentSessionFileName))); scoped_refptr<CommandStorageBackend> backend = CreateBackendWithRestoreType(); - AssertCommandsEqualsData(data, std::size(data), - backend->ReadLastSessionCommands().commands); + AssertCommandsEqualsData(data, backend->ReadLastSessionCommands().commands); } TEST_F(CommandStorageBackendTest, NewFileOnTruncate) {
diff --git a/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc b/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc index 46dbf5b..8ac5bc6 100644 --- a/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc +++ b/components/spellcheck/renderer/spellcheck_multilingual_unittest.cc
@@ -11,7 +11,7 @@ #include <utility> #include <vector> -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/memory/raw_ptr.h" #include "base/path_service.h" #include "base/strings/string_split.h" @@ -80,29 +80,25 @@ TestingSpellCheckProvider* provider() { return provider_.get(); } protected: - void ExpectSpellCheckWordResults(const std::string& languages, - const SpellcheckTestCase* test_cases, - size_t num_test_cases) { + void ExpectSpellCheckWordResults( + const std::string& languages, + base::span<const SpellcheckTestCase> test_cases) { ReinitializeSpellCheck(languages); - for (size_t i = 0; i < num_test_cases; ++i) { + for (size_t i = 0; i < test_cases.size(); ++i) { size_t misspelling_start = 0; size_t misspelling_length = 0; static_cast<blink::WebTextCheckClient*>(provider()) - ->CheckSpelling(blink::WebString::FromUTF16(base::WideToUTF16( - UNSAFE_TODO(test_cases[i]).input)), + ->CheckSpelling(blink::WebString::FromUTF16( + base::WideToUTF16(test_cases[i].input)), misspelling_start, misspelling_length, nullptr); - UNSAFE_TODO(EXPECT_EQ(test_cases[i].expected_misspelling_start, - misspelling_start)) + EXPECT_EQ(test_cases[i].expected_misspelling_start, misspelling_start) << "Improper misspelling location found with the languages " - << languages << " when checking \"" - << UNSAFE_TODO(test_cases[i]).input << "\"."; - UNSAFE_TODO(EXPECT_EQ(test_cases[i].expected_misspelling_length, - misspelling_length)) + << languages << " when checking \"" << test_cases[i].input << "\"."; + EXPECT_EQ(test_cases[i].expected_misspelling_length, misspelling_length) << "Improper misspelling length found with the languages " - << languages << " when checking \"" - << UNSAFE_TODO(test_cases[i]).input << "\"."; + << languages << " when checking \"" << test_cases[i].input << "\"."; } } @@ -158,8 +154,7 @@ do { std::string reordered_languages = base::JoinString(permuted_languages, ","); - ExpectSpellCheckWordResults(reordered_languages, kTestCases, - std::size(kTestCases)); + ExpectSpellCheckWordResults(reordered_languages, kTestCases); } while (std::next_permutation(permuted_languages.begin(), permuted_languages.end())); } @@ -189,8 +184,9 @@ {L"sand hola sand hola sand hola", 0, 0}, {L"hola sand hola sand hola sand", 0, 0}, {L"hola:legs", 0, 9}, - {L"legs:hola", 0, 9}}; - ExpectSpellCheckWordResults("en-US,es-ES", kTestCases, std::size(kTestCases)); + {L"legs:hola", 0, 9}, + }; + ExpectSpellCheckWordResults("en-US,es-ES", kTestCases); } // If there are no spellcheck languages, no text should be marked as misspelled.
diff --git a/components/storage_monitor/storage_monitor_linux_unittest.cc b/components/storage_monitor/storage_monitor_linux_unittest.cc index 96e3cc6..cbba52f 100644 --- a/components/storage_monitor/storage_monitor_linux_unittest.cc +++ b/components/storage_monitor/storage_monitor_linux_unittest.cc
@@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <array> - // StorageMonitorLinux unit tests. #include "components/storage_monitor/storage_monitor_linux.h" @@ -13,10 +11,12 @@ #include <stdint.h> #include <stdio.h> +#include <array> #include <memory> #include <string> #include "base/check.h" +#include "base/containers/span.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/functional/bind.h" @@ -173,8 +173,7 @@ MtabTestData initial_test_data[] = { MtabTestData("dummydevice", "dummydir", kInvalidFS), }; - WriteToMtab(initial_test_data, std::size(initial_test_data), - /*overwrite=*/true); + WriteToMtab(initial_test_data, /*overwrite=*/true); monitor_ = std::make_unique<TestStorageMonitorLinux>(mtab_file_); mock_storage_observer_ = std::make_unique<MockRemovableStorageObserver>(); @@ -193,25 +192,23 @@ monitor_.reset(); } - // Append mtab entries from the |data| array of size |data_size| to the mtab + // Append mtab entries from the |data| span to the mtab // file, and run the message loop. - void AppendToMtabAndRunLoop(const MtabTestData* data, size_t data_size) { - WriteToMtab(data, data_size, /*overwrite=*/false); + void AppendToMtabAndRunLoop(base::span<const MtabTestData> data) { + WriteToMtab(data, /*overwrite=*/false); WaitForMtabUpdate(); } - // Overwrite the mtab file with mtab entries from the |data| array of size - // |data_size|, and run the message loop. - void OverwriteMtabAndRunLoop(const MtabTestData* data, size_t data_size) { - WriteToMtab(data, data_size, /*overwrite=*/true); + // Overwrite the mtab file with mtab entries from the |data| span, and run + // the message loop. + void OverwriteMtabAndRunLoop(base::span<const MtabTestData> data) { + WriteToMtab(data, /*overwrite=*/true); WaitForMtabUpdate(); } // Simplied version of OverwriteMtabAndRunLoop() that just deletes all the // entries in the mtab file. - void WriteEmptyMtabAndRunLoop() { - OverwriteMtabAndRunLoop(/*data=*/nullptr, /*data_size=*/0); - } + void WriteEmptyMtabAndRunLoop() { OverwriteMtabAndRunLoop(/*data=*/{}); } // Create a directory named |dir| relative to the test directory. // It has a DCIM directory, so StorageMonitorLinux recognizes it as a media @@ -283,12 +280,9 @@ } // Write the test mtab data to |mtab_file_|. - // |data| is an array of mtab entries. - // |data_size| is the array size of |data|. + // |data| is a span of mtab entries. // |overwrite| specifies whether to overwrite |mtab_file_|. - void WriteToMtab(const MtabTestData* data, - size_t data_size, - bool overwrite) { + void WriteToMtab(base::span<const MtabTestData> data, bool overwrite) { FILE* file = setmntent(mtab_file_.value().c_str(), overwrite ? "w" : "a"); ASSERT_TRUE(file); @@ -306,13 +300,10 @@ entry.mnt_opts = const_cast<char*>(kMountOpts); entry.mnt_freq = 0; entry.mnt_passno = 0; - for (size_t i = 0; i < data_size; ++i) { - entry.mnt_fsname = - const_cast<char*>(UNSAFE_TODO(data[i]).mount_device.c_str()); - entry.mnt_dir = - const_cast<char*>(UNSAFE_TODO(data[i]).mount_point.c_str()); - entry.mnt_type = - const_cast<char*>(UNSAFE_TODO(data[i]).mount_type.c_str()); + for (size_t i = 0; i < data.size(); ++i) { + entry.mnt_fsname = const_cast<char*>(data[i].mount_device.c_str()); + entry.mnt_dir = const_cast<char*>(data[i].mount_point.c_str()); + entry.mnt_type = const_cast<char*>(data[i].mount_type.c_str()); ASSERT_EQ(0, addmntent(file, &entry)); } ASSERT_EQ(1, endmntent(file)); @@ -341,7 +332,7 @@ }; // Only |kDeviceDCIM2| should be attached, since |kDeviceFixed| has a bad // path. - AppendToMtabAndRunLoop(test_data, std::size(test_data)); + AppendToMtabAndRunLoop(test_data); EXPECT_EQ(1, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); @@ -364,7 +355,7 @@ MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS), }; // |kDeviceDCIM1| should be attached as expected. - AppendToMtabAndRunLoop(test_data1, std::size(test_data1)); + AppendToMtabAndRunLoop(test_data1); EXPECT_EQ(1, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); @@ -377,7 +368,7 @@ MtabTestData test_data2[] = { MtabTestData(kDeviceFixed, test_path_b.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data2, std::size(test_data2)); + AppendToMtabAndRunLoop(test_data2); EXPECT_EQ(1, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); @@ -391,7 +382,7 @@ MtabTestData test_data3[] = { MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data3, std::size(test_data3)); + AppendToMtabAndRunLoop(test_data3); EXPECT_EQ(2, observer().attach_calls()); EXPECT_EQ(1, observer().detach_calls()); EXPECT_EQ(GetDeviceId(kDeviceNoDCIM), observer().last_attached().device_id()); @@ -419,7 +410,7 @@ MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS), MtabTestData(kDeviceDCIM2, test_path_b.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data1, std::size(test_data1)); + AppendToMtabAndRunLoop(test_data1); EXPECT_EQ(2, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); @@ -431,7 +422,7 @@ MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS), MtabTestData(kDeviceDCIM2, test_path_a.value(), kValidFS), }; - OverwriteMtabAndRunLoop(test_data2, std::size(test_data2)); + OverwriteMtabAndRunLoop(test_data2); EXPECT_EQ(4, observer().attach_calls()); EXPECT_EQ(2, observer().detach_calls()); @@ -456,7 +447,7 @@ MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS), MtabTestData(kDeviceDCIM2, test_path_b.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data1, std::size(test_data1)); + AppendToMtabAndRunLoop(test_data1); EXPECT_EQ(2, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); @@ -469,7 +460,7 @@ MtabTestData test_data2[] = { MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data2, std::size(test_data2)); + AppendToMtabAndRunLoop(test_data2); EXPECT_EQ(2, observer().attach_calls()); EXPECT_EQ(1, observer().detach_calls()); @@ -481,7 +472,7 @@ MtabTestData(kDeviceDCIM2, test_path_b.value(), kValidFS), MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS), }; - OverwriteMtabAndRunLoop(test_data3, std::size(test_data3)); + OverwriteMtabAndRunLoop(test_data3); EXPECT_EQ(3, observer().attach_calls()); EXPECT_EQ(2, observer().detach_calls()); @@ -492,14 +483,14 @@ MtabTestData test_data4[] = { MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data4, std::size(test_data4)); + AppendToMtabAndRunLoop(test_data4); EXPECT_EQ(3, observer().attach_calls()); EXPECT_EQ(2, observer().detach_calls()); // Detach |kDeviceDCIM1| from |kMountPointB|. // kDeviceDCIM1 -> kMountPointA * // kDeviceDCIM2 -> kMountPointB * - OverwriteMtabAndRunLoop(test_data1, std::size(test_data1)); + OverwriteMtabAndRunLoop(test_data1); EXPECT_EQ(5, observer().attach_calls()); EXPECT_EQ(3, observer().detach_calls()); @@ -521,7 +512,7 @@ MtabTestData test_data1[] = { MtabTestData(kDeviceDCIM1, test_path_a.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data1, std::size(test_data1)); + AppendToMtabAndRunLoop(test_data1); EXPECT_EQ(1, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); @@ -531,7 +522,7 @@ MtabTestData test_data2[] = { MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data2, std::size(test_data2)); + AppendToMtabAndRunLoop(test_data2); EXPECT_EQ(1, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); @@ -543,7 +534,7 @@ MtabTestData(kDeviceFixed, test_path_a.value(), kValidFS), }; RemoveDCIMDirFromMountPoint(kMountPointA); - AppendToMtabAndRunLoop(test_data3, std::size(test_data3)); + AppendToMtabAndRunLoop(test_data3); EXPECT_EQ(2, observer().attach_calls()); EXPECT_EQ(1, observer().detach_calls()); @@ -555,7 +546,7 @@ MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS), }; CreateMountPointWithDCIMDir(kMountPointA); - OverwriteMtabAndRunLoop(test_data4, std::size(test_data4)); + OverwriteMtabAndRunLoop(test_data4); EXPECT_EQ(2, observer().attach_calls()); EXPECT_EQ(1, observer().detach_calls()); @@ -567,7 +558,7 @@ MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS), }; base::DeleteFile(test_path_b.Append(kDCIMDirectoryName)); - AppendToMtabAndRunLoop(test_data5, std::size(test_data5)); + AppendToMtabAndRunLoop(test_data5); EXPECT_EQ(4, observer().attach_calls()); EXPECT_EQ(2, observer().detach_calls()); @@ -579,13 +570,13 @@ MtabTestData(kDeviceDCIM1, test_path_b.value(), kValidFS), }; CreateMountPointWithDCIMDir(kMountPointB); - OverwriteMtabAndRunLoop(test_data6, std::size(test_data6)); + OverwriteMtabAndRunLoop(test_data6); EXPECT_EQ(4, observer().attach_calls()); EXPECT_EQ(3, observer().detach_calls()); // Detach |kDeviceDCIM1| from |kMountPointB|. // kDeviceDCIM1 -> kMountPointA * - OverwriteMtabAndRunLoop(test_data1, std::size(test_data1)); + OverwriteMtabAndRunLoop(test_data1); EXPECT_EQ(4, observer().attach_calls()); EXPECT_EQ(3, observer().detach_calls()); @@ -613,7 +604,7 @@ MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS), MtabTestData(kDeviceFixed, test_path_c.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data1, std::size(test_data1)); + AppendToMtabAndRunLoop(test_data1); EXPECT_EQ(2, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls()); @@ -654,7 +645,7 @@ MtabTestData(kDeviceFixed, test_path_b.value(), kValidFS), MtabTestData(kDeviceFixed, test_path_c.value(), kValidFS), }; - AppendToMtabAndRunLoop(test_data2, std::size(test_data2)); + AppendToMtabAndRunLoop(test_data2); EXPECT_TRUE(notifier()->GetStorageInfoForPath(test_path_a, &device_info)); EXPECT_EQ(GetDeviceId(kDeviceDCIM1), device_info.device_id()); @@ -680,7 +671,7 @@ MtabTestData(kDeviceNoDCIM, test_path_b.value(), kValidFS), MtabTestData(kDeviceFixed, kInvalidPath, kInvalidFS), }; - AppendToMtabAndRunLoop(test_data1, std::size(test_data1)); + AppendToMtabAndRunLoop(test_data1); EXPECT_EQ(2, observer().attach_calls()); EXPECT_EQ(0, observer().detach_calls());
diff --git a/components/subresource_filter/core/common/test_ruleset_creator.cc b/components/subresource_filter/core/common/test_ruleset_creator.cc index 637cb66..bb67ca3 100644 --- a/components/subresource_filter/core/common/test_ruleset_creator.cc +++ b/components/subresource_filter/core/common/test_ruleset_creator.cc
@@ -9,7 +9,8 @@ #include <string_view> #include "base/check.h" -#include "base/compiler_specific.h" +#include "base/containers/span.h" +#include "base/containers/to_vector.h" #include "base/files/file_util.h" #include "base/strings/string_number_conversions.h" #include "base/threading/thread_restrictions.h" @@ -45,9 +46,7 @@ } ruleset_writer.Finish(); - auto* data = reinterpret_cast<const uint8_t*>(ruleset_contents.data()); - return std::vector<uint8_t>(data, - UNSAFE_TODO(data + ruleset_contents.size())); + return base::ToVector(base::as_byte_span(ruleset_contents)); } std::vector<uint8_t> SerializeIndexedRulesetWithMultipleRules(
diff --git a/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc b/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc index f9ae542d..9984516 100644 --- a/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc +++ b/components/sync/engine/cycle/sync_cycle_snapshot_unittest.cc
@@ -4,7 +4,6 @@ #include "components/sync/engine/cycle/sync_cycle_snapshot.h" -#include "base/i18n/rtl.h" #include "base/test/icu_test_util.h" #include "base/test/values_test_util.h" #include "base/values.h" @@ -19,8 +18,7 @@ TEST_F(SyncCycleSnapshotTest, SyncCycleSnapshotToValue) { // Formatting of "poll_interval" value depends on the current locale. // Expectations below use English (US) formatting. - base::test::ScopedRestoreICUDefaultLocale restore_locale; - base::i18n::SetICUDefaultLocale("en_US"); + base::test::ScopedRestoreICUDefaultLocale restore_locale("en_US"); ModelNeutralState model_neutral; model_neutral.num_successful_commits = 5;
diff --git a/components/tab_groups/BUILD.gn b/components/tab_groups/BUILD.gn index 184fd8d..4654a2e 100644 --- a/components/tab_groups/BUILD.gn +++ b/components/tab_groups/BUILD.gn
@@ -56,5 +56,6 @@ "android/java/res/values/colors.xml", "android/java/res/values/dimens.xml", ] + deps = [ "//components/strings:components_strings_grd" ] } }
diff --git a/components/tab_groups/android/java/src/org/chromium/components/tab_groups/TabGroupColorPickerUtils.java b/components/tab_groups/android/java/src/org/chromium/components/tab_groups/TabGroupColorPickerUtils.java index 94109f7..3df4811 100644 --- a/components/tab_groups/android/java/src/org/chromium/components/tab_groups/TabGroupColorPickerUtils.java +++ b/components/tab_groups/android/java/src/org/chromium/components/tab_groups/TabGroupColorPickerUtils.java
@@ -12,6 +12,7 @@ import androidx.annotation.ColorInt; import androidx.annotation.ColorRes; import androidx.annotation.DimenRes; +import androidx.annotation.StringRes; import androidx.core.content.ContextCompat; import com.google.android.material.color.MaterialColors; @@ -355,6 +356,39 @@ }; } + /** + * Get the accessibility string corresponding to the respective color item. This function should + * only be used for retrieving items from the tab group color picker. + * + * @param colorId The color id corresponding to the color item in the color picker. + */ + public static @StringRes int getTabGroupColorPickerItemColorAccessibilityString( + @TabGroupColorId int colorId) { + switch (colorId) { + case TabGroupColorId.GREY: + return R.string.tab_group_color_grey; + case TabGroupColorId.BLUE: + return R.string.tab_group_color_blue; + case TabGroupColorId.RED: + return R.string.tab_group_color_red; + case TabGroupColorId.YELLOW: + return R.string.tab_group_color_yellow; + case TabGroupColorId.GREEN: + return R.string.tab_group_color_green; + case TabGroupColorId.PINK: + return R.string.tab_group_color_pink; + case TabGroupColorId.PURPLE: + return R.string.tab_group_color_purple; + case TabGroupColorId.CYAN: + return R.string.tab_group_color_cyan; + case TabGroupColorId.ORANGE: + return R.string.tab_group_color_orange; + default: + assert false : "Invalid tab group color id " + colorId; + return Resources.ID_NULL; + } + } + private static @ColorInt int resolveGroupRelatedColor( Context context, @ColorRes int colorRes, boolean isIncognito) { @ColorInt int color = ContextCompat.getColor(context, colorRes);
diff --git a/components/tab_groups_strings.grdp b/components/tab_groups_strings.grdp index dd0e5e65..6609fca 100644 --- a/components/tab_groups_strings.grdp +++ b/components/tab_groups_strings.grdp
@@ -2,31 +2,31 @@ <grit-part> <!-- Tab Group Header Colors --> - <message name="IDS_TAB_GROUP_COLOR_GREY" desc="The accessibility label for a button in a color picker that is used to choose the color grey."> + <message name="IDS_TAB_GROUP_COLOR_GREY" desc="The accessibility label for a button in a color picker that is used to choose the color grey." formatter_data="android_java"> Grey </message> - <message name="IDS_TAB_GROUP_COLOR_BLUE" desc="The accessibility label for a button in a color picker that is used to choose the color blue."> + <message name="IDS_TAB_GROUP_COLOR_BLUE" desc="The accessibility label for a button in a color picker that is used to choose the color blue." formatter_data="android_java"> Blue </message> - <message name="IDS_TAB_GROUP_COLOR_RED" desc="The accessibility label for a button in a color picker that is used to choose the color red."> + <message name="IDS_TAB_GROUP_COLOR_RED" desc="The accessibility label for a button in a color picker that is used to choose the color red." formatter_data="android_java"> Red </message> - <message name="IDS_TAB_GROUP_COLOR_YELLOW" desc="The accessibility label for a button in a color picker that is used to choose the color yellow."> + <message name="IDS_TAB_GROUP_COLOR_YELLOW" desc="The accessibility label for a button in a color picker that is used to choose the color yellow." formatter_data="android_java"> Yellow </message> - <message name="IDS_TAB_GROUP_COLOR_GREEN" desc="The accessibility label for a button in a color picker that is used to choose the color green."> + <message name="IDS_TAB_GROUP_COLOR_GREEN" desc="The accessibility label for a button in a color picker that is used to choose the color green." formatter_data="android_java"> Green </message> - <message name="IDS_TAB_GROUP_COLOR_PINK" desc="The accessibility label for a button in a color picker that is used to choose the color pink."> + <message name="IDS_TAB_GROUP_COLOR_PINK" desc="The accessibility label for a button in a color picker that is used to choose the color pink." formatter_data="android_java"> Pink </message> - <message name="IDS_TAB_GROUP_COLOR_PURPLE" desc="The accessibility label for a button in a color picker that is used to choose the color purple."> + <message name="IDS_TAB_GROUP_COLOR_PURPLE" desc="The accessibility label for a button in a color picker that is used to choose the color purple." formatter_data="android_java"> Purple </message> - <message name="IDS_TAB_GROUP_COLOR_CYAN" desc="The accessibility label for a button in a color picker that is used to choose the color cyan."> + <message name="IDS_TAB_GROUP_COLOR_CYAN" desc="The accessibility label for a button in a color picker that is used to choose the color cyan." formatter_data="android_java"> Cyan </message> - <message name="IDS_TAB_GROUP_COLOR_ORANGE" desc="The accessibility label for a button in a color picker that is used to choose the color orange."> + <message name="IDS_TAB_GROUP_COLOR_ORANGE" desc="The accessibility label for a button in a color picker that is used to choose the color orange." formatter_data="android_java"> Orange </message>
diff --git a/components/trusted_vault/securebox_unittest.cc b/components/trusted_vault/securebox_unittest.cc index a9ea828e..dfd08987 100644 --- a/components/trusted_vault/securebox_unittest.cc +++ b/components/trusted_vault/securebox_unittest.cc
@@ -12,7 +12,8 @@ #include <string_view> #include <vector> -#include "base/compiler_specific.h" +#include "base/containers/span.h" +#include "base/containers/to_vector.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "testing/gmock/include/gmock/gmock.h" @@ -29,8 +30,7 @@ using testing::SizeIs; std::vector<uint8_t> StringToBytes(std::string_view str) { - const uint8_t* raw_data = reinterpret_cast<const uint8_t*>(str.data()); - return std::vector<uint8_t>(raw_data, UNSAFE_TODO(raw_data + str.length())); + return base::ToVector(base::as_byte_span(str)); } class SecureBoxTest : public testing::Test {
diff --git a/components/user_data_importer/content/BUILD.gn b/components/user_data_importer/content/BUILD.gn index 3ee0019..adbb729 100644 --- a/components/user_data_importer/content/BUILD.gn +++ b/components/user_data_importer/content/BUILD.gn
@@ -23,7 +23,8 @@ "//components/strings:components_strings_grit", "//components/user_data_importer/common", "//components/user_data_importer/mojom", - "//components/user_data_importer/utility:safari_data_importer", + "//components/user_data_importer/utility", + "//components/user_data_importer/utility:bookmarks", "//components/user_data_importer/utility:zip_ffi_glue", "//content/public/browser", "//content/public/child",
diff --git a/components/user_data_importer/ios/BUILD.gn b/components/user_data_importer/ios/BUILD.gn index 40f9ec98e..578a274 100644 --- a/components/user_data_importer/ios/BUILD.gn +++ b/components/user_data_importer/ios/BUILD.gn
@@ -14,7 +14,7 @@ public_deps = [ ":bookmark_parser" ] deps = [ "//base", - "//components/user_data_importer/utility:safari_data_importer", + "//components/user_data_importer/utility:bookmarks", "//ios/web/public/js_messaging:web_view_js_utils", "//url", ]
diff --git a/components/user_data_importer/utility/BUILD.gn b/components/user_data_importer/utility/BUILD.gn index d37f485..ca9eab0 100644 --- a/components/user_data_importer/utility/BUILD.gn +++ b/components/user_data_importer/utility/BUILD.gn
@@ -5,23 +5,48 @@ import("//build/config/zip.gni") import("//build/rust/rust_static_library.gni") -source_set("safari_data_importer") { +source_set("utility") { + sources = [ + "history_callback_from_rust.h", + "importer_metrics_recorder.cc", + "importer_metrics_recorder.h", + ] + deps = [ + ":bookmarks", + "//base", + "//components/user_data_importer/common", + ] +} + +source_set("bookmarks") { sources = [ "bookmark_parser.cc", "bookmark_parser.h", "bookmark_util.cc", "bookmark_util.h", - "history_callback_from_rust.h", + ] + deps = [ + "//base", + "//components/bookmarks/browser", + "//components/favicon_base", + "//components/reading_list/core", + "//components/user_data_importer/common", + ] +} + +source_set("safari_data_importer") { + sources = [ "safari_data_import_client.h", "safari_data_importer.cc", "safari_data_importer.h", ] deps = [ + ":bookmarks", + ":utility", ":zip_ffi_glue", "//base", "//components/bookmarks/browser", - "//components/favicon_base", "//components/history/core/browser", "//components/password_manager/core/browser/features:utils", "//components/password_manager/core/browser/import:importer", @@ -94,7 +119,9 @@ testonly = true sources = [ "safari_data_importer_unittest.cc" ] deps = [ + ":bookmarks", ":safari_data_importer", + ":utility", "//base", "//base/test:test_support", "//components/affiliations/core/browser:test_support",
diff --git a/components/user_data_importer/utility/importer_metrics_recorder.cc b/components/user_data_importer/utility/importer_metrics_recorder.cc new file mode 100644 index 0000000..783a256 --- /dev/null +++ b/components/user_data_importer/utility/importer_metrics_recorder.cc
@@ -0,0 +1,176 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/user_data_importer/utility/importer_metrics_recorder.h" + +#include <cstdint> +#include <optional> +#include <string> +#include <vector> + +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" +#include "base/strings/string_util.h" +#include "base/time/time.h" + +namespace user_data_importer { + +BookmarksImportError ConvertBookmarkError( + BookmarkParser::BookmarkParsingError error) { + switch (error) { + case BookmarkParser::BookmarkParsingError::kTooBig: + return BookmarksImportError::kTooBig; + case BookmarkParser::BookmarkParsingError::kParsingFailed: + return BookmarksImportError::kParsingFailed; + case BookmarkParser::BookmarkParsingError::kTimedOut: + return BookmarksImportError::kTimeout; + case BookmarkParser::BookmarkParsingError::kOther: + return BookmarksImportError::kOther; + default: + NOTREACHED(base::NotFatalUntil::M145) + << "Unknown error: " << static_cast<int>(error); + return BookmarksImportError::kOther; + } +} + +namespace { + +// These values must match those declared in the corresponding histograms.xml +// file, as they are used to construct histogram names. +std::string GetSourceName(ImporterMetricsRecorder::Source source) { + switch (source) { + case ImporterMetricsRecorder::Source::kOsMigration: + return "OSMigration"; + case ImporterMetricsRecorder::Source::kSafari: + return "Safari"; + } +} + +// These values must match those declared in the corresponding histograms.xml +// file, as they are used to construct histogram names. +std::string GetDataTypeName(DataTypeMetrics::DataType data_type) { + switch (data_type) { + case DataTypeMetrics::DataType::kBookmarks: + return "Bookmarks"; + case DataTypeMetrics::DataType::kHistory: + return "History"; + case DataTypeMetrics::DataType::kPasswords: + return "Passwords"; + case DataTypeMetrics::DataType::kPaymentCards: + return "PaymentCards"; + case DataTypeMetrics::DataType::kReadingList: + return "ReadingList"; + } +} + +} // namespace + +DataTypeMetrics::DataTypeMetrics(const std::string& source_name, + const DataTypeMetrics::DataType data_type) + : source_name_(source_name), data_type_name_(GetDataTypeName(data_type)) {} + +DataTypeMetrics::~DataTypeMetrics() = default; + +void DataTypeMetrics::LogOutcome(ImportOutcome outcome) { + base::UmaHistogramEnumeration(GetMetricName("Outcome"), outcome); +} + +void DataTypeMetrics::LogFileSizeBytes(int64_t size_bytes) { + if (size_bytes < 0) { + return; + } + + int file_size_kb = static_cast<int>(size_bytes / 1024); + base::UmaHistogramMemoryKB(GetMetricName("FileSize"), file_size_kb); +} + +void DataTypeMetrics::OnPreparationStarted() { + parse_start_time_ = base::TimeTicks::Now(); +} + +void DataTypeMetrics::OnPreparationFinished(size_t prepared_count) { + prepared_count_ = prepared_count; + + if (parse_start_time_) { + base::TimeDelta duration = base::TimeTicks::Now() - *parse_start_time_; + base::UmaHistogramCustomTimes(GetMetricName("PrepareDuration"), duration, + base::Milliseconds(1), base::Minutes(10), + /*buckets=*/50); + parse_start_time_.reset(); + } + base::UmaHistogramCounts10000(GetMetricName("PreparedCount"), + prepared_count_); +} + +void DataTypeMetrics::OnImportStarted() { + import_start_time_ = base::TimeTicks::Now(); +} + +void DataTypeMetrics::OnImportFinished(size_t completed_count) { + if (import_start_time_) { + base::TimeDelta duration = base::TimeTicks::Now() - *import_start_time_; + base::UmaHistogramCustomTimes(GetMetricName("ImportDuration"), duration, + base::Milliseconds(1), base::Minutes(10), + /*buckets=*/50); + import_start_time_.reset(); + } + + base::UmaHistogramCounts10000(GetMetricName("ImportedCount"), + completed_count); + + if (prepared_count_ > 0) { + int success_percentage = static_cast<int>( + (static_cast<double>(completed_count) / prepared_count_) * 100.0); + base::UmaHistogramPercentage(GetMetricName("SuccessRate"), + success_percentage); + } +} + +std::string DataTypeMetrics::GetMetricName(std::string_view suffix) { + return base::JoinString( + {"UserDataImporter", source_name_, data_type_name_, suffix}, + /*separator=*/"."); +} + +ImporterMetricsRecorder::ImporterMetricsRecorder( + ImporterMetricsRecorder::Source source) + : source_name_(GetSourceName(source)), + bookmark_metrics_(source_name_, DataTypeMetrics::DataType::kBookmarks), + history_metrics_(source_name_, DataTypeMetrics::DataType::kHistory), + password_metrics_(source_name_, DataTypeMetrics::DataType::kPasswords), + payment_card_metrics_(source_name_, + DataTypeMetrics::DataType::kPaymentCards), + reading_list_metrics_(source_name_, + DataTypeMetrics::DataType::kReadingList) {} + +ImporterMetricsRecorder::~ImporterMetricsRecorder() = default; + +void ImporterMetricsRecorder::OnFlowStarted() { + flow_start_time_ = base::TimeTicks::Now(); +} + +void ImporterMetricsRecorder::OnFlowFinished() { + base::TimeTicks flow_end_time = base::TimeTicks::Now(); + + // Log the total flow duration. + base::TimeDelta duration = flow_end_time - flow_start_time_; + base::UmaHistogramCustomTimes(GetMetricName("FlowDuration"), duration, + base::Milliseconds(1), base::Minutes(10), + /*buckets=*/50); +} + +void ImporterMetricsRecorder::LogBookmarksError(BookmarksImportError error) { + base::UmaHistogramEnumeration(GetMetricName("Bookmarks.Error"), error); +} + +void ImporterMetricsRecorder::LogPasswordsError(PasswordsImportError error) { + base::UmaHistogramEnumeration(GetMetricName("Passwords.Error"), error); +} + +std::string ImporterMetricsRecorder::GetMetricName(std::string_view suffix) { + return base::JoinString({"UserDataImporter", source_name_, suffix}, + /*separator=*/"."); +} + +} // namespace user_data_importer
diff --git a/components/user_data_importer/utility/importer_metrics_recorder.h b/components/user_data_importer/utility/importer_metrics_recorder.h new file mode 100644 index 0000000..764e76d --- /dev/null +++ b/components/user_data_importer/utility/importer_metrics_recorder.h
@@ -0,0 +1,156 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_USER_DATA_IMPORTER_UTILITY_IMPORTER_METRICS_RECORDER_H_ +#define COMPONENTS_USER_DATA_IMPORTER_UTILITY_IMPORTER_METRICS_RECORDER_H_ + +#include <cstdint> +#include <optional> +#include <string> + +#include "base/time/time.h" +#include "components/user_data_importer/utility/bookmark_parser.h" + +/** + * This file contains a class for logging metrics which are broadly applicable + * to importing user data. Some data types (i.e., instances of DataTypeMetrics) + * may not apply to all importers, and importers may include additional logging + * beyond these common metrics in their implementations. + */ + +namespace user_data_importer { + +// Specific error states for Bookmarks import. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// LINT.IfChange(BookmarksImportError) +enum class BookmarksImportError { + kFailedToRead = 0, + kTooBig = 1, + kParsingFailed = 2, + kTimeout = 3, + kOther = 4, + kMaxValue = kOther, +}; +// LINT.ThenChange(//tools/metrics/histograms/metadata/user_data_importer/enums.xml:UserDataImportBookmarksError) + +// Helper function to convert from the parser's error enum to the metrics enum. +BookmarksImportError ConvertBookmarkError( + BookmarkParser::BookmarkParsingError error); + +// Specific error states for Passwords import. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// LINT.IfChange(PasswordsImportError) +enum class PasswordsImportError { + kFailedToRead = 0, + kTooBig = 1, + kParsingFailed = 2, + kTimeout = 3, + kOther = 4, + kMaxValue = kOther, +}; +// LINT.ThenChange(//tools/metrics/histograms/metadata/user_data_importer/enums.xml:UserDataImportPasswordsError) + +// Represents metrics for a single data type. Encapsulates the data common +// to all supported data types. +class DataTypeMetrics { + public: + // Indicates the type of data being imported. Corresponds to the + // ImportDataType variants in histograms.xml, with the exception of + // NotSupported, which is not supported. + // LINT.IfChange(ImportDataType) + enum class DataType { + kBookmarks = 0, + kHistory = 1, + kPasswords = 2, + kPaymentCards = 3, + kReadingList = 4 + }; + // LINT.ThenChange(//tools/metrics/histograms/metadata/user_data_importer/histograms.xml:ImportDataType) + + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + // LINT.IfChange(ImportOutcome) + enum class ImportOutcome { + kNotPresent = 0, // No file for this data type was provided. + kFailure = 1, // A file was processed but no data could be imported. + kSuccess = 2, // At least one data entry was successfully imported. + kMaxValue = kSuccess, + }; + // LINT.ThenChange(//tools/metrics/histograms/metadata/user_data_importer/enums.xml:UserDataImportOutcome) + + DataTypeMetrics(const std::string& source_name, const DataType data_type); + ~DataTypeMetrics(); + + // Methods to log metrics. + void LogOutcome(ImportOutcome outcome); + void LogFileSizeBytes(int64_t size_bytes); + + // Timestamp recording methods + void OnPreparationStarted(); + void OnPreparationFinished(size_t prepared_count); + void OnImportStarted(); + void OnImportFinished(size_t completed_count); + + private: + std::string GetMetricName(std::string_view suffix); + + const std::string source_name_; + const std::string data_type_name_; + + std::optional<base::TimeTicks> parse_start_time_; + std::optional<base::TimeTicks> import_start_time_; + + size_t prepared_count_ = 0; +}; + +// Logs metrics accumulated in the process of importing user data. +class ImporterMetricsRecorder { + public: + // Indicates the source of the data being imported. + // LINT.IfChange(ImportSource) + enum class Source { + kOsMigration = 0, + kSafari = 1, + }; + // LINT.ThenChange(//tools/metrics/histograms/metadata/user_data_importer/histograms.xml:ImportSource) + + explicit ImporterMetricsRecorder(const Source source); + ~ImporterMetricsRecorder(); + + // Call to record the start of the import process. + void OnFlowStarted(); + + // Call to record the end of the import process. + void OnFlowFinished(); + + // Accessors for logging metrics common to each data type. + DataTypeMetrics& bookmark_metrics() { return bookmark_metrics_; } + DataTypeMetrics& history_metrics() { return history_metrics_; } + DataTypeMetrics& password_metrics() { return password_metrics_; } + DataTypeMetrics& payment_card_metrics() { return payment_card_metrics_; } + DataTypeMetrics& reading_list_metrics() { return reading_list_metrics_; } + + // Log specific failure cases, as documented in the respective enums above. + void LogBookmarksError(BookmarksImportError error); + void LogPasswordsError(PasswordsImportError error); + + private: + std::string GetMetricName(std::string_view suffix); + + const std::string source_name_; + + base::TimeTicks flow_start_time_; + + DataTypeMetrics bookmark_metrics_; + DataTypeMetrics history_metrics_; + DataTypeMetrics password_metrics_; + DataTypeMetrics payment_card_metrics_; + DataTypeMetrics reading_list_metrics_; +}; + +} // namespace user_data_importer + +#endif // COMPONENTS_USER_DATA_IMPORTER_UTILITY_IMPORTER_METRICS_RECORDER_H_
diff --git a/components/user_data_importer/utility/safari_data_importer.cc b/components/user_data_importer/utility/safari_data_importer.cc index 4d7a957..89f6b0c 100644 --- a/components/user_data_importer/utility/safari_data_importer.cc +++ b/components/user_data_importer/utility/safari_data_importer.cc
@@ -8,6 +8,7 @@ #include "base/containers/span_rust.h" #include "base/files/file_util.h" #include "base/memory/raw_ptr.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/task/bind_post_task.h" @@ -25,11 +26,36 @@ #include "components/strings/grit/components_strings.h" #include "components/user_data_importer/utility/bookmark_util.h" #include "components/user_data_importer/utility/history_callback_from_rust.h" +#include "components/user_data_importer/utility/importer_metrics_recorder.h" #include "components/user_data_importer/utility/parsing_ffi/lib.rs.h" #include "ui/base/l10n/l10n_util.h" namespace { +// Error states reported when an entire import flow failed. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// LINT.IfChange(TotalFailureError) +enum class TotalFailureError { + kNoFileProvided = 0, + kFileTooBig = 1, + kUnzipFailed = 2, + kOther = 3, + kMaxValue = kOther, +}; +// LINT.ThenChange(//tools/metrics/histograms/metadata/user_data_importer/enums.xml:UserDataImportTotalFailureError) + +void LogTotalFailureError(TotalFailureError error) { + base::UmaHistogramEnumeration("UserDataImporter.Safari.TotalFailureError", + error); +} + +void LogInputFileSize(size_t size_bytes) { + int file_size_kb = static_cast<int>(size_bytes / 1024); + base::UmaHistogramMemoryKB("UserDataImporter.Safari.TotalFileSize", + file_size_kb); +} + std::string_view RustStringToStringView(const rust::String& rust_string) { return std::string_view(rust_string.data(), rust_string.length()); } @@ -149,6 +175,28 @@ return url_row; } +// Returns an error enum appropriate for logging if the password importer +// status indicates an error, or std::nullopt if it is OK to proceed. +std::optional<user_data_importer::PasswordsImportError> +TranslatePasswordStatusToError(password_manager::ImportResults::Status status) { + switch (status) { + case password_manager::ImportResults::CONFLICTS: + case password_manager::ImportResults::SUCCESS: + return std::nullopt; + case password_manager::ImportResults::IO_ERROR: + case password_manager::ImportResults::BAD_FORMAT: + return user_data_importer::PasswordsImportError::kFailedToRead; + case password_manager::ImportResults::MAX_FILE_SIZE: + case password_manager::ImportResults::NUM_PASSWORDS_EXCEEDED: + return user_data_importer::PasswordsImportError::kTooBig; + case password_manager::ImportResults::NONE: + case password_manager::ImportResults::UNKNOWN_ERROR: + case password_manager::ImportResults::DISMISSED: + case password_manager::ImportResults::IMPORT_ALREADY_ACTIVE: + default: + return user_data_importer::PasswordsImportError::kOther; + } +} } // namespace namespace user_data_importer { @@ -209,18 +257,24 @@ bookmark_model_(CHECK_DEREF(bookmark_model)), reading_list_model_(CHECK_DEREF(reading_list_model)), sync_service_(sync_service), + metrics_recorder_(ImporterMetricsRecorder::Source::kSafari), app_locale_(std::move(app_locale)) {} SafariDataImporter::~SafariDataImporter() = default; void SafariDataImporter::PrepareImport(const base::FilePath& path) { + metrics_recorder_.OnFlowStarted(); + std::string zip_filename = path.MaybeAsASCII(); if (zip_filename.empty()) { - // TODO(crbug.com/407587751): Log error. + LogTotalFailureError(TotalFailureError::kNoFileProvided); client_->OnTotalFailure(); return; } + // TODO(crbug.com/407587751): Log the total filesize. + LogInputFileSize(0); + blocking_worker_.AsyncCall(&BlockingWorker::CreateZipFileArchive) .WithArgs(std::move(zip_filename)) .Then(base::BindOnce(&SafariDataImporter::OnZipArchiveReady, @@ -242,6 +296,7 @@ GetRunner(), base::BindOnce(&SafariDataImporter::OnHistoryImportCompleted, weak_factory_.GetWeakPtr())); + metrics_recorder_.history_metrics().OnImportStarted(); blocking_worker_.AsyncCall(&BlockingWorker::ImportHistory) .WithArgs(std::make_unique<RustHistoryCallback>( std::move(parse_history_callback), @@ -251,17 +306,22 @@ if (password_importer_ && password_importer_->IsState( password_manager::PasswordImporter::kUserInteractionRequired)) { + metrics_recorder_.password_metrics().OnImportStarted(); + // TODO(crbug.com/407587751): Move this to a task. password_importer_->ContinueImport( selected_password_ids, - base::BindOnce(&SafariDataImportClient::OnPasswordsImported, - client_->AsWeakPtr())); + base::BindOnce(&SafariDataImporter::OnPasswordImportCompleted, + weak_factory_.GetWeakPtr())); } + metrics_recorder_.bookmark_metrics().OnImportStarted(); + metrics_recorder_.reading_list_metrics().OnImportStarted(); GetRunner()->PostTask( FROM_HERE, base::BindOnce(&SafariDataImporter::ContinueImportBookmarks, weak_factory_.GetWeakPtr())); + metrics_recorder_.payment_card_metrics().OnImportStarted(); GetRunner()->PostTask( FROM_HERE, base::BindOnce(&SafariDataImporter::ContinueImportPaymentCards, weak_factory_.GetWeakPtr())); @@ -316,27 +376,39 @@ : 0u; } -std::optional<base::FilePath> +SafariDataImporter::BlockingWorker::BookmarkUnzipResult::BookmarkUnzipResult( + std::optional<base::FilePath> p, + size_t size) + : path(std::move(p)), file_size_bytes(size) {} +SafariDataImporter::BlockingWorker::BookmarkUnzipResult:: + ~BookmarkUnzipResult() = default; +SafariDataImporter::BlockingWorker::BookmarkUnzipResult::BookmarkUnzipResult( + BookmarkUnzipResult&&) = default; +SafariDataImporter::BlockingWorker::BookmarkUnzipResult& +SafariDataImporter::BlockingWorker::BookmarkUnzipResult::operator=( + SafariDataImporter::BlockingWorker::BookmarkUnzipResult&&) = default; + +SafariDataImporter::BlockingWorker::BookmarkUnzipResult SafariDataImporter::BlockingWorker::WriteBookmarksToTmpFile() { std::string html_data = Unzip(FileType::Bookmarks); if (html_data.empty()) { - return std::nullopt; + return BookmarkUnzipResult(std::nullopt, 0); } bookmarks_temp_dir_ = std::make_unique<base::ScopedTempDir>(); if (!bookmarks_temp_dir_->CreateUniqueTempDir()) { - return std::nullopt; + return BookmarkUnzipResult(std::nullopt, 0); } base::FilePath path = bookmarks_temp_dir_->GetPath().AppendASCII("bookmarks.html"); if (!base::WriteFile(path, html_data)) { - return std::nullopt; + return BookmarkUnzipResult(std::nullopt, 0); } - return path; + return BookmarkUnzipResult(path, html_data.length()); } void SafariDataImporter::BlockingWorker::ParseBookmarks( @@ -346,14 +418,28 @@ bookmark_parser_->Parse(*bookmarks_html, std::move(bookmarks_callback)); } -std::vector<PaymentCardEntry> +SafariDataImporter::BlockingWorker::PaymentCardParseResult:: + PaymentCardParseResult(std::vector<PaymentCardEntry> e, size_t size) + : entries(std::move(e)), file_size_bytes(size) {} +SafariDataImporter::BlockingWorker::PaymentCardParseResult:: + ~PaymentCardParseResult() = default; +SafariDataImporter::BlockingWorker::PaymentCardParseResult:: + PaymentCardParseResult( + SafariDataImporter::BlockingWorker::PaymentCardParseResult&&) = default; +SafariDataImporter::BlockingWorker::PaymentCardParseResult& +SafariDataImporter::BlockingWorker::PaymentCardParseResult::operator=( + SafariDataImporter::BlockingWorker::PaymentCardParseResult&&) = default; + +SafariDataImporter::BlockingWorker::PaymentCardParseResult SafariDataImporter::BlockingWorker::ParsePaymentCards() { std::vector<PaymentCardEntry> payment_cards; if (!zip_file_archive_ || !(*zip_file_archive_)->parse_payment_cards(payment_cards)) { - return {}; + return PaymentCardParseResult({}, 0); } - return payment_cards; + return PaymentCardParseResult( + std::move(payment_cards), + GetUncompressedFileSizeInBytes(FileType::PaymentCards)); } void SafariDataImporter::BlockingWorker::ImportHistory( @@ -372,25 +458,30 @@ void SafariDataImporter::OnZipArchiveReady(bool success) { if (!success) { - // Nothing to import, early exit. + LogTotalFailureError(TotalFailureError::kUnzipFailed); client_->OnTotalFailure(); return; } // Passwords import may require conflict resolution, so it is done first. + metrics_recorder_.password_metrics().OnPreparationStarted(); blocking_worker_.AsyncCall(&BlockingWorker::Unzip) .WithArgs(FileType::Passwords) .Then(base::BindOnce(&SafariDataImporter::PreparePasswords, weak_factory_.GetWeakPtr())); + metrics_recorder_.payment_card_metrics().OnPreparationStarted(); blocking_worker_.AsyncCall(&BlockingWorker::ParsePaymentCards) .Then(base::BindOnce(&SafariDataImporter::PreparePaymentCards, weak_factory_.GetWeakPtr())); + metrics_recorder_.bookmark_metrics().OnPreparationStarted(); + metrics_recorder_.reading_list_metrics().OnPreparationStarted(); blocking_worker_.AsyncCall(&BlockingWorker::WriteBookmarksToTmpFile) .Then(base::BindOnce(&SafariDataImporter::PrepareBookmarks, weak_factory_.GetWeakPtr())); + metrics_recorder_.history_metrics().OnPreparationStarted(); blocking_worker_.AsyncCall(&BlockingWorker::GetUncompressedFileSizeInBytes) .WithArgs(FileType::SafariHistory) .Then(base::BindOnce(&SafariDataImporter::PrepareHistory, @@ -398,6 +489,17 @@ } void SafariDataImporter::PreparePasswords(std::string csv_data) { + if (csv_data.empty()) { + metrics_recorder_.password_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kNotPresent); + + // Empty results object, indicating no work could be done. + password_manager::ImportResults results; + client_->OnPasswordsReady(results); + } + + metrics_recorder_.password_metrics().LogFileSizeBytes(csv_data.length()); + password_manager::PasswordForm::Store to_store = { password_manager::features_util::IsAccountStorageEnabled(sync_service_) ? password_manager::PasswordForm::Store::kAccountStore @@ -405,31 +507,42 @@ password_importer_->Import( std::move(csv_data), to_store, - base::BindOnce(&SafariDataImportClient::OnPasswordsReady, - client_->AsWeakPtr())); + base::BindOnce(&SafariDataImporter::OnPasswordsParsed, + weak_factory_.GetWeakPtr())); } void SafariDataImporter::PreparePaymentCards( - std::vector<PaymentCardEntry> payment_cards) { - if (payment_cards.empty()) { + SafariDataImporter::BlockingWorker::PaymentCardParseResult result) { + if (result.entries.empty()) { + metrics_recorder_.payment_card_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kNotPresent); client_->OnPaymentCardsReady(/* count= */ 0); return; } + metrics_recorder_.payment_card_metrics().LogFileSizeBytes( + result.file_size_bytes); + cards_to_import_.clear(); - cards_to_import_.reserve(payment_cards.size()); - std::ranges::transform(payment_cards, std::back_inserter(cards_to_import_), + cards_to_import_.reserve(result.entries.size()); + std::ranges::transform(result.entries, std::back_inserter(cards_to_import_), [this](const auto& card) { return ConvertToAutofillCreditCard(card, app_locale_); }); - client_->OnPaymentCardsReady(cards_to_import_.size()); + size_t count = cards_to_import_.size(); + metrics_recorder_.payment_card_metrics().OnPreparationFinished(count); + client_->OnPaymentCardsReady(count); } void SafariDataImporter::PrepareBookmarks( - std::optional<base::FilePath> bookmarks_html) { - if (!bookmarks_html || bookmarks_html->empty()) { + SafariDataImporter::BlockingWorker::BookmarkUnzipResult result) { + if (!result.path || result.path->empty()) { + metrics_recorder_.bookmark_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kNotPresent); + metrics_recorder_.reading_list_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kNotPresent); client_->OnBookmarksReady(/* count= */ 0); return; } @@ -437,18 +550,32 @@ auto import_bookmarks_callback = base::BindPostTask( GetRunner(), base::BindOnce(&SafariDataImporter::OnBookmarksParsed, weak_factory_.GetWeakPtr())); + metrics_recorder_.bookmark_metrics().LogFileSizeBytes(result.file_size_bytes); + metrics_recorder_.reading_list_metrics().LogFileSizeBytes( + result.file_size_bytes); blocking_worker_.AsyncCall(&BlockingWorker::ParseBookmarks) - .WithArgs(bookmarks_html, std::move(import_bookmarks_callback)); + .WithArgs(result.path, std::move(import_bookmarks_callback)); +} + +void SafariDataImporter::OnPasswordsParsed( + const password_manager::ImportResults& results) { + auto error = TranslatePasswordStatusToError(results.status); + if (error) { + metrics_recorder_.LogPasswordsError(*error); + return; + } + + size_t count = results.displayed_entries.size() + results.number_to_import; + metrics_recorder_.password_metrics().OnPreparationFinished(count); + + client_->OnPasswordsReady(results); } void SafariDataImporter::OnBookmarksParsed( BookmarkParser::BookmarkParsingResult result) { ASSIGN_OR_RETURN(BookmarkParser::ParsedBookmarks value, std::move(result), - [this](auto) { - // TODO(crbug.com/407587751): Log error to UMA. - client_->OnBookmarksReady(/* count= */ 0); - }); + &SafariDataImporter::OnBookmarkParsingError, this); pending_bookmarks_ = std::move(value.bookmarks); pending_reading_list_ = std::move(value.reading_list); @@ -460,10 +587,26 @@ } } + metrics_recorder_.bookmark_metrics().OnPreparationFinished( + importable_bookmarks_count); + metrics_recorder_.reading_list_metrics().OnPreparationFinished( + pending_reading_list_.size()); + client_->OnBookmarksReady(importable_bookmarks_count + pending_reading_list_.size()); } +void SafariDataImporter::OnBookmarkParsingError( + BookmarkParser::BookmarkParsingError error) { + metrics_recorder_.LogBookmarksError(ConvertBookmarkError(error)); + metrics_recorder_.bookmark_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kFailure); + metrics_recorder_.reading_list_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kFailure); + + client_->OnBookmarksReady(/* count= */ 0); +} + void SafariDataImporter::PrepareHistory(size_t file_size_bytes) { // This is an approximation of the number of bytes per URL entry in the // history file. @@ -471,6 +614,15 @@ size_t approximate_number_of_urls = (file_size_bytes > 0) ? (file_size_bytes / kBytesPerURL) + 1 : 0; + if (file_size_bytes == 0) { + metrics_recorder_.history_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kNotPresent); + } else { + metrics_recorder_.history_metrics().LogFileSizeBytes(file_size_bytes); + metrics_recorder_.history_metrics().OnPreparationFinished( + approximate_number_of_urls); + } + // TODO(crbug.com/407587751): Pass list of profiles. client_->OnHistoryReady(approximate_number_of_urls, {}); } @@ -494,12 +646,26 @@ } } -// Invoked once parsing of history is completed. Forwards the results to -// `client_`. void SafariDataImporter::OnHistoryImportCompleted() { + metrics_recorder_.history_metrics().OnImportFinished(history_urls_imported_); + metrics_recorder_.history_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kSuccess); client_->OnHistoryImported(history_urls_imported_); } +void SafariDataImporter::OnPasswordImportCompleted( + const password_manager::ImportResults& results) { + metrics_recorder_.password_metrics().OnImportFinished( + results.number_imported); + // At this phase of import, any status other than SUCCESS is a failure, as we + // expect the flow to have concluded. + metrics_recorder_.password_metrics().LogOutcome( + results.status == password_manager::ImportResults::SUCCESS + ? DataTypeMetrics::ImportOutcome::kSuccess + : DataTypeMetrics::ImportOutcome::kFailure); + client_->OnPasswordsImported(results); +} + void SafariDataImporter::ContinueImportPaymentCards() { if (cards_to_import_.empty()) { client_->OnPaymentCardsImported(/* count= */ 0); @@ -528,6 +694,10 @@ ++imported_credit_cards; } + metrics_recorder_.payment_card_metrics().OnImportFinished( + imported_credit_cards); + metrics_recorder_.payment_card_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kSuccess); client_->OnPaymentCardsImported(imported_credit_cards); } @@ -538,6 +708,15 @@ size_t imported_reading_list_count = user_data_importer::ImportReadingList( &*reading_list_model_, std::move(pending_reading_list_)); + metrics_recorder_.bookmark_metrics().OnImportFinished( + imported_bookmarks_count); + metrics_recorder_.reading_list_metrics().OnImportFinished( + imported_reading_list_count); + metrics_recorder_.bookmark_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kSuccess); + metrics_recorder_.reading_list_metrics().LogOutcome( + DataTypeMetrics::ImportOutcome::kSuccess); + client_->OnBookmarksImported(imported_bookmarks_count + imported_reading_list_count); }
diff --git a/components/user_data_importer/utility/safari_data_importer.h b/components/user_data_importer/utility/safari_data_importer.h index 31b3cc0..9608c22 100644 --- a/components/user_data_importer/utility/safari_data_importer.h +++ b/components/user_data_importer/utility/safari_data_importer.h
@@ -9,6 +9,7 @@ #include "base/threading/sequence_bound.h" #include "components/password_manager/core/browser/import/password_importer.h" #include "components/user_data_importer/utility/bookmark_parser.h" +#include "components/user_data_importer/utility/importer_metrics_recorder.h" #include "components/user_data_importer/utility/parsing_ffi/lib.rs.h" #include "components/user_data_importer/utility/safari_data_import_client.h" @@ -108,10 +109,38 @@ // Returns the uncompressed size of a file within the zip file archive. size_t GetUncompressedFileSizeInBytes(FileType filetype); + struct BookmarkUnzipResult { + std::optional<base::FilePath> path; + size_t file_size_bytes; + + explicit BookmarkUnzipResult(std::optional<base::FilePath> p, + size_t size); + ~BookmarkUnzipResult(); + + BookmarkUnzipResult(BookmarkUnzipResult&&); + BookmarkUnzipResult& operator=(BookmarkUnzipResult&&); + BookmarkUnzipResult(const BookmarkUnzipResult&) = delete; + BookmarkUnzipResult& operator=(const BookmarkUnzipResult&) = delete; + }; + // Unzips bookmarks in the ZIP archive and writes the contents to a // `bookmarks.html` file in a tmp directory. Returns nullopt if the file // could not be created. - std::optional<base::FilePath> WriteBookmarksToTmpFile(); + BookmarkUnzipResult WriteBookmarksToTmpFile(); + + struct PaymentCardParseResult { + std::vector<PaymentCardEntry> entries; + size_t file_size_bytes; + + explicit PaymentCardParseResult(std::vector<PaymentCardEntry> e, + size_t size); + ~PaymentCardParseResult(); + + PaymentCardParseResult(PaymentCardParseResult&&); + PaymentCardParseResult& operator=(PaymentCardParseResult&&); + PaymentCardParseResult(const PaymentCardParseResult&) = delete; + PaymentCardParseResult& operator=(const PaymentCardParseResult&) = delete; + }; void ParseBookmarks( std::optional<base::FilePath> bookmarks_html, @@ -119,7 +148,7 @@ // Finds a file containing payment cards in the ZIP archive, parses it, and // returns the output. Returns empty on error. - std::vector<PaymentCardEntry> ParsePaymentCards(); + PaymentCardParseResult ParsePaymentCards(); // Attempts to import history from the zip file archive. // `parse_history_callback` may be called multiple times during this @@ -149,16 +178,25 @@ // Converts payment_cards to autofill::CreditCard objects. Informs `client_` // that cards are ready when done. - void PreparePaymentCards(std::vector<PaymentCardEntry> payment_cards); + void PreparePaymentCards( + BlockingWorker::PaymentCardParseResult payment_cards); // Attempts to parse the provided HTML data. Informs `client_` that bookmarks // are ready when done. - void PrepareBookmarks(std::optional<base::FilePath> html); + void PrepareBookmarks(BlockingWorker::BookmarkUnzipResult result); + + // Receives the result of the first pass of the password importer, which + // parses passwords and identifies any conflicts, then pauses. Informs the + // client that passwords are ready. + void OnPasswordsParsed(const password_manager::ImportResults& results); // Receives the result of parsing bookmarks, stores them for later use, - // and invokes `callback` with the number of parsed bookmarks. + // and informs the client that bookmarks are ready. void OnBookmarksParsed(BookmarkParser::BookmarkParsingResult result); + // Logs an error and indicates to the client that no bookmarks are available. + void OnBookmarkParsingError(BookmarkParser::BookmarkParsingError error); + // Calls `history_callback` with an approximation of the number of URLs // contained in one or more files with total size `file_size_bytes`. void PrepareHistory(size_t file_size_bytes); @@ -171,6 +209,11 @@ // `client_`. void OnHistoryImportCompleted(); + // Invoked once parsing of passwords is completed. Forwards the results to + // `client_`. + void OnPasswordImportCompleted( + const password_manager::ImportResults& results); + // Imports Credit Cards to the Payments Data Manager. void ContinueImportPaymentCards(); @@ -224,6 +267,9 @@ // permanent storage. std::vector<ImportedBookmarkEntry> pending_reading_list_; + // Helper object which logs metrics about the import flow. + ImporterMetricsRecorder metrics_recorder_; + // The application locale, used to set credit card information. const std::string app_locale_;
diff --git a/components/user_data_importer/utility/safari_data_importer_unittest.cc b/components/user_data_importer/utility/safari_data_importer_unittest.cc index 7d7303e..e6415e1 100644 --- a/components/user_data_importer/utility/safari_data_importer_unittest.cc +++ b/components/user_data_importer/utility/safari_data_importer_unittest.cc
@@ -201,7 +201,9 @@ base::FilePath path = dir.GetPath().AppendASCII("bookmarks.html"); ASSERT_TRUE(base::WriteFile(path, html_data)); - importer_->PrepareBookmarks(std::move(path)); + importer_->PrepareBookmarks( + SafariDataImporter::BlockingWorker::BookmarkUnzipResult( + std::move(path), html_data.length())); Synchronize(); } @@ -217,7 +219,9 @@ } void PreparePaymentCards(std::vector<PaymentCardEntry> payment_cards) { - importer_->PreparePaymentCards(std::move(payment_cards)); + importer_->PreparePaymentCards( + SafariDataImporter::BlockingWorker::PaymentCardParseResult( + std::move(payment_cards), /*size=*/0)); Synchronize(); }
diff --git a/components/user_education/common/ntp_promo/ntp_promo_controller.cc b/components/user_education/common/ntp_promo/ntp_promo_controller.cc index 354cb4fa..5a9d67f 100644 --- a/components/user_education/common/ntp_promo/ntp_promo_controller.cc +++ b/components/user_education/common/ntp_promo/ntp_promo_controller.cc
@@ -85,19 +85,21 @@ NtpPromoController::~NtpPromoController() = default; -bool NtpPromoController::HasShowablePromos(Profile* profile) const { - for (const auto& id : registry_->GetNtpPromoIdentifiers()) { - if (const auto* spec = registry_->GetNtpPromoSpecification(id)) { - if (spec->eligibility_callback().Run(profile) != - NtpPromoSpecification::Eligibility::kIneligible) { - return true; - } - } - } - return false; +bool NtpPromoController::HasShowablePromos(Profile* profile) { + // Generate promo lists here, since the Eligibility callback results are + // insufficient. Promo callbacks may report Eligible or Completed, but be + // suppressed for several reasons. + auto promos = GenerateShowablePromos(profile, /*apply_ordering=*/false); + return !promos.pending.empty() || !promos.completed.empty(); } NtpShowablePromos NtpPromoController::GenerateShowablePromos(Profile* profile) { + return GenerateShowablePromos(profile, /*apply_ordering=*/true); +} + +NtpShowablePromos NtpPromoController::GenerateShowablePromos( + Profile* profile, + bool apply_ordering) { std::vector<NtpPromoIdentifier> pending_promo_ids; std::vector<NtpPromoIdentifier> completed_promo_ids; const auto now = base::Time::Now(); @@ -132,9 +134,11 @@ .push_back(id); } - pending_promo_ids = order_policy_->OrderPendingPromos(pending_promo_ids); - completed_promo_ids = - order_policy_->OrderCompletedPromos(completed_promo_ids); + if (apply_ordering) { + pending_promo_ids = order_policy_->OrderPendingPromos(pending_promo_ids); + completed_promo_ids = + order_policy_->OrderCompletedPromos(completed_promo_ids); + } NtpShowablePromos showable_promos; showable_promos.pending = MakeShowablePromos(pending_promo_ids);
diff --git a/components/user_education/common/ntp_promo/ntp_promo_controller.h b/components/user_education/common/ntp_promo/ntp_promo_controller.h index 2554e3e..ac33cbecf 100644 --- a/components/user_education/common/ntp_promo/ntp_promo_controller.h +++ b/components/user_education/common/ntp_promo/ntp_promo_controller.h
@@ -63,8 +63,10 @@ NtpPromoController(NtpPromoRegistry& registry, UserEducationStorageService& storage_service); - // Determines if there are any showable proms. - virtual bool HasShowablePromos(Profile* profile) const; + // Determines if there are any showable promos. For consistency, this is + // essentially a wrapper around promo-list-generation logic, which may mutate + // stored prefs. + virtual bool HasShowablePromos(Profile* profile); // Provides ordered lists of eligible and completed promos, intended to be // displayed by the NTP. May update prefs as a side effect. @@ -88,6 +90,12 @@ static base::TimeDelta GetClickedPromoHideDurationForTest(); private: + // Internal variation of promo list generation, shared between "has promos" + // and "make promo lists" logic. When only checking if there are promos to + // show, the (relatively expensive) ordering logic can be skipped. + NtpShowablePromos GenerateShowablePromos(Profile* profile, + bool apply_ordering); + // Updates the data on the promo shown in the top spot. void OnPromoShownInTopSpot(NtpPromoIdentifier id);
diff --git a/components/user_education/common/ntp_promo/ntp_promo_controller_unittest.cc b/components/user_education/common/ntp_promo/ntp_promo_controller_unittest.cc index 6e5416b8..f8ea2aa9 100644 --- a/components/user_education/common/ntp_promo/ntp_promo_controller_unittest.cc +++ b/components/user_education/common/ntp_promo/ntp_promo_controller_unittest.cc
@@ -266,4 +266,10 @@ controller_.OnPromosShown({kPromoId}, {}); } +TEST_F(NtpPromoControllerTest, HasShowablePromos) { + EXPECT_FALSE(controller_.HasShowablePromos(nullptr)); + RegisterPromo(kPromoId, kEligible); + EXPECT_TRUE(controller_.HasShowablePromos(nullptr)); +} + } // namespace user_education
diff --git a/components/variations/BUILD.gn b/components/variations/BUILD.gn index 26d30ce..f994ae9 100644 --- a/components/variations/BUILD.gn +++ b/components/variations/BUILD.gn
@@ -68,6 +68,8 @@ "seed_reader_writer.h", "seed_response.cc", "seed_response.h", + "sticky_activation_manager.cc", + "sticky_activation_manager.h", "study_filtering.cc", "study_filtering.h", "synthetic_trial_registry.cc",
diff --git a/components/variations/antishuffle_unittest.cc b/components/variations/antishuffle_unittest.cc index 393dd39..8c67a17 100644 --- a/components/variations/antishuffle_unittest.cc +++ b/components/variations/antishuffle_unittest.cc
@@ -115,9 +115,11 @@ auto client_state = CreateDummyClientFilterableState(); base::FeatureList feature_list; VariationsLayers layers(seed, entropy_providers); - VariationsSeedProcessor().CreateTrialsFromSeed( - seed, *client_state, base::BindRepeating(NoopUIStringOverrideCallback), - entropy_providers, layers, &feature_list); + StickyActivationManager sticky_activation_manager(/*local_state=*/nullptr); + VariationsSeedProcessor(sticky_activation_manager) + .CreateTrialsFromSeed(seed, *client_state, + base::BindRepeating(NoopUIStringOverrideCallback), + entropy_providers, layers, &feature_list); } } // namespace
diff --git a/components/variations/fuzzers/create_trial_from_study_fuzzer.cc b/components/variations/fuzzers/create_trial_from_study_fuzzer.cc index a71d8a97..637d830 100644 --- a/components/variations/fuzzers/create_trial_from_study_fuzzer.cc +++ b/components/variations/fuzzers/create_trial_from_study_fuzzer.cc
@@ -65,9 +65,10 @@ ProcessedStudy processed_study; VariationsLayers layers; if (processed_study.Init(&study)) { - VariationsSeedProcessor().CreateTrialFromStudy( - processed_study, override_callback.callback(), entropy_providers, - layers, &feature_list); + StickyActivationManager sticky_activation_manager(/*local_state=*/nullptr); + VariationsSeedProcessor(sticky_activation_manager) + .CreateTrialFromStudy(processed_study, override_callback.callback(), + entropy_providers, layers, &feature_list); } }
diff --git a/components/variations/fuzzers/create_trials_from_seed_fuzzer.cc b/components/variations/fuzzers/create_trials_from_seed_fuzzer.cc index d2f2c35..3028fc8 100644 --- a/components/variations/fuzzers/create_trials_from_seed_fuzzer.cc +++ b/components/variations/fuzzers/create_trials_from_seed_fuzzer.cc
@@ -78,9 +78,10 @@ // The following is a test value for limited entropy randomization source "00000000000000000000000000000001"); VariationsLayers layers(seed, entropy_providers); - VariationsSeedProcessor().CreateTrialsFromSeed( - seed, *client_state, override_callback.callback(), entropy_providers, - layers, &feature_list); + StickyActivationManager sticky_activation_manager(/*local_state=*/nullptr); + VariationsSeedProcessor(sticky_activation_manager) + .CreateTrialsFromSeed(seed, *client_state, override_callback.callback(), + entropy_providers, layers, &feature_list); } DEFINE_PROTO_FUZZER(const VariationsSeed& seed) {
diff --git a/components/variations/fuzzers/create_trials_from_seed_fuzzer_v2.cc b/components/variations/fuzzers/create_trials_from_seed_fuzzer_v2.cc index e48f0023..3db5e3c 100644 --- a/components/variations/fuzzers/create_trials_from_seed_fuzzer_v2.cc +++ b/components/variations/fuzzers/create_trials_from_seed_fuzzer_v2.cc
@@ -133,9 +133,11 @@ base::HistogramTester histogram_tester; auto seed = test_case.seed(); VariationsLayers layers(seed, entropy_providers); - VariationsSeedProcessor().CreateTrialsFromSeed( - seed, *client_state, base::BindRepeating(NoopUIStringOverrideCallback), - entropy_providers, layers, &feature_list); + StickyActivationManager sticky_activation_manager(/*local_state=*/nullptr); + VariationsSeedProcessor(sticky_activation_manager) + .CreateTrialsFromSeed(seed, *client_state, + base::BindRepeating(NoopUIStringOverrideCallback), + entropy_providers, layers, &feature_list); // There are numerous conditions for which the seed could be rejected. They // should all be caught during the initial seed validation. Post validation,
diff --git a/components/variations/processed_study.cc b/components/variations/processed_study.cc index 3f39e04..314968b 100644 --- a/components/variations/processed_study.cc +++ b/components/variations/processed_study.cc
@@ -195,6 +195,34 @@ return true; } +// Validates the study type enums. +bool ValidateStudyTypeEnums(const Study& study) { + // Note: These enums are specifically defined as `features.enum_type = OPEN`, + // meaning unknown values are present as integers on the original field. This + // allows us to validate them using IsValid() without needing to use proto + // reflection (which is more expensive) on unknown values. + if (study.has_consistency() && + !Study::Consistency_IsValid(study.consistency())) { + LogInvalidReason(InvalidStudyReason::kUnsupportedStudyConsistency); + DVLOG(1) << study.name() + << " has an unsupported consistency: " << study.consistency(); + return false; + } + if (study.has_activation_type() && + !Study::ActivationType_IsValid(study.activation_type())) { + LogInvalidReason(InvalidStudyReason::kUnsupportedStudyActivationType); + DVLOG(1) << study.name() << " has an unsupported activation type: " + << study.activation_type(); + return false; + } + if (study.activation_type() == Study::STICKY_AFTER_QUERY) { + // TODO: crbug.com/435630455 - STICKY_AFTER_QUERY studies are under + // development but not yet supported. + return false; + } + return true; +} + // Validates the sanity of |study| and computes the total probability and // whether all assignments are to a single group. bool ValidateStudyAndComputeTotalProbability( @@ -225,6 +253,10 @@ return false; } + if (!ValidateStudyTypeEnums(study)) { + return false; + } + for (const auto& experiment : study.experiment()) { const auto& flag = experiment.forcing_flag(); // Forcing flags are passed to CommandLine::HasSwitch. It should be safe to @@ -270,16 +302,18 @@ int ProcessedStudy::GetExperimentIndexByName(const std::string& name) const { for (int i = 0; i < study_->experiment_size(); ++i) { - if (study_->experiment(i).name() == name) + if (study_->experiment(i).name() == name) { return i; + } } return -1; } const std::string_view ProcessedStudy::GetDefaultExperimentName() const { - if (study_->default_experiment_name().empty()) + if (study_->default_experiment_name().empty()) { return kGenericDefaultExperimentName; + } return study_->default_experiment_name(); }
diff --git a/components/variations/processed_study.h b/components/variations/processed_study.h index f0176de3..da43cd0 100644 --- a/components/variations/processed_study.h +++ b/components/variations/processed_study.h
@@ -33,7 +33,9 @@ kInvalidExperimentName = 12, kInvalidFeatureName = 13, kInvalidForcingFlag = 14, - kMaxValue = kInvalidForcingFlag, + kUnsupportedStudyConsistency = 15, + kUnsupportedStudyActivationType = 16, + kMaxValue = kUnsupportedStudyActivationType, }; class Study;
diff --git a/components/variations/processed_study_unittest.cc b/components/variations/processed_study_unittest.cc index 3f9eed7..36cda52 100644 --- a/components/variations/processed_study_unittest.cc +++ b/components/variations/processed_study_unittest.cc
@@ -420,4 +420,48 @@ EXPECT_FALSE(processed_study.all_assignments_to_one_group()); } +TEST(ProcessedStudyTest, InitWithInvalidStudyConsistency) { + Study study = CreateValidStudy(); + // See also InvalidEnumValuesArePreserved. + // Set to 100, which isn't a valid enum value. + study.set_consistency(Study::Consistency(100)); + + base::HistogramTester histogram_tester; + ProcessedStudy processed_study; + EXPECT_FALSE(processed_study.Init(&study)); + histogram_tester.ExpectUniqueSample( + kInvalidStudyReasonHistogram, + InvalidStudyReason::kUnsupportedStudyConsistency, 1); +} + +TEST(ProcessedStudyTest, InitWithInvalidStudyActivationType) { + Study study = CreateValidStudy(); + // See also InvalidEnumValuesArePreserved. + // Set to 100, which isn't a valid enum value. + study.set_activation_type(Study::ActivationType(100)); + + base::HistogramTester histogram_tester; + ProcessedStudy processed_study; + EXPECT_FALSE(processed_study.Init(&study)); + histogram_tester.ExpectUniqueSample( + kInvalidStudyReasonHistogram, + InvalidStudyReason::kUnsupportedStudyActivationType, 1); +} + +TEST(ProcessedStudyTest, InvalidEnumValuesArePreserved) { + // This checks that the proto uses `features.enum_type = OPEN` for these + // enums, which causes unknown enum values to be preserved as integers. + Study study = CreateValidStudy(); + // Set both to 100, which isn't a valid enum value for either one. + study.set_consistency(Study::Consistency(100)); + study.set_activation_type(Study::ActivationType(100)); + auto serialized_study = study.SerializeAsString(); + Study parsed_study; + parsed_study.ParseFromString(serialized_study); + EXPECT_EQ(parsed_study.consistency(), 100); + EXPECT_FALSE(Study::Consistency_IsValid(parsed_study.consistency())); + EXPECT_EQ(parsed_study.activation_type(), 100); + EXPECT_FALSE(Study::ActivationType_IsValid(parsed_study.activation_type())); +} + } // namespace variations
diff --git a/components/variations/proto/study.proto b/components/variations/proto/study.proto index c4fbbaf..d3fd677 100644 --- a/components/variations/proto/study.proto +++ b/components/variations/proto/study.proto
@@ -36,6 +36,11 @@ // Consistency setting for a study. enum Consistency { + // OPEN enum type causes unknown values get preserved in the field directly, + // as opposed to the field defaulting to the first value. We then validate + // this explicitly in processed_study.cc. + option features.enum_type = OPEN; + SESSION = 0; // Can't change within a session. PERMANENT = 1; // Can't change for a given user. } @@ -46,7 +51,7 @@ // Optionally specifies which layer the study is a part of. A study must // specify both the ID of the layer and the ID(s) of the layer member(s) - // within that layer that the study should be constrained to. + // within that layer to which the study should be constrained. LayerMemberReference layer = 16; // Name of the experiment that gets the default experience. This experiment @@ -485,6 +490,11 @@ // Specifies whether the study starts as active initially, or whether it // requires the client to query its state before it is marked as active. enum ActivationType { + // OPEN enum type causes unknown values get preserved in the field directly, + // as opposed to the field defaulting to the first value. We then validate + // this explicitly in processed_study.cc. + option features.enum_type = OPEN; + // The study will be activated when its state is queried by the client. // This is recommended for most studies that include client code. ACTIVATE_ON_QUERY = 0; @@ -492,6 +502,14 @@ // The study will be automatically activated when it is created. This // is recommended for studies that do not have any client logic. ACTIVATE_ON_STARTUP = 1; + + // The study is first activated when it is queried. On browser restarts, the + // study remains active unless the client would be assigned to a different + // group. This is recommended to avoid problems of differential triggering + // associated with ACTIVATE_ON_QUERY and for studying longer-term effects + // without activation on start up. Only valid for studies using PERMANENT + // consistency. + STICKY_AFTER_QUERY = 2; } // Activation type for this study. Defaults to ACTIVATE_ON_QUERY if omitted.
diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc index 2787a0f..db6a236 100644 --- a/components/variations/service/variations_field_trial_creator.cc +++ b/components/variations/service/variations_field_trial_creator.cc
@@ -206,7 +206,8 @@ seed_store_(std::move(seed_store)), application_locale_( language::GetApplicationLocale(seed_store_->local_state())), - ui_string_overrider_(ui_string_overrider) {} + ui_string_overrider_(ui_string_overrider), + sticky_activation_manager_(seed_store_->local_state()) {} VariationsFieldTrialCreator::~VariationsFieldTrialCreator() = default; @@ -652,8 +653,6 @@ base::FeatureList* feature_list, SafeSeedManagerBase* safe_seed_manager, std::unique_ptr<ClientFilterableState> client_state) { - // This histogram name uses "VariationsFieldTrialCreator" rather than - // "VariationsFieldTrialCreator" for consistency with historical data TRACE_EVENT0("startup", "VariationsFieldTrialCreator::CreateTrialsFromSeed"); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CHECK(!create_trials_from_seed_called_); @@ -732,11 +731,12 @@ // directly to VariationsSeedProcessor (which is in components/variations and // not components/variations/service) as the variations component should not // depend on //ui/base. - VariationsSeedProcessor().CreateTrialsFromSeed( - seed, *client_state, - base::BindRepeating(&VariationsFieldTrialCreator::OverrideUIString, - base::Unretained(this)), - entropy_providers, layers, feature_list); + VariationsSeedProcessor(sticky_activation_manager_) + .CreateTrialsFromSeed( + seed, *client_state, + base::BindRepeating(&VariationsFieldTrialCreator::OverrideUIString, + base::Unretained(this)), + entropy_providers, layers, feature_list); VLOG(1) << "CreateTrialsFromSeed complete with " << "seed.version='" << seed.version() << "'";
diff --git a/components/variations/service/variations_field_trial_creator.h b/components/variations/service/variations_field_trial_creator.h index ea0d5526..a3c9c1e2 100644 --- a/components/variations/service/variations_field_trial_creator.h +++ b/components/variations/service/variations_field_trial_creator.h
@@ -27,6 +27,7 @@ #include "components/variations/service/safe_seed_manager.h" #include "components/variations/service/ui_string_overrider.h" #include "components/variations/service/variations_service_client.h" +#include "components/variations/sticky_activation_manager.h" #include "components/variations/variations_seed_store.h" #include "components/version_info/channel.h" @@ -326,6 +327,8 @@ // These strings are cached before the resource bundle is initialized. std::unordered_map<int, std::u16string> overridden_strings_map_; + StickyActivationManager sticky_activation_manager_; + SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/components/variations/service/variations_service.cc b/components/variations/service/variations_service.cc index 3136b98e..de22877 100644 --- a/components/variations/service/variations_service.cc +++ b/components/variations/service/variations_service.cc
@@ -42,6 +42,7 @@ #include "components/variations/pref_names.h" #include "components/variations/proto/variations_seed.pb.h" #include "components/variations/seed_response.h" +#include "components/variations/sticky_activation_manager.h" #include "components/variations/variations_safe_seed_store_local_state.h" #include "components/variations/variations_seed_simulator.h" #include "components/variations/variations_switches.h" @@ -554,6 +555,7 @@ SafeSeedManager::RegisterPrefs(registry); VariationsSeedStore::RegisterPrefs(registry); RegisterFieldTrialInternalsPrefs(*registry); + StickyActivationManager::RegisterPrefs(*registry); registry->RegisterIntegerPref( prefs::kDeviceVariationsRestrictionsByPolicy,
diff --git a/components/variations/sticky_activation_manager.cc b/components/variations/sticky_activation_manager.cc new file mode 100644 index 0000000..b6bacaaa --- /dev/null +++ b/components/variations/sticky_activation_manager.cc
@@ -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. + +#include "components/variations/sticky_activation_manager.h" + +#include "components/prefs/pref_registry_simple.h" + +namespace variations { + +StickyActivationManager::StickyActivationManager(PrefService* local_state) + : local_state_(local_state) {} + +StickyActivationManager::~StickyActivationManager() = default; + +// static +void StickyActivationManager::RegisterPrefs(PrefRegistrySimple& registry) {} + +} // namespace variations
diff --git a/components/variations/sticky_activation_manager.h b/components/variations/sticky_activation_manager.h new file mode 100644 index 0000000..970dd8c --- /dev/null +++ b/components/variations/sticky_activation_manager.h
@@ -0,0 +1,47 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VARIATIONS_STICKY_ACTIVATION_MANAGER_H_ +#define COMPONENTS_VARIATIONS_STICKY_ACTIVATION_MANAGER_H_ + +#include "base/component_export.h" +#include "base/memory/raw_ptr.h" + +class PrefService; +class PrefRegistrySimple; + +namespace variations { + +// Manages the set of field trials marked with the activation type +// STICKY_AFTER_QUERY. Responsible for persisting information about activated +// trials to Local State and using that information to determine if a trial +// should be activated on the next startup. +// +// A sticky trial should be activated on startup if it was active in the +// previous session (including from stickiness on startup) and its group +// selection did not change (i.e. due to a change to its config or something +// external like the client's randomization inputs). +// +// TODO: crbug.com/435630455 - This class is under development. +class COMPONENT_EXPORT(VARIATIONS) StickyActivationManager { + public: + // `local_state` may be null for tests, in which case no prior stickiness + // information will be loaded and none will be saved. + explicit StickyActivationManager(PrefService* local_state); + + StickyActivationManager(const StickyActivationManager&) = delete; + StickyActivationManager& operator=(const StickyActivationManager&) = delete; + + ~StickyActivationManager(); + + // Registers the prefs used by this class. + static void RegisterPrefs(PrefRegistrySimple& registry); + + private: + raw_ptr<PrefService> local_state_; +}; + +} // namespace variations + +#endif // COMPONENTS_VARIATIONS_STICKY_ACTIVATION_MANAGER_H_
diff --git a/components/variations/study_filtering.cc b/components/variations/study_filtering.cc index 4f7e515..ed60046 100644 --- a/components/variations/study_filtering.cc +++ b/components/variations/study_filtering.cc
@@ -276,6 +276,15 @@ // effects, this helps to avoid annoying users with experimental group // churn while traveling. return client_state.permanent_consistency_country; + // Note: Study_Consistency is an OPEN proto enum, so the below values appear + // in the generated code to indicate the field could have other values. + // However, we validate this in processed_study.cc to reject such studies, + // so in practice, only the cases above will be seen. We list them here + // instead of a "default" case to still get the benefit of the compiler + // reminding us to update this code if a new enum value is added. + case Study_Consistency_Study_Consistency_INT_MIN_SENTINEL_DO_NOT_USE_: + case Study_Consistency_Study_Consistency_INT_MAX_SENTINEL_DO_NOT_USE_: + break; } // Unless otherwise specified, use an empty country that won't pass any
diff --git a/components/variations/uniformity_unittest.cc b/components/variations/uniformity_unittest.cc index c057671..738cb788 100644 --- a/components/variations/uniformity_unittest.cc +++ b/components/variations/uniformity_unittest.cc
@@ -144,9 +144,11 @@ VariationsLayers layers(seed, entropy_providers); // This should mimic the call through SetUpFieldTrials from // android_webview/browser/aw_feature_list_creator.cc - VariationsSeedProcessor().CreateTrialsFromSeed( - seed, *client_state, base::BindRepeating(NoopUIStringOverrideCallback), - entropy_providers, layers, &feature_list); + StickyActivationManager sticky_activation_manager(/*local_state=*/nullptr); + VariationsSeedProcessor(sticky_activation_manager) + .CreateTrialsFromSeed(seed, *client_state, + base::BindRepeating(NoopUIStringOverrideCallback), + entropy_providers, layers, &feature_list); testing::ClearAllVariationIDs(); return base::FieldTrialList::FindFullName(kStudyName); }
diff --git a/components/variations/variations_seed_processor.cc b/components/variations/variations_seed_processor.cc index dc58e48..104258d 100644 --- a/components/variations/variations_seed_processor.cc +++ b/components/variations/variations_seed_processor.cc
@@ -280,7 +280,9 @@ experiment.has_google_web_trigger_experiment_id(); } -VariationsSeedProcessor::VariationsSeedProcessor() = default; +VariationsSeedProcessor::VariationsSeedProcessor( + StickyActivationManager& sticky_activation_manager) + : sticky_activation_manager_(sticky_activation_manager) {} VariationsSeedProcessor::~VariationsSeedProcessor() = default;
diff --git a/components/variations/variations_seed_processor.h b/components/variations/variations_seed_processor.h index ba95443..3e878026 100644 --- a/components/variations/variations_seed_processor.h +++ b/components/variations/variations_seed_processor.h
@@ -11,9 +11,11 @@ #include "base/component_export.h" #include "base/functional/callback_forward.h" +#include "base/memory/raw_ref.h" #include "components/variations/entropy_provider.h" #include "components/variations/proto/study.pb.h" #include "components/variations/proto/variations_seed.pb.h" +#include "components/variations/sticky_activation_manager.h" namespace base { class FeatureList; @@ -48,7 +50,9 @@ using UIStringOverrideCallback = base::RepeatingCallback<void(uint32_t, const std::u16string&)>; - VariationsSeedProcessor(); + // Note: The `sticky_activation_manager` must outlive this class. + explicit VariationsSeedProcessor( + StickyActivationManager& sticky_activation_manager); VariationsSeedProcessor(const VariationsSeedProcessor&) = delete; VariationsSeedProcessor& operator=(const VariationsSeedProcessor&) = delete; @@ -82,6 +86,10 @@ const EntropyProviders& entropy_providers, const VariationsLayers& layers, base::FeatureList* feature_list); + + // Used to manage studies that use sticky activation, to determine which ones + // should be activated on startup per their prior state. + raw_ref<StickyActivationManager> sticky_activation_manager_; }; } // namespace variations
diff --git a/components/variations/variations_seed_processor_unittest.cc b/components/variations/variations_seed_processor_unittest.cc index 034fda6..7dfdea1 100644 --- a/components/variations/variations_seed_processor_unittest.cc +++ b/components/variations/variations_seed_processor_unittest.cc
@@ -166,6 +166,8 @@ // chrome. class ChromeEnvironment { public: + ChromeEnvironment() : sticky_activation_manager_(/*local_state=*/nullptr) {} + bool HasHighEntropy() { return true; } bool HasLimitedEntropy() { return true; } @@ -185,15 +187,21 @@ VariationsLayers layers(seed, entropy_providers); // This should mimic the call through SetUpFieldTrials from // components/variations/service/variations_service.cc - VariationsSeedProcessor().CreateTrialsFromSeed( - seed, *client_state, callback, entropy_providers, layers, feature_list); + VariationsSeedProcessor(sticky_activation_manager_) + .CreateTrialsFromSeed(seed, *client_state, callback, entropy_providers, + layers, feature_list); } + + private: + StickyActivationManager sticky_activation_manager_; }; // WebViewEnvironment calls CreateTrialsFromSeed with arguments similar to // WebView. class WebViewEnvironment { public: + WebViewEnvironment() : sticky_activation_manager_(/*local_state=*/nullptr) {} + bool HasHighEntropy() { return false; } bool HasLimitedEntropy() { return false; } @@ -211,9 +219,13 @@ VariationsLayers layers(seed, entropy_providers); // This should mimic the call through SetUpFieldTrials from // android_webview/browser/aw_feature_list_creator.cc - VariationsSeedProcessor().CreateTrialsFromSeed( - seed, *client_state, callback, entropy_providers, layers, feature_list); + VariationsSeedProcessor(sticky_activation_manager_) + .CreateTrialsFromSeed(seed, *client_state, callback, entropy_providers, + layers, feature_list); } + + private: + StickyActivationManager sticky_activation_manager_; }; template <typename Environment> @@ -600,7 +612,8 @@ AddExperiment("Default", 0, study3); study3->set_activation_type(Study::ACTIVATE_ON_QUERY); - VariationsSeedProcessor seed_processor; + StickyActivationManager sticky_activation_manager(/*local_state=*/nullptr); + VariationsSeedProcessor seed_processor(sticky_activation_manager); this->CreateTrialsFromSeed(seed); // Non-specified and ACTIVATE_ON_QUERY should not start active, but
diff --git a/components/viz/common/yuv_readback_unittest.cc b/components/viz/common/yuv_readback_unittest.cc index be0b97f..4c2c9346 100644 --- a/components/viz/common/yuv_readback_unittest.cc +++ b/components/viz/common/yuv_readback_unittest.cc
@@ -365,15 +365,24 @@ auto run_quit_closure = [](base::OnceClosure quit_closure, bool result) { std::move(quit_closure).Run(); }; + std::optional<base::span<uint8_t>> maybe_span_y = + output_frame->writable_span(media::VideoFrame::Plane::kY); + ASSERT_TRUE(maybe_span_y); + std::optional<base::span<uint8_t>> maybe_span_u = + output_frame->writable_span(media::VideoFrame::Plane::kU); + ASSERT_TRUE(maybe_span_u); + std::optional<base::span<uint8_t>> maybe_span_v = + output_frame->writable_span(media::VideoFrame::Plane::kV); + ASSERT_TRUE(maybe_span_v); + yuv_reader->ReadbackYUV( src_texture, gfx::Size(xsize, ysize), gfx::Rect(0, 0, xsize, ysize), output_frame->stride(media::VideoFrame::Plane::kY), - output_frame->writable_data(media::VideoFrame::Plane::kY), + maybe_span_y.value(), output_frame->stride(media::VideoFrame::Plane::kU), - output_frame->writable_data(media::VideoFrame::Plane::kU), + maybe_span_u.value(), output_frame->stride(media::VideoFrame::Plane::kV), - output_frame->writable_data(media::VideoFrame::Plane::kV), - gfx::Point(xmargin, ymargin), + maybe_span_v.value(), gfx::Point(xmargin, ymargin), base::BindOnce(run_quit_closure, run_loop.QuitClosure())); const gfx::Rect paste_rect(gfx::Point(xmargin, ymargin),
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index 710a1ac..aa2d6943 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -583,11 +583,22 @@ uint8_t y_foreground, uint8_t u_foreground, uint8_t v_foreground) { - int planes[] = {media::VideoFrame::Plane::kY, media::VideoFrame::Plane::kU, - media::VideoFrame::Plane::kV}; - uint8_t yuv_background[] = {y_background, u_background, v_background}; - uint8_t yuv_foreground[] = {y_foreground, u_foreground, v_foreground}; - int sample_size[] = {1, 2, 2}; + auto planes = std::to_array<int>({ + media::VideoFrame::Plane::kY, + media::VideoFrame::Plane::kU, + media::VideoFrame::Plane::kV, + }); + auto yuv_background = std::to_array<uint8_t>({ + y_background, + u_background, + v_background, + }); + auto yuv_foreground = std::to_array<uint8_t>({ + y_foreground, + u_foreground, + v_foreground, + }); + auto sample_size = std::to_array<int>({1, 2, 2}); for (int i = 0; i < 3; ++i) { memset(video_frame_->writable_data(planes[i]), yuv_background[i],
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc index c225b7f..985d2a6 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -13,6 +13,7 @@ #include <tuple> #include <utility> +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/numerics/safe_conversions.h" #include "base/strings/stringprintf.h" @@ -165,21 +166,19 @@ } void AddResourcesToFrame(CompositorFrame* frame, - ResourceId* resource_ids, - size_t num_resource_ids) { - for (size_t i = 0u; i < num_resource_ids; ++i) { + base::span<ResourceId> resource_ids) { + for (ResourceId resource_id : resource_ids) { TransferableResource resource; - resource.id = resource_ids[i]; + resource.id = resource_id; resource.set_texture_target(GL_TEXTURE_2D); resource.set_sync_token(frame_sync_token_); frame->resource_list.push_back(resource); } } - void SubmitCompositorFrameWithResources(ResourceId* resource_ids, - size_t num_resource_ids) { + void SubmitCompositorFrameWithResources(base::span<ResourceId> resource_ids) { auto frame = MakeDefaultInteractiveCompositorFrame(kBeginFrameSourceId); - AddResourcesToFrame(&frame, resource_ids, num_resource_ids); + AddResourcesToFrame(&frame, resource_ids); support_->SubmitCompositorFrame(local_surface_id_, std::move(frame)); EXPECT_EQ(surface_observer_->last_created_surface_id().local_surface_id(), local_surface_id_); @@ -205,11 +204,11 @@ return false; } - void UnrefResources(ResourceId* ids_to_unref, - int* counts_to_unref, - size_t num_ids_to_unref) { + void UnrefResources(base::span<ResourceId> ids_to_unref, + base::span<int> counts_to_unref) { + CHECK_EQ(ids_to_unref.size(), counts_to_unref.size()); std::vector<ReturnedResource> unref_array; - for (size_t i = 0; i < num_ids_to_unref; ++i) { + for (size_t i = 0; i < ids_to_unref.size(); ++i) { ReturnedResource resource; resource.sync_token = consumer_sync_token_; resource.id = ids_to_unref[i]; @@ -219,25 +218,26 @@ support_->UnrefResources(std::move(unref_array)); } - void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids, - size_t expected_resources) { + void CheckReturnedResourcesMatchExpected( + base::span<ResourceId> expected_returned_ids) { const std::vector<ReturnedResource>& actual_resources = fake_support_client_.returned_resources(); - ASSERT_EQ(expected_resources, actual_resources.size()); - for (size_t i = 0; i < expected_resources; ++i) { + ASSERT_EQ(expected_returned_ids.size(), actual_resources.size()); + for (size_t i = 0; i < expected_returned_ids.size(); ++i) { EXPECT_EQ(expected_returned_ids[i], actual_resources[i].id); } fake_support_client_.clear_returned_resources(); } - void CheckReturnedResourcesMatchExpected(ResourceId* expected_returned_ids, - int* expected_returned_counts, - size_t expected_resources, - gpu::SyncToken expected_sync_token) { + void CheckReturnedResourcesMatchExpected( + base::span<ResourceId> expected_returned_ids, + base::span<int> expected_returned_counts, + gpu::SyncToken expected_sync_token) { + CHECK_EQ(expected_returned_ids.size(), expected_returned_counts.size()); const std::vector<ReturnedResource>& actual_resources = fake_support_client_.returned_resources(); - ASSERT_EQ(expected_resources, actual_resources.size()); - for (size_t i = 0; i < expected_resources; ++i) { + ASSERT_EQ(expected_returned_ids.size(), actual_resources.size()); + for (size_t i = 0; i < expected_returned_ids.size(); ++i) { const auto& resource = actual_resources[i]; EXPECT_EQ(expected_sync_token, resource.sync_token); EXPECT_EQ(expected_returned_ids[i], resource.id); @@ -397,8 +397,7 @@ // with no resource provider action in between. TEST_P(AckOnSurfaceActivationWhenInteractiveTest, ResourceLifetimeSimple) { ResourceId first_frame_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3)}; - SubmitCompositorFrameWithResources(first_frame_ids, - std::size(first_frame_ids)); + SubmitCompositorFrameWithResources(first_frame_ids); // All of the resources submitted in the first frame are still in use at this // time by virtue of being in the pending frame, so none can be returned to @@ -408,19 +407,17 @@ // The second frame references no resources of first frame and thus should // make all resources of first frame available to be returned. - SubmitCompositorFrameWithResources(nullptr, 0); + SubmitCompositorFrameWithResources({}); ResourceId expected_returned_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3)}; int expected_returned_counts[] = {1, 1, 1}; // Resources were never consumed so no sync token should be set. CheckReturnedResourcesMatchExpected( - expected_returned_ids, expected_returned_counts, - std::size(expected_returned_counts), gpu::SyncToken()); + expected_returned_ids, expected_returned_counts, gpu::SyncToken()); ResourceId third_frame_ids[] = {ResourceId(4), ResourceId(5), ResourceId(6)}; - SubmitCompositorFrameWithResources(third_frame_ids, - std::size(third_frame_ids)); + SubmitCompositorFrameWithResources(third_frame_ids); // All of the resources submitted in the third frame are still in use at this // time by virtue of being in the pending frame, so none can be returned to @@ -431,16 +428,15 @@ // The forth frame references no resources of third frame and thus should // make all resources of third frame available to be returned. ResourceId forth_frame_ids[] = {ResourceId(7), ResourceId(8), ResourceId(9)}; - SubmitCompositorFrameWithResources(forth_frame_ids, - std::size(forth_frame_ids)); + SubmitCompositorFrameWithResources(forth_frame_ids); ResourceId forth_expected_returned_ids[] = {ResourceId(4), ResourceId(5), ResourceId(6)}; int forth_expected_returned_counts[] = {1, 1, 1}; // Resources were never consumed so no sync token should be set. - CheckReturnedResourcesMatchExpected( - forth_expected_returned_ids, forth_expected_returned_counts, - std::size(forth_expected_returned_counts), gpu::SyncToken()); + CheckReturnedResourcesMatchExpected(forth_expected_returned_ids, + forth_expected_returned_counts, + gpu::SyncToken()); } // Tests submitting a frame with resources followed by one with no resources @@ -448,8 +444,7 @@ TEST_P(AckOnSurfaceActivationWhenInteractiveTest, ResourceLifetimeSimpleWithProviderHoldingAlive) { ResourceId first_frame_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3)}; - SubmitCompositorFrameWithResources(first_frame_ids, - std::size(first_frame_ids)); + SubmitCompositorFrameWithResources(first_frame_ids); // All of the resources submitted in the first frame are still in use at this // time by virtue of being in the pending frame, so none can be returned to @@ -462,13 +457,13 @@ // The second frame references no resources and thus should make all resources // available to be returned as soon as the resource provider releases them. - SubmitCompositorFrameWithResources(nullptr, 0); + SubmitCompositorFrameWithResources({}); EXPECT_EQ(0u, fake_support_client_.returned_resources().size()); fake_support_client_.clear_returned_resources(); int release_counts[] = {1, 1, 1}; - UnrefResources(first_frame_ids, release_counts, std::size(first_frame_ids)); + UnrefResources(first_frame_ids, release_counts); // None are returned to the client since DidReceiveCompositorAck is not // invoked. @@ -480,31 +475,28 @@ // Submitting an empty frame causes previous resources referenced by the // previous frame to be returned to client. - SubmitCompositorFrameWithResources(nullptr, 0); + SubmitCompositorFrameWithResources({}); ResourceId expected_returned_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3)}; int expected_returned_counts[] = {1, 1, 1}; CheckReturnedResourcesMatchExpected( - expected_returned_ids, expected_returned_counts, - std::size(expected_returned_counts), consumer_sync_token_); + expected_returned_ids, expected_returned_counts, consumer_sync_token_); } // Tests referencing a resource, unref'ing it to zero, then using it again // before returning it to the client. TEST_P(AckOnSurfaceActivationWhenInteractiveTest, ResourceReusedBeforeReturn) { ResourceId first_frame_ids[] = {ResourceId(7)}; - SubmitCompositorFrameWithResources(first_frame_ids, - std::size(first_frame_ids)); + SubmitCompositorFrameWithResources(first_frame_ids); // This removes all references to resource id 7. - SubmitCompositorFrameWithResources(nullptr, 0); + SubmitCompositorFrameWithResources({}); // This references id 7 again. - SubmitCompositorFrameWithResources(first_frame_ids, - std::size(first_frame_ids)); + SubmitCompositorFrameWithResources(first_frame_ids); // This removes it again. - SubmitCompositorFrameWithResources(nullptr, 0); + SubmitCompositorFrameWithResources({}); // Now it should be returned. // We don't care how many entries are in the returned array for 7, so long as @@ -523,16 +515,14 @@ // multiple providers. TEST_P(AckOnSurfaceActivationWhenInteractiveTest, ResourceRefMultipleTimes) { ResourceId first_frame_ids[] = {ResourceId(3), ResourceId(4)}; - SubmitCompositorFrameWithResources(first_frame_ids, - std::size(first_frame_ids)); + SubmitCompositorFrameWithResources(first_frame_ids); // Ref resources from the first frame twice. RefCurrentFrameResources(); RefCurrentFrameResources(); ResourceId second_frame_ids[] = {ResourceId(4), ResourceId(5)}; - SubmitCompositorFrameWithResources(second_frame_ids, - std::size(second_frame_ids)); + SubmitCompositorFrameWithResources(second_frame_ids); // Ref resources from the second frame 3 times. RefCurrentFrameResources(); @@ -541,7 +531,7 @@ // Submit a frame with no resources to remove all current frame refs from // submitted resources. - SubmitCompositorFrameWithResources(nullptr, 0); + SubmitCompositorFrameWithResources({}); EXPECT_EQ(0u, fake_support_client_.returned_resources().size()); fake_support_client_.clear_returned_resources(); @@ -554,19 +544,18 @@ SCOPED_TRACE("unref all 3"); ResourceId ids_to_unref[] = {ResourceId(3), ResourceId(4), ResourceId(5)}; int counts[] = {1, 1, 1}; - UnrefResources(ids_to_unref, counts, std::size(ids_to_unref)); + UnrefResources(ids_to_unref, counts); EXPECT_EQ(0u, fake_support_client_.returned_resources().size()); fake_support_client_.clear_returned_resources(); - UnrefResources(ids_to_unref, counts, std::size(ids_to_unref)); - SubmitCompositorFrameWithResources(nullptr, 0); + UnrefResources(ids_to_unref, counts); + SubmitCompositorFrameWithResources({}); ResourceId expected_returned_ids[] = {ResourceId(3)}; int expected_returned_counts[] = {1}; CheckReturnedResourcesMatchExpected( - expected_returned_ids, expected_returned_counts, - std::size(expected_returned_counts), consumer_sync_token_); + expected_returned_ids, expected_returned_counts, consumer_sync_token_); } // Expected refs remaining: @@ -576,14 +565,13 @@ SCOPED_TRACE("unref 4 and 5"); ResourceId ids_to_unref[] = {ResourceId(4), ResourceId(5)}; int counts[] = {1, 1}; - UnrefResources(ids_to_unref, counts, std::size(ids_to_unref)); - SubmitCompositorFrameWithResources(nullptr, 0); + UnrefResources(ids_to_unref, counts); + SubmitCompositorFrameWithResources({}); ResourceId expected_returned_ids[] = {ResourceId(5)}; int expected_returned_counts[] = {1}; CheckReturnedResourcesMatchExpected( - expected_returned_ids, expected_returned_counts, - std::size(expected_returned_counts), consumer_sync_token_); + expected_returned_ids, expected_returned_counts, consumer_sync_token_); } // Now, just 2 refs remaining on resource 4. Unref both at once and make sure @@ -592,21 +580,19 @@ SCOPED_TRACE("unref only 4"); ResourceId ids_to_unref[] = {ResourceId(4)}; int counts[] = {2}; - UnrefResources(ids_to_unref, counts, std::size(ids_to_unref)); - SubmitCompositorFrameWithResources(nullptr, 0); + UnrefResources(ids_to_unref, counts); + SubmitCompositorFrameWithResources({}); ResourceId expected_returned_ids[] = {ResourceId(4)}; int expected_returned_counts[] = {2}; CheckReturnedResourcesMatchExpected( - expected_returned_ids, expected_returned_counts, - std::size(expected_returned_counts), consumer_sync_token_); + expected_returned_ids, expected_returned_counts, consumer_sync_token_); } } TEST_P(AckOnSurfaceActivationWhenInteractiveTest, ResourceLifetime) { ResourceId first_frame_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3)}; - SubmitCompositorFrameWithResources(first_frame_ids, - std::size(first_frame_ids)); + SubmitCompositorFrameWithResources(first_frame_ids); // This test relied on CompositorFrameSinkSupport::ReturnResources to not send // as long as there has been no DidReceiveCompositorFrameAck. Such that @@ -626,15 +612,13 @@ // ones. We expect to receive back resource 1 with a count of 1 since it was // only referenced by the first frame. ResourceId second_frame_ids[] = {ResourceId(2), ResourceId(3), ResourceId(4)}; - SubmitCompositorFrameWithResources(second_frame_ids, - std::size(second_frame_ids)); + SubmitCompositorFrameWithResources(second_frame_ids); { SCOPED_TRACE("second frame"); ResourceId expected_returned_ids[] = {ResourceId(1)}; int expected_returned_counts[] = {1}; CheckReturnedResourcesMatchExpected( - expected_returned_ids, expected_returned_counts, - std::size(expected_returned_counts), gpu::SyncToken()); + expected_returned_ids, expected_returned_counts, gpu::SyncToken()); } // The third frame references a disjoint set of resources, so we expect to @@ -643,8 +627,7 @@ // resource ID 4 will have a count of 1. ResourceId third_frame_ids[] = {ResourceId(10), ResourceId(11), ResourceId(12), ResourceId(13)}; - SubmitCompositorFrameWithResources(third_frame_ids, - std::size(third_frame_ids)); + SubmitCompositorFrameWithResources(third_frame_ids); { SCOPED_TRACE("third frame"); @@ -652,8 +635,7 @@ ResourceId(4)}; int expected_returned_counts[] = {2, 2, 1}; CheckReturnedResourcesMatchExpected( - expected_returned_ids, expected_returned_counts, - std::size(expected_returned_counts), gpu::SyncToken()); + expected_returned_ids, expected_returned_counts, gpu::SyncToken()); } // Simulate a ResourceProvider taking a ref on all of the resources. @@ -661,8 +643,7 @@ ResourceId fourth_frame_ids[] = {ResourceId(12), ResourceId(13)}; - SubmitCompositorFrameWithResources(fourth_frame_ids, - std::size(fourth_frame_ids)); + SubmitCompositorFrameWithResources(fourth_frame_ids); EXPECT_EQ(0u, fake_support_client_.returned_resources().size()); @@ -680,21 +661,20 @@ int counts[] = {1, 1, 1, 1}; // If we are always acking upon surface activation, we will not have any // pending surfaces and we will unref here. - UnrefResources(ids_to_unref, counts, std::size(ids_to_unref)); + UnrefResources(ids_to_unref, counts); } // Nothing is returned to the client yet since DidReceiveCompositorFrameAck // is not invoked. { SCOPED_TRACE("fourth frame, first unref"); - CheckReturnedResourcesMatchExpected(nullptr, nullptr, 0, - consumer_sync_token_); + CheckReturnedResourcesMatchExpected({}, {}, consumer_sync_token_); } { ResourceId ids_to_unref[] = {ResourceId(12), ResourceId(13)}; int counts[] = {1, 1}; - UnrefResources(ids_to_unref, counts, std::size(ids_to_unref)); + UnrefResources(ids_to_unref, counts); } // Resources 12 and 13 are still in use by the current frame, so they @@ -703,7 +683,7 @@ // If we submit an empty frame, however, they should become available. // Resources that were previously unref'd also return at this point. - SubmitCompositorFrameWithResources(nullptr, 0u); + SubmitCompositorFrameWithResources({}); { SCOPED_TRACE("fourth frame, second unref"); @@ -711,8 +691,7 @@ ResourceId(12), ResourceId(13)}; int expected_returned_counts[] = {1, 1, 2, 2}; CheckReturnedResourcesMatchExpected( - expected_returned_ids, expected_returned_counts, - std::size(expected_returned_counts), consumer_sync_token_); + expected_returned_ids, expected_returned_counts, consumer_sync_token_); } } @@ -827,8 +806,7 @@ auto frame = MakeDefaultInteractiveCompositorFrame(); ResourceId frame_resource_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3)}; - AddResourcesToFrame(&frame, frame_resource_ids, - std::size(frame_resource_ids)); + AddResourcesToFrame(&frame, frame_resource_ids); EXPECT_FALSE(SubmitCompositorFrameWithCopyRequest(std::move(frame), std::move(request))); @@ -836,8 +814,7 @@ EXPECT_TRUE(did_receive_aborted_copy_result); // All the resources in the rejected frame should have been returned. - CheckReturnedResourcesMatchExpected(frame_resource_ids, - std::size(frame_resource_ids)); + CheckReturnedResourcesMatchExpected(frame_resource_ids); manager_->InvalidateFrameSinkId(kAnotherArbitraryFrameSinkId); } @@ -1143,8 +1120,7 @@ .Build(); ResourceId frame_resource_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3)}; - AddResourcesToFrame(&frame, frame_resource_ids, - std::size(frame_resource_ids)); + AddResourcesToFrame(&frame, frame_resource_ids); result = support_->MaybeSubmitCompositorFrame( local_surface_id_, std::move(frame), std::nullopt, 0); @@ -1152,8 +1128,7 @@ EXPECT_EQ(SubmitResult::SIZE_MISMATCH, result); // All the resources in the rejected frame should have been returned. - CheckReturnedResourcesMatchExpected(frame_resource_ids, - std::size(frame_resource_ids)); + CheckReturnedResourcesMatchExpected(frame_resource_ids); } // Check that if the device scale factor of a CompositorFrame doesn't match the @@ -2158,8 +2133,7 @@ GetRequestRegionProperties_SurfaceWithNoCaptureIdentifier) { ResourceId first_frame_ids[] = {ResourceId(1), ResourceId(2), ResourceId(3), ResourceId(4), ResourceId(5)}; - SubmitCompositorFrameWithResources(first_frame_ids, - std::size(first_frame_ids)); + SubmitCompositorFrameWithResources(first_frame_ids); const auto props_with_frame = support_->GetRequestRegionProperties(VideoCaptureSubTarget()); EXPECT_EQ((kDefaultOutputRect), props_with_frame->render_pass_subrect);
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc index 8769532..a6141f9 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -118,8 +118,10 @@ : gfx::ColorSpace::CreateSRGBLinear(); switch (buffer_format_preference) { case mojom::BufferFormatPreference::kPreferGpuMemoryBuffer: + case mojom::BufferFormatPreference::kPreferSharedImageWithNativeHandle: return std::make_unique<GpuMemoryBufferVideoFramePool>( - capacity, format, color_space, context_provider); + capacity, format, color_space, context_provider, + buffer_format_preference); case mojom::BufferFormatPreference::kDefault: return std::make_unique<SharedMemoryVideoFramePool>(capacity); default: @@ -128,7 +130,8 @@ } case media::PIXEL_FORMAT_NV12: return std::make_unique<GpuMemoryBufferVideoFramePool>( - capacity, format, gfx::ColorSpace::CreateREC709(), context_provider); + capacity, format, gfx::ColorSpace::CreateREC709(), context_provider, + buffer_format_preference); default: NOTREACHED(); } @@ -327,7 +330,6 @@ frame_pool_ = GetVideoFramePoolForFormat( pixel_format_, kFramePoolCapacity, buffer_format_preference_, gmb_video_frame_pool_context_provider_); - RefreshEntireSourceNow(); } }
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h index b387d22..ebe2ac33 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -26,6 +26,7 @@ #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/video_capture_target.h" #include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h" +#include "components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.h" #include "components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h" #include "components/viz/service/frame_sinks/video_capture/video_capture_overlay.h" #include "components/viz/service/frame_sinks/video_capture/video_frame_pool.h" @@ -189,6 +190,16 @@ const gfx::Size& source_size, media::VideoPixelFormat pixel_format); + // Returns the BufferFormatPreference currently used by the gpu frame pool. + // Intended for test verification. Assumes that the frame pool is of type + // GpuMemoryBufferVideoFramePool, which must hold true for tests that + // query this method. + mojom::BufferFormatPreference gpu_frame_pool_buffer_format_for_testing() + const { + return static_cast<GpuMemoryBufferVideoFramePool*>(frame_pool_.get()) + ->buffer_format_preference(); + } + private: friend class FrameSinkVideoCapturerTest;
diff --git a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc index af234a4..aa943f84 100644 --- a/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -2229,6 +2229,28 @@ EXPECT_EQ(RegionCaptureCropId(), frame_sink_.current_crop_id()); } +// Tests that buffer_format_preference is correctly passed to the +// GpuVideoFramePool +TEST_P(FrameSinkVideoCapturerTest, BufferFormatPreferencePassedToGpuFramePool) { + // GpuMemoryBuffer only kicks in for ARGB and NV12 pixel formats. + if (pixel_format_ != media::PIXEL_FORMAT_ARGB && + pixel_format_ != media::PIXEL_FORMAT_NV12) { + return; + } + + // GpuMemoryBuffer only kicks in for the kPreferGpuMemoryBuffer and + // kPreferSharedImageWithNativeHandle formats. + if (buffer_format_preference_ == mojom::BufferFormatPreference::kDefault) { + return; + } + + NiceMock<MockConsumer> consumer; + StartCapture(&consumer); + EXPECT_EQ(capturer_->gpu_frame_pool_buffer_format_for_testing(), + buffer_format_preference_); + StopCapture(); +} + INSTANTIATE_TEST_SUITE_P( All, FrameSinkVideoCapturerTest,
diff --git a/components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.cc b/components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.cc index 258245a..c5db8f1 100644 --- a/components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.cc +++ b/components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.cc
@@ -14,11 +14,13 @@ int capacity, media::VideoPixelFormat format, const gfx::ColorSpace& color_space, - GmbVideoFramePoolContextProvider* context_provider) + GmbVideoFramePoolContextProvider* context_provider, + mojom::BufferFormatPreference buffer_format_preference) : VideoFramePool(capacity), format_(format), color_space_(color_space), - context_provider_(context_provider) { + context_provider_(context_provider), + buffer_format_preference_(buffer_format_preference) { RecreateVideoFramePool(); } @@ -74,8 +76,13 @@ auto pool_context = context_provider_->CreateContext( base::BindOnce(&GpuMemoryBufferVideoFramePool::RecreateVideoFramePool, weak_factory_.GetWeakPtr())); + // Determine whether the video frame pool should use CPU mappable buffers. + // If the caller prefers SharedImage with native handle (i.e., no CPU + // mapping), pass false. Otherwise, default to requiring CPU access. video_frame_pool_ = media::RenderableGpuMemoryBufferVideoFramePool::Create( - std::move(pool_context), format_); + std::move(pool_context), format_, + buffer_format_preference_ != + mojom::BufferFormatPreference::kPreferSharedImageWithNativeHandle); video_frame_pool_generation_++; num_reserved_frames_ = 0;
diff --git a/components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.h b/components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.h index 64e1e61..2653655 100644 --- a/components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.h +++ b/components/viz/service/frame_sinks/video_capture/gpu_memory_buffer_video_frame_pool.h
@@ -11,6 +11,7 @@ #include "components/viz/service/frame_sinks/video_capture/video_frame_pool.h" #include "components/viz/service/viz_service_export.h" #include "media/video/renderable_gpu_memory_buffer_video_frame_pool.h" +#include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h" namespace viz { @@ -24,7 +25,8 @@ int capacity, media::VideoPixelFormat format, const gfx::ColorSpace& color_space, - GmbVideoFramePoolContextProvider* context_provider); + GmbVideoFramePoolContextProvider* context_provider, + mojom::BufferFormatPreference buffer_format_preference); ~GpuMemoryBufferVideoFramePool() override; GpuMemoryBufferVideoFramePool(const GpuMemoryBufferVideoFramePool&& other) = @@ -42,6 +44,12 @@ size_t GetNumberOfReservedFrames() const override; + // Returns the buffer format preference used to configure this pool. + // This can be used in tests to verify how the pool was initialized. + mojom::BufferFormatPreference buffer_format_preference() const { + return buffer_format_preference_; + } + private: void RecreateVideoFramePool(); @@ -73,6 +81,10 @@ SEQUENCE_CHECKER(sequence_checker_); + // Our consumer preferred VideoBufferHandle type. + mojom::BufferFormatPreference buffer_format_preference_ = + mojom::BufferFormatPreference::kDefault; + base::WeakPtrFactory<GpuMemoryBufferVideoFramePool> weak_factory_{this}; };
diff --git a/components/viz/service/frame_sinks/video_capture/shared_memory_video_frame_pool_unittest.cc b/components/viz/service/frame_sinks/video_capture/shared_memory_video_frame_pool_unittest.cc index ee7ecad..41566b1e 100644 --- a/components/viz/service/frame_sinks/video_capture/shared_memory_video_frame_pool_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/shared_memory_video_frame_pool_unittest.cc
@@ -6,7 +6,7 @@ #include <memory> -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "media/base/video_frame.h" #include "media/base/video_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -159,14 +159,14 @@ // Returns true iff each plane of the given |frame| is filled with // |values[plane]|. -bool PlanesAreFilledWithValues(const VideoFrame& frame, const uint8_t* values) { +bool PlanesAreFilledWithValues(const VideoFrame& frame, + base::span<const uint8_t> values) { static_assert(VideoFrame::Plane::kU == (VideoFrame::Plane::kY + 1) && VideoFrame::Plane::kV == (VideoFrame::Plane::kU + 1), "enum values changed, will break code below"); for (int plane = VideoFrame::Plane::kY; plane <= VideoFrame::Plane::kV; ++plane) { - const uint8_t expected_value = - UNSAFE_TODO(values[plane - VideoFrame::Plane::kY]); + const uint8_t expected_value = values[plane - VideoFrame::Plane::kY]; for (int y = 0; y < frame.rows(plane); ++y) { const uint8_t* row = UNSAFE_TODO(frame.visible_data(plane) + y * frame.stride(plane));
diff --git a/components/viz/service/frame_sinks/video_capture/video_capture_overlay.cc b/components/viz/service/frame_sinks/video_capture/video_capture_overlay.cc index 2558644..4849f335 100644 --- a/components/viz/service/frame_sinks/video_capture/video_capture_overlay.cc +++ b/components/viz/service/frame_sinks/video_capture/video_capture_overlay.cc
@@ -10,8 +10,9 @@ #include <string> #include <utility> -#include "base/compiler_specific.h" +#include "base/containers/auto_spanification_helper.h" #include "base/containers/heap_array.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/numerics/safe_conversions.h" #include "base/strings/stringprintf.h" @@ -561,9 +562,10 @@ } else { int pos = 0; for (int y = 0; y < size_.height(); ++y) { - const uint32_t* src = scaled_image.getAddr32(0, y); + base::span<const uint32_t> src = + UNSAFE_SKBITMAP_GETADDR32(scaled_image, 0, y); for (int x = 0; x < size_.width(); ++x) { - const uint32_t pixel = UNSAFE_TODO(src[x]); + const uint32_t pixel = src[x]; alphas[pos] = ((pixel >> SK_A32_SHIFT) & 0xff) / 255.0f; colors[pos].SetPoint(((pixel >> SK_R32_SHIFT) & 0xff) / 255.0f, ((pixel >> SK_G32_SHIFT) & 0xff) / 255.0f,
diff --git a/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc b/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc index 91bdb5f..f5170bd4 100644 --- a/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc +++ b/components/viz/service/frame_sinks/video_capture/video_capture_overlay_unittest.cc
@@ -11,6 +11,7 @@ #include "base/command_line.h" #include "base/compiler_specific.h" +#include "base/containers/auto_spanification_helper.h" #include "base/containers/span.h" #include "base/files/file_path.h" #include "base/functional/bind.h" @@ -536,13 +537,13 @@ }; pos = 0; for (int row = 0; row < size.height(); ++row) { - uint32_t* out = canonical_bitmap.getAddr32(0, row); + base::span<uint32_t> out = + UNSAFE_SKBITMAP_GETADDR32(canonical_bitmap, 0, row); for (int col = 0; col < size.width(); ++col) { - UNSAFE_TODO(out[col]) = - ((UINT32_C(255) << SK_A32_SHIFT) | - (ToClamped255(colors[pos].x()) << SK_R32_SHIFT) | - (ToClamped255(colors[pos].y()) << SK_G32_SHIFT) | - (ToClamped255(colors[pos].z()) << SK_B32_SHIFT)); + out[col] = ((UINT32_C(255) << SK_A32_SHIFT) | + (ToClamped255(colors[pos].x()) << SK_R32_SHIFT) | + (ToClamped255(colors[pos].y()) << SK_G32_SHIFT) | + (ToClamped255(colors[pos].z()) << SK_B32_SHIFT)); ++pos; } } @@ -598,14 +599,14 @@ } void ExpectRendersAs(base::span<VideoCaptureOverlay::OnceRenderer> renderers, - const char* const* expected_files, - const std::size_t count, + base::span<const char* const> expected_files, const gfx::Size& video_frame_size) { - for (std::size_t i = 0; i < count; ++i) { + ASSERT_EQ(renderers.size(), expected_files.size()); + for (std::size_t i = 0; i < renderers.size(); ++i) { auto frame = CreateVideoFrame(video_frame_size); CHECK(renderers[i]); std::move(renderers[i]).Run(frame.get()); - UNSAFE_TODO(EXPECT_TRUE(FrameMatchesPNG(*frame, expected_files[i]))); + EXPECT_TRUE(FrameMatchesPNG(*frame, expected_files[i])); } } @@ -734,8 +735,7 @@ "overlay_moves_2_1.png", "overlay_moves_2_2.png", "overlay_moves_lr.png", }; - ExpectRendersAs(renderers, kGoldenFiles.data(), kGoldenFiles.size(), - video_frame_size); + ExpectRendersAs(renderers, kGoldenFiles, video_frame_size); } // Tests that the overlay will be partially rendered (clipped) when any part of @@ -803,8 +803,7 @@ "overlay_clips_ll.png", }; - ExpectRendersAs(renderers, kGoldenFiles.data(), kGoldenFiles.size(), - video_frame_size); + ExpectRendersAs(renderers, kGoldenFiles, video_frame_size); } TEST_P(VideoCaptureOverlayRenderTest, HandlesEmptySubRegion) { @@ -880,8 +879,7 @@ "overlay_clips_ll_subregion.png", }; - ExpectRendersAs(renderers, kGoldenFiles.data(), kGoldenFiles.size(), - compositor_frame_subrect.size()); + ExpectRendersAs(renderers, kGoldenFiles, compositor_frame_subrect.size()); } TEST_P(VideoCaptureOverlayRenderTest, ScalesToContentRegion) { @@ -934,7 +932,7 @@ "overlay_clips_ll_contentscaled.png", }; - ExpectRendersAs(renderers, kGoldenFiles.data(), kGoldenFiles.size(), + ExpectRendersAs(renderers, kGoldenFiles, gfx::Size(content_rect.right(), content_rect.bottom())); }
diff --git a/components/viz/test/gl_scaler_test_util.cc b/components/viz/test/gl_scaler_test_util.cc index 305914b9..035ef13 100644 --- a/components/viz/test/gl_scaler_test_util.cc +++ b/components/viz/test/gl_scaler_test_util.cc
@@ -11,6 +11,8 @@ #include "base/check_op.h" #include "base/compiler_specific.h" +#include "base/containers/auto_spanification_helper.h" +#include "base/containers/span.h" #include "base/notreached.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkImageInfo.h" @@ -151,29 +153,31 @@ switch (pattern) { case HORIZONTAL_STRIPES: for (int y = 0; y < size.height(); ++y) { - uint32_t* const pixels = result.getAddr32(0, y); + const base::span<uint32_t> pixels = + UNSAFE_SKBITMAP_GETADDR32(result, 0, y); const uint32_t stripe_rgba = cycle_as_rgba[y % cycle_as_rgba.size()]; for (int x = 0; x < size.width(); ++x) { - UNSAFE_TODO(pixels[x]) = stripe_rgba; + pixels[x] = stripe_rgba; } } break; case VERTICAL_STRIPES: for (int y = 0; y < size.height(); ++y) { - uint32_t* const pixels = result.getAddr32(0, y); + const base::span<uint32_t> pixels = + UNSAFE_SKBITMAP_GETADDR32(result, 0, y); for (int x = 0; x < size.width(); ++x) { - UNSAFE_TODO(pixels[x]) = cycle_as_rgba[x % cycle_as_rgba.size()]; + pixels[x] = cycle_as_rgba[x % cycle_as_rgba.size()]; } } break; case STAGGERED: for (int y = 0; y < size.height(); ++y) { - uint32_t* const pixels = result.getAddr32(0, y); + const base::span<uint32_t> pixels = + UNSAFE_SKBITMAP_GETADDR32(result, 0, y); for (int x = 0; x < size.width(); ++x) { - UNSAFE_TODO(pixels[x]) = - cycle_as_rgba[(x + y) % cycle_as_rgba.size()]; + pixels[x] = cycle_as_rgba[(x + y) % cycle_as_rgba.size()]; } } break; @@ -202,19 +206,18 @@ // Loop, transforming one row of pixels at a time. std::vector<gfx::ColorTransform::TriStim> stims(image->width()); for (int y = 0; y < image->height(); ++y) { - uint32_t* const pixels = image->getAddr32(0, y); + const base::span<uint32_t> pixels = UNSAFE_SKBITMAP_GETADDR32(image, 0, y); for (int x = 0; x < image->width(); ++x) { - stims[x].set_x(((UNSAFE_TODO(pixels[x]) >> kRedShift) & 0xff) / 255.0f); - stims[x].set_y(((UNSAFE_TODO(pixels[x]) >> kGreenShift) & 0xff) / 255.0f); - stims[x].set_z(((UNSAFE_TODO(pixels[x]) >> kBlueShift) & 0xff) / 255.0f); + stims[x].set_x(((pixels[x] >> kRedShift) & 0xff) / 255.0f); + stims[x].set_y(((pixels[x] >> kGreenShift) & 0xff) / 255.0f); + stims[x].set_z(((pixels[x] >> kBlueShift) & 0xff) / 255.0f); } transform->Transform(stims.data(), stims.size()); for (int x = 0; x < image->width(); ++x) { - UNSAFE_TODO(pixels[x]) = - ((ToClamped255(stims[x].x()) << kRedShift) | - (ToClamped255(stims[x].y()) << kGreenShift) | - (ToClamped255(stims[x].z()) << kBlueShift) | - (((UNSAFE_TODO(pixels[x]) >> kAlphaShift) & 0xff) << kAlphaShift)); + pixels[x] = ((ToClamped255(stims[x].x()) << kRedShift) | + (ToClamped255(stims[x].y()) << kGreenShift) | + (ToClamped255(stims[x].z()) << kBlueShift) | + (((pixels[x] >> kAlphaShift) & 0xff) << kAlphaShift)); } } } @@ -235,13 +238,12 @@ // static void GLScalerTestUtil::SwizzleBitmap(SkBitmap* image) { for (int y = 0; y < image->height(); ++y) { - uint32_t* const pixels = image->getAddr32(0, y); + const base::span<uint32_t> pixels = UNSAFE_SKBITMAP_GETADDR32(image, 0, y); for (int x = 0; x < image->width(); ++x) { - UNSAFE_TODO(pixels[x]) = - ((((UNSAFE_TODO(pixels[x]) >> kBlueShift) & 0xff) << kRedShift) | - (((UNSAFE_TODO(pixels[x]) >> kGreenShift) & 0xff) << kGreenShift) | - (((UNSAFE_TODO(pixels[x]) >> kRedShift) & 0xff) << kBlueShift) | - (((UNSAFE_TODO(pixels[x]) >> kAlphaShift) & 0xff) << kAlphaShift)); + pixels[x] = ((((pixels[x] >> kBlueShift) & 0xff) << kRedShift) | + (((pixels[x] >> kGreenShift) & 0xff) << kGreenShift) | + (((pixels[x] >> kRedShift) & 0xff) << kBlueShift) | + (((pixels[x] >> kAlphaShift) & 0xff) << kAlphaShift)); } } } @@ -261,16 +263,16 @@ }; const int shift = kShiftForChannel[channel]; for (int y = 0; y < result.height(); ++y) { - const uint32_t* const src = source.getAddr32(0, y); - uint32_t* const dst = result.getAddr32(0, y); + const base::span<const uint32_t> src = + UNSAFE_SKBITMAP_GETADDR32(source, 0, y); + const base::span<uint32_t> dst = UNSAFE_SKBITMAP_GETADDR32(result, 0, y); for (int x = 0; x < result.width(); ++x) { // (src[0..3]) (dst) // RGBA RGBA RGBA RGBA --> RRRR (if channel is 0) - UNSAFE_TODO(dst[x]) = - ((((UNSAFE_TODO(src[x * 4 + 0]) >> shift) & 0xff) << kRedShift) | - (((UNSAFE_TODO(src[x * 4 + 1]) >> shift) & 0xff) << kGreenShift) | - (((UNSAFE_TODO(src[x * 4 + 2]) >> shift) & 0xff) << kBlueShift) | - (((UNSAFE_TODO(src[x * 4 + 3]) >> shift) & 0xff) << kAlphaShift)); + dst[x] = ((((src[x * 4 + 0] >> shift) & 0xff) << kRedShift) | + (((src[x * 4 + 1] >> shift) & 0xff) << kGreenShift) | + (((src[x * 4 + 2] >> shift) & 0xff) << kBlueShift) | + (((src[x * 4 + 3] >> shift) & 0xff) << kAlphaShift)); } } return result; @@ -310,20 +312,20 @@ // Iterate over the pixels of |out|, sampling each of the 4 components of each // of |plane|'s pixels. for (int y = 0; y < out->height(); ++y) { - const uint32_t* const src = plane.getAddr32(0, y / row_sampling_ratio); - uint32_t* const dst = out->getAddr32(0, y); + const base::span<const uint32_t> src = + UNSAFE_SKBITMAP_GETADDR32(plane, 0, y / row_sampling_ratio); + const base::span<uint32_t> dst = UNSAFE_SKBITMAP_GETADDR32(out, 0, y); for (int x = 0; x < out->width(); ++x) { // Zero-out the existing byte (e.g., if channel==1, then "RGBA" → "R0BA"). - UNSAFE_TODO(dst[x]) &= output_retain_mask; + dst[x] &= output_retain_mask; // From |src|, grab one of "XYZW". Then, copy it to the target byte in // |dst| (e.g., if x_src_ch=3, then grab "W" from |src|, and |dst| changes // from "R0BA" to "RWBA"). const int x_src = x / col_sampling_ratio; const int x_src_ch = (x / ch_sampling_ratio) % 4; - UNSAFE_TODO(dst[x]) |= - ((UNSAFE_TODO(src[x_src]) >> kShiftForChannel[x_src_ch]) & 0xff) - << output_shift; + dst[x] |= ((src[x_src] >> kShiftForChannel[x_src_ch]) & 0xff) + << output_shift; } } } @@ -371,11 +373,12 @@ // Iterate over all the pixels of |out|, calculate where the data for that // said pixel is. for (int y = 0; y < out->height(); ++y) { - const uint32_t* const src = plane.getAddr32(0, y / row_sampling_ratio); - uint32_t* const dst = out->getAddr32(0, y); + const base::span<const uint32_t> src = + UNSAFE_SKBITMAP_GETADDR32(plane, 0, y / row_sampling_ratio); + const base::span<uint32_t> dst = UNSAFE_SKBITMAP_GETADDR32(out, 0, y); for (int x = 0; x < out->width(); ++x) { // Zero-out the existing byte (e.g., "RGBA" → "R00A"). - UNSAFE_TODO(dst[x]) &= zero_green_blue_mask; + dst[x] &= zero_green_blue_mask; // Find which half-texel to look at: const int src_half_texel = x / col_sampling_ratio; @@ -385,14 +388,10 @@ const int src_channel = 2 * (src_half_texel % 2); // Grab the 2 consecutive channels, starting at |src_channel|: - UNSAFE_TODO(dst[x]) |= - ((UNSAFE_TODO(src[src_texel]) >> kShiftForChannel[src_channel]) & - 0xff) - << kGreenShift; - UNSAFE_TODO(dst[x]) |= - ((UNSAFE_TODO(src[src_texel]) >> kShiftForChannel[src_channel + 1]) & - 0xff) - << kBlueShift; + dst[x] |= ((src[src_texel] >> kShiftForChannel[src_channel]) & 0xff) + << kGreenShift; + dst[x] |= ((src[src_texel] >> kShiftForChannel[src_channel + 1]) & 0xff) + << kBlueShift; } } }
diff --git a/components/viz/test/test_raster_interface.h b/components/viz/test/test_raster_interface.h index 136976e2..fcdb33815 100644 --- a/components/viz/test/test_raster_interface.h +++ b/components/viz/test/test_raster_interface.h
@@ -117,7 +117,7 @@ const gfx::Point& source_starting_point, const SkImageInfo& dst_info, GLuint dst_row_bytes, - unsigned char* out, + base::span<uint8_t> out, base::OnceCallback<void(bool)> readback_done) override {} void ReadbackYUVPixelsAsync( const gpu::Mailbox& source_mailbox, @@ -126,11 +126,11 @@ const gfx::Rect& output_rect, bool vertically_flip_texture, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void()> release_mailbox, base::OnceCallback<void(bool)> readback_done) override {}
diff --git a/components/webauthn/json/value_conversions_unittest.cc b/components/webauthn/json/value_conversions_unittest.cc index 681bf0c..d77e261e 100644 --- a/components/webauthn/json/value_conversions_unittest.cc +++ b/components/webauthn/json/value_conversions_unittest.cc
@@ -15,6 +15,8 @@ #include <string_view> #include <vector> +#include "base/containers/span.h" +#include "base/containers/to_vector.h" #include "base/json/json_string_value_serializer.h" #include "base/time/time.h" #include "build/build_config.h" @@ -74,8 +76,7 @@ } std::vector<uint8_t> ToByteVector(std::string_view in) { - const uint8_t* in_ptr = reinterpret_cast<const uint8_t*>(in.data()); - return std::vector<uint8_t>(in_ptr, in_ptr + in.size()); + return base::ToVector(base::as_byte_span(in)); } constexpr char kAppId[] = "https://example.test/appid.json";
diff --git a/content/browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc b/content/browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc index e341261..b44dab3 100644 --- a/content/browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc +++ b/content/browser/accessibility/ax_platform_node_textprovider_win_browsertest.cc
@@ -2,14 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/342213636): Remove this and spanify to fix the errors. -#pragma allow_unsafe_buffers -#endif - #include "ui/accessibility/platform/ax_platform_node_textprovider_win.h" #include <optional> +#include <vector> #include "base/strings/escape.h" #include "base/strings/utf_string_conversions.h" @@ -36,20 +32,6 @@ namespace content { -#define ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(safearray, expected_size) \ - { \ - EXPECT_EQ(sizeof(ITextRangeProvider*), ::SafeArrayGetElemsize(safearray)); \ - ASSERT_EQ(1u, SafeArrayGetDim(safearray)); \ - LONG array_lower_bound; \ - ASSERT_HRESULT_SUCCEEDED( \ - SafeArrayGetLBound(safearray, 1, &array_lower_bound)); \ - LONG array_upper_bound; \ - ASSERT_HRESULT_SUCCEEDED( \ - SafeArrayGetUBound(safearray, 1, &array_upper_bound)); \ - size_t count = array_upper_bound - array_lower_bound + 1; \ - ASSERT_EQ(expected_size, count); \ - } - #define EXPECT_UIA_TEXTRANGE_EQ(provider, expected_content) \ { \ base::win::ScopedBstr provider_content; \ @@ -135,6 +117,25 @@ ASSERT_NE(nullptr, text_provider.Get()); } + std::vector<ComPtr<ITextRangeProvider>> GetTextRangeProvidersFromTextProvider( + ComPtr<ITextProvider>& text_provider) { + base::win::ScopedSafearray text_provider_ranges; + EXPECT_HRESULT_SUCCEEDED( + text_provider->GetVisibleRanges(text_provider_ranges.Receive())); + + auto lock_scope = + text_provider_ranges.CreateLockScope<VT_UNKNOWN>().value(); + + std::vector<ComPtr<ITextRangeProvider>> text_range_providers; + for (IUnknown* unknown : lock_scope) { + ComPtr<ITextRangeProvider> text_range_provider; + EXPECT_HRESULT_SUCCEEDED( + unknown->QueryInterface(IID_PPV_ARGS(&text_range_provider))); + text_range_providers.push_back(text_range_provider); + } + return text_range_providers; + } + private: ui::BrowserAccessibility* FindNodeInSubtree( ui::BrowserAccessibility& node, @@ -194,20 +195,12 @@ ComPtr<ITextProvider> text_provider; GetTextProviderFromTextNode(text_provider, node); - base::win::ScopedSafearray text_provider_ranges; - EXPECT_HRESULT_SUCCEEDED( - text_provider->GetVisibleRanges(text_provider_ranges.Receive())); - ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(text_provider_ranges.Get(), 2U); + std::vector<ComPtr<ITextRangeProvider>> text_range_providers = + GetTextRangeProvidersFromTextProvider(text_provider); + ASSERT_EQ(2u, text_range_providers.size()); - ITextRangeProvider** array_data; - ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( - text_provider_ranges.Get(), reinterpret_cast<void**>(&array_data))); - - EXPECT_UIA_TEXTRANGE_EQ(array_data[0], L"AAA BBB"); - EXPECT_UIA_TEXTRANGE_EQ(array_data[1], L"CCCCCC"); - - ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(text_provider_ranges.Get())); - text_provider_ranges.Reset(); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[0].Get(), L"AAA BBB"); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[1].Get(), L"CCCCCC"); } IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextProviderWinBrowserTest, @@ -231,21 +224,13 @@ ComPtr<ITextProvider> text_provider; GetTextProviderFromTextNode(text_provider, node); - base::win::ScopedSafearray text_provider_ranges; - EXPECT_HRESULT_SUCCEEDED( - text_provider->GetVisibleRanges(text_provider_ranges.Receive())); - ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(text_provider_ranges.Get(), 3U); + std::vector<ComPtr<ITextRangeProvider>> text_range_providers = + GetTextRangeProvidersFromTextProvider(text_provider); + ASSERT_EQ(3u, text_range_providers.size()); - ITextRangeProvider** array_data; - ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( - text_provider_ranges.Get(), reinterpret_cast<void**>(&array_data))); - - EXPECT_UIA_TEXTRANGE_EQ(array_data[0], L"one two"); - EXPECT_UIA_TEXTRANGE_EQ(array_data[1], L"three four"); - EXPECT_UIA_TEXTRANGE_EQ(array_data[2], L"five six"); - - ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(text_provider_ranges.Get())); - text_provider_ranges.Reset(); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[0].Get(), L"one two"); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[1].Get(), L"three four"); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[2].Get(), L"five six"); } IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextProviderWinBrowserTest, @@ -269,43 +254,35 @@ ComPtr<ITextProvider> text_provider; GetTextProviderFromTextNode(text_provider, node); - base::win::ScopedSafearray text_provider_ranges; - EXPECT_HRESULT_SUCCEEDED( - text_provider->GetVisibleRanges(text_provider_ranges.Receive())); - ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(text_provider_ranges.Get(), 3U); + std::vector<ComPtr<ITextRangeProvider>> text_range_providers = + GetTextRangeProvidersFromTextProvider(text_provider); + ASSERT_EQ(3u, text_range_providers.size()); - ITextRangeProvider** array_data; - ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( - text_provider_ranges.Get(), reinterpret_cast<void**>(&array_data))); - - EXPECT_UIA_TEXTRANGE_EQ(array_data[0], L"one two"); - EXPECT_UIA_TEXTRANGE_EQ(array_data[1], L"three four"); - EXPECT_UIA_TEXTRANGE_EQ(array_data[2], L"five six"); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[0].Get(), L"one two"); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[1].Get(), L"three four"); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[2].Get(), L"five six"); { base::win::ScopedBstr find_string(L"two"); Microsoft::WRL::ComPtr<ITextRangeProvider> text_range_provider_found; - EXPECT_HRESULT_SUCCEEDED(array_data[0]->FindText( + EXPECT_HRESULT_SUCCEEDED(text_range_providers[0]->FindText( find_string.Get(), false, false, &text_range_provider_found)); ASSERT_TRUE(text_range_provider_found.Get()); } { base::win::ScopedBstr find_string(L"three"); Microsoft::WRL::ComPtr<ITextRangeProvider> text_range_provider_found; - EXPECT_HRESULT_SUCCEEDED(array_data[1]->FindText( + EXPECT_HRESULT_SUCCEEDED(text_range_providers[1]->FindText( find_string.Get(), false, false, &text_range_provider_found)); ASSERT_TRUE(text_range_provider_found.Get()); } { base::win::ScopedBstr find_string(L"five six"); Microsoft::WRL::ComPtr<ITextRangeProvider> text_range_provider_found; - EXPECT_HRESULT_SUCCEEDED(array_data[2]->FindText( + EXPECT_HRESULT_SUCCEEDED(text_range_providers[2]->FindText( find_string.Get(), false, false, &text_range_provider_found)); ASSERT_TRUE(text_range_provider_found.Get()); } - - ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(text_provider_ranges.Get())); - text_provider_ranges.Reset(); } IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextProviderWinBrowserTest, @@ -329,14 +306,9 @@ ComPtr<ITextProvider> text_provider; GetTextProviderFromTextNode(text_provider, gc_node); - base::win::ScopedSafearray text_provider_ranges; - EXPECT_HRESULT_SUCCEEDED( - text_provider->GetVisibleRanges(text_provider_ranges.Receive())); - ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(text_provider_ranges.Get(), 1U); - - ITextRangeProvider** array_data; - ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( - text_provider_ranges.Get(), reinterpret_cast<void**>(&array_data))); + std::vector<ComPtr<ITextRangeProvider>> text_range_providers = + GetTextRangeProvidersFromTextProvider(text_provider); + ASSERT_EQ(1u, text_range_providers.size()); // If the `embedded_object_character` was being exposed, the search for this // string would fail. @@ -346,11 +318,9 @@ // mess up the text range. Filing a bug for `GetText`. CRBug: 1445692 base::win::ScopedBstr find_string(L"hello"); Microsoft::WRL::ComPtr<ITextRangeProvider> text_range_provider_found; - EXPECT_HRESULT_SUCCEEDED(array_data[0]->FindText( + EXPECT_HRESULT_SUCCEEDED(text_range_providers[0]->FindText( find_string.Get(), false, false, &text_range_provider_found)); ASSERT_TRUE(text_range_provider_found.Get()); - ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(text_provider_ranges.Get())); - text_provider_ranges.Reset(); } IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextProviderWinBrowserTest, @@ -374,18 +344,11 @@ ComPtr<ITextProvider> text_provider; GetTextProviderFromTextNode(text_provider, gc_node); - base::win::ScopedSafearray text_provider_ranges; - EXPECT_HRESULT_SUCCEEDED( - text_provider->GetVisibleRanges(text_provider_ranges.Receive())); - ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(text_provider_ranges.Get(), 1U); + std::vector<ComPtr<ITextRangeProvider>> text_range_providers = + GetTextRangeProvidersFromTextProvider(text_provider); + ASSERT_EQ(1u, text_range_providers.size()); - ITextRangeProvider** array_data; - ASSERT_HRESULT_SUCCEEDED(::SafeArrayAccessData( - text_provider_ranges.Get(), reinterpret_cast<void**>(&array_data))); - - EXPECT_UIA_TEXTRANGE_EQ(array_data[0], L"hello"); - ASSERT_HRESULT_SUCCEEDED(::SafeArrayUnaccessData(text_provider_ranges.Get())); - text_provider_ranges.Reset(); + EXPECT_UIA_TEXTRANGE_EQ(text_range_providers[0].Get(), L"hello"); } IN_PROC_BROWSER_TEST_F(AXPlatformNodeTextProviderWinBrowserTest, @@ -408,7 +371,7 @@ base::win::ScopedSafearray visible_ranges; EXPECT_HRESULT_SUCCEEDED( text_provider->GetVisibleRanges(visible_ranges.Receive())); - ASSERT_UIA_SAFEARRAY_OF_TEXTRANGEPROVIDER(visible_ranges.Get(), 1U); + ASSERT_EQ(1u, visible_ranges.GetCount()); LONG index = 0; ComPtr<ITextRangeProvider> text_range_provider;
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index fed11cd..d4d9a19 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -933,10 +933,7 @@ return; } - // In the case of accessible name from kAttribute, the aria-label will be - // mapped to one of the container title, content description or supplemental - // description, we should exclude aria-label from mapping to text. - if (!IsAccessibleNameFromAttribute() && !is_non_atomic_text_field) { + if (AccessibleNameMapsToTextProperty() && !is_non_atomic_text_field) { text = GetNameAsString16(); } if (ui::IsRangeValueSupported(GetRole())) { @@ -1072,11 +1069,8 @@ // If we're returning the value as the main text, the name needs to be // part of the hint. if (ShouldExposeValueAsName(GetValueForControl())) { - // In the case of accessible name from kAttribute, the name will be - // mapped to one of the container title, content description or supplemental - // description, we should exclude name from mapping to hint. std::u16string name = - IsAccessibleNameFromAttribute() ? u"" : GetNameAsString16(); + AccessibleNameMapsToTextProperty() ? GetNameAsString16() : u""; if (!name.empty()) { strings.push_back(name); } @@ -1165,7 +1159,9 @@ std::u16string BrowserAccessibilityAndroid::GetContainerTitle() const { // Accessible name from kAttribute, is Android container role. - if (IsAccessibleNameFromAttribute() && ui::IsContainerOnAndroid(GetRole())) { + if (HasIntAttribute(ax::mojom::IntAttribute::kNameFrom) && + GetNameFrom() == ax::mojom::NameFrom::kAttribute && + ui::IsContainerOnAndroid(GetRole())) { return GetNameAsString16(); } return u""; @@ -1174,7 +1170,11 @@ std::u16string BrowserAccessibilityAndroid::GetContentDescription() const { // Accessible name from kAttribute, is not Android container role, supports // naming from child content. - if (IsAccessibleNameFromAttribute() && !ui::IsContainerOnAndroid(GetRole()) && + if (base::FeatureList::IsEnabled( + features::kAccessibilityPopulateSupplementalDescriptionApi) && + HasIntAttribute(ax::mojom::IntAttribute::kNameFrom) && + GetNameFrom() == ax::mojom::NameFrom::kAttribute && + !ui::IsContainerOnAndroid(GetRole()) && ui::SupportsNamingWithChildContent(GetRole())) { return GetNameAsString16(); } @@ -1184,31 +1184,73 @@ std::u16string BrowserAccessibilityAndroid::GetSupplementalDescription() const { // Accessible name from kAttribute, is not Android container role, does not // support naming from child content. - if (IsAccessibleNameFromAttribute() && !ui::IsContainerOnAndroid(GetRole()) && + if (base::FeatureList::IsEnabled( + features::kAccessibilityPopulateSupplementalDescriptionApi) && + HasIntAttribute(ax::mojom::IntAttribute::kNameFrom) && + GetNameFrom() == ax::mojom::NameFrom::kAttribute && + !ui::IsContainerOnAndroid(GetRole()) && !ui::SupportsNamingWithChildContent(GetRole())) { return GetNameAsString16(); } return u""; } -bool BrowserAccessibilityAndroid::IsAccessibleNameFromAttribute() const { - return base::FeatureList::IsEnabled( - features::kAccessibilityPopulateSupplementalDescriptionApi) && - HasIntAttribute(ax::mojom::IntAttribute::kNameFrom) && - GetNameFrom() == ax::mojom::NameFrom::kAttribute; +bool BrowserAccessibilityAndroid::AccessibleNameMapsToTextProperty() const { + // 1. If the accessible name comes from the node's content (e.g., inner text) + // and not a specific attribute (like aria-label), it's considered part of + // the main text. + if (!HasIntAttribute(ax::mojom::IntAttribute::kNameFrom) || + GetNameFrom() != ax::mojom::NameFrom::kAttribute) { + return true; + } + + // 2. If the node gets its name from a container's title (e.g., a <figure> + // with a <figcaption>), the name is considered a title, not regular text. + if (!GetContainerTitle().empty()) { + return false; + } + + // 3. The following checks depend on a feature flag. If it's disabled, we + // revert to the default behavior of mapping to the text property. + if (!base::FeatureList::IsEnabled( + features::kAccessibilityPopulateSupplementalDescriptionApi)) { + return true; + } + + // 4. At this point, the name is from an attribute (like aria-label), but it + // should only be mapped to the text property if there is no other + // descriptive content (like a content description or supplemental + // description) available to use instead. + return GetContentDescription().empty() && + GetSupplementalDescription().empty(); } std::u16string BrowserAccessibilityAndroid::GetAccessibleNameUTF16() const { + // 1. The primary source for an accessible name is the direct text content. + // If it's available, we use it immediately. std::u16string name = GetTextContentUTF16(); - if (name.empty()) { - name = GetContainerTitle(); + if (!name.empty()) { + return name; } + + // 2. If text content is empty, check if the name is *supposed* to map to the + // text property anyway. If so, it means the accessible name is intentionally + // empty, and we should not check any fallback sources. + if (AccessibleNameMapsToTextProperty()) { + return {}; // Return an empty string. + } + + // 3. If the name doesn't map to the text property (e.g., it comes from an + // attribute like `aria-label`), we check a chain of fallback sources in + // order of priority. + name = GetContainerTitle(); if (name.empty()) { name = GetContentDescription(); } if (name.empty()) { name = GetSupplementalDescription(); } + return name; }
diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h index b86b534..fbcacffc 100644 --- a/content/browser/accessibility/browser_accessibility_android.h +++ b/content/browser/accessibility/browser_accessibility_android.h
@@ -298,9 +298,9 @@ bool HasOnlyTextAndImageChildren() const; bool HasListMarkerChild() const; - // Returns true if the accessible name source (kNameFrom) comes from - // kAttribute. - bool IsAccessibleNameFromAttribute() const; + // Returns true if the accessible name should be mapped to android's text + // property. + bool AccessibleNameMapsToTextProperty() const; // This method determines if a node should expose its value as a name, which // is placed in the Android API's "text" attribute. For controls that can take
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index c4d4a29..d25680d 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -547,6 +547,7 @@ AccessibilityCSSInlinePositionRelative) { RunCSSTest(FILE_PATH_LITERAL("inline-position-relative.html")); } + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCSSIframeHidden) { RunCSSTest(FILE_PATH_LITERAL("iframe-hidden.html")); @@ -1861,6 +1862,7 @@ AccessibilityAriaSetCountsWithHiddenItems) { RunAriaTest(FILE_PATH_LITERAL("aria-set-counts-with-hidden-items.html")); } + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAriaSlider) { RunAriaTest(FILE_PATH_LITERAL("aria-slider.html")); } @@ -2584,6 +2586,7 @@ AccessibilityCustomElementWithAriaOwnsInside) { RunHtmlTest(FILE_PATH_LITERAL("custom-element-with-aria-owns-inside.html")); } + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityCustomElementWithAriaOwnsInsideSlot) { RunHtmlTest( @@ -2846,6 +2849,7 @@ DISABLED_AccessibilityIframeCoordinatesCrossProcess) { RunHtmlTest(FILE_PATH_LITERAL("iframe-coordinates-cross-process.html")); } + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityIframePadding) { RunHtmlTest(FILE_PATH_LITERAL("iframe-padding.html")); } @@ -3658,6 +3662,7 @@ AccessibilityPopoverRichHint) { RunPopoverHintTest(FILE_PATH_LITERAL("popover-rich-hint.html")); } + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityPre) { RunHtmlTest(FILE_PATH_LITERAL("pre.html")); } @@ -3792,6 +3797,7 @@ MAYBE_AccessibilitySelectOpen) { RunHtmlTest(FILE_PATH_LITERAL("select-open.html")); } + IN_PROC_BROWSER_TEST_P(CustomizableSelectDisabledDumpAccessibilityTreeTest, MAYBE_AccessibilitySelectOpen) { RunHtmlTest(FILE_PATH_LITERAL("select-open.html")); @@ -3810,6 +3816,7 @@ AccessibilitySelectFollowsFocus) { RunHtmlTest(FILE_PATH_LITERAL("select-follows-focus.html")); } + IN_PROC_BROWSER_TEST_P(CustomizableSelectDisabledDumpAccessibilityTreeTest, AccessibilitySelectFollowsFocus) { RunHtmlTest(FILE_PATH_LITERAL("select-follows-focus.html")); @@ -3820,6 +3827,7 @@ RunHtmlTest( FILE_PATH_LITERAL("select-follows-focus-aria-selected-false.html")); } + IN_PROC_BROWSER_TEST_P(CustomizableSelectDisabledDumpAccessibilityTreeTest, AccessibilitySelectFollowsFocusAriaSelectedFalse) { RunHtmlTest( @@ -3830,6 +3838,7 @@ AccessibilitySelectFollowsFocusMultiselect) { RunHtmlTest(FILE_PATH_LITERAL("select-follows-focus-multiselect.html")); } + IN_PROC_BROWSER_TEST_P(CustomizableSelectDisabledDumpAccessibilityTreeTest, AccessibilitySelectFollowsFocusMultiselect) { RunHtmlTest(FILE_PATH_LITERAL("select-follows-focus-multiselect.html")); @@ -4648,10 +4657,130 @@ RunHtmlTest(FILE_PATH_LITERAL("svg-and-math-elements.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLAction) { + RunMathMLTest(FILE_PATH_LITERAL("maction.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLAnnotation) { + RunMathMLTest(FILE_PATH_LITERAL("annotation.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLAnnotationXML) { + RunMathMLTest(FILE_PATH_LITERAL("annotation-xml.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLError) { + RunMathMLTest(FILE_PATH_LITERAL("merror.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLFraction) { + RunMathMLTest(FILE_PATH_LITERAL("mfrac.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLIdentifier) { + RunMathMLTest(FILE_PATH_LITERAL("mi.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLMath) { + RunMathMLTest(FILE_PATH_LITERAL("math.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLMultiscripts) { + RunMathMLTest(FILE_PATH_LITERAL("mmultiscripts.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLNone) { + RunMathMLTest(FILE_PATH_LITERAL("none.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLNumber) { + RunMathMLTest(FILE_PATH_LITERAL("mn.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLOperator) { + RunMathMLTest(FILE_PATH_LITERAL("mo.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLOver) { + RunMathMLTest(FILE_PATH_LITERAL("mover.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLPadded) { + RunMathMLTest(FILE_PATH_LITERAL("mpadded.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLPhantom) { + RunMathMLTest(FILE_PATH_LITERAL("mphantom.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLPrescripts) { + RunMathMLTest(FILE_PATH_LITERAL("mprescripts.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLRoot) { + RunMathMLTest(FILE_PATH_LITERAL("mroot.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLRow) { + RunMathMLTest(FILE_PATH_LITERAL("mrow.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLSemantics) { + RunMathMLTest(FILE_PATH_LITERAL("semantics.html")); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLSpace) { RunMathMLTest(FILE_PATH_LITERAL("mspace.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLSquareRoot) { + RunMathMLTest(FILE_PATH_LITERAL("msqrt.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLStringLiteral) { + RunMathMLTest(FILE_PATH_LITERAL("ms.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLStyle) { + RunMathMLTest(FILE_PATH_LITERAL("mstyle.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLSub) { + RunMathMLTest(FILE_PATH_LITERAL("msub.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLSubSup) { + RunMathMLTest(FILE_PATH_LITERAL("msubsup.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLSup) { + RunMathMLTest(FILE_PATH_LITERAL("msup.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLTable) { + RunMathMLTest(FILE_PATH_LITERAL("mtable.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLTableCell) { + RunMathMLTest(FILE_PATH_LITERAL("mtd.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLTableRow) { + RunMathMLTest(FILE_PATH_LITERAL("mtr.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLText) { + RunMathMLTest(FILE_PATH_LITERAL("mtext.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLUnder) { + RunMathMLTest(FILE_PATH_LITERAL("munder.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLUnderOver) { + RunMathMLTest(FILE_PATH_LITERAL("munderover.html")); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, MathMLUnknown) { RunMathMLTest(FILE_PATH_LITERAL("unknown.html")); }
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index 07bd81d..6ae29247 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -2133,6 +2133,14 @@ : protocol::Audits::AffectedRequest::Create() .SetUrl(issue_details->request->url) .Build(); + auto source_code_location = + issue_details->sourceCodeLocation.is_null() + ? nullptr + : protocol::Audits::SourceCodeLocation::Create() + .SetUrl(issue_details->sourceCodeLocation->url.value()) + .SetLineNumber(issue_details->sourceCodeLocation->line) + .SetColumnNumber(issue_details->sourceCodeLocation->column) + .Build(); std::string issue_type; switch (issue_details->type) { case blink::mojom::UserReidentificationIssueType::kBlockedFrameNavigation: @@ -2143,6 +2151,10 @@ issue_type = protocol::Audits::UserReidentificationIssueTypeEnum:: BlockedSubresource; break; + case blink::mojom::UserReidentificationIssueType::kNoisedCanvasReadback: + issue_type = protocol::Audits::UserReidentificationIssueTypeEnum:: + NoisedCanvasReadback; + break; default: NOTREACHED(); }
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc index d634ef67..9280fd9d 100644 --- a/content/browser/download/save_package.cc +++ b/content/browser/download/save_package.cc
@@ -89,11 +89,13 @@ // name-conflict files which has same base file name. const int32_t kMaxFileOrdinalNumber = 9999; +#if BUILDFLAG(IS_WIN) // Maximum length for file path. Since Windows have MAX_PATH limitation for // file path, we need to make sure length of file path of every saved file -// is less than MAX_PATH -#if BUILDFLAG(IS_WIN) +// is less than MAX_PATH. const uint32_t kMaxFilePathLength = MAX_PATH - 1; +// Maximum component length for NTFS/FAT32 compatibility. +const uint32_t kMaxComponentLength = 255; #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) const uint32_t kMaxFilePathLength = PATH_MAX - 1; #endif @@ -405,18 +407,45 @@ } } -// On POSIX, the length of |base_name| + |file_name_ext| is further -// restricted by NAME_MAX. The maximum allowed path looks like: -// '/path/to/save_dir' + '/' + NAME_MAX. -uint32_t SavePackage::GetMaxPathLengthForDirectory( +// static +uint32_t SavePackage::ComputeMaxPathLengthForDirectory( const base::FilePath& base_dir) { + // Query runtime filesystem constraints. + int runtime_max = base::GetMaximumPathComponentLength(base_dir); + uint32_t max_component_length; + + if (runtime_max > 0) { + max_component_length = static_cast<uint32_t>(runtime_max); + } else { + // Fall back to platform defaults if query fails. #if BUILDFLAG(IS_WIN) - return kMaxFilePathLength; + // NTFS/FAT32 compatible. + max_component_length = kMaxComponentLength; #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) + // Standard POSIX limit. + max_component_length = NAME_MAX; +#endif + } + + return std::min(kMaxFilePathLength, + static_cast<uint32_t>(base_dir.value().length() + 1 + + max_component_length)); +} + +uint32_t SavePackage::GetMaxPathLengthForDirectory() const { + // Use platform defaults to avoid blocking I/O during save operations. + uint32_t max_component_length; + +#if BUILDFLAG(IS_WIN) + max_component_length = kMaxComponentLength; +#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) + max_component_length = NAME_MAX; +#endif + return std::min( kMaxFilePathLength, - static_cast<uint32_t>(base_dir.value().length()) + NAME_MAX + 1); -#endif + static_cast<uint32_t>(saved_main_directory_path_.value().length() + 1 + + max_component_length)); } // static @@ -437,9 +466,33 @@ if (static_cast<int>(base_name->length()) <= available_length) return true; - // Limited room. Truncate |base_name| to fit. + // Limited room. Truncate |base_name| to fit, respecting character boundaries. if (available_length > 0) { - *base_name = base_name->substr(0, available_length); +#if BUILDFLAG(IS_WIN) + // On Windows, FilePath uses UTF-16, so truncate at UTF-16 code unit + // boundaries. + if (static_cast<size_t>(available_length) < base_name->length()) { + *base_name = base_name->substr(0, available_length); + } +#else + // On POSIX, FilePath uses native encoding (usually UTF-8) + // Convert to UTF-8, truncate safely, then convert back. + std::string utf8_name = base::FilePath(*base_name).AsUTF8Unsafe(); + std::string truncated_utf8; + base::TruncateUTF8ToByteSize(utf8_name, available_length, &truncated_utf8); + + // Convert back to native string, but handle potential encoding issues. + base::FilePath temp_path = base::FilePath::FromUTF8Unsafe(truncated_utf8); + *base_name = temp_path.value(); + + // Double-check that the result fits - if conversion caused expansion, + // retry. + if (static_cast<int>(base_name->length()) > available_length) { + // If UTF-8 conversion caused size increase, use simple byte truncation + // as a last resort (this should be rare). + *base_name = base_name->substr(0, available_length); + } +#endif return true; } @@ -477,8 +530,8 @@ file_path.RemoveExtension().BaseName().value(); base::FilePath::StringType file_name_ext = file_path.Extension(); - // Need to make sure the suggested file name is not too long. - uint32_t max_path = GetMaxPathLengthForDirectory(saved_main_directory_path_); + // Get path length constraints for truncation. + uint32_t max_path = GetMaxPathLengthForDirectory(); // Get safe pure file name. if (!TruncateBaseNameToFitPathConstraints( @@ -1458,8 +1511,8 @@ suggested_filename.RemoveExtension().BaseName().value(); base::FilePath::StringType file_name_ext = suggested_filename.Extension(); - // Need to make sure the suggested file name is not too long. - uint32_t max_path = GetMaxPathLengthForDirectory(save_dir); + // Get path length constraints for truncation. + uint32_t max_path = SavePackage::ComputeMaxPathLengthForDirectory(save_dir); if (TruncateBaseNameToFitPathConstraints(save_dir, file_name_ext, max_path, &base_name)) {
diff --git a/content/browser/download/save_package.h b/content/browser/download/save_package.h index 5d7e905..4693e0f 100644 --- a/content/browser/download/save_package.h +++ b/content/browser/download/save_package.h
@@ -147,6 +147,13 @@ friend class WebContentsImpl; FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestSuggestedSaveNames); FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestLongSafePureFilename); + FRIEND_TEST_ALL_PREFIXES(SavePackageTest, + TestComputeMaxPathLengthForDirectory); + FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestTruncateBaseNameEdgeCases); + FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestUTF8FilenameTruncation); + FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestDirectoryWithTrailingSeparator); + FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestEmptyExtension); + FRIEND_TEST_ALL_PREFIXES(SavePackageTest, TestVeryLongDirectory); FRIEND_TEST_ALL_PREFIXES(SavePackageFencedFrameTest, DontRequestSavableResourcesFromFencedFrames); FRIEND_TEST_ALL_PREFIXES(SavePackageBrowserTest, ImplicitCancel); @@ -211,28 +218,18 @@ // Update the download history of this item upon completion. void FinalizeDownloadEntry(); - // Return max length of a path for a specific base directory. - // This is needed on POSIX, which restrict the length of file names in - // addition to the restriction on the length of path names. - // |base_dir| is assumed to be a directory name with no trailing slash. - static uint32_t GetMaxPathLengthForDirectory(const base::FilePath& base_dir); + // Queries runtime filesystem constraints for maximum path length. + // Performs blocking I/O - only call on file threads during path selection. + static uint32_t ComputeMaxPathLengthForDirectory( + const base::FilePath& base_dir); - // Truncates a filename to fit length constraints. - // - // |directory| : Directory containing target file. - // |extension| : Extension. - // |max_path_len| : Maximum size allowed for |len(directory + base_name + - // extension|. - // |base_name| : Variable portion. The length of this component will be - // adjusted to fit the length constraints described at - // |max_path_len| above. - // - // Returns true if |base_name| could be successfully adjusted to fit the - // aforementioned constraints, or false otherwise. - // TODO(asanka): This function is wrong. |base_name| cannot be truncated - // without knowing its encoding and truncation has to be performed on - // character boundaries. Also the implementation doesn't look up the actual - // path constraints and instead uses hard coded constants. crbug.com/618737 + // Returns conservative maximum path length using platform defaults. + // Non-blocking - safe to call during save operations. + uint32_t GetMaxPathLengthForDirectory() const; + + // Truncates |base_name| to fit within |max_path_len| for the full path. + // Respects UTF-8 character boundaries on POSIX systems. + // Returns true if truncation succeeded, false if no valid name possible. static bool TruncateBaseNameToFitPathConstraints( const base::FilePath& directory, const base::FilePath::StringType& extension,
diff --git a/content/browser/download/save_package_unittest.cc b/content/browser/download/save_package_unittest.cc index 1560807..08c8cf4 100644 --- a/content/browser/download/save_package_unittest.cc +++ b/content/browser/download/save_package_unittest.cc
@@ -45,10 +45,8 @@ // This constant copied from save_package.cc. #if BUILDFLAG(IS_WIN) const uint32_t kMaxFilePathLength = MAX_PATH - 1; -const uint32_t kMaxFileNameLength = MAX_PATH - 1; #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) const uint32_t kMaxFilePathLength = PATH_MAX - 1; -const uint32_t kMaxFileNameLength = NAME_MAX; #endif bool HasOrdinalNumber(const base::FilePath::StringType& filename) { @@ -263,11 +261,15 @@ const base::FilePath::StringType ext(FPL_HTML_EXTENSION); base::FilePath::StringType filename = GetLongFileName(); - // Test that the filename + extension doesn't exceed kMaxFileNameLength - uint32_t max_path = SavePackage::GetMaxPathLengthForDirectory(save_dir); + // Test filename truncation respects length constraints. + uint32_t max_path = SavePackage::ComputeMaxPathLengthForDirectory(save_dir); ASSERT_TRUE(SavePackage::TruncateBaseNameToFitPathConstraints( save_dir, ext, max_path, &filename)); - EXPECT_TRUE(filename.length() <= kMaxFileNameLength-ext.length()); + // Verify truncation worked by checking the total path length fits + // constraints. + uint32_t total_path_length = + save_dir.value().length() + 1 + filename.length() + ext.length(); + EXPECT_LE(total_path_length, max_path); } // GetUrlToBeSaved method should return correct url to be saved. @@ -291,6 +293,165 @@ EXPECT_EQ(view_source_url, contents()->GetLastCommittedURL()); } +// Test ComputeMaxPathLengthForDirectory with various directory lengths. +TEST_F(SavePackageTest, TestComputeMaxPathLengthForDirectory) { + // Test with short directory. + base::FilePath short_dir(FPL("dir")); + uint32_t max_path_short = + SavePackage::ComputeMaxPathLengthForDirectory(short_dir); + EXPECT_GT(max_path_short, short_dir.value().length()); + + // Test with longer directory. + base::FilePath long_dir(FPL("very/long/directory/path/structure")); + uint32_t max_path_long = + SavePackage::ComputeMaxPathLengthForDirectory(long_dir); + EXPECT_GT(max_path_long, long_dir.value().length()); + + // Verify that the function returns reasonable values. + // The max path should account for directory length + separator + component + // limit. + EXPECT_LE(short_dir.value().length() + 1, max_path_short); + EXPECT_LE(long_dir.value().length() + 1, max_path_long); + + // Both should be positive and reasonable. + EXPECT_GT(max_path_short, 0u); + EXPECT_GT(max_path_long, 0u); +} + +// Test TruncateBaseNameToFitPathConstraints edge cases. +TEST_F(SavePackageTest, TestTruncateBaseNameEdgeCases) { + const base::FilePath save_dir(FPL("test")); + const base::FilePath::StringType ext(FPL(".html")); + + // Test with filename that doesn't need truncation. + base::FilePath::StringType short_name(FPL("short")); + uint32_t max_path = SavePackage::ComputeMaxPathLengthForDirectory(save_dir); + ASSERT_TRUE(SavePackage::TruncateBaseNameToFitPathConstraints( + save_dir, ext, max_path, &short_name)); + EXPECT_EQ(short_name, FPL("short")); + + // Test with very small max_path_len that forces base_name to be cleared. + base::FilePath::StringType any_name(FPL("filename")); + uint32_t tiny_max = + save_dir.value().length() + ext.length(); // No room for base_name. + EXPECT_FALSE(SavePackage::TruncateBaseNameToFitPathConstraints( + save_dir, ext, tiny_max, &any_name)); + EXPECT_TRUE(any_name.empty()); + + // Test with max_path_len exactly fitting directory + separator + extension. + base::FilePath::StringType zero_name(FPL("test")); + uint32_t exact_max = save_dir.value().length() + 1 + ext.length(); + EXPECT_FALSE(SavePackage::TruncateBaseNameToFitPathConstraints( + save_dir, ext, exact_max, &zero_name)); +} + +// Test UTF-8 filename truncation on POSIX systems. +TEST_F(SavePackageTest, TestUTF8FilenameTruncation) { + const base::FilePath save_dir(FPL("test")); + const base::FilePath::StringType ext(FPL(".html")); + + // Create a filename with multibyte UTF-8 characters. + base::FilePath::StringType utf8_name; +#if BUILDFLAG(IS_WIN) + // On Windows, use UTF-16. + utf8_name = L"файл测试テスト"; +#else + // On POSIX, use UTF-8. + utf8_name = "файл测试テスト"; +#endif + + // Make the name very long to force truncation. + for (int i = 0; i < 20; ++i) { + utf8_name += utf8_name; + } + + uint32_t max_path = SavePackage::ComputeMaxPathLengthForDirectory(save_dir); + base::FilePath::StringType original_name = utf8_name; + + ASSERT_TRUE(SavePackage::TruncateBaseNameToFitPathConstraints( + save_dir, ext, max_path, &utf8_name)); + + // Verify truncation occurred. + EXPECT_LT(utf8_name.length(), original_name.length()); + + // Verify total path fits constraints. + uint32_t total_length = + save_dir.value().length() + 1 + utf8_name.length() + ext.length(); + EXPECT_LE(total_length, max_path); + +#if !BUILDFLAG(IS_WIN) + // On POSIX, verify the truncated string is valid UTF-8. + std::string utf8_result = base::FilePath(utf8_name).AsUTF8Unsafe(); + EXPECT_FALSE(utf8_result.empty()); +#endif +} + +// Test directory with trailing separator. +TEST_F(SavePackageTest, TestDirectoryWithTrailingSeparator) { + // Create directory with trailing separator using platform-specific separator. + base::FilePath::StringType dir_str = FPL("test"); + dir_str += base::FilePath::kSeparators[0]; + base::FilePath dir_with_sep(dir_str); + ASSERT_TRUE(dir_with_sep.EndsWithSeparator()); + + const base::FilePath::StringType ext(FPL(".html")); + base::FilePath::StringType filename(FPL("testfile")); + + uint32_t max_path = + SavePackage::ComputeMaxPathLengthForDirectory(dir_with_sep); + + ASSERT_TRUE(SavePackage::TruncateBaseNameToFitPathConstraints( + dir_with_sep, ext, max_path, &filename)); + + // Should handle trailing separator correctly - no extra separator needed. + uint32_t total_length = + dir_with_sep.value().length() + filename.length() + ext.length(); + EXPECT_LE(total_length, max_path); +} + +// Test empty extension. +TEST_F(SavePackageTest, TestEmptyExtension) { + const base::FilePath save_dir(FPL("test")); + const base::FilePath::StringType empty_ext; + base::FilePath::StringType filename = GetLongFileName(); + + uint32_t max_path = SavePackage::ComputeMaxPathLengthForDirectory(save_dir); + + ASSERT_TRUE(SavePackage::TruncateBaseNameToFitPathConstraints( + save_dir, empty_ext, max_path, &filename)); + + uint32_t total_length = save_dir.value().length() + 1 + filename.length(); + EXPECT_LE(total_length, max_path); +} + +// Test very long directory path. +TEST_F(SavePackageTest, TestVeryLongDirectory) { + // Create a very long directory path. + base::FilePath::StringType long_path_str; + for (int i = 0; i < 50; ++i) { + long_path_str += FPL("very_long_directory_name/"); + } + base::FilePath long_dir(long_path_str); + + const base::FilePath::StringType ext(FPL(".html")); + base::FilePath::StringType filename(FPL("test")); + + uint32_t max_path = SavePackage::ComputeMaxPathLengthForDirectory(long_dir); + + bool result = SavePackage::TruncateBaseNameToFitPathConstraints( + long_dir, ext, max_path, &filename); + + if (result) { + // If truncation succeeded, verify constraints are met. + uint32_t total_length = + long_dir.value().length() + 1 + filename.length() + ext.length(); + EXPECT_LE(total_length, max_path); + } else { + // If truncation failed, filename should be empty. + EXPECT_TRUE(filename.empty()); + } +} + class SavePackageFencedFrameTest : public SavePackageTest { public: SavePackageFencedFrameTest() {
diff --git a/content/browser/file_system_access/file_system_access_file_handle_impl.cc b/content/browser/file_system_access/file_system_access_file_handle_impl.cc index 0c0a197..5b797fdd 100644 --- a/content/browser/file_system_access/file_system_access_file_handle_impl.cc +++ b/content/browser/file_system_access/file_system_access_file_handle_impl.cc
@@ -191,9 +191,8 @@ CreateFileWriterCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug.com/40276567): Review whether to switch to write-only. RunWithPermission( - blink::mojom::FileSystemAccessPermissionMode::kReadWrite, + FileSystemAccessManagerImpl::GetEffectiveWritePermissionMode(), base::BindOnce(&FileSystemAccessFileHandleImpl::CreateFileWriterImpl, weak_factory_.GetWeakPtr(), keep_existing_data, auto_close, mode), @@ -538,8 +537,7 @@ blink::mojom::FileSystemAccessWritableFileStreamLockMode mode, CreateFileWriterCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // TODO(crbug.com/40276567): Update if this only needs write-only permission - DCHECK_EQ(GetReadWritePermissionStatus(), + DCHECK_EQ(GetEffectiveWritePermissionStatus(), blink::mojom::PermissionStatus::GRANTED); // TODO(crbug.com/40194651): Expand this check to all backends. @@ -615,8 +613,7 @@ return; } - // TODO(crbug.com/40276567): Update if this only needs write-only permission - if (GetReadWritePermissionStatus() != PermissionStatus::GRANTED) { + if (GetEffectiveWritePermissionStatus() != PermissionStatus::GRANTED) { std::move(callback).Run(file_system_access_error::FromStatus( FileSystemAccessStatus::kPermissionDenied), mojo::NullRemote());
diff --git a/content/browser/file_system_access/file_system_access_file_handle_impl_browsertest.cc b/content/browser/file_system_access/file_system_access_file_handle_impl_browsertest.cc index fd1c65c..8b6214e5 100644 --- a/content/browser/file_system_access/file_system_access_file_handle_impl_browsertest.cc +++ b/content/browser/file_system_access/file_system_access_file_handle_impl_browsertest.cc
@@ -7,21 +7,78 @@ #include "base/files/scoped_temp_dir.h" #include "base/test/scoped_feature_list.h" #include "content/browser/file_system_access/features.h" +#include "content/browser/file_system_access/file_system_access_manager_impl.h" +#include "content/browser/file_system_access/mock_file_system_access_permission_context.h" +#include "content/browser/file_system_access/mock_file_system_access_permission_grant.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" +#include "content/public/test/fake_file_system_access_permission_context.h" #include "content/public/test/file_system_chooser_test_helpers.h" +#include "content/shell/browser/shell.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/features_generated.h" namespace content { -class FileSystemAccessFileHandleImplBrowserTest : public ContentBrowserTest { +namespace { + +using blink::mojom::FileSystemAccessPermissionMode; +using testing::_; +using testing::Eq; +using testing::Invoke; +using testing::Return; + +// For injecting mock permission grants into the FileSystemAccessManager. +class TestPermissionContext : public FakeFileSystemAccessPermissionContext { public: - FileSystemAccessFileHandleImplBrowserTest() { + TestPermissionContext() { + read_grant_ = base::MakeRefCounted< + testing::StrictMock<MockFileSystemAccessPermissionGrant>>(); + write_grant_ = base::MakeRefCounted< + testing::StrictMock<MockFileSystemAccessPermissionGrant>>(); + } + ~TestPermissionContext() override = default; + + scoped_refptr<FileSystemAccessPermissionGrant> GetReadPermissionGrant( + const url::Origin& origin, + const PathInfo& path, + HandleType handle_type, + UserAction user_action) override { + return read_grant_; + } + + scoped_refptr<FileSystemAccessPermissionGrant> GetWritePermissionGrant( + const url::Origin& origin, + const PathInfo& path, + HandleType handle_type, + UserAction user_action) override { + return write_grant_; + } + + MockFileSystemAccessPermissionGrant& read_grant() { return *read_grant_; } + MockFileSystemAccessPermissionGrant& write_grant() { return *write_grant_; } + + private: + scoped_refptr<testing::StrictMock<MockFileSystemAccessPermissionGrant>> + read_grant_; + scoped_refptr<testing::StrictMock<MockFileSystemAccessPermissionGrant>> + write_grant_; +}; + +} // namespace + +class FileSystemAccessFileHandleImplBrowserTestBase + : public ContentBrowserTest { + public: + FileSystemAccessFileHandleImplBrowserTestBase() { scoped_features_.InitAndEnableFeature( blink::features::kFileSystemAccessLocal); } @@ -91,6 +148,9 @@ base::test::ScopedFeatureList scoped_features_; }; +class FileSystemAccessFileHandleImplBrowserTest + : public FileSystemAccessFileHandleImplBrowserTestBase {}; + // TODO(crbug.com/40888337): Make this a WPT once crbug.com/1114920 is fixed. IN_PROC_BROWSER_TEST_F(FileSystemAccessFileHandleImplBrowserTest, MoveLocalToSandboxed) { @@ -136,11 +196,127 @@ "return await self.localFile.move('renamed.txt'); })()")); } +// Test params for `FileSystemAccessFileHandleImplWriteModeBrowserTest`. +struct WriteModeTestParams { + const char* test_name_suffix; + bool is_feature_enabled; + FileSystemAccessPermissionMode expected_mode; +}; + +// Browser tests for FileSystemAccessFileHandleImpl-related APIs, with a mock +// permission context to verify write permissions-related logic. +class FileSystemAccessFileHandleImplWriteModeBrowserTest + : public FileSystemAccessFileHandleImplBrowserTestBase, + public testing::WithParamInterface<WriteModeTestParams> { + public: + FileSystemAccessFileHandleImplWriteModeBrowserTest() { + if (GetParam().is_feature_enabled) { + scoped_feature_list_.InitAndEnableFeature( + blink::features::kFileSystemAccessWriteMode); + } else { + scoped_feature_list_.InitAndDisableFeature( + blink::features::kFileSystemAccessWriteMode); + } + } + + void SetUpOnMainThread() override { + FileSystemAccessFileHandleImplBrowserTestBase::SetUpOnMainThread(); + + permission_context_ = std::make_unique<TestPermissionContext>(); + static_cast<FileSystemAccessManagerImpl*>( + shell() + ->web_contents() + ->GetBrowserContext() + ->GetStoragePartition(shell()->web_contents()->GetSiteInstance()) + ->GetFileSystemAccessEntryFactory()) + ->SetPermissionContextForTesting(permission_context_.get()); + } + + protected: + // Configures the mock permission context to return GRANTED for the + // specified permission mode. This is used to simulate the user granting + // permission for a particular operation. + // + // Due to the use of `StrictMock` for the underlying permission grants, only + // the `GetStatus()` calls for the grants relevant to `expected_mode` are + // expected. Any unexpected calls to `GetStatus()` on the other grant (e.g., + // `read_grant` when `kWrite` mode is expected) will result in a test failure. + // This helps capture any unexpected permission status checks. + void ExpectGetPermissionStatusAndReturnGranted( + FileSystemAccessPermissionMode expected_mode) { + switch (expected_mode) { + case FileSystemAccessPermissionMode::kRead: + EXPECT_CALL(permission_context_->read_grant(), GetStatus()) + .WillRepeatedly(Return(blink::mojom::PermissionStatus::GRANTED)); + return; + case FileSystemAccessPermissionMode::kReadWrite: + EXPECT_CALL(permission_context_->read_grant(), GetStatus()) + .WillRepeatedly(Return(blink::mojom::PermissionStatus::GRANTED)); + EXPECT_CALL(permission_context_->write_grant(), GetStatus()) + .WillRepeatedly(Return(blink::mojom::PermissionStatus::GRANTED)); + return; + case FileSystemAccessPermissionMode::kWrite: + EXPECT_CALL(permission_context_->write_grant(), GetStatus()) + .WillRepeatedly(Return(blink::mojom::PermissionStatus::GRANTED)); + return; + } + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + std::unique_ptr<TestPermissionContext> permission_context_ = nullptr; +}; + +// Verifies that `createWritable()` on a local FS requests the correct +// permission mode depending on whether the `kFileSystemAccessWriteMode` feature +// is enabled. +IN_PROC_BROWSER_TEST_P(FileSystemAccessFileHandleImplWriteModeBrowserTest, + Local_CreateFileWriter_RequestsCorrectPermissions) { + CreateTestFileInDirectory(temp_dir_.GetPath(), "test file"); + + ExpectGetPermissionStatusAndReturnGranted(GetParam().expected_mode); + + EXPECT_TRUE(ExecJs(shell(), + "(async () => {" + "return await self.localFile.createWritable(); })()")); +} + +// Verifies that `createWritable()` on a sandboxed FS requests the correct +// permission mode depending on whether the `kFileSystemAccessWriteMode` +// feature is enabled. +IN_PROC_BROWSER_TEST_P(FileSystemAccessFileHandleImplWriteModeBrowserTest, + Sandboxed_CreateFileWriter_RequestsCorrectPermissions) { + EXPECT_TRUE(NavigateToURL(shell(), test_url_)); + + ExpectGetPermissionStatusAndReturnGranted(GetParam().expected_mode); + + EXPECT_TRUE(ExecJs(shell(), + "(async () => {" + " const root = await navigator.storage.getDirectory();" + " const file = await root.getFileHandle('test.txt', " + " {create: true});" + " return await file.createWritable();" + "})()")); +} + +INSTANTIATE_TEST_SUITE_P( + /* no prefix */, + FileSystemAccessFileHandleImplWriteModeBrowserTest, + testing::Values( + WriteModeTestParams{"WriteModeDisabled", false, + FileSystemAccessPermissionMode::kReadWrite}, + WriteModeTestParams{"WriteModeEnabled", true, + FileSystemAccessPermissionMode::kWrite}), + [](const testing::TestParamInfo<WriteModeTestParams>& info) { + return info.param.test_name_suffix; + }); + class FileSystemAccessFileHandleGetUniqueIdBrowserTest - : public FileSystemAccessFileHandleImplBrowserTest { + : public FileSystemAccessFileHandleImplBrowserTestBase { public: void SetUpCommandLine(base::CommandLine* command_line) override { - FileSystemAccessFileHandleImplBrowserTest::SetUpCommandLine(command_line); + FileSystemAccessFileHandleImplBrowserTestBase::SetUpCommandLine( + command_line); // Enable File System Access experimental features, which includes the // getUniqueId() method. command_line->AppendSwitch( @@ -176,10 +352,10 @@ " self.file2 = e;" " return e.name; })()")); - EXPECT_TRUE(EvalJs(shell(), - "(async () => {" - "return await self.file2.isSameEntry(self.file1); })()") - .ExtractBool()); + EXPECT_EQ(true, + EvalJs(shell(), + "(async () => {" + "return await self.file2.isSameEntry(self.file1); })()")); auto uniqueId1 = EvalJs(shell(), "(async () => {" "return await self.file1.getUniqueId(); })()")
diff --git a/content/browser/file_system_access/file_system_access_file_handle_impl_unittest.cc b/content/browser/file_system_access/file_system_access_file_handle_impl_unittest.cc index 221fa2f..4a8d76e 100644 --- a/content/browser/file_system_access/file_system_access_file_handle_impl_unittest.cc +++ b/content/browser/file_system_access/file_system_access_file_handle_impl_unittest.cc
@@ -66,6 +66,7 @@ namespace content { +using blink::mojom::FileSystemAccessStatus; using blink::mojom::PermissionStatus; using storage::FileSystemURL; using testing::_; @@ -74,7 +75,7 @@ // A matcher to check if a `RequestPermission()` call is successful and // returns the expected permission status. MATCHER_P(IsOkAndPermissionStatus, status, "") { - if (arg.first->status != blink::mojom::FileSystemAccessStatus::kOk) { + if (arg.first->status != FileSystemAccessStatus::kOk) { *result_listener << "FileSystemAccessStatus is " << arg.first->status; return false; } @@ -85,6 +86,26 @@ return true; } +// A matcher to check the result of a `CreateFileWriter()` call. +MATCHER_P(FileWriterCreationIs, expected_status, "") { + const auto& result = arg.first; + const auto& writer = arg.second; + + if (result->status != expected_status) { + *result_listener << "FileSystemAccessStatus is " << result->status + << ", expected " << expected_status; + return false; + } + + bool should_be_valid = (expected_status == FileSystemAccessStatus::kOk); + if (writer.is_valid() != should_be_valid) { + *result_listener << "writer validity is " << writer.is_valid() + << ", expected " << should_be_valid; + return false; + } + return true; +} + // Test fixture for FileSystemAccessFileHandleImpl. // // The permission context in this fixture is always null, so the relevant @@ -317,7 +338,7 @@ return future.Take(); } - blink::mojom::FileSystemAccessStatus TestLockMode( + FileSystemAccessStatus TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode lock_mode) { return std::get<blink::mojom::FileSystemAccessErrorPtr>( OpenAccessHandle(lock_mode)) @@ -345,10 +366,28 @@ }; #endif -class FileSystemAccessFileHandleImplTest - : public FileSystemAccessFileHandleImplTestBase {}; +class FileSystemAccessFileHandleImplCreateFileWriterTest + : public FileSystemAccessFileHandleImplTestBase { + public: + // Creates a file writer and waits for the operation to complete. Returns a + // pair containing the error and the writer remote. + std::pair<blink::mojom::FileSystemAccessErrorPtr, + mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> + CreateFileWriter( + bool keep_existing_data, + bool auto_close, + blink::mojom::FileSystemAccessWritableFileStreamLockMode lock_mode) { + base::test::TestFuture< + blink::mojom::FileSystemAccessErrorPtr, + mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> + future; + handle_->CreateFileWriter(keep_existing_data, auto_close, lock_mode, + future.GetCallback()); + return future.Take(); + } +}; -TEST_F(FileSystemAccessFileHandleImplTest, CreateFileWriterOverLimitNotOK) { +TEST_F(FileSystemAccessFileHandleImplCreateFileWriterTest, OverLimitNotOK) { int max_files = 5; handle_->set_max_swap_files_for_testing(max_files); @@ -370,164 +409,86 @@ base::StringPrintf("test.%d.crswap", i))); } - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( + auto writer_pair = CreateFileWriter( /*keep_existing_data=*/false, /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; - std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed); + ASSERT_THAT(writer_pair, FileWriterCreationIs(FileSystemAccessStatus::kOk)); EXPECT_EQ("", ReadFile(swap_url)); - writers.push_back(std::move(writer_remote)); + writers.push_back(std::move(writer_pair.second)); } - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( - /*keep_existing_data=*/false, - /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; - std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, - blink::mojom::FileSystemAccessStatus::kOperationFailed); - EXPECT_FALSE(writer_remote.is_valid()); + EXPECT_THAT( + CreateFileWriter( + /*keep_existing_data=*/false, + /*auto_close=*/false, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed), + FileWriterCreationIs(FileSystemAccessStatus::kOperationFailed)); } -TEST_F(FileSystemAccessFileHandleImplTest, CreateFileWriterSiloedMode) { +TEST_F(FileSystemAccessFileHandleImplCreateFileWriterTest, SiloedMode) { mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer; - { - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( - /*keep_existing_data=*/false, - /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - std::tie(result, writer) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); - EXPECT_TRUE(writer.is_valid()); - } + // Keep the writer alive for the duration of the test. + auto writer_pair = CreateFileWriter( + /*keep_existing_data=*/false, + /*auto_close=*/false, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed); + ASSERT_THAT(writer_pair, FileWriterCreationIs(FileSystemAccessStatus::kOk)); + writer = std::move(writer_pair.second); // If file writer in siloed mode exists for a file handle, can create a writer // in siloed mode for the file handle. - { - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( - /*keep_existing_data=*/false, - /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; - std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); - EXPECT_TRUE(writer_remote.is_valid()); - } + EXPECT_THAT( + CreateFileWriter( + /*keep_existing_data=*/false, + /*auto_close=*/false, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed), + FileWriterCreationIs(FileSystemAccessStatus::kOk)); // If file writer in siloed mode exists for a file handle, can't create a // writer in exclusive mode for the file handle. - { - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( - /*keep_existing_data=*/false, - /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kExclusive, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; - std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ( - result->status, - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); - EXPECT_FALSE(writer_remote.is_valid()); - } + EXPECT_THAT( + CreateFileWriter( + /*keep_existing_data=*/false, + /*auto_close=*/false, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kExclusive), + FileWriterCreationIs( + FileSystemAccessStatus::kNoModificationAllowedError)); } -TEST_F(FileSystemAccessFileHandleImplTest, CreateFileWriterExclusiveMode) { +TEST_F(FileSystemAccessFileHandleImplCreateFileWriterTest, ExclusiveMode) { mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer; - - { - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( - /*keep_existing_data=*/false, - /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kExclusive, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - std::tie(result, writer) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); - EXPECT_TRUE(writer.is_valid()); - } + auto writer_pair = CreateFileWriter( + /*keep_existing_data=*/false, + /*auto_close=*/false, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kExclusive); + ASSERT_THAT(writer_pair, FileWriterCreationIs(FileSystemAccessStatus::kOk)); + writer = std::move(writer_pair.second); // If file writer in exclusive mode exists for a file handle, can't create a // writer in siloed mode for the file handle. - { - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( - /*keep_existing_data=*/false, - /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; - std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ( - result->status, - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); - EXPECT_FALSE(writer_remote.is_valid()); - } + EXPECT_THAT( + CreateFileWriter( + /*keep_existing_data=*/false, + /*auto_close=*/false, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed), + FileWriterCreationIs( + FileSystemAccessStatus::kNoModificationAllowedError)); // If file writer in exclusive mode exists for a file handle, can't create a // writer in exclusive mode for the file handle. - { - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( - /*keep_existing_data=*/false, - /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kExclusive, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; - std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ( - result->status, - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); - EXPECT_FALSE(writer_remote.is_valid()); - } + EXPECT_THAT( + CreateFileWriter( + /*keep_existing_data=*/false, + /*auto_close=*/false, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kExclusive), + FileWriterCreationIs( + FileSystemAccessStatus::kNoModificationAllowedError)); } -TEST_F(FileSystemAccessFileHandleImplTest, - CreateFileWriterWithExistingSwapFile) { +TEST_F(FileSystemAccessFileHandleImplCreateFileWriterTest, + WithExistingSwapFile) { const FileSystemURL swap_url = file_system_context_->CreateCrackedFileSystemURL( test_src_storage_key_, storage::kFileSystemTypeTest, @@ -538,22 +499,27 @@ file_system_context_.get(), swap_url)); // Creating the writer still succeeds. - base::test::TestFuture< - blink::mojom::FileSystemAccessErrorPtr, - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter>> - future; - handle_->CreateFileWriter( - /*keep_existing_data=*/true, - /*auto_close=*/false, - blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed, - future.GetCallback()); - blink::mojom::FileSystemAccessErrorPtr result; - mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; - std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); - EXPECT_TRUE(writer_remote.is_valid()); + EXPECT_THAT( + CreateFileWriter( + /*keep_existing_data=*/true, + /*auto_close=*/false, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed), + FileWriterCreationIs(FileSystemAccessStatus::kOk)); } +// Verifies that `auto_close` is plumbed through to the FileSystemAccessManager. +TEST_F(FileSystemAccessFileHandleImplCreateFileWriterTest, WithAutoClose) { + EXPECT_THAT( + CreateFileWriter( + /*keep_existing_data=*/true, + /*auto_close=*/true, + blink::mojom::FileSystemAccessWritableFileStreamLockMode::kSiloed), + FileWriterCreationIs(FileSystemAccessStatus::kOk)); +} + +// TODO(crbug.com/40276567): Add test to cover that swap file is truncated when +// `keep_existing_data` is false. + #if BUILDFLAG(IS_ANDROID) TEST_F(FileSystemAccessAccessHandleContentUriTest, CreateFileWriter) { base::test::TestFuture< @@ -568,7 +534,7 @@ blink::mojom::FileSystemAccessErrorPtr result; mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); EXPECT_TRUE(writer_remote.is_valid()); // Swap file should be created in cache dir. @@ -582,7 +548,10 @@ } #endif -TEST_F(FileSystemAccessFileHandleImplTest, Remove_NoWriteAccess) { +class FileSystemAccessFileHandleImplRemoveTest + : public FileSystemAccessFileHandleImplTestBase {}; + +TEST_F(FileSystemAccessFileHandleImplRemoveTest, NoWriteAccess) { base::FilePath file; ASSERT_TRUE(base::CreateTemporaryFileInDir(dir_.GetPath(), &file)); @@ -591,12 +560,11 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; handle->Remove(future.GetCallback()); - EXPECT_EQ(future.Get()->status, - blink::mojom::FileSystemAccessStatus::kPermissionDenied); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kPermissionDenied); EXPECT_TRUE(base::PathExists(file)); } -TEST_F(FileSystemAccessFileHandleImplTest, Remove_HasWriteAccess) { +TEST_F(FileSystemAccessFileHandleImplRemoveTest, HasWriteAccess) { base::FilePath file; ASSERT_TRUE(base::CreateTemporaryFileInDir(dir_.GetPath(), &file)); @@ -605,7 +573,7 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; handle->Remove(future.GetCallback()); - EXPECT_EQ(future.Get()->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kOk); EXPECT_FALSE(base::PathExists(file)); } @@ -616,7 +584,7 @@ access_handle_remote; std::tie(result, file, access_handle_remote) = OpenAccessHandle( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwrite); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); // File should be valid and no incognito remote is needed. EXPECT_TRUE(file->is_regular_file()); blink::mojom::FileSystemAccessRegularFilePtr regular_file = @@ -634,7 +602,7 @@ access_handle_remote; std::tie(result, file, access_handle_remote) = OpenAccessHandle( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwrite); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); // Incognito remote should be valid and no file is needed. EXPECT_TRUE(file->is_incognito_file_delegate()); EXPECT_TRUE(file->get_incognito_file_delegate().is_valid()); @@ -651,21 +619,21 @@ blink::mojom::FileSystemAccessAccessHandleFilePtr file; std::tie(result, file, access_handle_remote) = OpenAccessHandle( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwrite); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); // Cannot open another access handle in READWRITE mode. EXPECT_EQ(TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwrite), - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); + FileSystemAccessStatus::kNoModificationAllowedError); // Cannot open another access handle in a different mode. EXPECT_EQ(TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadOnly), - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); + FileSystemAccessStatus::kNoModificationAllowedError); EXPECT_EQ( TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwriteUnsafe), - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); + FileSystemAccessStatus::kNoModificationAllowedError); } TEST_F(FileSystemAccessAccessHandleTest, OpenAccessHandleLockModes_ReadOnly) { @@ -678,21 +646,21 @@ blink::mojom::FileSystemAccessAccessHandleFilePtr file; std::tie(result, file, access_handle_remote) = OpenAccessHandle( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadOnly); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); // Can open another access handle in READ_ONLY mode. EXPECT_EQ(TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadOnly), - blink::mojom::FileSystemAccessStatus::kOk); + FileSystemAccessStatus::kOk); // Cannot open another access handle in a different mode. EXPECT_EQ(TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwrite), - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); + FileSystemAccessStatus::kNoModificationAllowedError); EXPECT_EQ( TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwriteUnsafe), - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); + FileSystemAccessStatus::kNoModificationAllowedError); } TEST_F(FileSystemAccessAccessHandleTest, @@ -706,24 +674,27 @@ blink::mojom::FileSystemAccessAccessHandleFilePtr file; std::tie(result, file, access_handle_remote) = OpenAccessHandle( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwriteUnsafe); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); // Can open another access handle in READ_ONLY mode. EXPECT_EQ( TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwriteUnsafe), - blink::mojom::FileSystemAccessStatus::kOk); + FileSystemAccessStatus::kOk); // Cannot open another access handle in a different mode. EXPECT_EQ(TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadwrite), - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); + FileSystemAccessStatus::kNoModificationAllowedError); EXPECT_EQ(TestLockMode( blink::mojom::FileSystemAccessAccessHandleLockMode::kReadOnly), - blink::mojom::FileSystemAccessStatus::kNoModificationAllowedError); + FileSystemAccessStatus::kNoModificationAllowedError); } -TEST_F(FileSystemAccessFileHandleImplTest, Rename_NoWriteAccess) { +class FileSystemAccessFileHandleImplRenameTest + : public FileSystemAccessFileHandleImplTestBase {}; + +TEST_F(FileSystemAccessFileHandleImplRenameTest, NoWriteAccess) { base::FilePath file; ASSERT_TRUE(base::CreateTemporaryFileInDir(dir_.GetPath(), &file)); base::FilePath renamed_file = file.DirName().AppendASCII("new_name.txt"); @@ -733,13 +704,12 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; handle->Rename(renamed_file.BaseName().AsUTF8Unsafe(), future.GetCallback()); - EXPECT_EQ(future.Get()->status, - blink::mojom::FileSystemAccessStatus::kPermissionDenied); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kPermissionDenied); EXPECT_TRUE(base::PathExists(file)); EXPECT_FALSE(base::PathExists(renamed_file)); } -TEST_F(FileSystemAccessFileHandleImplTest, Rename_HasWriteAccess) { +TEST_F(FileSystemAccessFileHandleImplRenameTest, HasWriteAccess) { base::FilePath file; ASSERT_TRUE(base::CreateTemporaryFileInDir(dir_.GetPath(), &file)); base::FilePath renamed_file = file.DirName().AppendASCII("new_name.txt"); @@ -749,12 +719,15 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; handle->Rename(renamed_file.BaseName().AsUTF8Unsafe(), future.GetCallback()); - EXPECT_EQ(future.Get()->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kOk); EXPECT_FALSE(base::PathExists(file)); EXPECT_TRUE(base::PathExists(renamed_file)); } -TEST_F(FileSystemAccessFileHandleImplTest, Move_NoWriteAccess) { +class FileSystemAccessFileHandleImplMoveTest + : public FileSystemAccessFileHandleImplTestBase {}; + +TEST_F(FileSystemAccessFileHandleImplMoveTest, NoWriteAccess) { base::FilePath dest_dir; ASSERT_TRUE(base::CreateTemporaryDirInDir( dir_.GetPath(), FILE_PATH_LITERAL("dest"), &dest_dir)); @@ -775,13 +748,12 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; handle->Move(std::move(dir_remote), renamed_file.BaseName().AsUTF8Unsafe(), future.GetCallback()); - EXPECT_EQ(future.Get()->status, - blink::mojom::FileSystemAccessStatus::kPermissionDenied); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kPermissionDenied); EXPECT_TRUE(base::PathExists(file)); EXPECT_FALSE(base::PathExists(renamed_file)); } -TEST_F(FileSystemAccessFileHandleImplTest, Move_NoDestWriteAccess) { +TEST_F(FileSystemAccessFileHandleImplMoveTest, NoDestWriteAccess) { base::FilePath dest_dir; ASSERT_TRUE(base::CreateTemporaryDirInDir( dir_.GetPath(), FILE_PATH_LITERAL("dest"), &dest_dir)); @@ -802,13 +774,12 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; handle->Move(std::move(dir_remote), renamed_file.BaseName().AsUTF8Unsafe(), future.GetCallback()); - EXPECT_EQ(future.Get()->status, - blink::mojom::FileSystemAccessStatus::kPermissionDenied); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kPermissionDenied); EXPECT_TRUE(base::PathExists(file)); EXPECT_FALSE(base::PathExists(renamed_file)); } -TEST_F(FileSystemAccessFileHandleImplTest, Move_HasDestWriteAccess) { +TEST_F(FileSystemAccessFileHandleImplMoveTest, HasDestWriteAccess) { base::FilePath dest_dir; ASSERT_TRUE(base::CreateTemporaryDirInDir( dir_.GetPath(), FILE_PATH_LITERAL("dest"), &dest_dir)); @@ -829,13 +800,14 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; handle->Move(std::move(dir_remote), renamed_file.BaseName().AsUTF8Unsafe(), future.GetCallback()); - EXPECT_EQ(future.Get()->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kOk); EXPECT_FALSE(base::PathExists(file)); EXPECT_TRUE(base::PathExists(renamed_file)); } #if BUILDFLAG(IS_ANDROID) -TEST_F(FileSystemAccessFileHandleImplTest, ContentUriRenameMoveNotSupported) { +TEST_F(FileSystemAccessFileHandleImplMoveTest, + ContentUriRenameMoveNotSupported) { base::FilePath dest_dir; ASSERT_TRUE(base::CreateTemporaryDirInDir( dir_.GetPath(), FILE_PATH_LITERAL("dest"), &dest_dir)); @@ -865,7 +837,7 @@ handle->Rename(renamed_file.BaseName().AsUTF8Unsafe(), rename_future.GetCallback()); EXPECT_EQ(rename_future.Get()->status, - blink::mojom::FileSystemAccessStatus::kInvalidModificationError); + FileSystemAccessStatus::kInvalidModificationError); EXPECT_TRUE(base::PathExists(file)); EXPECT_FALSE(base::PathExists(renamed_file)); @@ -874,7 +846,7 @@ handle->Move(std::move(dir_remote), moved_file.BaseName().AsUTF8Unsafe(), move_future.GetCallback()); EXPECT_EQ(move_future.Get()->status, - blink::mojom::FileSystemAccessStatus::kInvalidModificationError); + FileSystemAccessStatus::kInvalidModificationError); EXPECT_TRUE(base::PathExists(file)); EXPECT_FALSE(base::PathExists(moved_file)); } @@ -938,7 +910,7 @@ blink::mojom::FileSystemAccessErrorPtr result; mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); EXPECT_TRUE(writer_remote.is_valid()); EXPECT_EQ(GetCloneFileResult(handle_), CloneFileResult::kAttemptedAndCompletedAsExpected); @@ -958,7 +930,7 @@ blink::mojom::FileSystemAccessErrorPtr result; mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); EXPECT_TRUE(writer_remote.is_valid()); EXPECT_EQ(GetCloneFileResult(handle_), CloneFileResult::kDidNotAttempt); } @@ -987,7 +959,7 @@ blink::mojom::FileSystemAccessErrorPtr result; mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); EXPECT_TRUE(writer_remote.is_valid()); EXPECT_EQ(GetCloneFileResult(handle_), CloneFileResult::kAttemptedAndCompletedAsExpected); @@ -1009,7 +981,7 @@ blink::mojom::FileSystemAccessErrorPtr result; mojo::PendingRemote<blink::mojom::FileSystemAccessFileWriter> writer_remote; std::tie(result, writer_remote) = future.Take(); - EXPECT_EQ(result->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(result->status, FileSystemAccessStatus::kOk); EXPECT_TRUE(writer_remote.is_valid()); EXPECT_EQ(GetCloneFileResult(handle_), CloneFileResult::kAttemptedAndAborted); } @@ -1126,7 +1098,7 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; source_handle->Rename(target_basename.AsUTF8Unsafe(), future.GetCallback()); - EXPECT_EQ(future.Get()->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kOk); if (source != target) { EXPECT_FALSE(base::PathExists(source)); } @@ -1137,7 +1109,7 @@ const base::FilePath& source, const base::FilePath& target, scoped_refptr<FixedFileSystemAccessPermissionGrant> target_grant, - blink::mojom::FileSystemAccessStatus result, + FileSystemAccessStatus result, bool expects_safe_name = true, std::optional<FileSystemAccessPermissionContext::SensitiveEntryResult> expected_sensitive_entry_result = std::nullopt) { @@ -1250,7 +1222,7 @@ base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future; handle->Move(std::move(dir_remote), target_basename.AsUTF8Unsafe(), future.GetCallback()); - EXPECT_EQ(future.Get()->status, blink::mojom::FileSystemAccessStatus::kOk); + EXPECT_EQ(future.Get()->status, FileSystemAccessStatus::kOk); if (source != target) { EXPECT_FALSE(base::PathExists(source)); } @@ -1261,7 +1233,7 @@ const base::FilePath& source, const base::FilePath& target, scoped_refptr<FixedFileSystemAccessPermissionGrant> target_grant, - blink::mojom::FileSystemAccessStatus result, + FileSystemAccessStatus result, bool expects_safe_name = true, std::optional<FileSystemAccessPermissionContext::SensitiveEntryResult> expected_sensitive_entry_result = std::nullopt) { @@ -1344,8 +1316,7 @@ if (!gesture_present()) { // The rename should fail because write access to the target is not granted. ExpectFileRenameFailure( - source, target, target_grant, - blink::mojom::FileSystemAccessStatus::kPermissionDenied + source, target, target_grant, FileSystemAccessStatus::kPermissionDenied // No user activation, so the sensitive entry access check is not // performed. ); @@ -1353,7 +1324,7 @@ // The rename should fail because write access to the target is not granted. ExpectFileRenameFailure( source, target, target_grant, - blink::mojom::FileSystemAccessStatus::kInvalidModificationError, + FileSystemAccessStatus::kInvalidModificationError, /*expects_safe_name=*/true, // With user activation, the sensitive entry access check should be // performed and allowed. @@ -1376,7 +1347,7 @@ ExpectFileRenameFailure( source, target, /*target_grant=*/allow_grant_, - blink::mojom::FileSystemAccessStatus::kInvalidArgument, + FileSystemAccessStatus::kInvalidArgument, /*expects_safe_name=*/false // The access is already granted to the target, so the sensitive entry // access check should not be performed. @@ -1389,7 +1360,7 @@ ExpectFileRenameFailure( source, target, /*target_grant=*/allow_grant_, - blink::mojom::FileSystemAccessStatus::kInvalidArgument, + FileSystemAccessStatus::kInvalidArgument, /*expects_safe_name=*/true, // Let the test fail because the sensitive entry access check is aborted. FileSystemAccessPermissionContext::SensitiveEntryResult::kAbort); @@ -1404,9 +1375,8 @@ TEST_P(FileSystemAccessFileHandleImplMovePermissionsTest, Move_NoTargetWriteAccessFails) { auto [source, target] = CreateSourceAndMaybeTarget(); - ExpectFileMoveFailure( - source, target, /*target_grant=*/ask_grant_, - blink::mojom::FileSystemAccessStatus::kPermissionDenied); + ExpectFileMoveFailure(source, target, /*target_grant=*/ask_grant_, + FileSystemAccessStatus::kPermissionDenied); } TEST_P(FileSystemAccessFileHandleImplMovePermissionsTest, Move_SameFile) { @@ -1419,7 +1389,7 @@ auto [source, target] = CreateSourceAndMaybeTarget(); ExpectFileMoveFailure(source, target, /*target_grant=*/allow_grant_, - blink::mojom::FileSystemAccessStatus::kInvalidArgument, + FileSystemAccessStatus::kInvalidArgument, /*expects_safe_name=*/false // The access is already granted to the target, so the // sensitive entry access check should not be performed. @@ -1431,7 +1401,7 @@ ExpectFileMoveFailure( source, target, /*target_grant=*/allow_grant_, - blink::mojom::FileSystemAccessStatus::kInvalidArgument, + FileSystemAccessStatus::kInvalidArgument, /*expects_safe_name=*/true, // Let the test fail because the sensitive entry access check is aborted. FileSystemAccessPermissionContext::SensitiveEntryResult::kAbort);
diff --git a/content/browser/file_system_access/file_system_access_handle_base.cc b/content/browser/file_system_access/file_system_access_handle_base.cc index d583a02..b91524d 100644 --- a/content/browser/file_system_access/file_system_access_handle_base.cc +++ b/content/browser/file_system_access/file_system_access_handle_base.cc
@@ -116,6 +116,12 @@ return handle_state_.write_grant->GetStatus(); } +FileSystemAccessHandleBase::PermissionStatus +FileSystemAccessHandleBase::GetEffectiveWritePermissionStatus() { + return GetPermissionStatusForMode( + FileSystemAccessManagerImpl::GetEffectiveWritePermissionMode()); +} + // TODO(crbug.com/40276567): Update callers if they only need write permission. void FileSystemAccessHandleBase::DoGetPermissionStatus( blink::mojom::FileSystemAccessPermissionMode mode,
diff --git a/content/browser/file_system_access/file_system_access_handle_base.h b/content/browser/file_system_access/file_system_access_handle_base.h index 76bcb4e0..ca593e1 100644 --- a/content/browser/file_system_access/file_system_access_handle_base.h +++ b/content/browser/file_system_access/file_system_access_handle_base.h
@@ -140,6 +140,12 @@ protected: virtual base::WeakPtr<FileSystemAccessHandleBase> AsWeakPtr() = 0; + // Returns the effective write permission status. + // This currently returns permission status for kReadWrite, but will switch to + // the one for kWrite only when the FileSystemAccessWriteMode feature is fully + // rolled out. + PermissionStatus GetEffectiveWritePermissionStatus(); + SEQUENCE_CHECKER(sequence_checker_); private:
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc index e2a162b..5f4fb26 100644 --- a/content/browser/file_system_access/file_system_access_manager_impl.cc +++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
@@ -28,7 +28,6 @@ #include "base/task/thread_pool.h" #include "base/types/expected_macros.h" #include "base/unguessable_token.h" -#include "base/uuid.h" #include "build/build_config.h" #include "components/services/storage/public/cpp/buckets/bucket_id.h" #include "components/services/storage/public/cpp/buckets/bucket_locator.h" @@ -63,6 +62,7 @@ #include "storage/browser/file_system/file_system_url.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/common/file_system/file_system_types.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_data_transfer_token.mojom.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h" @@ -2070,6 +2070,15 @@ return weak_factory_.GetWeakPtr(); } +// static +blink::mojom::FileSystemAccessPermissionMode +FileSystemAccessManagerImpl::GetEffectiveWritePermissionMode() { + return base::FeatureList::IsEnabled( + blink::features::kFileSystemAccessWriteMode) + ? blink::mojom::FileSystemAccessPermissionMode::kWrite + : blink::mojom::FileSystemAccessPermissionMode::kReadWrite; +} + bool FileSystemAccessManagerImpl::IsSafePathComponent( storage::FileSystemType type, const url::Origin& origin,
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.h b/content/browser/file_system_access/file_system_access_manager_impl.h index d5dcc3f..59f67a2 100644 --- a/content/browser/file_system_access/file_system_access_manager_impl.h +++ b/content/browser/file_system_access/file_system_access_manager_impl.h
@@ -46,6 +46,7 @@ #include "third_party/blink/public/mojom/file_system_access/file_system_access_file_writer.mojom.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_observer_host.mojom.h" +#include "third_party/blink/public/mojom/file_system_access/file_system_access_permission_mode.mojom.h" #include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" namespace blink { @@ -389,6 +390,13 @@ // system. storage::FileSystemURL CreateFileSystemURLFromPath(const PathInfo& path_info); + // Returns the effective permission mode for operations that require write + // access. This currently returns kReadWrite, but will switch to kWrite only + // when the FileSystemAccessWriteMode feature is fully rolled out. + // See https://crbug.com/40276567. + static blink::mojom::FileSystemAccessPermissionMode + GetEffectiveWritePermissionMode(); + void Shutdown(); // The File System Access API should not give access to files that might
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/content/browser/indexed_db/indexed_db_leveldb_coding.cc index 73b8a06..de1aeb8 100644 --- a/content/browser/indexed_db/indexed_db_leveldb_coding.cc +++ b/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -19,6 +19,7 @@ #include "base/containers/span.h" #include "base/notreached.h" #include "base/numerics/byte_conversions.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/strcat.h" #include "base/strings/string_view_util.h" #include "base/strings/utf_string_conversions.h" @@ -645,9 +646,11 @@ return false; int64_t length = 0; - if (!DecodeVarInt(slice, &length) || length < 0) + size_t bytes; + if (!DecodeVarInt(slice, &length) || + !base::CheckMul(length, sizeof(char16_t)).AssignIfValid(&bytes)) { return false; - size_t bytes = length * sizeof(char16_t); + } if (slice->size() < bytes) return false; @@ -664,11 +667,15 @@ return false; int64_t length = 0; - if (!DecodeVarInt(slice, &length) || length < 0) + size_t size; + if (!DecodeVarInt(slice, &length) || + !base::MakeCheckedNum(length).AssignIfValid(&size)) { return false; - size_t size = length; - if (slice->size() < size) + } + + if (slice->size() < size) { return false; + } value->assign(slice->data(), size); slice->remove_prefix(size); @@ -680,9 +687,12 @@ return false; int64_t length = 0; - if (!DecodeVarInt(slice, &length) || length < 0) + size_t size; + if (!DecodeVarInt(slice, &length) || + !base::MakeCheckedNum(length).AssignIfValid(&size)) { return false; - size_t size = length; + } + if (slice->size() < size) return false; @@ -993,21 +1003,24 @@ *ok = false; return 0; } - if (len1 < 0 || len2 < 0) { + + size_t size1, size2; + if (!base::CheckMul(len1, sizeof(char16_t)).AssignIfValid(&size1) || + !base::CheckMul(len2, sizeof(char16_t)).AssignIfValid(&size2)) { *ok = false; return 0; } - if (slice1->size() < len1 * sizeof(char16_t) || - slice2->size() < len2 * sizeof(char16_t)) { + + if (slice1->size() < size1 || slice2->size() < size2) { *ok = false; return 0; } // Extract the string data, and advance the passed slices. - std::string_view string1(slice1->data(), len1 * sizeof(char16_t)); - std::string_view string2(slice2->data(), len2 * sizeof(char16_t)); - slice1->remove_prefix(len1 * sizeof(char16_t)); - slice2->remove_prefix(len2 * sizeof(char16_t)); + std::string_view string1(slice1->data(), size1); + std::string_view string2(slice2->data(), size2); + slice1->remove_prefix(size1); + slice2->remove_prefix(size2); *ok = true; // Strings are UTF-16BE encoded, so a simple memcmp is sufficient. @@ -1022,12 +1035,13 @@ *ok = false; return 0; } - if (len1 < 0 || len2 < 0) { + + size_t size1, size2; + if (!base::MakeCheckedNum(len1).AssignIfValid(&size1) || + !base::MakeCheckedNum(len2).AssignIfValid(&size2)) { *ok = false; return 0; } - size_t size1 = len1; - size_t size2 = len2; if (slice1->size() < size1 || slice2->size() < size2) { *ok = false;
diff --git a/content/browser/loader/merkle_integrity_source_stream.cc b/content/browser/loader/merkle_integrity_source_stream.cc index 49bc8a5..c399b55 100644 --- a/content/browser/loader/merkle_integrity_source_stream.cc +++ b/content/browser/loader/merkle_integrity_source_stream.cc
@@ -54,7 +54,7 @@ next_proof.size() != SHA256_DIGEST_LENGTH) { failed_ = true; } else { - UNSAFE_TODO(memcpy(next_proof_, next_proof.data(), SHA256_DIGEST_LENGTH)); + base::span(next_proof_).copy_from(base::as_byte_span(next_proof)); } } @@ -221,9 +221,9 @@ #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION // The fuzzer will have a hard time fixing up chains of hashes, so, if // building in fuzzer mode, everything hashes to the same garbage value. - UNSAFE_TODO(memset(sha256, 0x42, SHA256_DIGEST_LENGTH)); + std::ranges::fill(sha256, 0x42); #endif - if (UNSAFE_TODO(memcmp(sha256, next_proof_, SHA256_DIGEST_LENGTH)) != 0) { + if (base::span(sha256) != base::span(next_proof_)) { return false; } @@ -234,7 +234,7 @@ // Save the next proof. CHECK_EQ(static_cast<size_t>(SHA256_DIGEST_LENGTH), hash.size()); - UNSAFE_TODO(memcpy(next_proof_, hash.data(), SHA256_DIGEST_LENGTH)); + base::span(next_proof_).copy_from(base::as_bytes(hash)); } // Copy whatever output there is room for.
diff --git a/content/browser/memory/swap_metrics_driver_impl_linux.cc b/content/browser/memory/swap_metrics_driver_impl_linux.cc index 2e72e4662..f50f787f 100644 --- a/content/browser/memory/swap_metrics_driver_impl_linux.cc +++ b/content/browser/memory/swap_metrics_driver_impl_linux.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "base/byte_count.h" #include "base/memory/ptr_util.h" #include "base/process/process_metrics.h" #include "base/time/time.h" @@ -16,10 +17,10 @@ namespace { bool HasSwap() { - base::SystemMemoryInfoKB memory_info; + base::SystemMemoryInfo memory_info; if (!base::GetSystemMemoryInfo(&memory_info)) return false; - return memory_info.swap_total > 0; + return memory_info.swap_total > base::ByteCount(0); } } // namespace
diff --git a/content/browser/preloading/prerender/prerender_metrics.cc b/content/browser/preloading/prerender/prerender_metrics.cc index 6e82eef..0a26d739 100644 --- a/content/browser/preloading/prerender/prerender_metrics.cc +++ b/content/browser/preloading/prerender/prerender_metrics.cc
@@ -56,8 +56,8 @@ int32_t HeaderMismatchHasher(const std::string& header, HeaderMismatchType mismatch_type) { // Throw two bits away to encode the mismatch type. - // {0---30} bits are the encoded hash number. - // {31, 32} bits encode the mismatch type. + // {0---29} bits are the encoded hash number. + // {30, 31} bits encode the mismatch type. static_assert(HeaderMismatchType::kMaxValue == 3u, "HeaderMismatchType should use 2 bits at most."); return static_cast<int32_t>(base::HashMetricNameAs32Bits(header) << 2 |
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc index 156fa90..475629d 100644 --- a/content/browser/renderer_host/legacy_render_widget_host_win.cc +++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -22,6 +22,7 @@ #include "content/public/browser/content_browser_client.h" #include "content/public/common/content_client.h" #include "content/public/common/content_switches.h" +#include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/platform/ax_fragment_root_win.h" #include "ui/accessibility/platform/ax_platform.h" #include "ui/accessibility/platform/ax_system_caret_win.h" @@ -299,6 +300,14 @@ is_uia_request && ::ui::AXPlatform::GetInstance().IsUiaProviderEnabled(); const bool is_msaa_request = static_cast<DWORD>(OBJID_CLIENT) == obj_id; + if (is_uia_active && disconnecting_fragment_root_) { + // An application that calls UiaDisconnectProvider should not respond to a + // re-entrant WM_GETOBJECT message by returning a pointer to the provider + // that it is trying to disconnect. + // https://learn.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiadisconnectprovider + return 0; + } + if (is_uia_request) { CHECK_DEREF(CHECK_DEREF(GetContentClient()).browser()) .OnUiaProviderRequested(is_uia_active); @@ -600,11 +609,21 @@ LRESULT LegacyRenderWidgetHostHWND::OnDestroy(UINT message, WPARAM w_param, LPARAM l_param) { - // If we have ever returned a UIA object via WM_GETOBJECT, signal that all - // objects associated with this HWND can be discarded. See: - // https://docs.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiareturnrawelementprovider#remarks + if (ax_fragment_root_ && + base::FeatureList::IsEnabled(features::kUiaDisconnectRootProviders)) { + // Note that the fragment root's element provider is being disconnected so + // that re-entrant WM_GETOBJECT messages are not serviced. + disconnecting_fragment_root_ = true; + + // Clean up UIA resources associated with this window's fragment root; see + // https://learn.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiadisconnectprovider. + ::UiaDisconnectProvider(ax_fragment_root_->GetProvider()); + } + if (did_return_uia_object_) { - UiaReturnRawElementProvider(hwnd(), 0, 0, nullptr); + // Disassociate this window from MSAA clients that are observing events; see + // https://docs.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiareturnrawelementprovider#remarks + ::UiaReturnRawElementProvider(hwnd(), 0, 0, nullptr); } return 0;
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.h b/content/browser/renderer_host/legacy_render_widget_host_win.h index 17952b4..f9699ff 100644 --- a/content/browser/renderer_host/legacy_render_widget_host_win.h +++ b/content/browser/renderer_host/legacy_render_widget_host_win.h
@@ -201,6 +201,11 @@ // cause re-entrancy during teardown. https://crbug.com/1087553 bool did_return_uia_object_ = false; + // Set to true immediately before disconnecting the fragment root's element + // provider. From that point onward, any request for UiaRootObjectId via + // WM_GET_OBJECT will be ignored. + bool disconnecting_fragment_root_ = false; + // This class provides functionality to register the legacy window as a // Direct Manipulation consumer. This allows us to support smooth scroll // in Chrome on Windows 10.
diff --git a/content/browser/resources/traces_internals/trace_recorder.css b/content/browser/resources/traces_internals/trace_recorder.css index 21dc6503..bf12876 100644 --- a/content/browser/resources/traces_internals/trace_recorder.css +++ b/content/browser/resources/traces_internals/trace_recorder.css
@@ -109,8 +109,12 @@ margin: 8px 0; } -.category-grid { +.config-grid { display: grid; + gap: 2px 16px; + align-items: start; +} +.category-grid { /* Define column templates. - 80px for the checkbox - 1fr for the name (takes up 1 fraction of the remaining space) @@ -118,15 +122,12 @@ - 4fr for the description (takes up 4x the space of name/tags) */ grid-template-columns: 40px 1fr 1fr 4fr; - gap: 2px 16px; - align-items: start; } - .tags-grid { - display: grid; grid-template-columns: 40px 40px 1fr; - gap: 2px 16px; - align-items: start; +} +.etw-grid { + grid-template-columns: 40px 1fr 4fr; } .header-row-group { @@ -136,8 +137,7 @@ } .header-row-group, -.category-row, -.tag-row { +.row { /* This allows the cells to refer back to the parent .category-grid for their layout instructions.
diff --git a/content/browser/resources/traces_internals/trace_recorder.html.ts b/content/browser/resources/traces_internals/trace_recorder.html.ts index e1f2d78..830eb550 100644 --- a/content/browser/resources/traces_internals/trace_recorder.html.ts +++ b/content/browser/resources/traces_internals/trace_recorder.html.ts
@@ -3,6 +3,14 @@ // found in the LICENSE file. import {html} from '//resources/lit/v3_0/lit.rollup.js'; +// clang-format off +// <if expr="not is_win"> +import {nothing} from '//resources/lit/v3_0/lit.rollup.js'; +// </if> +// clang-format on + + + import type {TraceRecorderElement} from './trace_recorder.js'; function getPrivacyFilterHtml(this: TraceRecorderElement) { @@ -25,8 +33,6 @@ * UI card for configuring trace buffers. */ function getBufferConfigurationCardHtml(this: TraceRecorderElement) { - const buffer = this.traceConfig?.buffers?.[0]; - // clang-format off return html` <div class="card"> @@ -35,37 +41,74 @@ Buffer Configuration </cr-expand-button> <cr-collapse ?opened="${this.buffersExpanded_}"> - ${buffer ? html` - <div class="buffer-config-container"> - <div class="buffer-row-container growing-row"> - <h3>In-memory buffer size: ${Math.floor(this.bufferSizeMb)}MB</h3> - <cr-slider - min="4" - max="512" - .value="${this.bufferSizeMb}" - @cr-slider-value-changed="${this.onSliderValueChanged_}"> - </cr-slider> - </div> - <div class="buffer-row-container"> - <h3>Recording mode</h3> - <select class="md-select" value="${buffer.fillPolicy}" - @change="${this.onSelectValueChanged_}"> - <option value=${this.fillPolicyEnum.RING_BUFFER}> - RING BUFFER - </option> - <option value=${this.fillPolicyEnum.DISCARD}> - DISCARD - </option> - </select> - </div> + <div class="buffer-config-container"> + <div class="buffer-row-container growing-row"> + <h3>In-memory buffer size: ${Math.floor(this.bufferSizeMb)}MB</h3> + <cr-slider + min="4" + max="512" + .value="${this.bufferSizeMb}" + @cr-slider-value-changed="${this.onBufferSizeChanged_}"> + </cr-slider> </div> - ` : ''} + <div class="buffer-row-container"> + <h3>Recording mode</h3> + <select class="md-select" value="${this.bufferFillPolicy}" + @change="${this.onBufferFillPolicyChanged_}"> + <option value=${this.fillPolicyEnum.RING_BUFFER}> + RING BUFFER + </option> + <option value=${this.fillPolicyEnum.DISCARD}> + DISCARD + </option> + </select> + </div> + </div> </cr-collapse> </div> `; // clang-format on } +function getEtwConfigurationCardHtml(this: TraceRecorderElement) { + // clang-format off + // <if expr="is_win"> + return html` + <div class="card"> + <cr-expand-button class="cr-row" ?expanded="${this.etwExpanded_}" + @expanded-changed="${this.onEtwExpandedChanged_}"> + System Event Tracing for Windows + </cr-expand-button> + <cr-collapse class="expanded-content" ?opened="${this.etwExpanded_}"> + <div class="config-grid etw-grid"> + <div class="header-row-group"> + <div>Enable</div> + <div>Flag</div> + <div>Description</div> + </div> + ${this.etwProducers.map(producer => html` + <div class="row"> + <cr-toggle + class="config-toggle" + ?checked="${this.isEtwProducerEnabled(producer.flag)}" + @change="${(e: CustomEvent<boolean>) => + this.onEtwProducerChange_(e, producer.flag)}"> + </cr-toggle> + <div>${producer.name}</div> + <div>${producer.description}</div> + </div> + `)} + </div> + </cr-collapse> + </div> + `; + // </if> + // <if expr="not is_win"> + return nothing; + // </if> + // clang-format on +} + /** * UI card for selecting trace categories. */ @@ -79,14 +122,14 @@ </cr-expand-button> <cr-collapse class="expanded-content" ?opened="${this.tagsExpanded_}"> <p>Select the tags to enable or disable.</p> - <div class="tags-grid"> + <div class="config-grid tags-grid"> <div class="header-row-group"> <div>Enable</div> <div>Disable</div> <div>Tag</div> </div> ${this.trackEventTags.map(tagName => html` - <div class="tag-row"> + <div class="row"> <input type="checkbox" .checked="${this.isTagEnabled(tagName)}" @@ -112,7 +155,7 @@ class="expanded-content" ?opened="${this.categoriesExpanded_}"> <p>Select the categories to include in the trace config.</p> - <div class="category-grid"> + <div class="config-grid category-grid"> <div class="header-row-group"> <div>Enabled</div> <div>Name</div> @@ -120,7 +163,7 @@ <div>Description</div> </div> ${this.trackEventCategories.map(category => html` - <div class="category-row"> + <div class="row"> <input type="checkbox" .disabled="${this.isCategoryForced(category)}" @@ -180,6 +223,7 @@ ${getBufferConfigurationCardHtml.bind(this)()} ${getTrackEventCategoriesCardHtml.bind(this)()} + ${getEtwConfigurationCardHtml.bind(this)()} <cr-toast id="toast" duration="5000"> <div>${this.toastMessage}</div>
diff --git a/content/browser/resources/traces_internals/trace_recorder.ts b/content/browser/resources/traces_internals/trace_recorder.ts index 5c71d80..239ea230 100644 --- a/content/browser/resources/traces_internals/trace_recorder.ts +++ b/content/browser/resources/traces_internals/trace_recorder.ts
@@ -16,7 +16,11 @@ import type {Token} from '//resources/mojo/mojo/public/mojom/base/token.mojom-webui.js'; import {TraceConfig, TraceConfig_BufferConfig_FillPolicy} from './perfetto_config.js'; -import type {TraceConfig_BufferConfig, TrackEventConfig} from './perfetto_config.js'; +import type {DataSourceConfig, TraceConfig_BufferConfig, TrackEventConfig} from './perfetto_config.js'; +// <if expr="is_win"> +import {EtwConfig_KernelFlag} from './perfetto_config.js'; +import type {EtwConfig} from './perfetto_config.js'; +// </if> import {getCss} from './trace_recorder.css.js'; import {getHtml} from './trace_recorder.html.js'; import {downloadTraceData} from './trace_util.js'; @@ -55,15 +59,18 @@ return { toastMessage: {type: String}, bufferSizeMb: {type: Number}, - selectedBufferOption_: {type: Object}, + bufferFillPolicy: {type: Object}, tracingState: {type: String}, trackEventCategories: {type: Array}, trackEventTags: {type: Array}, privacyFilterEnabled_: {type: Boolean}, - traceConfig: {type: Object}, - trackEventConfig: {type: Object}, enabledCategories: {type: Object}, enabledTags: {type: Object}, + // <if expr="is_win"> + etwProducers: {type: Array}, + enabledEtwProducers: {type: Object}, + etwExpanded_: {type: Boolean}, + // </if> disabledTags: {type: Object}, buffersExpanded_: {type: Boolean}, categoriesExpanded_: {type: Boolean}, @@ -89,10 +96,6 @@ private encodedConfigString: string = ''; protected accessor toastMessage: string = ''; - protected accessor bufferSizeMb: number = 200; - protected accessor selectedBufferOption_: - TraceConfig_BufferConfig_FillPolicy = - TraceConfig_BufferConfig_FillPolicy.RING_BUFFER; // Initialize the tracing state to IDLE. protected accessor tracingState: TracingState = TracingState.IDLE; @@ -102,12 +105,27 @@ protected accessor privacyFilterEnabled_: boolean = false; - protected accessor traceConfig: TraceConfig|undefined; - protected accessor trackEventConfig: TrackEventConfig|undefined; + protected accessor bufferSizeMb: number = 200; + protected accessor bufferFillPolicy: TraceConfig_BufferConfig_FillPolicy = + TraceConfig_BufferConfig_FillPolicy.RING_BUFFER; + + protected traceConfig: TraceConfig|undefined; + protected trackEventConfig: TrackEventConfig|undefined; protected accessor enabledCategories: Set<string> = new Set(); protected accessor enabledTags: Set<string> = new Set(); protected accessor disabledTags: Set<string> = new Set(); + // <if expr="is_win"> + protected etwConfig: EtwConfig|undefined; + protected accessor etwProducers: Array<{ + name: string, + flag: EtwConfig_KernelFlag, + description: string, + }> = []; + protected accessor enabledEtwProducers: Set<EtwConfig_KernelFlag> = new Set(); + protected accessor etwExpanded_: boolean = false; + // </if> + protected accessor buffersExpanded_: boolean = false; protected accessor categoriesExpanded_: boolean = false; protected accessor tagsExpanded_: boolean = false; @@ -264,18 +282,18 @@ return this.disabledTags.has(tagName); } - protected onSliderValueChanged_(e: Event): void { + protected onBufferSizeChanged_(e: Event): void { const slider = e.target as CrSliderElement; this.bufferSizeMb = Math.floor(slider.value); this.updateBufferConfigField_('sizeKb', this.bufferSizeMb * 1024); } - protected onSelectValueChanged_(e: Event) { + protected onBufferFillPolicyChanged_(e: Event) { const selectElement = e.target as HTMLSelectElement; const policyValue = Number(selectElement.value) as TraceConfig_BufferConfig_FillPolicy; - this.selectedBufferOption_ = policyValue; + this.bufferFillPolicy = policyValue; this.updateBufferConfigField_('fillPolicy', policyValue); } @@ -307,6 +325,49 @@ this.updateUrlFromConfig_(); } + // <if expr="is_win"> + protected onEtwExpandedChanged_(e: CustomEvent<{value: boolean}>) { + this.etwExpanded_ = e.detail.value; + } + + protected isEtwProducerEnabled(producer: EtwConfig_KernelFlag): boolean { + return this.enabledEtwProducers.has(producer); + } + + protected onEtwProducerChange_( + event: CustomEvent<boolean>, producer: EtwConfig_KernelFlag): void { + if (!this.traceConfig) { + return; + } + const isChecked = event.detail; + + if (isChecked) { + this.enabledEtwProducers.add(producer); + } else { + this.enabledEtwProducers.delete(producer); + } + if (this.enabledEtwProducers.size === 0) { + this.enabledEtwProducers = new Set(); + this.etwConfig = undefined; + this.traceConfig.dataSources = this.traceConfig.dataSources?.filter( + ds => ds.config?.etwConfig === undefined); + } else { + if (!this.etwConfig) { + this.etwConfig = {}; + this.addDataSourceConfig_({ + name: 'org.chromium.etw_system', + targetBuffer: 0, + etwConfig: this.etwConfig, + }); + } + this.etwConfig.kernelFlags = [...this.enabledEtwProducers]; + this.enabledEtwProducers = new Set(this.etwConfig.kernelFlags); + } + + this.updateUrlFromConfig_(); + } + // </if> + protected onTagsChange_(event: Event, tagName: string, enabled: boolean): void { if (!this.trackEventConfig) { @@ -370,6 +431,21 @@ // Extract unique tags using flatMap and a Set. this.trackEventTags = [...new Set(categories.map(category => category.tags).flat())]; + + // <if expr="is_win"> + this.etwProducers = [ + { + name: 'Context switch', + flag: EtwConfig_KernelFlag.CSWITCH, + description: 'Enables context switch events', + }, + { + name: 'Ready Thread', + flag: EtwConfig_KernelFlag.DISPATCHER, + description: 'Enables ready thread events', + }, + ]; + // </if> } // Decodes a Base64 string into a Uint8Array. @@ -459,8 +535,20 @@ this.trackEventConfig = trackEventDataSource.config?.trackEventConfig; } else { this.trackEventConfig = this.createDefaultTrackEventConfig_(); - this.setDataSource_(this.traceConfig, this.trackEventConfig); + this.addDataSourceConfig_({ + name: 'track_event', + targetBuffer: 0, + trackEventConfig: this.trackEventConfig, + }); } + + // <if expr="is_win"> + const etwDataSource = this.traceConfig.dataSources?.find( + ds => ds.config?.etwConfig !== undefined); + if (etwDataSource) { + this.etwConfig = etwDataSource.config?.etwConfig; + } + // </if> } catch (e) { this.showToast_(`Could not parse trace config: ${e}`); this.initializeDefaultConfig_(); @@ -494,12 +582,27 @@ } private initializeDefaultConfig_(): void { + this.trackEventConfig = this.createDefaultTrackEventConfig_(); this.traceConfig = { buffers: this.createDefaultBufferConfig_(), - dataSources: [], + dataSources: [ + // DataSource for track events + { + config: { + name: 'track_event', + targetBuffer: 0, + trackEventConfig: this.trackEventConfig, + }, + }, + // DataSource for org.chromium.trace_metadata2 + { + config: { + name: 'org.chromium.trace_metadata2', + targetBuffer: 1, + }, + }, + ], }; - this.trackEventConfig = this.createDefaultTrackEventConfig_(); - this.setDataSource_(this.traceConfig, this.trackEventConfig); } private createDefaultBufferConfig_(): TraceConfig_BufferConfig[] { @@ -524,28 +627,14 @@ }; } - private setDataSource_( - config: TraceConfig, trackEventConfig: TrackEventConfig): void { - if (!config.dataSources) { - this.showToast_(`Could not get Data Source from Trace Config`); + private addDataSourceConfig_(config: DataSourceConfig) { + if (!this.traceConfig) { return; } - config.dataSources.push( - // DataSource for track events - { - config: { - name: 'track_event', - targetBuffer: 0, - trackEventConfig: trackEventConfig, - }, - }, - // DataSource for org.chromium.trace_metadata2 - { - config: { - name: 'org.chromium.trace_metadata2', - targetBuffer: 1, - }, - }); + if (!this.traceConfig.dataSources) { + this.traceConfig.dataSources = []; + } + this.traceConfig.dataSources.push({config: config}); } private updatePropertiesFromConfig_(): void { @@ -553,7 +642,7 @@ if (mainBuffer) { this.bufferSizeMb = Math.floor((mainBuffer.sizeKb ?? 0) / 1024); - this.selectedBufferOption_ = mainBuffer.fillPolicy ?? + this.bufferFillPolicy = mainBuffer.fillPolicy ?? TraceConfig_BufferConfig_FillPolicy.RING_BUFFER; } @@ -561,6 +650,12 @@ this.enabledCategories = new Set(this.trackEventConfig?.enabledCategories); this.enabledTags = new Set(this.trackEventConfig?.enabledTags); this.disabledTags = new Set(this.trackEventConfig?.disabledTags); + + // <if expr="is_win"> + if (this.etwConfig) { + this.enabledEtwProducers = new Set(this.etwConfig.kernelFlags); + } + // </if> } }
diff --git a/content/child/child_performance_coordinator.cc b/content/child/child_performance_coordinator.cc index 0c5cfe4..66c77ae9 100644 --- a/content/child/child_performance_coordinator.cc +++ b/content/child/child_performance_coordinator.cc
@@ -11,6 +11,7 @@ #include "base/functional/callback.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/weak_ptr.h" +#include "base/metrics/histogram_functions.h" #include "base/sequence_checker.h" #include "components/performance_manager/public/mojom/coordination_unit.mojom.h" #include "components/performance_manager/scenario_api/performance_scenarios.h" @@ -28,6 +29,9 @@ ChildPerformanceCoordinator::InitializeAndPassReceiver() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto receiver = coordination_unit_.BindNewPipeAndPassReceiver(); + base::UmaHistogramBoolean( + "PerformanceManager.InitializeChildProcessCoordination.RequestCount", + true); coordination_unit_->InitializeChildProcessCoordination( perfetto::ProcessTrack::Current().uuid, base::BindOnce( @@ -40,6 +44,9 @@ base::ReadOnlySharedMemoryRegion global_region, base::ReadOnlySharedMemoryRegion process_region) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::UmaHistogramBoolean( + "PerformanceManager.InitializeChildProcessCoordination.ResponseCount", + true); using performance_scenarios::ScenarioScope; if (global_region.IsValid()) { global_scenario_memory_.emplace(ScenarioScope::kGlobal,
diff --git a/content/public/test/test_file_error_injector.cc b/content/public/test/test_file_error_injector.cc index 59420be..7b5e918 100644 --- a/content/public/test/test_file_error_injector.cc +++ b/content/public/test/test_file_error_injector.cc
@@ -52,9 +52,8 @@ // DownloadFile interface. download::DownloadInterruptReason ValidateAndWriteDataToFile( int64_t offset, - const char* data, - size_t bytes_to_validate, - size_t bytes_to_write) override; + base::span<const uint8_t> to_validate, + base::span<const uint8_t> to_write) override; download::DownloadInterruptReason HandleStreamCompletionStatus( SourceStream* source_stream) override; @@ -178,16 +177,16 @@ } download::DownloadInterruptReason -DownloadFileWithError::ValidateAndWriteDataToFile(int64_t offset, - const char* data, - size_t bytes_to_validate, - size_t bytes_to_write) { +DownloadFileWithError::ValidateAndWriteDataToFile( + int64_t offset, + base::span<const uint8_t> to_validate, + base::span<const uint8_t> to_write) { download::DownloadInterruptReason origin_error = download::DownloadFileImpl::ValidateAndWriteDataToFile( - offset, data, bytes_to_validate, bytes_to_write); + offset, to_validate, to_write); if (error_info_.data_write_offset == -1 || ((offset <= error_info_.data_write_offset) && - (offset + bytes_to_write >= + (offset + to_write.size() >= static_cast<size_t>(error_info_.data_write_offset)))) { return ShouldReturnError(TestFileErrorInjector::FILE_OPERATION_WRITE, origin_error);
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist index 041278c..dbfcf503 100644 --- a/content/test/content_test_bundle_data.filelist +++ b/content/test/content_test_bundle_data.filelist
@@ -6163,133 +6163,131 @@ data/accessibility/material-design/version-info-expected-auralinux.txt data/accessibility/material-design/version-info-expected-blink.txt data/accessibility/material-design/version-info.html +data/accessibility/mathml/annotation-expected-blink.txt data/accessibility/mathml/annotation-node-expected-auralinux.txt -data/accessibility/mathml/annotation-node-expected-blink.txt data/accessibility/mathml/annotation-node-expected-mac.txt +data/accessibility/mathml/annotation-xml-expected-blink.txt data/accessibility/mathml/annotation-xml-node-expected-auralinux.txt -data/accessibility/mathml/annotation-xml-node-expected-blink.txt data/accessibility/mathml/annotation-xml-node-expected-mac.txt data/accessibility/mathml/annotation-xml.html data/accessibility/mathml/annotation.html +data/accessibility/mathml/maction-expected-blink.txt data/accessibility/mathml/maction-node-expected-auralinux.txt -data/accessibility/mathml/maction-node-expected-blink.txt data/accessibility/mathml/maction-node-expected-mac.txt data/accessibility/mathml/maction.html +data/accessibility/mathml/math-expected-blink.txt data/accessibility/mathml/math-node-expected-auralinux.txt -data/accessibility/mathml/math-node-expected-blink.txt data/accessibility/mathml/math-node-expected-mac.txt data/accessibility/mathml/math-node-expected-uia-win.txt data/accessibility/mathml/math-node-expected-win.txt data/accessibility/mathml/math.html +data/accessibility/mathml/merror-expected-blink.txt data/accessibility/mathml/merror-node-expected-auralinux.txt -data/accessibility/mathml/merror-node-expected-blink.txt data/accessibility/mathml/merror-node-expected-mac.txt data/accessibility/mathml/merror.html +data/accessibility/mathml/mfrac-expected-blink.txt data/accessibility/mathml/mfrac-node-expected-auralinux.txt -data/accessibility/mathml/mfrac-node-expected-blink.txt data/accessibility/mathml/mfrac-node-expected-mac.txt data/accessibility/mathml/mfrac.html +data/accessibility/mathml/mi-expected-blink.txt data/accessibility/mathml/mi-node-expected-auralinux.txt -data/accessibility/mathml/mi-node-expected-blink.txt data/accessibility/mathml/mi-node-expected-mac.txt data/accessibility/mathml/mi.html +data/accessibility/mathml/mmultiscripts-expected-blink.txt data/accessibility/mathml/mmultiscripts-node-expected-auralinux.txt -data/accessibility/mathml/mmultiscripts-node-expected-blink.txt data/accessibility/mathml/mmultiscripts-node-expected-mac.txt data/accessibility/mathml/mmultiscripts.html +data/accessibility/mathml/mn-expected-blink.txt data/accessibility/mathml/mn-node-expected-auralinux.txt -data/accessibility/mathml/mn-node-expected-blink.txt data/accessibility/mathml/mn-node-expected-mac.txt data/accessibility/mathml/mn.html +data/accessibility/mathml/mo-expected-blink.txt data/accessibility/mathml/mo-node-expected-auralinux.txt -data/accessibility/mathml/mo-node-expected-blink.txt data/accessibility/mathml/mo-node-expected-mac.txt data/accessibility/mathml/mo.html +data/accessibility/mathml/mover-expected-blink.txt data/accessibility/mathml/mover-node-expected-auralinux.txt -data/accessibility/mathml/mover-node-expected-blink.txt data/accessibility/mathml/mover-node-expected-mac.txt data/accessibility/mathml/mover.html +data/accessibility/mathml/mpadded-expected-blink.txt data/accessibility/mathml/mpadded-node-expected-auralinux.txt -data/accessibility/mathml/mpadded-node-expected-blink.txt data/accessibility/mathml/mpadded-node-expected-mac.txt data/accessibility/mathml/mpadded.html +data/accessibility/mathml/mphantom-expected-blink.txt data/accessibility/mathml/mphantom-node-expected-auralinux.txt -data/accessibility/mathml/mphantom-node-expected-blink.txt data/accessibility/mathml/mphantom-node-expected-mac.txt data/accessibility/mathml/mphantom.html +data/accessibility/mathml/mprescripts-expected-blink.txt data/accessibility/mathml/mprescripts-node-expected-auralinux.txt -data/accessibility/mathml/mprescripts-node-expected-blink.txt data/accessibility/mathml/mprescripts-node-expected-mac.txt data/accessibility/mathml/mprescripts.html +data/accessibility/mathml/mroot-expected-blink.txt data/accessibility/mathml/mroot-node-expected-auralinux.txt -data/accessibility/mathml/mroot-node-expected-blink.txt data/accessibility/mathml/mroot-node-expected-mac.txt data/accessibility/mathml/mroot.html +data/accessibility/mathml/mrow-expected-blink.txt data/accessibility/mathml/mrow-node-expected-auralinux.txt -data/accessibility/mathml/mrow-node-expected-blink.txt data/accessibility/mathml/mrow-node-expected-mac.txt data/accessibility/mathml/mrow.html +data/accessibility/mathml/ms-expected-blink.txt data/accessibility/mathml/ms-node-expected-auralinux.txt -data/accessibility/mathml/ms-node-expected-blink.txt data/accessibility/mathml/ms-node-expected-mac.txt data/accessibility/mathml/ms.html data/accessibility/mathml/mspace-expected-blink.txt -data/accessibility/mathml/mspace-node-expected-blink.txt data/accessibility/mathml/mspace.html +data/accessibility/mathml/msqrt-expected-blink.txt data/accessibility/mathml/msqrt-node-expected-auralinux.txt -data/accessibility/mathml/msqrt-node-expected-blink.txt data/accessibility/mathml/msqrt-node-expected-mac.txt data/accessibility/mathml/msqrt.html +data/accessibility/mathml/mstyle-expected-blink.txt data/accessibility/mathml/mstyle-node-expected-auralinux.txt -data/accessibility/mathml/mstyle-node-expected-blink.txt data/accessibility/mathml/mstyle-node-expected-mac.txt data/accessibility/mathml/mstyle.html +data/accessibility/mathml/msub-expected-blink.txt data/accessibility/mathml/msub-node-expected-auralinux.txt -data/accessibility/mathml/msub-node-expected-blink.txt data/accessibility/mathml/msub-node-expected-mac.txt data/accessibility/mathml/msub.html +data/accessibility/mathml/msubsup-expected-blink.txt data/accessibility/mathml/msubsup-node-expected-auralinux.txt -data/accessibility/mathml/msubsup-node-expected-blink.txt data/accessibility/mathml/msubsup-node-expected-mac.txt data/accessibility/mathml/msubsup.html +data/accessibility/mathml/msup-expected-blink.txt data/accessibility/mathml/msup-node-expected-auralinux.txt -data/accessibility/mathml/msup-node-expected-blink.txt data/accessibility/mathml/msup-node-expected-mac.txt data/accessibility/mathml/msup.html +data/accessibility/mathml/mtable-expected-blink.txt data/accessibility/mathml/mtable-node-expected-auralinux.txt -data/accessibility/mathml/mtable-node-expected-blink.txt data/accessibility/mathml/mtable-node-expected-mac.txt data/accessibility/mathml/mtable.html +data/accessibility/mathml/mtd-expected-blink.txt data/accessibility/mathml/mtd-node-expected-auralinux.txt -data/accessibility/mathml/mtd-node-expected-blink.txt data/accessibility/mathml/mtd-node-expected-mac.txt data/accessibility/mathml/mtd.html +data/accessibility/mathml/mtext-expected-blink.txt data/accessibility/mathml/mtext-node-expected-auralinux.txt -data/accessibility/mathml/mtext-node-expected-blink.txt data/accessibility/mathml/mtext-node-expected-mac.txt data/accessibility/mathml/mtext.html +data/accessibility/mathml/mtr-expected-blink.txt data/accessibility/mathml/mtr-node-expected-auralinux.txt -data/accessibility/mathml/mtr-node-expected-blink.txt data/accessibility/mathml/mtr-node-expected-mac.txt data/accessibility/mathml/mtr.html +data/accessibility/mathml/munder-expected-blink.txt data/accessibility/mathml/munder-node-expected-auralinux.txt -data/accessibility/mathml/munder-node-expected-blink.txt data/accessibility/mathml/munder-node-expected-mac.txt data/accessibility/mathml/munder.html +data/accessibility/mathml/munderover-expected-blink.txt data/accessibility/mathml/munderover-node-expected-auralinux.txt -data/accessibility/mathml/munderover-node-expected-blink.txt data/accessibility/mathml/munderover-node-expected-mac.txt data/accessibility/mathml/munderover.html +data/accessibility/mathml/none-expected-blink.txt data/accessibility/mathml/none-node-expected-auralinux.txt -data/accessibility/mathml/none-node-expected-blink.txt data/accessibility/mathml/none-node-expected-mac.txt data/accessibility/mathml/none.html +data/accessibility/mathml/semantics-expected-blink.txt data/accessibility/mathml/semantics-node-expected-auralinux.txt -data/accessibility/mathml/semantics-node-expected-blink.txt data/accessibility/mathml/semantics-node-expected-mac.txt data/accessibility/mathml/semantics.html data/accessibility/mathml/unknown-expected-blink.txt -data/accessibility/mathml/unknown-node-expected-blink.txt data/accessibility/mathml/unknown.html data/accessibility/readme.md data/accessibility/regression/add-child-of-not-included-in-tree-chain-expected-blink.txt
diff --git a/content/test/data/accessibility/aria/aria-flowto-expected-android-external.txt b/content/test/data/accessibility/aria/aria-flowto-expected-android-external.txt index 694ca44..fb5d5661 100644 --- a/content/test/data/accessibility/aria/aria-flowto-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-flowto-expected-android-external.txt
@@ -1,3 +1,3 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++View text:"current" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] +++View text:"Lorem ipsum" containerTitle:"current" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++View text:"next" viewIdResName:"next" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="footer", roleDescription="footer"]
diff --git a/content/test/data/accessibility/aria/aria-flowto-expected-android.txt b/content/test/data/accessibility/aria/aria-flowto-expected-android.txt index 08b56a5..85fa3ba 100644 --- a/content/test/data/accessibility/aria/aria-flowto-expected-android.txt +++ b/content/test/data/accessibility/aria/aria-flowto-expected-android.txt
@@ -1,3 +1,3 @@ android.webkit.WebView focusable focused -++android.view.View role_description='region' interesting name='current' +++android.view.View role_description='region' interesting name='Lorem ipsum' container_title='current' ++android.view.View role_description='footer' interesting name='next'
diff --git a/content/test/data/accessibility/aria/aria-form-expected-android-external.txt b/content/test/data/accessibility/aria/aria-form-expected-android-external.txt index 943c3e03..601a6dd8 100644 --- a/content/test/data/accessibility/aria/aria-form-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-form-expected-android-external.txt
@@ -1,7 +1,7 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Unnamed ARIA form: must fall back to the native role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++TextView text:"Unnamed ARIA form on plain div uses generic container role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++View text:"Named form" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="form"] +++View text:"Named ARIA form#1 gets the form role." containerTitle:"Named form" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="form"] ++View text:"Named ARIA form#2 gets the form role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="form"] ++++TextView text:"Named ARIA form#2 gets the form role." viewIdResName:"form-name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View text:"Named form" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="form"]
diff --git a/content/test/data/accessibility/aria/aria-form-expected-android.txt b/content/test/data/accessibility/aria/aria-form-expected-android.txt index aa2b04a..c532473 100644 --- a/content/test/data/accessibility/aria/aria-form-expected-android.txt +++ b/content/test/data/accessibility/aria/aria-form-expected-android.txt
@@ -1,7 +1,7 @@ android.webkit.WebView focusable focused ++android.view.View interesting name='Unnamed ARIA form: must fall back to the native role.' ++android.widget.TextView interesting name='Unnamed ARIA form on plain div uses generic container role.' -++android.view.View interesting name='Named form' +++android.view.View interesting name='Named ARIA form#1 gets the form role.' container_title='Named form' ++android.view.View name='Named ARIA form#2 gets the form role.' ++++android.widget.TextView interesting name='Named ARIA form#2 gets the form role.' ++android.view.View interesting name='Named form'
diff --git a/content/test/data/accessibility/aria/aria-label-with-tabindex-expected-android-external.txt b/content/test/data/accessibility/aria/aria-label-with-tabindex-expected-android-external.txt index a8b8343..d3a24e4 100644 --- a/content/test/data/accessibility/aria/aria-label-with-tabindex-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-label-with-tabindex-expected-android-external.txt
@@ -1,7 +1,7 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++View text:"test-label" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] +++View containerTitle:"test-label" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++++TextView text:"Test" heading actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 3"] ++++TextView text:"This is test content within a section, tab index negative 1. I am missing on Android." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] -++View text:"test-label-2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] +++View containerTitle:"test-label-2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++++TextView text:"Test" heading actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 3"] ++++TextView text:"This is test content within a section, no tab index." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/aria/aria-label-with-tabindex-expected-android.txt b/content/test/data/accessibility/aria/aria-label-with-tabindex-expected-android.txt index 943dfd85..ff9fec4 100644 --- a/content/test/data/accessibility/aria/aria-label-with-tabindex-expected-android.txt +++ b/content/test/data/accessibility/aria/aria-label-with-tabindex-expected-android.txt
@@ -1,7 +1,7 @@ android.webkit.WebView focusable focused -++android.view.View role_description='region' focusable interesting name='test-label' +++android.view.View role_description='region' focusable interesting container_title='test-label' ++++android.widget.TextView role_description='heading 3' heading interesting name='Test' ++++android.widget.TextView interesting name='This is test content within a section, tab index negative 1. I am missing on Android.' -++android.view.View role_description='region' name='test-label-2' +++android.view.View role_description='region' container_title='test-label-2' ++++android.widget.TextView role_description='heading 3' heading interesting name='Test' ++++android.widget.TextView interesting name='This is test content within a section, no tab index.'
diff --git a/content/test/data/accessibility/aria/aria-region-expected-android-external.txt b/content/test/data/accessibility/aria/aria-region-expected-android-external.txt index bde0a45..82e676f 100644 --- a/content/test/data/accessibility/aria/aria-region-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-region-expected-android-external.txt
@@ -1,7 +1,7 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Unnamed ARIA region: must fall back to the native role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++TextView text:"Unnamed ARIA region on plain div uses generic container role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++View text:"Named region" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] +++View text:"Named ARIA region#1 gets the region role." containerTitle:"Named region" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++View text:"Named ARIA region#2 gets the region role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++++TextView text:"Named ARIA region#2 gets the region role." viewIdResName:"region-name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View text:"Named region" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"]
diff --git a/content/test/data/accessibility/aria/aria-region-expected-android.txt b/content/test/data/accessibility/aria/aria-region-expected-android.txt index 2991f9d..e3a3d59 100644 --- a/content/test/data/accessibility/aria/aria-region-expected-android.txt +++ b/content/test/data/accessibility/aria/aria-region-expected-android.txt
@@ -1,7 +1,7 @@ android.webkit.WebView focusable focused ++android.view.View interesting name='Unnamed ARIA region: must fall back to the native role.' ++android.widget.TextView interesting name='Unnamed ARIA region on plain div uses generic container role.' -++android.view.View role_description='region' interesting name='Named region' +++android.view.View role_description='region' interesting name='Named ARIA region#1 gets the region role.' container_title='Named region' ++android.view.View role_description='region' name='Named ARIA region#2 gets the region role.' ++++android.widget.TextView interesting name='Named ARIA region#2 gets the region role.' ++android.view.View role_description='region' interesting name='Named region'
diff --git a/content/test/data/accessibility/aria/supplemental-description-nav-expected-android.txt b/content/test/data/accessibility/aria/supplemental-description-nav-expected-android.txt index 5b7fcf9..7997921 100644 --- a/content/test/data/accessibility/aria/supplemental-description-nav-expected-android.txt +++ b/content/test/data/accessibility/aria/supplemental-description-nav-expected-android.txt
@@ -1,6 +1,6 @@ android.webkit.WebView focusable focused ++android.widget.TextView interesting name='The nav element defines a set of navigation links:' -++com.google.android.material.navigation.NavigationView role_description='navigation' name='programming languages' +++com.google.android.material.navigation.NavigationView role_description='navigation' container_title='programming languages' ++++android.view.View role_description='link' clickable focusable link interesting name='HTML' ++++++android.widget.TextView name='HTML' ++++android.widget.TextView interesting name=' | '
diff --git a/content/test/data/accessibility/aria/supplemental-description-region-expected-android.txt b/content/test/data/accessibility/aria/supplemental-description-region-expected-android.txt index 3bbf583..8889c25 100644 --- a/content/test/data/accessibility/aria/supplemental-description-region-expected-android.txt +++ b/content/test/data/accessibility/aria/supplemental-description-region-expected-android.txt
@@ -1,4 +1,4 @@ android.webkit.WebView focusable focused ++android.view.View -++++android.view.View role_description='region' name='Example' +++++android.view.View role_description='region' container_title='Example' ++++++android.widget.TextView interesting name='The region role should be reserved for sections of content sufficiently important that users will likely want to navigate to the section easily and to have it listed in a summary of the page.'
diff --git a/content/test/data/accessibility/html/form-expected-android-external.txt b/content/test/data/accessibility/html/form-expected-android-external.txt index 944d815..041f3ba 100644 --- a/content/test/data/accessibility/html/form-expected-android-external.txt +++ b/content/test/data/accessibility/html/form-expected-android-external.txt
@@ -1,5 +1,5 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="sectionWithoutName"] ++++Button text:"Submit" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] -++View text:"Name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="form"] +++View containerTitle:"Name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="form"] ++++Button text:"Submit" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/html/form-expected-android.txt b/content/test/data/accessibility/html/form-expected-android.txt index 8dc8f2e..ef48e6e8 100644 --- a/content/test/data/accessibility/html/form-expected-android.txt +++ b/content/test/data/accessibility/html/form-expected-android.txt
@@ -1,5 +1,5 @@ android.webkit.WebView focusable focused ++android.view.View ++++android.widget.Button role_description='button' clickable focusable interesting name='Submit' -++android.view.View name='Name' +++android.view.View container_title='Name' ++++android.widget.Button role_description='button' clickable focusable interesting name='Submit'
diff --git a/content/test/data/accessibility/html/iframe-cross-process-expected-android-external.txt b/content/test/data/accessibility/html/iframe-cross-process-expected-android-external.txt index 6e0ed2f..6ab3e0b 100644 --- a/content/test/data/accessibility/html/iframe-cross-process-expected-android-external.txt +++ b/content/test/data/accessibility/html/iframe-cross-process-expected-android-external.txt
@@ -1,7 +1,7 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Before frame" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="iframe"] +++++View containerTitle:"Cross-process iframe" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="iframe"] ++++++View text:"Error" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++++++++TextView text:"Could not load the requested resource.\nError code: -6 (net::ERR_FILE_NOT_FOUND)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"After frame" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"]
diff --git a/content/test/data/accessibility/html/iframe-expected-android-external.txt b/content/test/data/accessibility/html/iframe-expected-android-external.txt index 7a3176e..ac428c1f 100644 --- a/content/test/data/accessibility/html/iframe-expected-android-external.txt +++ b/content/test/data/accessibility/html/iframe-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="iframe"] +++++View containerTitle:"Empty iframe" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="iframe"] ++++++View actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"]
diff --git a/content/test/data/accessibility/html/iframe-expected-android.txt b/content/test/data/accessibility/html/iframe-expected-android.txt index e4319a996..5de80b4 100644 --- a/content/test/data/accessibility/html/iframe-expected-android.txt +++ b/content/test/data/accessibility/html/iframe-expected-android.txt
@@ -1,4 +1,4 @@ android.webkit.WebView focusable focused ++android.view.View -++++android.view.View focusable interesting +++++android.view.View focusable interesting container_title='Empty iframe' ++++++android.view.View
diff --git a/content/test/data/accessibility/html/landmark-expected-android.txt b/content/test/data/accessibility/html/landmark-expected-android.txt index 10119ce..399f4e9 100644 --- a/content/test/data/accessibility/html/landmark-expected-android.txt +++ b/content/test/data/accessibility/html/landmark-expected-android.txt
@@ -10,7 +10,7 @@ ++android.view.View role_description='banner' interesting name='This is an ARIA banner landmark.' ++android.view.View role_description='complementary' interesting name='This is an ARIA complementary landmark.' ++android.view.View role_description='content information' interesting name='This is an ARIA contentinfo landmark.' -++android.view.View interesting name='Named form' +++android.view.View interesting name='This is an ARIA form landmark.' container_title='Named form' ++android.view.View role_description='main' interesting name='This is an ARIA main landmark.' ++com.google.android.material.navigation.NavigationView role_description='navigation' interesting name='This is an ARIA navigation landmark.' ++android.widget.SearchView role_description='search' interesting name='This is an ARIA search landmark.'
diff --git a/content/test/data/accessibility/html/replaced-node-across-trees-expected-android-external.txt b/content/test/data/accessibility/html/replaced-node-across-trees-expected-android-external.txt index 34f8e11..af2c81e4 100644 --- a/content/test/data/accessibility/html/replaced-node-across-trees-expected-android-external.txt +++ b/content/test/data/accessibility/html/replaced-node-across-trees-expected-android-external.txt
@@ -1,7 +1,7 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"Before frame" viewIdResName:"s1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++View focusable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="iframe"] +++++View containerTitle:"Cross-process iframe" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="iframe"] ++++++View actions:[AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++++++++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++++++++TextView text:"Text in iframe" viewIdResName:"s1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"]
diff --git a/content/test/data/accessibility/html/section-expected-android-external.txt b/content/test/data/accessibility/html/section-expected-android-external.txt index 61ad2a7..ee3b89b 100644 --- a/content/test/data/accessibility/html/section-expected-android-external.txt +++ b/content/test/data/accessibility/html/section-expected-android-external.txt
@@ -1,6 +1,6 @@ WebView focusable focused actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"An unnamed section element gets the generic role." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="sectionWithoutName"] -++View text:"name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] +++View text:"Named section element #1 gets the region role" containerTitle:"name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++View text:"Named section element #2 gets the region role" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"] ++++TextView text:"Named section element #2 gets the region role" viewIdResName:"section1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++View text:"name" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="region", roleDescription="region"]
diff --git a/content/test/data/accessibility/html/section-expected-android.txt b/content/test/data/accessibility/html/section-expected-android.txt index 5e3358f2..05ddb37 100644 --- a/content/test/data/accessibility/html/section-expected-android.txt +++ b/content/test/data/accessibility/html/section-expected-android.txt
@@ -1,6 +1,6 @@ android.webkit.WebView focusable focused ++android.view.View interesting name='An unnamed section element gets the generic role.' -++android.view.View role_description='region' interesting name='name' +++android.view.View role_description='region' interesting name='Named section element #1 gets the region role' container_title='name' ++android.view.View role_description='region' name='Named section element #2 gets the region role' ++++android.widget.TextView interesting name='Named section element #2 gets the region role' ++android.view.View role_description='region' interesting name='name'
diff --git a/content/test/data/accessibility/mathml/annotation-expected-blink.txt b/content/test/data/accessibility/mathml/annotation-expected-blink.txt new file mode 100644 index 0000000..709794dd --- /dev/null +++ b/content/test/data/accessibility/mathml/annotation-expected-blink.txt
@@ -0,0 +1,13 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow +++++++++++mathMLFraction +++++++++++++mathMLNumber +++++++++++++++staticText name='1' +++++++++++++++++inlineTextBox name='1' +++++++++++++mathMLNumber +++++++++++++++staticText name='2' +++++++++++++++++inlineTextBox name='2' +++++++++++mathMLText
diff --git a/content/test/data/accessibility/mathml/annotation-node-expected-blink.txt b/content/test/data/accessibility/mathml/annotation-node-expected-blink.txt deleted file mode 100644 index 32fea28..0000000 --- a/content/test/data/accessibility/mathml/annotation-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLText
diff --git a/content/test/data/accessibility/mathml/annotation-xml-expected-blink.txt b/content/test/data/accessibility/mathml/annotation-xml-expected-blink.txt new file mode 100644 index 0000000..8476a4db --- /dev/null +++ b/content/test/data/accessibility/mathml/annotation-xml-expected-blink.txt
@@ -0,0 +1,17 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow +++++++++++mathMLFraction +++++++++++++mathMLNumber +++++++++++++++staticText name='1' +++++++++++++++++inlineTextBox name='1' +++++++++++++mathMLNumber +++++++++++++++staticText name='2' +++++++++++++++++inlineTextBox name='2' +++++++++++mathMLRow +++++++++++++genericContainer ignored +++++++++++++++genericContainer ignored +++++++++++++++genericContainer ignored +++++++++++++++genericContainer ignored
diff --git a/content/test/data/accessibility/mathml/annotation-xml-node-expected-blink.txt b/content/test/data/accessibility/mathml/annotation-xml-node-expected-blink.txt deleted file mode 100644 index 985cbc43..0000000 --- a/content/test/data/accessibility/mathml/annotation-xml-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRow
diff --git a/content/test/data/accessibility/mathml/maction-expected-blink.txt b/content/test/data/accessibility/mathml/maction-expected-blink.txt new file mode 100644 index 0000000..462ef237 --- /dev/null +++ b/content/test/data/accessibility/mathml/maction-expected-blink.txt
@@ -0,0 +1,8 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1'
diff --git a/content/test/data/accessibility/mathml/maction-node-expected-blink.txt b/content/test/data/accessibility/mathml/maction-node-expected-blink.txt deleted file mode 100644 index 985cbc43..0000000 --- a/content/test/data/accessibility/mathml/maction-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRow
diff --git a/content/test/data/accessibility/mathml/math-expected-blink.txt b/content/test/data/accessibility/mathml/math-expected-blink.txt new file mode 100644 index 0000000..b8cd6f3 --- /dev/null +++ b/content/test/data/accessibility/mathml/math-expected-blink.txt
@@ -0,0 +1,4 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath
diff --git a/content/test/data/accessibility/mathml/math-node-expected-blink.txt b/content/test/data/accessibility/mathml/math-node-expected-blink.txt deleted file mode 100644 index a536271..0000000 --- a/content/test/data/accessibility/mathml/math-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLMath
diff --git a/content/test/data/accessibility/mathml/merror-expected-blink.txt b/content/test/data/accessibility/mathml/merror-expected-blink.txt new file mode 100644 index 0000000..bcac6d1b --- /dev/null +++ b/content/test/data/accessibility/mathml/merror-expected-blink.txt
@@ -0,0 +1,17 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++++++mathMLNumber +++++++++++++staticText name='4' +++++++++++++++inlineTextBox name='4'
diff --git a/content/test/data/accessibility/mathml/merror-node-expected-blink.txt b/content/test/data/accessibility/mathml/merror-node-expected-blink.txt deleted file mode 100644 index 985cbc43..0000000 --- a/content/test/data/accessibility/mathml/merror-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRow
diff --git a/content/test/data/accessibility/mathml/mfrac-expected-blink.txt b/content/test/data/accessibility/mathml/mfrac-expected-blink.txt new file mode 100644 index 0000000..82d1704 --- /dev/null +++ b/content/test/data/accessibility/mathml/mfrac-expected-blink.txt
@@ -0,0 +1,11 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLFraction +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2'
diff --git a/content/test/data/accessibility/mathml/mfrac-node-expected-blink.txt b/content/test/data/accessibility/mathml/mfrac-node-expected-blink.txt deleted file mode 100644 index b7a2019de..0000000 --- a/content/test/data/accessibility/mathml/mfrac-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLFraction
diff --git a/content/test/data/accessibility/mathml/mi-expected-blink.txt b/content/test/data/accessibility/mathml/mi-expected-blink.txt new file mode 100644 index 0000000..8e0b147 --- /dev/null +++ b/content/test/data/accessibility/mathml/mi-expected-blink.txt
@@ -0,0 +1,7 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLIdentifier +++++++++++staticText name='sin' +++++++++++++inlineTextBox name='sin'
diff --git a/content/test/data/accessibility/mathml/mi-node-expected-blink.txt b/content/test/data/accessibility/mathml/mi-node-expected-blink.txt deleted file mode 100644 index 67c947ee..0000000 --- a/content/test/data/accessibility/mathml/mi-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLIdentifier
diff --git a/content/test/data/accessibility/mathml/mmultiscripts-expected-blink.txt b/content/test/data/accessibility/mathml/mmultiscripts-expected-blink.txt new file mode 100644 index 0000000..a570345f --- /dev/null +++ b/content/test/data/accessibility/mathml/mmultiscripts-expected-blink.txt
@@ -0,0 +1,29 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLMultiscripts +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++++++mathMLNoneScript +++++++++++mathMLNumber +++++++++++++staticText name='5' +++++++++++++++inlineTextBox name='5' +++++++++++mathMLPrescriptDelimiter +++++++++++mathMLNumber +++++++++++++staticText name='6' +++++++++++++++inlineTextBox name='6' +++++++++++mathMLNoneScript +++++++++++mathMLNumber +++++++++++++staticText name='8' +++++++++++++++inlineTextBox name='8' +++++++++++mathMLNumber +++++++++++++staticText name='9' +++++++++++++++inlineTextBox name='9'
diff --git a/content/test/data/accessibility/mathml/mmultiscripts-node-expected-blink.txt b/content/test/data/accessibility/mathml/mmultiscripts-node-expected-blink.txt deleted file mode 100644 index 8a665bcc..0000000 --- a/content/test/data/accessibility/mathml/mmultiscripts-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLMultiscripts
diff --git a/content/test/data/accessibility/mathml/mn-expected-blink.txt b/content/test/data/accessibility/mathml/mn-expected-blink.txt new file mode 100644 index 0000000..0a8575d --- /dev/null +++ b/content/test/data/accessibility/mathml/mn-expected-blink.txt
@@ -0,0 +1,7 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLNumber +++++++++++staticText name='42' +++++++++++++inlineTextBox name='42'
diff --git a/content/test/data/accessibility/mathml/mn-node-expected-blink.txt b/content/test/data/accessibility/mathml/mn-node-expected-blink.txt deleted file mode 100644 index 7d77967..0000000 --- a/content/test/data/accessibility/mathml/mn-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLNumber
diff --git a/content/test/data/accessibility/mathml/mo-expected-blink.txt b/content/test/data/accessibility/mathml/mo-expected-blink.txt new file mode 100644 index 0000000..f0b2746 --- /dev/null +++ b/content/test/data/accessibility/mathml/mo-expected-blink.txt
@@ -0,0 +1,7 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLOperator +++++++++++staticText name='+' +++++++++++++inlineTextBox name='+'
diff --git a/content/test/data/accessibility/mathml/mo-node-expected-blink.txt b/content/test/data/accessibility/mathml/mo-node-expected-blink.txt deleted file mode 100644 index 1fafde6..0000000 --- a/content/test/data/accessibility/mathml/mo-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLOperator
diff --git a/content/test/data/accessibility/mathml/mover-expected-blink.txt b/content/test/data/accessibility/mathml/mover-expected-blink.txt new file mode 100644 index 0000000..b5ccec0 --- /dev/null +++ b/content/test/data/accessibility/mathml/mover-expected-blink.txt
@@ -0,0 +1,11 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLOver +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2'
diff --git a/content/test/data/accessibility/mathml/mover-node-expected-blink.txt b/content/test/data/accessibility/mathml/mover-node-expected-blink.txt deleted file mode 100644 index 441eed89..0000000 --- a/content/test/data/accessibility/mathml/mover-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLOver
diff --git a/content/test/data/accessibility/mathml/mpadded-expected-blink.txt b/content/test/data/accessibility/mathml/mpadded-expected-blink.txt new file mode 100644 index 0000000..bcac6d1b --- /dev/null +++ b/content/test/data/accessibility/mathml/mpadded-expected-blink.txt
@@ -0,0 +1,17 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++++++mathMLNumber +++++++++++++staticText name='4' +++++++++++++++inlineTextBox name='4'
diff --git a/content/test/data/accessibility/mathml/mpadded-node-expected-blink.txt b/content/test/data/accessibility/mathml/mpadded-node-expected-blink.txt deleted file mode 100644 index 985cbc43..0000000 --- a/content/test/data/accessibility/mathml/mpadded-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRow
diff --git a/content/test/data/accessibility/mathml/mphantom-expected-blink.txt b/content/test/data/accessibility/mathml/mphantom-expected-blink.txt new file mode 100644 index 0000000..ad924c5 --- /dev/null +++ b/content/test/data/accessibility/mathml/mphantom-expected-blink.txt
@@ -0,0 +1,5 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow
diff --git a/content/test/data/accessibility/mathml/mphantom-node-expected-blink.txt b/content/test/data/accessibility/mathml/mphantom-node-expected-blink.txt deleted file mode 100644 index 985cbc43..0000000 --- a/content/test/data/accessibility/mathml/mphantom-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRow
diff --git a/content/test/data/accessibility/mathml/mprescripts-expected-blink.txt b/content/test/data/accessibility/mathml/mprescripts-expected-blink.txt new file mode 100644 index 0000000..a570345f --- /dev/null +++ b/content/test/data/accessibility/mathml/mprescripts-expected-blink.txt
@@ -0,0 +1,29 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLMultiscripts +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++++++mathMLNoneScript +++++++++++mathMLNumber +++++++++++++staticText name='5' +++++++++++++++inlineTextBox name='5' +++++++++++mathMLPrescriptDelimiter +++++++++++mathMLNumber +++++++++++++staticText name='6' +++++++++++++++inlineTextBox name='6' +++++++++++mathMLNoneScript +++++++++++mathMLNumber +++++++++++++staticText name='8' +++++++++++++++inlineTextBox name='8' +++++++++++mathMLNumber +++++++++++++staticText name='9' +++++++++++++++inlineTextBox name='9'
diff --git a/content/test/data/accessibility/mathml/mprescripts-node-expected-blink.txt b/content/test/data/accessibility/mathml/mprescripts-node-expected-blink.txt deleted file mode 100644 index 83e93a71..0000000 --- a/content/test/data/accessibility/mathml/mprescripts-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLPrescriptDelimiter
diff --git a/content/test/data/accessibility/mathml/mroot-expected-blink.txt b/content/test/data/accessibility/mathml/mroot-expected-blink.txt new file mode 100644 index 0000000..f3c317e --- /dev/null +++ b/content/test/data/accessibility/mathml/mroot-expected-blink.txt
@@ -0,0 +1,11 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRoot +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2'
diff --git a/content/test/data/accessibility/mathml/mroot-node-expected-blink.txt b/content/test/data/accessibility/mathml/mroot-node-expected-blink.txt deleted file mode 100644 index 9031466..0000000 --- a/content/test/data/accessibility/mathml/mroot-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRoot
diff --git a/content/test/data/accessibility/mathml/mrow-expected-blink.txt b/content/test/data/accessibility/mathml/mrow-expected-blink.txt new file mode 100644 index 0000000..bcac6d1b --- /dev/null +++ b/content/test/data/accessibility/mathml/mrow-expected-blink.txt
@@ -0,0 +1,17 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++++++mathMLNumber +++++++++++++staticText name='4' +++++++++++++++inlineTextBox name='4'
diff --git a/content/test/data/accessibility/mathml/mrow-node-expected-blink.txt b/content/test/data/accessibility/mathml/mrow-node-expected-blink.txt deleted file mode 100644 index 985cbc43..0000000 --- a/content/test/data/accessibility/mathml/mrow-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRow
diff --git a/content/test/data/accessibility/mathml/ms-expected-blink.txt b/content/test/data/accessibility/mathml/ms-expected-blink.txt new file mode 100644 index 0000000..d8e77f0 --- /dev/null +++ b/content/test/data/accessibility/mathml/ms-expected-blink.txt
@@ -0,0 +1,7 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLStringLiteral +++++++++++staticText name='"hello world"' +++++++++++++inlineTextBox name='"hello world"'
diff --git a/content/test/data/accessibility/mathml/ms-node-expected-blink.txt b/content/test/data/accessibility/mathml/ms-node-expected-blink.txt deleted file mode 100644 index 41a7469..0000000 --- a/content/test/data/accessibility/mathml/ms-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLStringLiteral
diff --git a/content/test/data/accessibility/mathml/mspace-node-expected-blink.txt b/content/test/data/accessibility/mathml/mspace-node-expected-blink.txt deleted file mode 100644 index c851aa73..0000000 --- a/content/test/data/accessibility/mathml/mspace-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -Test node not found.
diff --git a/content/test/data/accessibility/mathml/msqrt-expected-blink.txt b/content/test/data/accessibility/mathml/msqrt-expected-blink.txt new file mode 100644 index 0000000..8194834 --- /dev/null +++ b/content/test/data/accessibility/mathml/msqrt-expected-blink.txt
@@ -0,0 +1,17 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLSquareRoot +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++++++mathMLNumber +++++++++++++staticText name='4' +++++++++++++++inlineTextBox name='4'
diff --git a/content/test/data/accessibility/mathml/msqrt-node-expected-blink.txt b/content/test/data/accessibility/mathml/msqrt-node-expected-blink.txt deleted file mode 100644 index a8d0e4e1..0000000 --- a/content/test/data/accessibility/mathml/msqrt-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLSquareRoot
diff --git a/content/test/data/accessibility/mathml/mstyle-expected-blink.txt b/content/test/data/accessibility/mathml/mstyle-expected-blink.txt new file mode 100644 index 0000000..bcac6d1b --- /dev/null +++ b/content/test/data/accessibility/mathml/mstyle-expected-blink.txt
@@ -0,0 +1,17 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++++++mathMLNumber +++++++++++++staticText name='4' +++++++++++++++inlineTextBox name='4'
diff --git a/content/test/data/accessibility/mathml/mstyle-node-expected-blink.txt b/content/test/data/accessibility/mathml/mstyle-node-expected-blink.txt deleted file mode 100644 index 985cbc43..0000000 --- a/content/test/data/accessibility/mathml/mstyle-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRow
diff --git a/content/test/data/accessibility/mathml/msub-expected-blink.txt b/content/test/data/accessibility/mathml/msub-expected-blink.txt new file mode 100644 index 0000000..f00f4d4 --- /dev/null +++ b/content/test/data/accessibility/mathml/msub-expected-blink.txt
@@ -0,0 +1,11 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLSub +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2'
diff --git a/content/test/data/accessibility/mathml/msub-node-expected-blink.txt b/content/test/data/accessibility/mathml/msub-node-expected-blink.txt deleted file mode 100644 index 1c0562e0..0000000 --- a/content/test/data/accessibility/mathml/msub-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLSub
diff --git a/content/test/data/accessibility/mathml/msubsup-expected-blink.txt b/content/test/data/accessibility/mathml/msubsup-expected-blink.txt new file mode 100644 index 0000000..2de9507e --- /dev/null +++ b/content/test/data/accessibility/mathml/msubsup-expected-blink.txt
@@ -0,0 +1,14 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLSubSup +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3'
diff --git a/content/test/data/accessibility/mathml/msubsup-node-expected-blink.txt b/content/test/data/accessibility/mathml/msubsup-node-expected-blink.txt deleted file mode 100644 index bf9a1e7..0000000 --- a/content/test/data/accessibility/mathml/msubsup-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLSubSup
diff --git a/content/test/data/accessibility/mathml/msup-expected-blink.txt b/content/test/data/accessibility/mathml/msup-expected-blink.txt new file mode 100644 index 0000000..3152e878 --- /dev/null +++ b/content/test/data/accessibility/mathml/msup-expected-blink.txt
@@ -0,0 +1,11 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLSup +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2'
diff --git a/content/test/data/accessibility/mathml/msup-node-expected-blink.txt b/content/test/data/accessibility/mathml/msup-node-expected-blink.txt deleted file mode 100644 index 8191fcd..0000000 --- a/content/test/data/accessibility/mathml/msup-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLSup
diff --git a/content/test/data/accessibility/mathml/mtable-expected-blink.txt b/content/test/data/accessibility/mathml/mtable-expected-blink.txt new file mode 100644 index 0000000..ee2e47d --- /dev/null +++ b/content/test/data/accessibility/mathml/mtable-expected-blink.txt
@@ -0,0 +1,31 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLTable +++++++++++mathMLTableRow +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='1' +++++++++++++++++++inlineTextBox name='1' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='2' +++++++++++++++++++inlineTextBox name='2' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='3' +++++++++++++++++++inlineTextBox name='3' +++++++++++mathMLTableRow +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='4' +++++++++++++++++++inlineTextBox name='4' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='5' +++++++++++++++++++inlineTextBox name='5' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='6' +++++++++++++++++++inlineTextBox name='6'
diff --git a/content/test/data/accessibility/mathml/mtable-node-expected-blink.txt b/content/test/data/accessibility/mathml/mtable-node-expected-blink.txt deleted file mode 100644 index a0b8909..0000000 --- a/content/test/data/accessibility/mathml/mtable-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLTable
diff --git a/content/test/data/accessibility/mathml/mtd-expected-blink.txt b/content/test/data/accessibility/mathml/mtd-expected-blink.txt new file mode 100644 index 0000000..ee2e47d --- /dev/null +++ b/content/test/data/accessibility/mathml/mtd-expected-blink.txt
@@ -0,0 +1,31 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLTable +++++++++++mathMLTableRow +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='1' +++++++++++++++++++inlineTextBox name='1' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='2' +++++++++++++++++++inlineTextBox name='2' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='3' +++++++++++++++++++inlineTextBox name='3' +++++++++++mathMLTableRow +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='4' +++++++++++++++++++inlineTextBox name='4' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='5' +++++++++++++++++++inlineTextBox name='5' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='6' +++++++++++++++++++inlineTextBox name='6'
diff --git a/content/test/data/accessibility/mathml/mtd-node-expected-blink.txt b/content/test/data/accessibility/mathml/mtd-node-expected-blink.txt deleted file mode 100644 index 1739c78..0000000 --- a/content/test/data/accessibility/mathml/mtd-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLTableCell
diff --git a/content/test/data/accessibility/mathml/mtext-expected-blink.txt b/content/test/data/accessibility/mathml/mtext-expected-blink.txt new file mode 100644 index 0000000..0ddee935 --- /dev/null +++ b/content/test/data/accessibility/mathml/mtext-expected-blink.txt
@@ -0,0 +1,7 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLText +++++++++++staticText name='otherwise' +++++++++++++inlineTextBox name='otherwise'
diff --git a/content/test/data/accessibility/mathml/mtext-node-expected-blink.txt b/content/test/data/accessibility/mathml/mtext-node-expected-blink.txt deleted file mode 100644 index 32fea28..0000000 --- a/content/test/data/accessibility/mathml/mtext-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLText
diff --git a/content/test/data/accessibility/mathml/mtr-expected-blink.txt b/content/test/data/accessibility/mathml/mtr-expected-blink.txt new file mode 100644 index 0000000..ee2e47d --- /dev/null +++ b/content/test/data/accessibility/mathml/mtr-expected-blink.txt
@@ -0,0 +1,31 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLTable +++++++++++mathMLTableRow +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='1' +++++++++++++++++++inlineTextBox name='1' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='2' +++++++++++++++++++inlineTextBox name='2' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='3' +++++++++++++++++++inlineTextBox name='3' +++++++++++mathMLTableRow +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='4' +++++++++++++++++++inlineTextBox name='4' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='5' +++++++++++++++++++inlineTextBox name='5' +++++++++++++mathMLTableCell +++++++++++++++mathMLNumber +++++++++++++++++staticText name='6' +++++++++++++++++++inlineTextBox name='6'
diff --git a/content/test/data/accessibility/mathml/mtr-node-expected-blink.txt b/content/test/data/accessibility/mathml/mtr-node-expected-blink.txt deleted file mode 100644 index 57b946e..0000000 --- a/content/test/data/accessibility/mathml/mtr-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLTableRow
diff --git a/content/test/data/accessibility/mathml/munder-expected-blink.txt b/content/test/data/accessibility/mathml/munder-expected-blink.txt new file mode 100644 index 0000000..53e1827 --- /dev/null +++ b/content/test/data/accessibility/mathml/munder-expected-blink.txt
@@ -0,0 +1,11 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLUnder +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2'
diff --git a/content/test/data/accessibility/mathml/munder-node-expected-blink.txt b/content/test/data/accessibility/mathml/munder-node-expected-blink.txt deleted file mode 100644 index 150d220..0000000 --- a/content/test/data/accessibility/mathml/munder-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLUnder
diff --git a/content/test/data/accessibility/mathml/munderover-expected-blink.txt b/content/test/data/accessibility/mathml/munderover-expected-blink.txt new file mode 100644 index 0000000..c75f2eb0 --- /dev/null +++ b/content/test/data/accessibility/mathml/munderover-expected-blink.txt
@@ -0,0 +1,14 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLUnderOver +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3'
diff --git a/content/test/data/accessibility/mathml/munderover-node-expected-blink.txt b/content/test/data/accessibility/mathml/munderover-node-expected-blink.txt deleted file mode 100644 index 6e563b7..0000000 --- a/content/test/data/accessibility/mathml/munderover-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLUnderOver
diff --git a/content/test/data/accessibility/mathml/none-expected-blink.txt b/content/test/data/accessibility/mathml/none-expected-blink.txt new file mode 100644 index 0000000..a570345f --- /dev/null +++ b/content/test/data/accessibility/mathml/none-expected-blink.txt
@@ -0,0 +1,29 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLMultiscripts +++++++++++mathMLNumber +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++++++mathMLNumber +++++++++++++staticText name='2' +++++++++++++++inlineTextBox name='2' +++++++++++mathMLNumber +++++++++++++staticText name='3' +++++++++++++++inlineTextBox name='3' +++++++++++mathMLNoneScript +++++++++++mathMLNumber +++++++++++++staticText name='5' +++++++++++++++inlineTextBox name='5' +++++++++++mathMLPrescriptDelimiter +++++++++++mathMLNumber +++++++++++++staticText name='6' +++++++++++++++inlineTextBox name='6' +++++++++++mathMLNoneScript +++++++++++mathMLNumber +++++++++++++staticText name='8' +++++++++++++++inlineTextBox name='8' +++++++++++mathMLNumber +++++++++++++staticText name='9' +++++++++++++++inlineTextBox name='9'
diff --git a/content/test/data/accessibility/mathml/none-node-expected-blink.txt b/content/test/data/accessibility/mathml/none-node-expected-blink.txt deleted file mode 100644 index 77840c2..0000000 --- a/content/test/data/accessibility/mathml/none-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLNoneScript
diff --git a/content/test/data/accessibility/mathml/semantics-expected-blink.txt b/content/test/data/accessibility/mathml/semantics-expected-blink.txt new file mode 100644 index 0000000..b79bf17c --- /dev/null +++ b/content/test/data/accessibility/mathml/semantics-expected-blink.txt
@@ -0,0 +1,12 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++mathMLMath +++++++++mathMLRow +++++++++++mathMLFraction +++++++++++++mathMLNumber +++++++++++++++staticText name='1' +++++++++++++++++inlineTextBox name='1' +++++++++++++mathMLNumber +++++++++++++++staticText name='2' +++++++++++++++++inlineTextBox name='2'
diff --git a/content/test/data/accessibility/mathml/semantics-node-expected-blink.txt b/content/test/data/accessibility/mathml/semantics-node-expected-blink.txt deleted file mode 100644 index 985cbc43..0000000 --- a/content/test/data/accessibility/mathml/semantics-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -mathMLRow
diff --git a/content/test/data/accessibility/mathml/unknown-node-expected-blink.txt b/content/test/data/accessibility/mathml/unknown-node-expected-blink.txt deleted file mode 100644 index c851aa73..0000000 --- a/content/test/data/accessibility/mathml/unknown-node-expected-blink.txt +++ /dev/null
@@ -1 +0,0 @@ -Test node not found.
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 635814fc..0342979 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -450,7 +450,6 @@ # Flaky on Mac ASAN and AMD Radeon Pro 555X crbug.com/372055518 [ angle-metal asan intel-0x3e9b mac ] Pixel_WebGLReadPixelsTabSwitch_SoftwareCompositing [ Failure ] -crbug.com/372055518 [ mac amd-0x67ef angle-opengl graphite-disabled ] Pixel_WebGLReadPixelsTabSwitch_SoftwareCompositing [ RetryOnFailure ] # Flaky hang on Mac AMD GL ASAN crbug.com/40277254 [ mac amd angle-opengl asan ] Pixel_WebGPUDisplayP3 [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index a72c95b..f03b8ba 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -400,12 +400,6 @@ # Failing new updated tests crbug.com/406187744 conformance/offscreencanvas/offscreencanvas-transfer-image-bitmap.html [ Failure ] -# The validating command decoder suppressions here will not be fixed. -# finder:disable-narrowing Intentionally broad to suppress failures until validating decoder is removed. -crbug.com/angleproject/6245 [ no-passthrough ] conformance/extensions/ext-texture-compression-rgtc.html [ Failure ] -crbug.com/angleproject/6245 [ no-passthrough ] conformance/extensions/s3tc-and-rgtc.html [ Failure ] -crbug.com/angleproject/6245 [ no-passthrough ] conformance/extensions/webgl-compressed-texture-s3tc-srgb.html [ Failure ] -# finder:enable-narrowing # Failing on most platforms. Only runs with passthrough. crbug.com/1175371 [ angle-opengles chromeos mesa_ge_21.0 passthrough target-cpu-64 ] conformance/extensions/khr-parallel-shader-compile.html [ Failure ]
diff --git a/docs/website b/docs/website index a89f681..fce2849 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit a89f6810f6a5b0e11e4ec00387e9f97e8f6c23ae +Subproject commit fce2849a37a995b7d506faa923885369d45cd9c2
diff --git a/extensions/docs/buildflags.md b/extensions/docs/buildflags.md index 8d13c2e..e6384d5 100644 --- a/extensions/docs/buildflags.md +++ b/extensions/docs/buildflags.md
@@ -24,5 +24,12 @@ used to exclude code that is only supported under manifest V2, because desktop Android only supports manifest V3. +`ENABLE_PLATFORM_APPS` - Rarely used. Typically used to exclude Chrome Platform +Apps code from the rest of the extensions system. Platform Apps were app-like +pieces of software built with JS/HTML/CSS and resembling Chrome extensions. The +Chrome apps platform has been deprecated on Windows, Mac and Linux since ~2018. +Chrome OS is in the process of deprecating it, with managed users reaching end +of life in 2028. + The plan in the long run is to convert almost everything to `ENABLE_EXTENSIONS_CORE`, then rename that flag back to `ENABLE_EXTENSIONS`.
diff --git a/fuchsia_web/runners/cast/application_controller_impl.cc b/fuchsia_web/runners/cast/application_controller_impl.cc index 4266663..723b82b 100644 --- a/fuchsia_web/runners/cast/application_controller_impl.cc +++ b/fuchsia_web/runners/cast/application_controller_impl.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "fuchsia_web/runners/cast/application_controller_impl.h" #include <fidl/fuchsia.media.sessions2/cpp/hlcpp_conversion.h>
diff --git a/fuchsia_web/runners/cast/cast_component.cc b/fuchsia_web/runners/cast/cast_component.cc index 9c7edd4..c1af56b 100644 --- a/fuchsia_web/runners/cast/cast_component.cc +++ b/fuchsia_web/runners/cast/cast_component.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "fuchsia_web/runners/cast/cast_component.h"
diff --git a/fuchsia_web/runners/cast/pending_cast_component.cc b/fuchsia_web/runners/cast/pending_cast_component.cc index 6874d4bc..5cc1fc6 100644 --- a/fuchsia_web/runners/cast/pending_cast_component.cc +++ b/fuchsia_web/runners/cast/pending_cast_component.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "fuchsia_web/runners/cast/pending_cast_component.h"
diff --git a/fuchsia_web/webengine/BUILD.gn b/fuchsia_web/webengine/BUILD.gn index 56c9a79e..04167890 100644 --- a/fuchsia_web/webengine/BUILD.gn +++ b/fuchsia_web/webengine/BUILD.gn
@@ -17,6 +17,11 @@ # Only allow use by targets in this directory unless explicitly specified. visibility = [ ":*" ] +declare_args() { + # A temporary gn arg to enable the push messaging apis. + enable_push_messaging_api = false +} + config("web_engine_implementation") { defines = [ "WEB_ENGINE_IMPLEMENTATION" ] } @@ -182,6 +187,7 @@ ":web_engine_export_from_implementation", "//base", "//base:base_static", + "//build:branding_buildflags", "//build:chromecast_buildflags", "//components/cdm/renderer", "//components/client_hints/browser:in_memory", @@ -191,6 +197,7 @@ "//components/favicon/content", "//components/favicon/core", "//components/fuchsia_component_support", + "//components/gcm_driver", "//components/keyed_service/content", "//components/media_control/browser", "//components/media_control/renderer", @@ -317,6 +324,8 @@ "browser/navigation_policy_handler.h", "browser/navigation_policy_throttle.cc", "browser/navigation_policy_throttle.h", + "browser/push_messaging_service_impl.cc", + "browser/push_messaging_service_impl.h", "browser/theme_manager.cc", "browser/theme_manager.h", "browser/trace_event.h", @@ -373,9 +382,9 @@ ] } - # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and - # enable the diagnostic by removing this line. - configs += [ "//build/config/compiler:no_exit_time_destructors" ] + if (enable_push_messaging_api) { + defines = [ "WEB_ENGINE_ENABLE_PUSH_MESSAGING_API" ] + } } source_set("context_provider") {
diff --git a/fuchsia_web/webengine/browser/DEPS b/fuchsia_web/webengine/browser/DEPS index ed3c3313..db52119f 100644 --- a/fuchsia_web/webengine/browser/DEPS +++ b/fuchsia_web/webengine/browser/DEPS
@@ -5,6 +5,7 @@ "+components/client_hints/browser", "+components/favicon/content", "+components/favicon/core", + "+components/gcm_driver", "+components/keyed_service/content", "+components/keyed_service/core", "+components/on_load_script_injector/browser",
diff --git a/fuchsia_web/webengine/browser/push_messaging_service_impl.cc b/fuchsia_web/webengine/browser/push_messaging_service_impl.cc new file mode 100644 index 0000000..a823760 --- /dev/null +++ b/fuchsia_web/webengine/browser/push_messaging_service_impl.cc
@@ -0,0 +1,148 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "fuchsia_web/webengine/browser/push_messaging_service_impl.h" + +#include <memory> +#include <utility> + +#include "base/check.h" +#include "base/files/file_path.h" +#include "base/fuchsia/file_utils.h" +#include "base/memory/scoped_refptr.h" +#include "base/task/bind_post_task.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "build/branding_buildflags.h" +#include "components/gcm_driver/gcm_client_factory.h" +#include "components/gcm_driver/gcm_desktop_utils.h" +#include "components/gcm_driver/gcm_driver_constants.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/mojom/network_context.mojom.h" + +PushMessagingServiceImpl::PushMessagingServiceImpl( + content::BrowserContext& parent_context) + : parent_context_(parent_context) {} + +PushMessagingServiceImpl::~PushMessagingServiceImpl() = default; + +// PushMessagingService implementations. +void PushMessagingServiceImpl::SubscribeFromDocument( + const GURL& requesting_origin, + int64_t service_worker_registration_id, + int render_process_id, + int render_frame_id, + blink::mojom::PushSubscriptionOptionsPtr options, + bool user_gesture, + RegisterCallback callback) {} + +void PushMessagingServiceImpl::SubscribeFromWorker( + const GURL& requesting_origin, + int64_t service_worker_registration_id, + int render_process_id, + blink::mojom::PushSubscriptionOptionsPtr options, + RegisterCallback callback) {} + +void PushMessagingServiceImpl::GetSubscriptionInfo( + const GURL& origin, + int64_t service_worker_registration_id, + const std::string& sender_id, + const std::string& subscription_id, + SubscriptionInfoCallback callback) {} + +void PushMessagingServiceImpl::Unsubscribe( + blink::mojom::PushUnregistrationReason reason, + const GURL& requesting_origin, + int64_t service_worker_registration_id, + const std::string& sender_id, + UnregisterCallback callback) {} + +bool PushMessagingServiceImpl::SupportNonVisibleMessages() { + return false; +} + +void PushMessagingServiceImpl::DidDeleteServiceWorkerRegistration( + const GURL& origin, + int64_t service_worker_registration_id) {} + +void PushMessagingServiceImpl::DidDeleteServiceWorkerDatabase() {} + +// GCMAppHandler implementations. +void PushMessagingServiceImpl::ShutdownHandler() {} + +void PushMessagingServiceImpl::OnStoreReset() {} + +void PushMessagingServiceImpl::OnMessage(const std::string& app_id, + const gcm::IncomingMessage& message) {} + +void PushMessagingServiceImpl::OnMessagesDeleted(const std::string& app_id) {} + +void PushMessagingServiceImpl::OnSendError( + const std::string& app_id, + const gcm::GCMClient::SendErrorDetails& send_error_details) {} + +void PushMessagingServiceImpl::OnSendAcknowledged( + const std::string& app_id, + const std::string& message_id) {} + +gcm::GCMDriver& PushMessagingServiceImpl::GetGCMDriver() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!gcm_driver_) { + // No predefined blocking_task_runner, create one dedicated for gcm_driver. + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner( + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})); + + gcm_driver_ = gcm::CreateGCMDriverDesktop( + std::make_unique<gcm::GCMClientFactory>(), /* prefs = */ nullptr, + base::FilePath(base::kPersistedDataDirectoryPath) + .Append(gcm_driver::kGCMStoreDirname), + base::BindPostTask( + base::SequencedTaskRunner::GetCurrentDefault(), + base::BindRepeating( + &PushMessagingServiceImpl::RequestProxyResolvingSocketFactory, + weak_ptr_factory_.GetWeakPtr())), + GetSharedURLLoaderFactory(), + /* network_connection_tracker = */ nullptr, GetChannel(), + GetProductCategoryForSubtypes(), + content::BrowserThread::GetTaskRunnerForThread( + content::BrowserThread::ID::UI), + content::BrowserThread::GetTaskRunnerForThread( + content::BrowserThread::ID::IO), + blocking_task_runner); + } + DCHECK(gcm_driver_); + return *gcm_driver_.get(); +} + +void PushMessagingServiceImpl::RequestProxyResolvingSocketFactory( + mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory> + receiver) { + parent_context_.GetDefaultStoragePartition() + ->GetNetworkContext() + ->CreateProxyResolvingSocketFactory(std::move(receiver)); +} + +scoped_refptr<network::SharedURLLoaderFactory> +PushMessagingServiceImpl::GetSharedURLLoaderFactory() const { + return parent_context_.GetDefaultStoragePartition() + ->GetURLLoaderFactoryForBrowserProcess(); +} + +version_info::Channel PushMessagingServiceImpl::GetChannel() const { + // Only stable version of WebEngine is released to the users. + return version_info::Channel::STABLE; +} + +std::string PushMessagingServiceImpl::GetProductCategoryForSubtypes() const { +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + return "com.chrome.fuchsia"; +#else + return "org.chromium.fuchsia"; +#endif +}
diff --git a/fuchsia_web/webengine/browser/push_messaging_service_impl.h b/fuchsia_web/webengine/browser/push_messaging_service_impl.h new file mode 100644 index 0000000..610b72c --- /dev/null +++ b/fuchsia_web/webengine/browser/push_messaging_service_impl.h
@@ -0,0 +1,94 @@ +// 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 FUCHSIA_WEB_WEBENGINE_BROWSER_PUSH_MESSAGING_SERVICE_IMPL_H_ +#define FUCHSIA_WEB_WEBENGINE_BROWSER_PUSH_MESSAGING_SERVICE_IMPL_H_ + +#include <memory> + +#include "base/sequence_checker.h" +#include "base/version_info/channel.h" +#include "components/gcm_driver/gcm_app_handler.h" +#include "components/gcm_driver/gcm_driver.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/push_messaging_service.h" + +namespace content { +class BrowserContext; +} // namespace content + +class PushMessagingServiceImpl : public content::PushMessagingService, + public gcm::GCMAppHandler { + public: + PushMessagingServiceImpl(content::BrowserContext&); + ~PushMessagingServiceImpl() override; + + // PushMessagingService implementations. + void SubscribeFromDocument(const GURL& requesting_origin, + int64_t service_worker_registration_id, + int render_process_id, + int render_frame_id, + blink::mojom::PushSubscriptionOptionsPtr options, + bool user_gesture, + RegisterCallback callback) override; + void SubscribeFromWorker(const GURL& requesting_origin, + int64_t service_worker_registration_id, + int render_process_id, + blink::mojom::PushSubscriptionOptionsPtr options, + RegisterCallback callback) override; + void GetSubscriptionInfo(const GURL& origin, + int64_t service_worker_registration_id, + const std::string& sender_id, + const std::string& subscription_id, + SubscriptionInfoCallback callback) override; + void Unsubscribe(blink::mojom::PushUnregistrationReason reason, + const GURL& requesting_origin, + int64_t service_worker_registration_id, + const std::string& sender_id, + UnregisterCallback callback) override; + bool SupportNonVisibleMessages() override; + void DidDeleteServiceWorkerRegistration( + const GURL& origin, + int64_t service_worker_registration_id) override; + void DidDeleteServiceWorkerDatabase() override; + + // GCMAppHandler implementations. + void ShutdownHandler() override; + void OnStoreReset() override; + void OnMessage(const std::string& app_id, + const gcm::IncomingMessage& message) override; + void OnMessagesDeleted(const std::string& app_id) override; + void OnSendError( + const std::string& app_id, + const gcm::GCMClient::SendErrorDetails& send_error_details) override; + void OnSendAcknowledged(const std::string& app_id, + const std::string& message_id) override; + + private: + gcm::GCMDriver& GetGCMDriver(); + + void RequestProxyResolvingSocketFactory( + mojo::PendingReceiver<network::mojom::ProxyResolvingSocketFactory> + receiver); + + scoped_refptr<network::SharedURLLoaderFactory> GetSharedURLLoaderFactory() + const; + + version_info::Channel GetChannel() const; + + std::string GetProductCategoryForSubtypes() const; + + // Lazy initialized. + std::unique_ptr<gcm::GCMDriver> gcm_driver_; + + // Outlive this instance. + content::BrowserContext& parent_context_; + + SEQUENCE_CHECKER(sequence_checker_); + + // Must be the last member variable. + base::WeakPtrFactory<PushMessagingServiceImpl> weak_ptr_factory_{this}; +}; + +#endif // FUCHSIA_WEB_WEBENGINE_BROWSER_PUSH_MESSAGING_SERVICE_IMPL_H_
diff --git a/fuchsia_web/webengine/browser/web_engine_browser_context.cc b/fuchsia_web/webengine/browser/web_engine_browser_context.cc index 4077c35..2cdf2083 100644 --- a/fuchsia_web/webengine/browser/web_engine_browser_context.cc +++ b/fuchsia_web/webengine/browser/web_engine_browser_context.cc
@@ -123,7 +123,11 @@ content::PushMessagingService* WebEngineBrowserContext::GetPushMessagingService() { +#ifdef WEB_ENGINE_ENABLE_PUSH_MESSAGING_API + return &push_messaging_service_; +#else return nullptr; +#endif } content::StorageNotificationService* @@ -194,7 +198,12 @@ client_hints_delegate_(network_quality_tracker, IsJavaScriptAllowedCallback(), embedder_support::GetUserAgentMetadata()), - reduce_accept_language_delegate_(GetAcceptLanguages()) { + reduce_accept_language_delegate_(GetAcceptLanguages()) +#ifdef WEB_ENGINE_ENABLE_PUSH_MESSAGING_API + , + push_messaging_service_(*this) +#endif +{ SimpleKeyMap::GetInstance()->Associate(this, &simple_factory_key_); profile_metrics::SetBrowserProfileType(
diff --git a/fuchsia_web/webengine/browser/web_engine_browser_context.h b/fuchsia_web/webengine/browser/web_engine_browser_context.h index 9c4c8b8e..0bc2426b 100644 --- a/fuchsia_web/webengine/browser/web_engine_browser_context.h +++ b/fuchsia_web/webengine/browser/web_engine_browser_context.h
@@ -12,6 +12,7 @@ #include "components/keyed_service/core/simple_factory_key.h" #include "components/reduce_accept_language/browser/in_memory_reduce_accept_language_service.h" #include "content/public/browser/browser_context.h" +#include "fuchsia_web/webengine/browser/push_messaging_service_impl.h" #include "fuchsia_web/webengine/browser/web_engine_permission_delegate.h" class WebEngineNetLogObserver; @@ -76,6 +77,9 @@ client_hints::InMemoryClientHintsControllerDelegate client_hints_delegate_; reduce_accept_language::InMemoryReduceAcceptLanguageService reduce_accept_language_delegate_; +#ifdef WEB_ENGINE_ENABLE_PUSH_MESSAGING_API + PushMessagingServiceImpl push_messaging_service_; +#endif }; #endif // FUCHSIA_WEB_WEBENGINE_BROWSER_WEB_ENGINE_BROWSER_CONTEXT_H_
diff --git a/gpu/command_buffer/client/gl_helper.cc b/gpu/command_buffer/client/gl_helper.cc index 4def26d..094d359 100644 --- a/gpu/command_buffer/client/gl_helper.cc +++ b/gpu/command_buffer/client/gl_helper.cc
@@ -21,6 +21,7 @@ #include "base/functional/callback_helpers.h" #include "base/lazy_instance.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_span.h" #include "base/memory/ref_counted.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" @@ -154,7 +155,7 @@ GLenum texture_target, const gfx::Point& src_starting_point, const gfx::Size& dst_size, - unsigned char* out, + base::span<uint8_t> out, size_t row_stride_bytes, bool flip_y, GLenum format, @@ -166,7 +167,7 @@ const gfx::Size& dst_size, size_t bytes_per_row, // generally dst_size.width() * 4 size_t row_stride_bytes, // generally dst_size.width() * 4 - unsigned char* out, + base::span<uint8_t> out, GLenum format, GLenum type, size_t bytes_per_pixel, @@ -175,7 +176,7 @@ void ReadbackPlane(const gfx::Size& texture_size, int row_stride_bytes, - unsigned char* data, + base::span<uint8_t> data, int size_shift, const gfx::Rect& paste_rect, ReadbackSwizzle swizzle, @@ -198,7 +199,7 @@ size_t bytes_per_pixel_, size_t bytes_per_row_, size_t row_stride_bytes_, - unsigned char* pixels_, + base::span<uint8_t> pixels_, bool flip_y_, base::OnceCallback<void(bool)> callback_) : size(size_), @@ -217,7 +218,7 @@ size_t row_stride_bytes; bool flip_y; base::OnceCallback<void(bool)> callback; - raw_ptr<unsigned char> pixels; + base::raw_span<uint8_t> pixels; GLuint buffer = 0; GLuint query = 0; }; @@ -274,11 +275,11 @@ const gfx::Size& src_texture_size, const gfx::Rect& output_rect, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void(bool)> callback) override; @@ -356,7 +357,7 @@ const gfx::Size& dst_size, size_t bytes_per_row, size_t row_stride_bytes, - unsigned char* out, + base::span<uint8_t> out, GLenum format, GLenum type, size_t bytes_per_pixel, @@ -392,7 +393,7 @@ GLenum texture_target, const gfx::Point& src_starting_point, const gfx::Size& dst_size, - unsigned char* out, + base::span<uint8_t> out, size_t row_stride_bytes, bool flip_y, GLenum format, @@ -440,28 +441,34 @@ bool result = false; if (request->buffer != 0) { gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer); - unsigned char* src = static_cast<unsigned char*>(gl_->MapBufferCHROMIUM( - GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY)); - if (src) { + void* mapped_ptr = gl_->MapBufferCHROMIUM( + GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY); + if (mapped_ptr) { result = true; int dst_stride = base::saturated_cast<int>(request->row_stride_bytes); - int src_stride = base::saturated_cast<int>(request->bytes_per_pixel * - request->size.width()); + const size_t src_stride = + request->bytes_per_pixel * request->size.width(); + const size_t src_buffer_size = src_stride * request->size.height(); + base::span<const uint8_t> UNSAFE_TODO( + src_span(static_cast<const uint8_t*>(mapped_ptr), src_buffer_size)); + base::span<uint8_t> dst_span = request->pixels; + + size_t src_offset = 0; + size_t dst_offset = 0; size_t bytes_to_copy = std::min(request->row_stride_bytes, request->bytes_per_row); - unsigned char* dst = request->pixels; if (request->flip_y && request->size.height() > 1) { - UNSAFE_TODO(dst += dst_stride * (request->size.height() - 1)); + dst_offset = dst_stride * (request->size.height() - 1); dst_stride = -dst_stride; } // We need to use `RelaxedAtomicWriteMemcpy` because we might be writing // into memory observed by JS at the same time. - for (int y = 0; y < request->size.height(); y++) { - base::subtle::RelaxedAtomicWriteMemcpy( - UNSAFE_TODO(base::span(dst, bytes_to_copy)), - UNSAFE_TODO(base::span(src, bytes_to_copy))); - UNSAFE_TODO(dst += dst_stride); - UNSAFE_TODO(src += src_stride); + for (int y = 0; y < request->size.height(); ++y) { + auto src_row = src_span.subspan(src_offset, bytes_to_copy); + auto dst_row = dst_span.subspan(dst_offset, bytes_to_copy); + base::subtle::RelaxedAtomicWriteMemcpy(dst_row, src_row); + src_offset += src_stride; + dst_offset += dst_stride; } gl_->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM); } @@ -523,7 +530,7 @@ GLenum texture_target, const gfx::Point& src_starting_point, const gfx::Size& dst_size, - unsigned char* out, + base::span<uint8_t> out, size_t row_stride_bytes, bool flip_y, GLenum format, @@ -567,7 +574,7 @@ void GLHelper::CopyTextureToImpl::ReadbackPlane( const gfx::Size& texture_size, int row_stride_bytes, - unsigned char* data, + base::span<uint8_t> data, int size_shift, const gfx::Rect& paste_rect, ReadbackSwizzle swizzle, @@ -580,7 +587,7 @@ const bool kFlipY = false; size_t bytes_per_row = paste_rect.width() >> size_shift; ReadbackAsync(gfx::Point(), texture_size, bytes_per_row, row_stride_bytes, - UNSAFE_TODO(data + offset), + data.subspan(offset), (swizzle == kSwizzleBGRA) ? GL_BGRA_EXT : GL_RGBA, GL_UNSIGNED_BYTE, 4, kFlipY, std::move(callback)); } @@ -770,11 +777,11 @@ const gfx::Size& src_texture_size, const gfx::Rect& output_rect, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void(bool)> callback) { DCHECK(!(paste_location.x() & 1));
diff --git a/gpu/command_buffer/client/gl_helper.h b/gpu/command_buffer/client/gl_helper.h index dc65e4fe..ec44339 100644 --- a/gpu/command_buffer/client/gl_helper.h +++ b/gpu/command_buffer/client/gl_helper.h
@@ -153,9 +153,10 @@ SCALER_QUALITY_BEST = 3, }; - // Copies the texture data out of |texture| into |out|. - // |src_starting_point| an origin point of the rectangle fragment of the - // texture to copy, |dst_size| - size of the rectangle to copy. + // Copies the texture data out of `texture` into the caller-owned memory + // represented by `out`. + // `src_starting_point` an origin point of the rectangle fragment of the + // texture to copy, `dst_size` - size of the rectangle to copy. // No post processing is applied to the pixels. The // texture is assumed to have a format of GL_RGBA or GL_BGRA_EXT with a pixel // type of GL_UNSIGNED_BYTE. @@ -166,7 +167,7 @@ GLenum texture_target, const gfx::Point& src_starting_point, const gfx::Size& dst_size, - unsigned char* out, + base::span<uint8_t> out, size_t row_stride_bytes, bool flip_y, GLenum format, @@ -444,25 +445,25 @@ // Transforms a RGBA texture into I420 planar form, and then reads it back // from the GPU into system memory. See the GLHelper::ScalerInterface::Scale() - // method comments for the meaning/semantics of |src_texture_size| and - // |output_rect|. The process is: + // method comments for the meaning/semantics of `src_texture_size` and + // `output_rect`. The process is: // // 1. Scale the source texture to an intermediate texture. // 2. Planarize, producing textures containing the Y, U, and V planes. // 3. Read-back the planar data, copying it into the given output - // destination. |paste_location| specifies the where to place the output + // destination. `paste_location` specifies the where to place the output // pixels: Rect(paste_location.origin(), output_rect.size()). - // 4. Run |callback| with true on success, false on failure (with no output + // 4. Run `callback` with true on success, false on failure (with no output // modified). virtual void ReadbackYUV(GLuint texture, const gfx::Size& src_texture_size, const gfx::Rect& output_rect, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void(bool)> callback) = 0; };
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc index a4dfeaaa..639d617 100644 --- a/gpu/command_buffer/client/raster_implementation.cc +++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -1657,7 +1657,7 @@ const gfx::Point& source_starting_point, const SkImageInfo& dst_info, GLuint dst_row_bytes, - unsigned char* out, + base::span<uint8_t> out, base::OnceCallback<void(bool)> readback_done) { TRACE_EVENT0("gpu", "RasterImplementation::ReadbackARGBPixelsAsync"); DCHECK(!!readback_done); @@ -1674,7 +1674,7 @@ ReadbackImagePixelsINTERNAL(source_mailbox, dst_info, dst_row_bytes, source_starting_point.x(), source_starting_point.y(), /*plane_index=*/0, - std::move(readback_done), out); + std::move(readback_done), out.data()); } bool RasterImplementation::ReadbackImagePixels( @@ -1699,11 +1699,11 @@ const gfx::Rect& output_rect, bool vertically_flip_texture, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void()> release_mailbox, base::OnceCallback<void(bool)> readback_done) { @@ -1783,11 +1783,11 @@ EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); auto request = std::make_unique<AsyncYUVReadbackRequest>( - output_rect, query, y_plane_row_stride_bytes, y_offset, y_plane_data, - u_plane_row_stride_bytes, u_offset, u_plane_data, - v_plane_row_stride_bytes, v_offset, v_plane_data, - std::move(scoped_shared_memory), std::move(release_mailbox), - std::move(readback_done)); + output_rect, query, y_plane_row_stride_bytes, y_offset, + y_plane_data.data(), u_plane_row_stride_bytes, u_offset, + u_plane_data.data(), v_plane_row_stride_bytes, v_offset, + v_plane_data.data(), std::move(scoped_shared_memory), + std::move(release_mailbox), std::move(readback_done)); auto* request_ptr = request.get(); yuv_request_queue_.push(std::move(request)); SignalQuery(query,
diff --git a/gpu/command_buffer/client/raster_implementation.h b/gpu/command_buffer/client/raster_implementation.h index b4f4ee9..956acc0 100644 --- a/gpu/command_buffer/client/raster_implementation.h +++ b/gpu/command_buffer/client/raster_implementation.h
@@ -163,7 +163,7 @@ const gfx::Point& source_starting_point, const SkImageInfo& dst_info, GLuint dst_row_bytes, - unsigned char* out, + base::span<uint8_t> out, base::OnceCallback<void(bool)> readback_done) override; void ReadbackYUVPixelsAsync( @@ -173,11 +173,11 @@ const gfx::Rect& output_rect, bool vertically_flip_texture, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void()> release_mailbox, base::OnceCallback<void(bool)> readback_done) override;
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc index 10e712c..70616c31 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.cc +++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -284,7 +284,7 @@ const gfx::Point& source_starting_point, const SkImageInfo& dst_info, GLuint dst_row_bytes, - unsigned char* out, + base::span<uint8_t> out, base::OnceCallback<void(bool)> readback_done) { DCHECK(!readback_done.is_null()); DCHECK(dst_info.colorType() == kRGBA_8888_SkColorType || @@ -346,11 +346,11 @@ const gfx::Rect& output_rect, bool vertically_flip_texture, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void()> release_mailbox, base::OnceCallback<void(bool)> readback_done) {
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h index f19daa9..05692bb 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.h +++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -112,7 +112,7 @@ const gfx::Point& source_starting_point, const SkImageInfo& dst_info, GLuint dst_row_bytes, - unsigned char* out, + base::span<uint8_t> out, base::OnceCallback<void(bool)> readback_done) override; void ReadbackYUVPixelsAsync( @@ -122,11 +122,11 @@ const gfx::Rect& output_rect, bool vertically_flip_texture, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void()> release_mailbox, base::OnceCallback<void(bool)> readback_done) override;
diff --git a/gpu/command_buffer/client/raster_interface.h b/gpu/command_buffer/client/raster_interface.h index 50c3071c..ff123b2 100644 --- a/gpu/command_buffer/client/raster_interface.h +++ b/gpu/command_buffer/client/raster_interface.h
@@ -122,18 +122,19 @@ const gfx::ColorSpace& target_color_space, bool needs_mips) = 0; - // Starts an asynchronous readback of |source_mailbox| into caller-owned - // memory |out|. - // |dst_row_bytes| is a per row stride expected in the |out| buffer. + // Starts an asynchronous readback of `source_mailbox` into caller-owned + // memory represented by `out`. + // `dst_row_bytes` is a per row stride expected in the `out` buffer. // |source_origin| specifies texture coordinate directions, but - // pixels in |out| laid out with top-left origin. + // pixels in `out` are laid out with top-left origin. // Currently supports the kRGBA_8888_SkColorType and // kBGRA_8888_SkColorType color types. - // |out| must remain valid until |readback_done| is called with - // a bool indicating if the readback was successful. - // |source_size| describes dimensions of the |source_mailbox| texture. - // |dst_info| |source_starting_point| describe subregion that needs to be read - // On success |out| will contain the pixel data copied back from the GPU + // The memory backing `out` must remain valid until `readback_done` is called + // with a bool indicating if the readback was successful. + // `source_size` describes dimensions of the `source_mailbox` texture. + // `dst_info` and `source_starting_point` describe the subregion that needs + // to be read. + // On success, `out` will contain the pixel data copied back from the GPU // process. virtual void ReadbackARGBPixelsAsync( const gpu::Mailbox& source_mailbox, @@ -143,17 +144,17 @@ const gfx::Point& source_starting_point, const SkImageInfo& dst_info, GLuint dst_row_bytes, - unsigned char* out, + base::span<uint8_t> out, base::OnceCallback<void(bool)> readback_done) = 0; - // Starts an asynchronus readback and translation of RGBA |source_mailbox| - // into caller-owned |[yuv]_plane_data|. All provided pointers must remain - // valid until |readback_done| is called with a bool indicating if readback - // was successful. On success the provided memory will contain pixel data in - // I420 format copied from |source_mailbox| in the GPU process. - // |release_mailbox| is called when all operations requiring a valid mailbox - // have completed, indicating that the caller can perform any necessary - // cleanup. + // Starts an asynchronous readback and translation of RGBA `source_mailbox` + // into caller-owned memory represented by `[yuv]_plane_data`. The memory + // backing these spans must remain valid until `readback_done` is called with + // a bool indicating if readback was successful. On success, the provided + // spans will contain pixel data in I420 format copied from `source_mailbox` + // in the GPU process. `release_mailbox` is called when all operations + // requiring a valid mailbox have completed, indicating that the caller can + // perform any necessary cleanup. virtual void ReadbackYUVPixelsAsync( const gpu::Mailbox& source_mailbox, GLenum source_target, @@ -161,11 +162,11 @@ const gfx::Rect& output_rect, bool vertically_flip_texture, int y_plane_row_stride_bytes, - unsigned char* y_plane_data, + base::span<uint8_t> y_plane_data, int u_plane_row_stride_bytes, - unsigned char* u_plane_data, + base::span<uint8_t> u_plane_data, int v_plane_row_stride_bytes, - unsigned char* v_plane_data, + base::span<uint8_t> v_plane_data, const gfx::Point& paste_location, base::OnceCallback<void()> release_mailbox, base::OnceCallback<void(bool)> readback_done) = 0;
diff --git a/gpu/command_buffer/common/BUILD.gn b/gpu/command_buffer/common/BUILD.gn index b9cd79b..bf9b43d 100644 --- a/gpu/command_buffer/common/BUILD.gn +++ b/gpu/command_buffer/common/BUILD.gn
@@ -104,6 +104,7 @@ public_deps = [ ":mailbox", "//base", + "//components/viz/common:shared_image_format", "//mojo/public/cpp/system", "//ui/gfx:memory_buffer", "//ui/gfx/geometry",
diff --git a/gpu/command_buffer/common/DEPS b/gpu/command_buffer/common/DEPS index 086fa34..e581e26 100644 --- a/gpu/command_buffer/common/DEPS +++ b/gpu/command_buffer/common/DEPS
@@ -1,4 +1,6 @@ include_rules = [ + "+components/viz/common/resources/shared_image_format.h", + "+components/viz/common/resources/shared_image_format_utils.h", "+third_party/skia/include", ] specific_include_rules = {
diff --git a/gpu/command_buffer/common/gpu_memory_buffer_support.cc b/gpu/command_buffer/common/gpu_memory_buffer_support.cc index d0ab6e45..af5a2eac 100644 --- a/gpu/command_buffer/common/gpu_memory_buffer_support.cc +++ b/gpu/command_buffer/common/gpu_memory_buffer_support.cc
@@ -4,59 +4,43 @@ #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" -#include "base/check.h" #include "base/containers/contains.h" -#include "base/notreached.h" #include "build/build_config.h" +#include "components/viz/common/resources/shared_image_format_utils.h" #include "gpu/command_buffer/common/capabilities.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/geometry/size.h" namespace gpu { -bool IsImageFromGpuMemoryBufferFormatSupported( - gfx::BufferFormat format, +bool IsFormatSupportedForSIWithNativeBuffer( + viz::SharedImageFormat format, const gpu::Capabilities& capabilities) { - return capabilities.gpu_memory_buffer_formats.Has(format); + const gfx::BufferFormat buffer_format = + viz::SinglePlaneSharedImageFormatToBufferFormat(format); + return capabilities.gpu_memory_buffer_formats.Has(buffer_format); } -bool IsImageSizeValidForGpuMemoryBufferFormat(const gfx::Size& size, - gfx::BufferFormat format) { - switch (format) { - case gfx::BufferFormat::R_8: - case gfx::BufferFormat::R_16: - case gfx::BufferFormat::RG_88: - case gfx::BufferFormat::RG_1616: - case gfx::BufferFormat::BGR_565: - case gfx::BufferFormat::RGBA_4444: - case gfx::BufferFormat::RGBA_8888: - case gfx::BufferFormat::RGBX_8888: - case gfx::BufferFormat::BGRA_8888: - case gfx::BufferFormat::BGRX_8888: - case gfx::BufferFormat::BGRA_1010102: - case gfx::BufferFormat::RGBA_1010102: - case gfx::BufferFormat::RGBA_F16: - return true; - case gfx::BufferFormat::YVU_420: - case gfx::BufferFormat::YUV_420_BIPLANAR: - case gfx::BufferFormat::YUVA_420_TRIPLANAR: - case gfx::BufferFormat::P010: -#if BUILDFLAG(IS_CHROMEOS) - // Allow odd size for CrOS. - // TODO(https://crbug.com/1208788, https://crbug.com/1224781): Merge this - // with the path that uses gfx::IsOddHeightMultiPlanarBuffersAllowed. - return true; -#else - // U and V planes are subsampled by a factor of 2. - if (size.width() % 2 && !gfx::IsOddWidthMultiPlanarBuffersAllowed()) - return false; - if (size.height() % 2 && !gfx::IsOddHeightMultiPlanarBuffersAllowed()) - return false; - return true; -#endif // BUILDFLAG(IS_CHROMEOS) +bool IsSharedImageSizeValid(const gfx::Size& size, + viz::SharedImageFormat format) { + if (format.is_single_plane()) { + return true; } - NOTREACHED(); +#if BUILDFLAG(IS_CHROMEOS) + // Allow odd size for CrOS. + // TODO(https://crbug.com/1208788, https://crbug.com/1224781): Merge this + // with the path that uses gfx::IsOddHeightMultiPlanarBuffersAllowed. + return true; +#else + if (size.width() % 2 && !gfx::IsOddWidthMultiPlanarBuffersAllowed()) { + return false; + } + if (size.height() % 2 && !gfx::IsOddHeightMultiPlanarBuffersAllowed()) { + return false; + } + return true; +#endif // BUILDFLAG(IS_CHROMEOS) } } // namespace gpu
diff --git a/gpu/command_buffer/common/gpu_memory_buffer_support.h b/gpu/command_buffer/common/gpu_memory_buffer_support.h index 5713fd16..c89e48a 100644 --- a/gpu/command_buffer/common/gpu_memory_buffer_support.h +++ b/gpu/command_buffer/common/gpu_memory_buffer_support.h
@@ -7,6 +7,7 @@ #include "base/containers/enum_set.h" #include "build/build_config.h" +#include "components/viz/common/resources/shared_image_format.h" #include "gpu/command_buffer/common/gpu_command_buffer_common_export.h" #include "ui/gfx/buffer_types.h" #include "ui/gfx/geometry/size.h" @@ -21,16 +22,16 @@ struct Capabilities; -// Returns true if creating an image for a GpuMemoryBuffer with |format| is +// Returns true if creating a shared image with |format| is // supported by |capabilities|. -GPU_COMMAND_BUFFER_COMMON_EXPORT bool IsImageFromGpuMemoryBufferFormatSupported( - gfx::BufferFormat format, +GPU_COMMAND_BUFFER_COMMON_EXPORT bool IsFormatSupportedForSIWithNativeBuffer( + viz::SharedImageFormat format, const Capabilities& capabilities); // Returns true if |size| is valid for plane |plane| of |format|. -GPU_COMMAND_BUFFER_COMMON_EXPORT bool IsImageSizeValidForGpuMemoryBufferFormat( +GPU_COMMAND_BUFFER_COMMON_EXPORT bool IsSharedImageSizeValid( const gfx::Size& size, - gfx::BufferFormat format); + viz::SharedImageFormat format); } // namespace gpu
diff --git a/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc b/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc index cc86241..b1f6f9a 100644 --- a/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc +++ b/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
@@ -15,6 +15,42 @@ namespace { +std::pair<scoped_refptr<gpu::Buffer>, base::raw_span<uint8_t>> GetHandleInfo( + CommonDecoder* decoder, + const void* deserialize_pointer, + size_t deserialize_size) { + DCHECK(deserialize_pointer); + // Use CHECK instead of DCHECK because the cast of the memory to + // MemoryTransferHandle and subsequent reads won't be safe if deserialize_size + // is too small. + CHECK_EQ(deserialize_size, sizeof(MemoryTransferHandle)); + const volatile MemoryTransferHandle* handle = + reinterpret_cast<const volatile MemoryTransferHandle*>( + deserialize_pointer); + + uint32_t size = handle->size; + int32_t shm_id = handle->shm_id; + uint32_t shm_offset = handle->shm_offset; + + scoped_refptr<gpu::Buffer> buffer = + decoder->command_buffer_service()->GetTransferBuffer(shm_id); + if (buffer == nullptr) { + return std::make_pair(std::move(buffer), base::raw_span<uint8_t>()); + } + + void* ptr = buffer->GetDataAddress(shm_offset, size); + if (ptr == nullptr) { + return std::make_pair(std::move(buffer), base::raw_span<uint8_t>()); + } + + // SAFETY: gpu::Buffer::GetDataAddress() will return a valid pointer only when + // `shm_offset + size` is neither overflow nor greater than the total size of + // the whole transfer buffer. + auto buffer_data_view = + UNSAFE_BUFFERS(base::raw_span<uint8_t>(static_cast<uint8_t*>(ptr), size)); + return std::make_pair(std::move(buffer), buffer_data_view); +} + class ReadHandleImpl : public dawn::wire::server::MemoryTransferService::ReadHandle { public: @@ -56,7 +92,7 @@ : public dawn::wire::server::MemoryTransferService::WriteHandle { public: WriteHandleImpl(scoped_refptr<Buffer> buffer, - base::raw_span<const uint8_t> buffer_data_view) + base::raw_span<uint8_t> buffer_data_view) : buffer_(std::move(buffer)), buffer_data_view_(buffer_data_view) {} ~WriteHandleImpl() override = default; @@ -90,7 +126,7 @@ private: scoped_refptr<gpu::Buffer> buffer_; // Data view to client-visible shared memory owned by buffer_. - base::raw_span<const uint8_t> buffer_data_view_; + base::raw_span<uint8_t> buffer_data_view_; }; } // namespace @@ -105,36 +141,14 @@ const void* deserialize_pointer, size_t deserialize_size, ReadHandle** read_handle) { - DCHECK(deserialize_pointer); - // Use CHECK instead of DCHECK because the cast of the memory to - // MemoryTransferHandle and subsequent reads won't be safe if deserialize_size - // is too small. - CHECK_EQ(deserialize_size, sizeof(MemoryTransferHandle)); - const volatile MemoryTransferHandle* handle = - reinterpret_cast<const volatile MemoryTransferHandle*>( - deserialize_pointer); - - uint32_t size = handle->size; - int32_t shm_id = handle->shm_id; - uint32_t shm_offset = handle->shm_offset; - - scoped_refptr<gpu::Buffer> buffer = - decoder_->command_buffer_service()->GetTransferBuffer(shm_id); - if (buffer == nullptr) { + auto [buffer, buffer_data_view] = + GetHandleInfo(decoder_, deserialize_pointer, deserialize_size); + if (buffer_data_view.data() == nullptr) { return false; } - void* ptr = buffer->GetDataAddress(shm_offset, size); - if (ptr == nullptr) { - return false; - } - + DCHECK(buffer); DCHECK(read_handle); - // SAFETY: gpu::Buffer::GetDataAddress() will return a valid pointer only when - // `shm_offset + size` is neither overflow nor greater than the total size of - // the whole transfer buffer. - auto buffer_data_view = - UNSAFE_BUFFERS(base::raw_span<uint8_t>(static_cast<uint8_t*>(ptr), size)); *read_handle = new ReadHandleImpl(std::move(buffer), buffer_data_view); return true; @@ -144,36 +158,14 @@ const void* deserialize_pointer, size_t deserialize_size, WriteHandle** write_handle) { - DCHECK(deserialize_pointer); - // Use CHECK instead of DCHECK because the cast of the memory to - // MemoryTransferHandle and subsequent reads won't be safe if deserialize_size - // is too small. - CHECK_EQ(deserialize_size, sizeof(MemoryTransferHandle)); - const volatile MemoryTransferHandle* handle = - reinterpret_cast<const volatile MemoryTransferHandle*>( - deserialize_pointer); - - uint32_t size = handle->size; - int32_t shm_id = handle->shm_id; - uint32_t shm_offset = handle->shm_offset; - - scoped_refptr<gpu::Buffer> buffer = - decoder_->command_buffer_service()->GetTransferBuffer(shm_id); - if (buffer == nullptr) { + auto [buffer, buffer_data_view] = + GetHandleInfo(decoder_, deserialize_pointer, deserialize_size); + if (buffer_data_view.data() == nullptr) { return false; } - const void* ptr = buffer->GetDataAddress(shm_offset, size); - if (ptr == nullptr) { - return false; - } - + DCHECK(buffer); DCHECK(write_handle); - // SAFETY: gpu::Buffer::GetDataAddress() will return a valid pointer only when - // `shm_offset + size` is neither overflow nor greater than the total size of - // the whole transfer buffer. - auto buffer_data_view = UNSAFE_BUFFERS( - base::raw_span<const uint8_t>(static_cast<const uint8_t*>(ptr), size)); *write_handle = new WriteHandleImpl(std::move(buffer), buffer_data_view); return true;
diff --git a/gpu/command_buffer/service/shared_image/compound_image_backing.cc b/gpu/command_buffer/service/shared_image/compound_image_backing.cc index 527d45ac..17783da 100644 --- a/gpu/command_buffer/service/shared_image/compound_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/compound_image_backing.cc
@@ -373,8 +373,7 @@ return false; } - if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, - ToBufferFormat(format))) { + if (!gpu::IsSharedImageSizeValid(size, format)) { DVLOG(1) << "Invalid image size: " << size.ToString() << " for format: " << format.ToString(); return false;
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc index f1dc8931..c828b55 100644 --- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
@@ -683,10 +683,9 @@ CHECK(!format.PrefersExternalSampler()); // TOOD(hitawala): Move this size check to IsSupported. - const gfx::BufferFormat buffer_format = gpu::ToBufferFormat(format); - if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, buffer_format)) { + if (!gpu::IsSharedImageSizeValid(size, format)) { LOG(ERROR) << "Invalid image size " << size.ToString() << " for " - << gfx::BufferFormatToString(buffer_format); + << format.ToString(); return nullptr; }
diff --git a/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc b/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc index cb513d4d..0920275 100644 --- a/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc +++ b/gpu/command_buffer/service/shared_image/external_vk_image_backing.cc
@@ -275,9 +275,10 @@ SharedImageUsageSet usage, std::string debug_label, std::optional<gfx::BufferUsage> buffer_usage) { - if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, - ToBufferFormat(format))) { - DLOG(ERROR) << "Invalid image size for format."; + // TOOD(hitawala): Move this size check to IsSupported. + if (!gpu::IsSharedImageSizeValid(size, format)) { + LOG(ERROR) << "Invalid image size " << size.ToString() << " for " + << format.ToString(); return nullptr; }
diff --git a/gpu/command_buffer/tests/gl_helper_unittest.cc b/gpu/command_buffer/tests/gl_helper_unittest.cc index 649bb23..153cffe4 100644 --- a/gpu/command_buffer/tests/gl_helper_unittest.cc +++ b/gpu/command_buffer/tests/gl_helper_unittest.cc
@@ -18,6 +18,7 @@ #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted_memory.h" @@ -670,7 +671,8 @@ EXPECT_TRUE(ReadBackTexture( dst_texture, gfx::Rect(scaled_size), - static_cast<unsigned char*>(output_pixels.getPixels()), + UNSAFE_TODO(base::span(static_cast<uint8_t*>(output_pixels.getPixels()), + output_pixels.computeByteSize())), output_pixels.rowBytes(), flip_output, kRGBA_8888_SkColorType)); // If the bitmap shouldn't have changed - compare against input. @@ -755,7 +757,8 @@ EXPECT_TRUE(ReadBackTexture( dst_texture, gfx::Rect(entire_output_size), - static_cast<unsigned char*>(entire_output.getPixels()), + UNSAFE_TODO(base::span(static_cast<uint8_t*>(entire_output.getPixels()), + entire_output.computeByteSize())), entire_output.rowBytes(), /*flip_y=*/false, kRGBA_8888_SkColorType)); const std::string human_readable_test_params = base::StringPrintf( @@ -798,7 +801,9 @@ kRGBA_8888_SkColorType, kPremul_SkAlphaType)); EXPECT_TRUE(ReadBackTexture( dst_texture, gfx::Rect(patch_size), - static_cast<unsigned char*>(patch_output.getPixels()), + UNSAFE_TODO( + base::span(static_cast<uint8_t*>(patch_output.getPixels()), + patch_output.computeByteSize())), patch_output.rowBytes(), /*flip_y=*/false, kRGBA_8888_SkColorType)); SkBitmap expected; SkIRect expected_subrect{patch_rect.x(), patch_rect.y(), @@ -842,7 +847,9 @@ gl_->DeleteTextures(1, &src_subset_texture); EXPECT_TRUE(ReadBackTexture( dst_texture, gfx::Rect(patch_size), - static_cast<unsigned char*>(patch_output.getPixels()), + UNSAFE_TODO( + base::span(static_cast<uint8_t*>(patch_output.getPixels()), + patch_output.computeByteSize())), patch_output.rowBytes(), /*flip_y=*/false, kRGBA_8888_SkColorType)); Compare(&expected, &patch_output, 2, test_bitmap.get(), stages, @@ -995,7 +1002,7 @@ bool ReadBackTexture(GLuint src_texture, const gfx::Rect& src_rect, - unsigned char* pixels, + base::span<uint8_t> pixels, size_t pixels_stride, bool flip_y, SkColorType color_type) { @@ -1041,7 +1048,9 @@ // Initialize the output bitmap with Green color. // When the readback is over output bitmap should have the red color. output_pixels.eraseColor(SK_ColorGREEN); - uint8_t* pixels = static_cast<uint8_t*>(output_pixels.getPixels()); + auto pixels = + UNSAFE_TODO(base::span(static_cast<uint8_t*>(output_pixels.getPixels()), + output_pixels.computeByteSize())); if (!ReadBackTexture(src_texture, gfx::Rect(src_size), pixels, output_pixels.rowBytes(), /*flip_y=*/false, color_type) ||
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index 99ce5ed..b421619 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -363,6 +363,7 @@ "//components/embedder_support/origin_trials", "//components/headless/clipboard", "//components/headless/command_handler:switches", + "//components/headless/console_message_logger", "//components/headless/display_util", "//components/headless/screen_info", "//components/headless/select_file_dialog",
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc index cb6c463..1d95f5b5 100644 --- a/headless/lib/browser/headless_web_contents_impl.cc +++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -21,6 +21,7 @@ #include "base/trace_event/trace_event.h" #include "base/values.h" #include "build/build_config.h" +#include "components/headless/console_message_logger/headless_console_message_logger.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_termination_info.h" #include "content/public/browser/navigation_controller.h" @@ -276,6 +277,16 @@ headless_web_contents_->SetBounds(bounds); } + bool DidAddMessageToConsole(content::WebContents* source, + blink::mojom::ConsoleMessageLevel log_level, + const std::u16string& message, + int32_t line_no, + const std::u16string& source_id) override { + LogConsoleMessage(log_level, message, line_no, + /*is_builtin_component=*/false, source_id); + return true; + } + private: HeadlessBrowserImpl* browser() { return headless_web_contents_->browser(); }
diff --git a/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/targets/chromium.android.desktop.json b/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/targets/chromium.android.desktop.json index 0889220..3a4eb73 100644 --- a/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/targets/chromium.android.desktop.json +++ b/infra/config/generated/builders/ci/android-desktop-x64-compile-rel/targets/chromium.android.desktop.json
@@ -8,8 +8,8 @@ "gtest_tests": [ { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.android_browsertests.filter", "--emulator-debug-tags=all", "--gs-results-bucket=chromium-result-details", @@ -59,8 +59,8 @@ { "args": [ "--git-revision=${got_revision}", - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gtest_filter=-org.chromium.chrome.browser.ui.appmenu.AppMenuTest.testShowAppMenu_AnchorTop", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -114,8 +114,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -161,8 +161,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.unit_tests.filter", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -210,8 +210,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -258,6 +258,59 @@ ], "isolated_scripts": [ { + "args": [ + "--skipped", + "always", + "--test-type", + "testharness", + "reftest", + "crashtest", + "print-reftest", + "--additional-driver-flag=--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb" + ], + "ci_only": true, + "description": "Run with android_35_google_apis_tablet_x64", + "experiment_percentage": 100, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "android_chrome_wpt_tests", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "results_handler": "layout tests", + "swarming": { + "dimensions": { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-22.04", + "pool": "chromium.tests.avd" + }, + "named_caches": [ + { + "name": "android_35_google_apis_tablet_x64_tablet_landscape", + "path": ".android_emulator/android_35_google_apis_tablet_x64_tablet_landscape" + } + ], + "optional_dimensions": { + "60": { + "caches": "android_35_google_apis_tablet_x64_tablet_landscape" + } + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "chrome_public_wpt", + "test_id_prefix": "ninja://chrome/android:chrome_public_wpt/" + }, + { "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" },
diff --git a/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/targets/chromium.android.desktop.json b/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/targets/chromium.android.desktop.json index 0f34798..e0fa18d 100644 --- a/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/targets/chromium.android.desktop.json +++ b/infra/config/generated/builders/ci/android-desktop-x64-rel-15-tests/targets/chromium.android.desktop.json
@@ -3,8 +3,8 @@ "gtest_tests": [ { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.android_browsertests.filter", "--emulator-debug-tags=all", "--gs-results-bucket=chromium-result-details", @@ -54,8 +54,8 @@ { "args": [ "--git-revision=${got_revision}", - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gtest_filter=-org.chromium.chrome.browser.ui.appmenu.AppMenuTest.testShowAppMenu_AnchorTop", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -109,8 +109,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -156,8 +156,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.unit_tests.filter", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -205,8 +205,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -253,6 +253,59 @@ ], "isolated_scripts": [ { + "args": [ + "--skipped", + "always", + "--test-type", + "testharness", + "reftest", + "crashtest", + "print-reftest", + "--additional-driver-flag=--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb" + ], + "ci_only": true, + "description": "Run with android_35_google_apis_tablet_x64", + "experiment_percentage": 100, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "android_chrome_wpt_tests", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "results_handler": "layout tests", + "swarming": { + "dimensions": { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-22.04", + "pool": "chromium.tests.avd" + }, + "named_caches": [ + { + "name": "android_35_google_apis_tablet_x64_tablet_landscape", + "path": ".android_emulator/android_35_google_apis_tablet_x64_tablet_landscape" + } + ], + "optional_dimensions": { + "60": { + "caches": "android_35_google_apis_tablet_x64_tablet_landscape" + } + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "chrome_public_wpt", + "test_id_prefix": "ninja://chrome/android:chrome_public_wpt/" + }, + { "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" },
diff --git a/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg-persistent-emulator/targets/chromium.fuchsia.fyi.json b/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg-persistent-emulator/targets/chromium.fuchsia.fyi.json index ba1cebe..768bce1 100644 --- a/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg-persistent-emulator/targets/chromium.fuchsia.fyi.json +++ b/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg-persistent-emulator/targets/chromium.fuchsia.fyi.json
@@ -19,7 +19,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -48,7 +48,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -77,7 +77,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -106,7 +106,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -135,7 +135,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -164,7 +164,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [
diff --git a/infra/config/generated/builders/ci/mac-vm/gn-args.json b/infra/config/generated/builders/ci/mac-vm/gn-args.json index b864c08..6034d5b 100644 --- a/infra/config/generated/builders/ci/mac-vm/gn-args.json +++ b/infra/config/generated/builders/ci/mac-vm/gn-args.json
@@ -1,7 +1,8 @@ { "gn_args": { - "is_component_build": true, - "is_debug": true, + "dcheck_always_on": false, + "is_component_build": false, + "is_debug": false, "symbol_level": 1, "target_cpu": "arm64", "target_os": "mac",
diff --git a/infra/config/generated/builders/ci/mac-vm/properties.json b/infra/config/generated/builders/ci/mac-vm/properties.json index e9d6f65f..1afd5b0 100644 --- a/infra/config/generated/builders/ci/mac-vm/properties.json +++ b/infra/config/generated/builders/ci/mac-vm/properties.json
@@ -19,8 +19,9 @@ "apply_configs": [ "mb" ], - "build_config": "Debug", + "build_config": "Release", "config": "chromium", + "target_arch": "arm", "target_bits": 64, "target_platform": "mac" },
diff --git a/infra/config/generated/builders/ci/mac-vm/targets/chromium.fyi.json b/infra/config/generated/builders/ci/mac-vm/targets/chromium.fyi.json index d060e8c..1a70192 100644 --- a/infra/config/generated/builders/ci/mac-vm/targets/chromium.fyi.json +++ b/infra/config/generated/builders/ci/mac-vm/targets/chromium.fyi.json
@@ -32,7 +32,7 @@ "pool": "chromium.tests.macvm" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 + "shards": 7 }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
diff --git a/infra/config/generated/builders/try/android-desktop-15-x64-rel/targets/chromium.android.desktop.json b/infra/config/generated/builders/try/android-desktop-15-x64-rel/targets/chromium.android.desktop.json index 0889220..3a4eb73 100644 --- a/infra/config/generated/builders/try/android-desktop-15-x64-rel/targets/chromium.android.desktop.json +++ b/infra/config/generated/builders/try/android-desktop-15-x64-rel/targets/chromium.android.desktop.json
@@ -8,8 +8,8 @@ "gtest_tests": [ { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.android_browsertests.filter", "--emulator-debug-tags=all", "--gs-results-bucket=chromium-result-details", @@ -59,8 +59,8 @@ { "args": [ "--git-revision=${got_revision}", - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gtest_filter=-org.chromium.chrome.browser.ui.appmenu.AppMenuTest.testShowAppMenu_AnchorTop", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -114,8 +114,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -161,8 +161,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.unit_tests.filter", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -210,8 +210,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -258,6 +258,59 @@ ], "isolated_scripts": [ { + "args": [ + "--skipped", + "always", + "--test-type", + "testharness", + "reftest", + "crashtest", + "print-reftest", + "--additional-driver-flag=--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb" + ], + "ci_only": true, + "description": "Run with android_35_google_apis_tablet_x64", + "experiment_percentage": 100, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "android_chrome_wpt_tests", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "results_handler": "layout tests", + "swarming": { + "dimensions": { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-22.04", + "pool": "chromium.tests.avd" + }, + "named_caches": [ + { + "name": "android_35_google_apis_tablet_x64_tablet_landscape", + "path": ".android_emulator/android_35_google_apis_tablet_x64_tablet_landscape" + } + ], + "optional_dimensions": { + "60": { + "caches": "android_35_google_apis_tablet_x64_tablet_landscape" + } + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "chrome_public_wpt", + "test_id_prefix": "ninja://chrome/android:chrome_public_wpt/" + }, + { "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" },
diff --git a/infra/config/generated/builders/try/android-desktop-x64-rel/targets/chromium.android.desktop.json b/infra/config/generated/builders/try/android-desktop-x64-rel/targets/chromium.android.desktop.json index 0889220..3a4eb73 100644 --- a/infra/config/generated/builders/try/android-desktop-x64-rel/targets/chromium.android.desktop.json +++ b/infra/config/generated/builders/try/android-desktop-x64-rel/targets/chromium.android.desktop.json
@@ -8,8 +8,8 @@ "gtest_tests": [ { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.android_browsertests.filter", "--emulator-debug-tags=all", "--gs-results-bucket=chromium-result-details", @@ -59,8 +59,8 @@ { "args": [ "--git-revision=${got_revision}", - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gtest_filter=-org.chromium.chrome.browser.ui.appmenu.AppMenuTest.testShowAppMenu_AnchorTop", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -114,8 +114,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -161,8 +161,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.unit_tests.filter", "--gs-results-bucket=chromium-result-details", "--recover-devices" @@ -210,8 +210,8 @@ }, { "args": [ - "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -258,6 +258,59 @@ ], "isolated_scripts": [ { + "args": [ + "--skipped", + "always", + "--test-type", + "testharness", + "reftest", + "crashtest", + "print-reftest", + "--additional-driver-flag=--force-android-desktop", + "--avd-config=../../tools/android/avd/proto/android_35_google_apis_tablet_x64_tablet_landscape.textpb" + ], + "ci_only": true, + "description": "Run with android_35_google_apis_tablet_x64", + "experiment_percentage": 100, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "android_chrome_wpt_tests", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "results_handler": "layout tests", + "swarming": { + "dimensions": { + "cores": "8", + "cpu": "x86-64", + "device_os": null, + "device_type": null, + "os": "Ubuntu-22.04", + "pool": "chromium.tests.avd" + }, + "named_caches": [ + { + "name": "android_35_google_apis_tablet_x64_tablet_landscape", + "path": ".android_emulator/android_35_google_apis_tablet_x64_tablet_landscape" + } + ], + "optional_dimensions": { + "60": { + "caches": "android_35_google_apis_tablet_x64_tablet_landscape" + } + }, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test": "chrome_public_wpt", + "test_id_prefix": "ninja://chrome/android:chrome_public_wpt/" + }, + { "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" },
diff --git a/infra/config/generated/builders/try/fuchsia-fyi-x64-dbg-persistent-emulator/targets/chromium.fuchsia.fyi.json b/infra/config/generated/builders/try/fuchsia-fyi-x64-dbg-persistent-emulator/targets/chromium.fuchsia.fyi.json index ba1cebe..768bce1 100644 --- a/infra/config/generated/builders/try/fuchsia-fyi-x64-dbg-persistent-emulator/targets/chromium.fuchsia.fyi.json +++ b/infra/config/generated/builders/try/fuchsia-fyi-x64-dbg-persistent-emulator/targets/chromium.fuchsia.fyi.json
@@ -19,7 +19,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -48,7 +48,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -77,7 +77,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -106,7 +106,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -135,7 +135,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [ @@ -164,7 +164,7 @@ "swarming": { "dimensions": { "kvm": "1", - "os": "Ubuntu-20.04", + "os": "Ubuntu-22.04", "pool": "chromium.tests.fuchsia" }, "named_caches": [
diff --git a/infra/config/generated/builders/try/mac-vm/gn-args.json b/infra/config/generated/builders/try/mac-vm/gn-args.json index b864c08..6034d5b 100644 --- a/infra/config/generated/builders/try/mac-vm/gn-args.json +++ b/infra/config/generated/builders/try/mac-vm/gn-args.json
@@ -1,7 +1,8 @@ { "gn_args": { - "is_component_build": true, - "is_debug": true, + "dcheck_always_on": false, + "is_component_build": false, + "is_debug": false, "symbol_level": 1, "target_cpu": "arm64", "target_os": "mac",
diff --git a/infra/config/generated/builders/try/mac-vm/properties.json b/infra/config/generated/builders/try/mac-vm/properties.json index df855227..8ac5cdc1 100644 --- a/infra/config/generated/builders/try/mac-vm/properties.json +++ b/infra/config/generated/builders/try/mac-vm/properties.json
@@ -19,8 +19,9 @@ "apply_configs": [ "mb" ], - "build_config": "Debug", + "build_config": "Release", "config": "chromium", + "target_arch": "arm", "target_bits": 64, "target_platform": "mac" },
diff --git a/infra/config/generated/builders/try/mac-vm/targets/chromium.fyi.json b/infra/config/generated/builders/try/mac-vm/targets/chromium.fyi.json index d060e8c..1a70192 100644 --- a/infra/config/generated/builders/try/mac-vm/targets/chromium.fyi.json +++ b/infra/config/generated/builders/try/mac-vm/targets/chromium.fyi.json
@@ -32,7 +32,7 @@ "pool": "chromium.tests.macvm" }, "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 + "shards": 7 }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/"
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.desktop.fyi.star b/infra/config/subprojects/chromium/ci/chromium.android.desktop.fyi.star index 8a1d634..fc95b30 100644 --- a/infra/config/subprojects/chromium/ci/chromium.android.desktop.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.android.desktop.fyi.star
@@ -75,7 +75,7 @@ ], ), targets = targets.bundle( - targets = "android_desktop_fyi_tests", + targets = "android_desktop_fyi_gtests", mixins = [ "15-desktop-x64-emulator", "emulator-8-cores",
diff --git a/infra/config/subprojects/chromium/ci/chromium.android.desktop.star b/infra/config/subprojects/chromium/ci/chromium.android.desktop.star index 80780fbe..7f75283 100644 --- a/infra/config/subprojects/chromium/ci/chromium.android.desktop.star +++ b/infra/config/subprojects/chromium/ci/chromium.android.desktop.star
@@ -267,11 +267,17 @@ targets = [ "android_desktop_junit_tests", targets.bundle( - targets = "android_desktop_tests", + targets = "android_desktop_gtests", mixins = [ "15-desktop-x64-emulator", "emulator-8-cores", - "force-android-desktop", + ], + ), + targets.bundle( + targets = "android_desktop_isolated_script_tests", + mixins = [ + "15-desktop-x64-emulator", + "emulator-8-cores", ], ), ], @@ -292,6 +298,11 @@ ], ci_only = True, ), + # TODO(crbug.com/436488951): Promote out of experimental. + "android_chrome_wpt_tests": targets.mixin( + ci_only = True, + experiment_percentage = 100, + ), "unit_tests": targets.mixin( args = [ "--test-launcher-filter-file=../../testing/buildbot/filters/android.desktop.emulator_15.unit_tests.filter",
diff --git a/infra/config/subprojects/chromium/ci/chromium.fuchsia.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fuchsia.fyi.star index fbfe123..d6c6c68 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fuchsia.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fuchsia.fyi.star
@@ -295,7 +295,7 @@ ], mixins = [ "fuchsia-persistent-emulator", - "linux-focal", + "linux-jammy", targets.mixin( swarming = targets.swarming( dimensions = {
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 504764972..4ac4a75 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -948,17 +948,19 @@ chromium_config = builder_config.chromium_config( config = "chromium", apply_configs = ["mb"], - build_config = builder_config.build_config.DEBUG, + build_config = builder_config.build_config.RELEASE, + target_arch = builder_config.target_arch.ARM, target_bits = 64, target_platform = builder_config.target_platform.MAC, ), ), gn_args = gn_args.config( configs = [ - "debug_builder", + "release_builder", "remoteexec", "mac", "arm64", + "minimal_symbols", ], ), targets = targets.bundle(
diff --git a/infra/config/targets/bundles.star b/infra/config/targets/bundles.star index 2fc20ed..c02796d 100644 --- a/infra/config/targets/bundles.star +++ b/infra/config/targets/bundles.star
@@ -412,7 +412,7 @@ # Android desktop FYI tests that run on AVDs or devices. Specific emulator or # device mixins should be added where this is used. targets.bundle( - name = "android_desktop_fyi_tests", + name = "android_desktop_fyi_gtests", targets = [ "android_browsertests", "android_smoke_tests", @@ -438,24 +438,10 @@ }, ) -# Android desktop tests that run on a Linux host. -targets.bundle( - name = "android_desktop_junit_tests", - targets = [ - "chrome_junit_tests", - ], - mixins = [ - "has_native_resultdb_integration", - "junit-swarming-emulator", - "linux-jammy", - "x86-64", - ], -) - # Android desktop tests that run on AVDs or devices. Specific emulator or # device mixins should be added where this is used. targets.bundle( - name = "android_desktop_tests", + name = "android_desktop_gtests", targets = [ "android_browsertests", "chrome_public_unit_test_apk", @@ -464,6 +450,7 @@ "video_encode_accelerator_tests", ], mixins = [ + "force-android-desktop", "has_native_resultdb_integration", "linux-jammy", "x86-64", @@ -488,6 +475,40 @@ ) targets.bundle( + name = "android_desktop_isolated_script_tests", + targets = [ + "android_chrome_wpt_tests", + ], + mixins = [ + "android_desktop_wpt_args", + "has_native_resultdb_integration", + "linux-jammy", + "x86-64", + ], + per_test_modifications = { + "android_chrome_wpt_tests": targets.mixin( + swarming = targets.swarming( + shards = 4, + ), + ), + }, +) + +# Android desktop tests that run on a Linux host. +targets.bundle( + name = "android_desktop_junit_tests", + targets = [ + "chrome_junit_tests", + ], + mixins = [ + "has_native_resultdb_integration", + "junit-swarming-emulator", + "linux-jammy", + "x86-64", + ], +) + +targets.bundle( name = "android_emulator_specific_chrome_public_tests", targets = [ "chrome_public_test_apk", @@ -6100,7 +6121,7 @@ per_test_modifications = { "interactive_ui_tests": targets.mixin( swarming = targets.swarming( - shards = 6, + shards = 7, ), ), },
diff --git a/infra/config/targets/mixins.star b/infra/config/targets/mixins.star index 2923432..a410d27 100644 --- a/infra/config/targets/mixins.star +++ b/infra/config/targets/mixins.star
@@ -417,6 +417,14 @@ ) targets.mixin( + name = "android_desktop_wpt_args", + generate_pyl_entry = False, + args = [ + "--additional-driver-flag=--force-android-desktop", + ], +) + +targets.mixin( name = "arm64", # All references have been moved to starlark generate_pyl_entry = False,
diff --git a/internal b/internal index c9abe897..e988aca 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit c9abe897da1efecb78ad3207f7c1493b3a33b1f0 +Subproject commit e988acaa4e16e19cacdca3b6bb9565872c40072c
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 49feef61..2b42b4d 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -433,6 +433,9 @@ <message name="IDS_IOS_AUTOFILL_CREDIT_CARD_AUTOFILL_DATA" desc="The accessible name for the button in the keyboard accessory shown when filling out forms used to open the expanded view to see credit card autofill data. This is spoken by VoiceOver. [Length: unlimited] [iOS only]"> Payment methods </message> + <message name="IDS_IOS_AUTOFILL_CVC" desc="The placeholder text for credit card security code in the payments card unmask dialog. [iOS only]"> + Security code + </message> <message name="IDS_IOS_AUTOFILL_DEPENDENT_LOCALITY" desc="Title of the field of a profile address representing the neighborhood. A dependent locality is a subunit of a locality, where a 'locality' is roughly equivalent to a city. Examples of dependent localities include inner-city districts and suburbs. Only used in certain countries, like Brazil and Mexico, for example. [Length: 15em] [iOS only]"> Neighborhood </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AUTOFILL_CVC.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AUTOFILL_CVC.png.sha1 new file mode 100644 index 0000000..9491c05 --- /dev/null +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AUTOFILL_CVC.png.sha1
@@ -0,0 +1 @@ +08279eab52158f6bb55ae55dc35bb162a621bcd9 \ No newline at end of file
diff --git a/ios/chrome/browser/authentication/ui_bundled/separate_profiles_egtest.mm b/ios/chrome/browser/authentication/ui_bundled/separate_profiles_egtest.mm index fd9404b..8605809 100644 --- a/ios/chrome/browser/authentication/ui_bundled/separate_profiles_egtest.mm +++ b/ios/chrome/browser/authentication/ui_bundled/separate_profiles_egtest.mm
@@ -117,8 +117,15 @@ // Tests that signing in from a signed out state with a managed account // shows the enterprise onboarding only the first time and that by default // existing browsing data is kept separate from the managed profile. -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testSigninWithManagedAccountFromUnsignedStateSeparateData { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testSigninWithManagedAccountFromUnsignedStateSeparateData \ + DISABLED_testSigninWithManagedAccountFromUnsignedStateSeparateData +#else +#define MAYBE_testSigninWithManagedAccountFromUnsignedStateSeparateData \ + testSigninWithManagedAccountFromUnsignedStateSeparateData +#endif +- (void)MAYBE_testSigninWithManagedAccountFromUnsignedStateSeparateData { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -218,7 +225,8 @@ // shows the enterprise onboarding only the first time. And if the user // decides to keep their existing data into the managed profile, the existing // profile is converted. -// TODO(crbug.com/433320893): Re-enable this test. +// TODO(crbug.com/411035267): The test fails flakily on simulator. +// TODO(crbug.com/433320893): And on device. - (void)DISABLED_testSigninWithManagedAccountFromUnsignedStateConvertsProfile { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { @@ -321,9 +329,16 @@ // Tests that signing in from a signed out state with a managed account shows // the enterprise onboarding only the first time. And the user cannot merge // existing browsing data because it is disabled by policy. -// TODO(crbug.com/433320893): Re-enable this test. +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testSigninWithManagedAccountFromUnsignedStateWithDataMigrationDisabled \ + DISABLED_testSigninWithManagedAccountFromUnsignedStateWithDataMigrationDisabled +#else +#define MAYBE_testSigninWithManagedAccountFromUnsignedStateWithDataMigrationDisabled \ + testSigninWithManagedAccountFromUnsignedStateWithDataMigrationDisabled +#endif - (void) - DISABLED_testSigninWithManagedAccountFromUnsignedStateWithDataMigrationDisabled { + MAYBE_testSigninWithManagedAccountFromUnsignedStateWithDataMigrationDisabled { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -640,8 +655,15 @@ // Tests switching to a managed account (and thus managed profile) and back via // the account menu. -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testSwitchFromPersonalToManagedAndBack { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testSwitchFromPersonalToManagedAndBack \ + DISABLED_testSwitchFromPersonalToManagedAndBack +#else +#define MAYBE_testSwitchFromPersonalToManagedAndBack \ + testSwitchFromPersonalToManagedAndBack +#endif +- (void)MAYBE_testSwitchFromPersonalToManagedAndBack { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -719,9 +741,16 @@ // Tests switching to a managed account (and thus managed profile) and the // managed account is removed while the enterprise onboarding is shown. -// TODO(crbug.com/433320893): Re-enable this test. +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testSwitchFromPersonalToManagedAndManagedAccountRemovedFromDevice \ + DISABLED_testSwitchFromPersonalToManagedAndManagedAccountRemovedFromDevice +#else +#define MAYBE_testSwitchFromPersonalToManagedAndManagedAccountRemovedFromDevice \ + testSwitchFromPersonalToManagedAndManagedAccountRemovedFromDevice +#endif - (void) - DISABLED_testSwitchFromPersonalToManagedAndManagedAccountRemovedFromDevice { + MAYBE_testSwitchFromPersonalToManagedAndManagedAccountRemovedFromDevice { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -768,8 +797,15 @@ // Tests switching to a managed account but refusing the enterprise onboarding // screen. -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testRefuseToSwitchToManageAccount { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testRefuseToSwitchToManageAccount \ + DISABLED_testRefuseToSwitchToManageAccount +#else +#define MAYBE_testRefuseToSwitchToManageAccount \ + testRefuseToSwitchToManageAccount +#endif +- (void)MAYBE_testRefuseToSwitchToManageAccount { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -853,8 +889,15 @@ @"Profile should be personal"); } -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testProfileDeletedOnRemoveManagedAccount { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testProfileDeletedOnRemoveManagedAccount \ + DISABLED_testProfileDeletedOnRemoveManagedAccount +#else +#define MAYBE_testProfileDeletedOnRemoveManagedAccount \ + testProfileDeletedOnRemoveManagedAccount +#endif +- (void)MAYBE_testProfileDeletedOnRemoveManagedAccount { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -984,8 +1027,15 @@ @"Profile should have been switched back to personal"); } -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testProfileDeletedOnManagedAccountGone { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testProfileDeletedOnManagedAccountGone \ + DISABLED_testProfileDeletedOnManagedAccountGone +#else +#define MAYBE_testProfileDeletedOnManagedAccountGone \ + testProfileDeletedOnManagedAccountGone +#endif +- (void)MAYBE_testProfileDeletedOnManagedAccountGone { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -1114,8 +1164,13 @@ // Tests signing in with a managed account during the FRE. This should convert // the existing profile to a managed profile. -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testSignInWithManagedAccount { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testSignInWithManagedAccount DISABLED_testSignInWithManagedAccount +#else +#define MAYBE_testSignInWithManagedAccount testSignInWithManagedAccount +#endif +- (void)MAYBE_testSignInWithManagedAccount { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return;
diff --git a/ios/chrome/browser/authentication/ui_bundled/separate_profiles_migration_egtest.mm b/ios/chrome/browser/authentication/ui_bundled/separate_profiles_migration_egtest.mm index b4bdaef..539cdc1 100644 --- a/ios/chrome/browser/authentication/ui_bundled/separate_profiles_migration_egtest.mm +++ b/ios/chrome/browser/authentication/ui_bundled/separate_profiles_migration_egtest.mm
@@ -124,8 +124,15 @@ } } -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testMigrateWithManagedPrimaryAccount { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testMigrateWithManagedPrimaryAccount \ + DISABLED_testMigrateWithManagedPrimaryAccount +#else +#define MAYBE_testMigrateWithManagedPrimaryAccount \ + testMigrateWithManagedPrimaryAccount +#endif +- (void)MAYBE_testMigrateWithManagedPrimaryAccount { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return;
diff --git a/ios/chrome/browser/authentication/ui_bundled/separate_profiles_rollback_egtest.mm b/ios/chrome/browser/authentication/ui_bundled/separate_profiles_rollback_egtest.mm index 9a4e69e..2ee6b1aa 100644 --- a/ios/chrome/browser/authentication/ui_bundled/separate_profiles_rollback_egtest.mm +++ b/ios/chrome/browser/authentication/ui_bundled/separate_profiles_rollback_egtest.mm
@@ -129,8 +129,14 @@ @"Separate profiles should be disabled now"); } -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testRollbackWithManagedProfile { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testRollbackWithManagedProfile \ + DISABLED_testRollbackWithManagedProfile +#else +#define MAYBE_testRollbackWithManagedProfile testRollbackWithManagedProfile +#endif +- (void)MAYBE_testRollbackWithManagedProfile { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -224,8 +230,15 @@ @"Should be in the managed profile again"); } -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testRollbackWithManagedProfile_ManagedAccountRemoved { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testRollbackWithManagedProfile_ManagedAccountRemoved \ + DISABLED_testRollbackWithManagedProfile_ManagedAccountRemoved +#else +#define MAYBE_testRollbackWithManagedProfile_ManagedAccountRemoved \ + testRollbackWithManagedProfile_ManagedAccountRemoved +#endif +- (void)MAYBE_testRollbackWithManagedProfile_ManagedAccountRemoved { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return; @@ -316,8 +329,15 @@ @"Separate profiles should still be enabled"); } -// TODO(crbug.com/433320893): Re-enable this test. -- (void)DISABLED_testRollbackWithManagedProfile_KillSwitch { +// TODO(crbug.com/433320893): Re-enable this test on device. +#if !TARGET_OS_SIMULATOR +#define MAYBE_testRollbackWithManagedProfile_KillSwitch \ + DISABLED_testRollbackWithManagedProfile_KillSwitch +#else +#define MAYBE_testRollbackWithManagedProfile_KillSwitch \ + testRollbackWithManagedProfile_KillSwitch +#endif +- (void)MAYBE_testRollbackWithManagedProfile_KillSwitch { // Separate profiles are only available in iOS 17+. if (!@available(iOS 17, *)) { return;
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_coordinator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_coordinator.mm index 78896b52..d195e54d 100644 --- a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_coordinator.mm +++ b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_coordinator.mm
@@ -45,8 +45,8 @@ } - (void)dealloc { - CHECK(!self.mediator, base::NotFatalUntil::M142); - CHECK(!self.accountChooserViewController, base::NotFatalUntil::M142); + CHECK(!self.mediator, base::NotFatalUntil::M144); + CHECK(!self.accountChooserViewController, base::NotFatalUntil::M144); } #pragma mark - ChromeCoordinator
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm index 119fab2..6cba0f5 100644 --- a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm +++ b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_account_chooser/consistency_account_chooser_mediator.mm
@@ -53,8 +53,8 @@ } - (void)dealloc { - DCHECK(!_identityManager); - DCHECK(!_accountManagerService); + CHECK(!_identityManager, base::NotFatalUntil::M145); + CHECK(!_accountManagerService, base::NotFatalUntil::M145); } - (void)disconnect {
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm index 26ecc098..09cd24b 100644 --- a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm +++ b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm
@@ -451,6 +451,10 @@ - (void)consistencyDefaultAccountCoordinatorOpenIdentityChooser: (ConsistencyDefaultAccountCoordinator*)coordinator { + if (self.accountChooserCoordinator) { + // This can occur if the user double tap on the button. + return; + } self.accountChooserCoordinator = [[ConsistencyAccountChooserCoordinator alloc] initWithBaseViewController:self.navigationController browser:self.browser
diff --git a/ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.h b/ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.h index c1b3fe7..8d53df4 100644 --- a/ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.h +++ b/ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.h
@@ -12,6 +12,7 @@ #import "ios/chrome/browser/autocomplete/model/tab_matcher_impl.h" class AutocompleteScoringModelService; +class AimEligibilityService; class OnDeviceTailModelService; class ProfileIOS; struct ProviderStateService; @@ -75,6 +76,9 @@ ProviderStateService* GetProviderStateService() const override; base::CallbackListSubscription GetLensSuggestInputsWhenReady( LensOverlaySuggestInputsCallback callback) const override; + AimEligibilityService* GetAimEligibilityService() const override; + tab_groups::TabGroupSyncService* GetTabGroupSyncService() const override; + std::string GetAcceptLanguages() const override; std::string GetEmbedderRepresentationOfAboutScheme() const override; std::vector<std::u16string> GetBuiltinURLs() override; @@ -82,7 +86,6 @@ component_updater::ComponentUpdateService* GetComponentUpdateService() override; signin::IdentityManager* GetIdentityManager() const override; - tab_groups::TabGroupSyncService* GetTabGroupSyncService() const override; bool IsOffTheRecord() const override; bool IsIncognitoProfile() const override; bool IsGuestSession() const override; @@ -113,10 +116,9 @@ void CloseIncognitoWindows() override {} void PromptPageTranslation() override {} void OpenLensOverlay(bool show) override {} - void IssueContextualSearchRequest( - const GURL& destination_url, - AutocompleteMatchType::Type match_type, - bool is_zero_prefix_suggestion) override {} + void IssueContextualSearchRequest(const GURL& destination_url, + AutocompleteMatchType::Type match_type, + bool is_zero_prefix_suggestion) override {} private: raw_ptr<ProfileIOS> profile_;
diff --git a/ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.mm b/ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.mm index f1bbac1..89c6280 100644 --- a/ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.mm +++ b/ios/chrome/browser/autocomplete/model/autocomplete_provider_client_impl.mm
@@ -205,6 +205,16 @@ << "GetLensSuggestInputsWhenReady is not implemented by default."; } +tab_groups::TabGroupSyncService* +AutocompleteProviderClientImpl::GetTabGroupSyncService() const { + return nullptr; +} + +AimEligibilityService* +AutocompleteProviderClientImpl::GetAimEligibilityService() const { + return nullptr; +} + std::string AutocompleteProviderClientImpl::GetAcceptLanguages() const { return profile_->GetPrefs()->GetString(language::prefs::kAcceptLanguages); } @@ -242,11 +252,6 @@ return IdentityManagerFactory::GetForProfile(profile_); } -tab_groups::TabGroupSyncService* -AutocompleteProviderClientImpl::GetTabGroupSyncService() const { - return nullptr; -} - bool AutocompleteProviderClientImpl::IsOffTheRecord() const { return profile_->IsOffTheRecord(); }
diff --git a/ios/chrome/browser/autofill/ui_bundled/save_card_infobar_metrics_recorder.h b/ios/chrome/browser/autofill/ui_bundled/save_card_infobar_metrics_recorder.h index e5c11aa..1bcc986 100644 --- a/ios/chrome/browser/autofill/ui_bundled/save_card_infobar_metrics_recorder.h +++ b/ios/chrome/browser/autofill/ui_bundled/save_card_infobar_metrics_recorder.h
@@ -17,8 +17,10 @@ EditedExpirationMonth = 1, // Save Card Infobar expiration year was edited. EditedExpirationYear = 2, + // Save Card Infobar cvc was edited. + EditedCvc = 3, // Highest enumerator. Recommended by Histogram metrics best practices. - kMaxValue = EditedExpirationYear, + kMaxValue = EditedCvc, }; // Used to record metrics related to Save Card Infobar specific events.
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_service.h b/ios/chrome/browser/credential_provider/model/credential_provider_service.h index c7990ee0..918734c6 100644 --- a/ios/chrome/browser/credential_provider/model/credential_provider_service.h +++ b/ios/chrome/browser/credential_provider/model/credential_provider_service.h
@@ -147,6 +147,9 @@ // Syncs whether or not PRF is enabled. void UpdatePasskeyPRFSetting(); + // Syncs whether or not Large Blob is enabled. + void UpdatePasskeyLargeBlobSetting(); + // Syncs whether or not signal API is enabled. void UpdateSignalAPISetting();
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_service.mm b/ios/chrome/browser/credential_provider/model/credential_provider_service.mm index 9b6e92b..994b990 100644 --- a/ios/chrome/browser/credential_provider/model/credential_provider_service.mm +++ b/ios/chrome/browser/credential_provider/model/credential_provider_service.mm
@@ -218,6 +218,7 @@ UpdatePasswordSyncSetting(); UpdateAutomaticPasskeyUpgradeSetting(); UpdatePasskeyPRFSetting(); + UpdatePasskeyLargeBlobSetting(); UpdateSignalAPISetting(); } @@ -596,6 +597,18 @@ forKey:AppGroupUserDefaulsCredentialProviderPasskeyPRFEnabled()]; } +void CredentialProviderService::UpdatePasskeyLargeBlobSetting() { + if (!IsLastUsedProfile()) { + return; + } + + BOOL is_enabled = + base::FeatureList::IsEnabled(kCredentialProviderPasskeyLargeBlob); + [app_group::GetGroupUserDefaults() + setObject:[NSNumber numberWithBool:is_enabled] + forKey:AppGroupUserDefaulsCredentialProviderPasskeyLargeBlobEnabled()]; +} + void CredentialProviderService::UpdateSignalAPISetting() { if (!IsLastUsedProfile()) { return;
diff --git a/ios/chrome/browser/credential_provider/model/features.h b/ios/chrome/browser/credential_provider/model/features.h index b95d90f..c2a91f5 100644 --- a/ios/chrome/browser/credential_provider/model/features.h +++ b/ios/chrome/browser/credential_provider/model/features.h
@@ -14,6 +14,9 @@ // Feature flag to enable passkey PRF support in the credential provider. BASE_DECLARE_FEATURE(kCredentialProviderPasskeyPRF); +// Feature flag to enable passkey Large Blob support in the credential provider. +BASE_DECLARE_FEATURE(kCredentialProviderPasskeyLargeBlob); + // Feature flag to enable the performance improvements for the credential // provider. BASE_DECLARE_FEATURE(kCredentialProviderPerformanceImprovements);
diff --git a/ios/chrome/browser/credential_provider/model/features.mm b/ios/chrome/browser/credential_provider/model/features.mm index 872d2ea..dbfbcba5 100644 --- a/ios/chrome/browser/credential_provider/model/features.mm +++ b/ios/chrome/browser/credential_provider/model/features.mm
@@ -12,6 +12,10 @@ "CredentialProviderPasskeyPRF", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kCredentialProviderPasskeyLargeBlob, + "CredentialProviderPasskeyLargeBlob", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kCredentialProviderPerformanceImprovements, "CredentialProviderPerformanceImprovements", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/ios/chrome/browser/dom_distiller/model/distiller_service_unittest.mm b/ios/chrome/browser/dom_distiller/model/distiller_service_unittest.mm index db25937..86f70368 100644 --- a/ios/chrome/browser/dom_distiller/model/distiller_service_unittest.mm +++ b/ios/chrome/browser/dom_distiller/model/distiller_service_unittest.mm
@@ -8,6 +8,7 @@ #import "components/dom_distiller/core/article_distillation_update.h" #import "components/dom_distiller/core/distiller_page.h" +#import "components/dom_distiller/core/dom_distiller_constants.h" #import "components/dom_distiller/core/proto/distilled_article.pb.h" #import "ios/chrome/browser/dom_distiller/model/distiller_service_factory.h" #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h" @@ -23,6 +24,9 @@ OnDistillationDone(url, &empty_result); } bool ShouldFetchOfflineData() override { return false; } + dom_distiller::DistillerType GetDistillerType() override { + return dom_distiller::DistillerType::kDOMDistiller; + } }; } // namespace
diff --git a/ios/chrome/browser/download/ui/download_manager_egtest.mm b/ios/chrome/browser/download/ui/download_manager_egtest.mm index d05cf897..a893f16 100644 --- a/ios/chrome/browser/download/ui/download_manager_egtest.mm +++ b/ios/chrome/browser/download/ui/download_manager_egtest.mm
@@ -240,7 +240,8 @@ // Tests filename label. [[EarlGrey selectElementWithMatcher:grey_allOf(grey_text(@"download-example"), - grey_sufficientlyVisible(), nil)] + grey_minimumVisiblePercent(0.65), + nil)] assertWithMatcher:grey_notNil()]; } @@ -292,7 +293,8 @@ // Tests filename label. [[EarlGrey selectElementWithMatcher:grey_allOf(grey_text(@"download-example"), - grey_sufficientlyVisible(), nil)] + grey_minimumVisiblePercent(0.65), + nil)] assertWithMatcher:grey_notNil()]; } @@ -451,26 +453,12 @@ // Tests that filename label and "Open in Downloads" button are showing. - (void)testVisibleFileNameAndOpenInDownloads { -// TODO(crbug.com/432003647): Re-enable the test on iOS26. -#if defined(__IPHONE_26_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_26_0 - if (iOS26_OR_ABOVE()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 26."); - } -#endif - [_helper testVisibleFileNameAndOpenInDownloads]; } // Tests that "Open in..." works if the download ended while waiting in a // different tab which also contains a download task. - (void)testSwitchTabsAndOpenInDownloads { - // TODO(crbug.com/432003077): Re-enable the test on iOS26. -#if defined(__IPHONE_26_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_26_0 - if (iOS26_OR_ABOVE()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 26."); - } -#endif - [_helper testSwitchTabsAndOpenInDownloads]; }
diff --git a/ios/chrome/browser/enterprise/model/idle/BUILD.gn b/ios/chrome/browser/enterprise/model/idle/BUILD.gn index db48cd0..0004f1d 100644 --- a/ios/chrome/browser/enterprise/model/idle/BUILD.gn +++ b/ios/chrome/browser/enterprise/model/idle/BUILD.gn
@@ -33,6 +33,7 @@ "//ios/chrome/browser/shared/model/profile", "//ios/chrome/browser/shared/model/profile:profile_keyed_service_factory", "//ios/chrome/browser/shared/model/web_state_list", + "//ios/chrome/browser/signin/model", "//ios/chrome/browser/signin/model:authentication_service", "//ios/chrome/browser/signin/model:authentication_service_factory", "//ios/chrome/browser/web_state_list/model/web_usage_enabler", @@ -55,6 +56,7 @@ "//components/policy/core/browser:test_support", "//components/pref_registry", "//components/prefs", + "//components/signin/public/identity_manager", "//ios/chrome/browser/browsing_data/model:test_support", "//ios/chrome/browser/prefs/model", "//ios/chrome/browser/shared/model/application_context", @@ -63,6 +65,7 @@ "//ios/chrome/browser/shared/model/profile/test", "//ios/chrome/browser/shared/model/web_state_list", "//ios/chrome/browser/shared/model/web_state_list/test:test_support", + "//ios/chrome/browser/signin/model", "//ios/chrome/browser/signin/model:authentication_service", "//ios/chrome/browser/signin/model:authentication_service_factory", "//ios/chrome/browser/signin/model:fake_system_identity",
diff --git a/ios/chrome/browser/enterprise/model/idle/DEPS b/ios/chrome/browser/enterprise/model/idle/DEPS index eb2abf8b..e2a5864 100644 --- a/ios/chrome/browser/enterprise/model/idle/DEPS +++ b/ios/chrome/browser/enterprise/model/idle/DEPS
@@ -3,11 +3,10 @@ # found in the LICENSE file. include_rules = [ - "+ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.h", - "+ios/chrome/browser/browsing_data/model", - "+ios/chrome/browser/discover_feed/model", - "+ios/chrome/browser/signin/model/authentication_service.h", - "+ios/chrome/browser/signin/model/authentication_service_factory.h", + "+ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.h", + "+ios/chrome/browser/browsing_data/model", + "+ios/chrome/browser/discover_feed/model", + "+ios/chrome/browser/signin/model/identity_manager_factory.h", ] specific_include_rules = {
diff --git a/ios/chrome/browser/enterprise/model/idle/action.mm b/ios/chrome/browser/enterprise/model/idle/action.mm index a41f8e7..fc1ebd0 100644 --- a/ios/chrome/browser/enterprise/model/idle/action.mm +++ b/ios/chrome/browser/enterprise/model/idle/action.mm
@@ -22,6 +22,7 @@ #import "components/enterprise/idle/idle_pref_names.h" #import "components/enterprise/idle/metrics.h" #import "components/prefs/pref_service.h" +#import "components/signin/public/identity_manager/identity_manager.h" #import "ios/chrome/browser/authentication/ui_bundled/signin/signin_utils.h" #import "ios/chrome/browser/browsing_data/model/browsing_data_remover_factory.h" #import "ios/chrome/browser/browsing_data/model/browsing_data_remover_observer.h" @@ -31,8 +32,7 @@ #import "ios/chrome/browser/shared/model/browser/browser_list.h" #import "ios/chrome/browser/shared/model/browser/browser_list_factory.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" -#import "ios/chrome/browser/signin/model/authentication_service.h" -#import "ios/chrome/browser/signin/model/authentication_service_factory.h" +#import "ios/chrome/browser/signin/model/identity_manager_factory.h" #import "ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.h" namespace enterprise_idle { @@ -65,10 +65,9 @@ // Action: void Run(ProfileIOS* profile, Continuation continuation) override { - AuthenticationService* authentication_service = - AuthenticationServiceFactory::GetForProfile(profile); - if (authentication_service->HasPrimaryIdentity( - signin::ConsentLevel::kSignin)) { + signin::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile); + if (identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) { signout_start_time_ = base::TimeTicks::Now(); signin::MultiProfileSignOutForProfile( profile,
diff --git a/ios/chrome/browser/enterprise/model/idle/action_unittest.mm b/ios/chrome/browser/enterprise/model/idle/action_unittest.mm index 163eb44..f979548 100644 --- a/ios/chrome/browser/enterprise/model/idle/action_unittest.mm +++ b/ios/chrome/browser/enterprise/model/idle/action_unittest.mm
@@ -12,6 +12,7 @@ #import "base/time/time.h" #import "components/enterprise/idle/idle_pref_names.h" #import "components/prefs/pref_service.h" +#import "components/signin/public/identity_manager/identity_manager.h" #import "ios/chrome/browser/browsing_data/model/fake_browsing_data_remover.h" #import "ios/chrome/browser/enterprise/model/idle/action_runner_impl.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h" @@ -27,6 +28,7 @@ #import "ios/chrome/browser/signin/model/fake_authentication_service_delegate.h" #import "ios/chrome/browser/signin/model/fake_system_identity.h" #import "ios/chrome/browser/signin/model/fake_system_identity_manager.h" +#import "ios/chrome/browser/signin/model/identity_manager_factory.h" #import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" #import "ios/web/public/test/fakes/fake_navigation_manager.h" #import "ios/web/public/test/fakes/fake_web_state.h" @@ -53,6 +55,7 @@ incognito_browsing_data_remover_ = std::make_unique<FakeBrowsingDataRemover>(); action_factory_ = std::make_unique<ActionFactory>(); + identity_manager_ = IdentityManagerFactory::GetForProfile(profile()); histogram_tester_ = std::make_unique<base::HistogramTester>(); } @@ -140,6 +143,7 @@ IOSChromeScopedTestingLocalState scoped_testing_local_state_; TestProfileManagerIOS profile_manager_; std::unique_ptr<ActionFactory> action_factory_; + raw_ptr<signin::IdentityManager> identity_manager_; std::unique_ptr<FakeBrowsingDataRemover> main_browsing_data_remover_; std::unique_ptr<FakeBrowsingDataRemover> incognito_browsing_data_remover_; raw_ptr<TestProfileIOS> profile_; @@ -256,8 +260,8 @@ // Check that the right action is added. EXPECT_EQ(static_cast<int>(ActionType::kSignOut), actions.top()->priority()); SignIn(); - ASSERT_TRUE(authentication_service_->HasPrimaryIdentity( - signin::ConsentLevel::kSignin)); + ASSERT_TRUE( + identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSignin)); base::RunLoop run_loop; // The test needs to wait for the call so that the action is not removed // before sign out completes. @@ -265,8 +269,8 @@ .WillOnce(base::test::RunClosure(run_loop.QuitClosure())); actions.top()->Run(profile(), continuation.Get()); run_loop.Run(); - ASSERT_FALSE(authentication_service_->HasPrimaryIdentity( - signin::ConsentLevel::kSignin)); + ASSERT_FALSE( + identity_manager_->HasPrimaryAccount(signin::ConsentLevel::kSignin)); actions.pop(); histogram_tester_->ExpectUniqueSample( "Enterprise.IdleTimeoutPolicies.Success.SignOut", true, 1);
diff --git a/ios/chrome/browser/enterprise/model/idle/idle_service.mm b/ios/chrome/browser/enterprise/model/idle/idle_service.mm index 0a3f436..c7ecfe28 100644 --- a/ios/chrome/browser/enterprise/model/idle/idle_service.mm +++ b/ios/chrome/browser/enterprise/model/idle/idle_service.mm
@@ -11,8 +11,7 @@ #import "components/enterprise/idle/metrics.h" #import "components/prefs/pref_service.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h" -#import "ios/chrome/browser/signin/model/authentication_service.h" -#import "ios/chrome/browser/signin/model/authentication_service_factory.h" +#import "ios/chrome/browser/signin/model/identity_manager_factory.h" namespace enterprise_idle { @@ -164,9 +163,8 @@ } void IdleService::MaybeRunActionsForState(LastState last_state) { - last_action_set_ = - GetActionSet(profile_->GetPrefs(), - AuthenticationServiceFactory::GetForProfile(profile_)); + last_action_set_ = GetActionSet( + profile_->GetPrefs(), IdentityManagerFactory::GetForProfile(profile_)); if (!IsAnyActionNeededToRun()) { PostCheckIdleTask(GetTimeout());
diff --git a/ios/chrome/browser/enterprise/model/idle/idle_timeout_policy_utils.h b/ios/chrome/browser/enterprise/model/idle/idle_timeout_policy_utils.h index 5a1d7c6..bef4ee5 100644 --- a/ios/chrome/browser/enterprise/model/idle/idle_timeout_policy_utils.h +++ b/ios/chrome/browser/enterprise/model/idle/idle_timeout_policy_utils.h
@@ -5,9 +5,10 @@ #ifndef IOS_CHROME_BROWSER_ENTERPRISE_MODEL_IDLE_IDLE_TIMEOUT_POLICY_UTILS_H_ #define IOS_CHROME_BROWSER_ENTERPRISE_MODEL_IDLE_IDLE_TIMEOUT_POLICY_UTILS_H_ -#import "ios/chrome/browser/signin/model/authentication_service.h" - class PrefService; +namespace signin { +class IdentityManager; +} // namespace signin namespace enterprise_idle { @@ -19,7 +20,8 @@ // Returns the action set based on the value of `IdleTimeoutActions`. // The action set only contains `signout` if the user is signed in. -ActionSet GetActionSet(PrefService* prefs, AuthenticationService* auth_service); +ActionSet GetActionSet(PrefService* prefs, + signin::IdentityManager* identity_manager); } // namespace enterprise_idle
diff --git a/ios/chrome/browser/enterprise/model/idle/idle_timeout_policy_utils.mm b/ios/chrome/browser/enterprise/model/idle/idle_timeout_policy_utils.mm index 3324d4b..ab16189d 100644 --- a/ios/chrome/browser/enterprise/model/idle/idle_timeout_policy_utils.mm +++ b/ios/chrome/browser/enterprise/model/idle/idle_timeout_policy_utils.mm
@@ -6,11 +6,12 @@ #import "components/enterprise/idle/action_type.h" #import "components/prefs/pref_service.h" +#import "components/signin/public/identity_manager/identity_manager.h" namespace enterprise_idle { ActionSet GetActionSet(PrefService* prefs, - AuthenticationService* auth_service) { + signin::IdentityManager* identity_manager) { std::vector<ActionType> action_types = GetActionTypesFromPrefs(prefs); ActionSet action_set; for (ActionType action_type : action_types) { @@ -23,7 +24,7 @@ // not signed in before actions run. case ActionType::kSignOut: action_set.signout = - auth_service->HasPrimaryIdentity(signin::ConsentLevel::kSignin); + identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin); break; case ActionType::kClearBrowsingHistory:
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 21cc6ce9..fe1b563 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -2683,9 +2683,6 @@ flags_ui::kOsIos, FEATURE_VALUE_TYPE(password_manager::features:: kIOSEnablePasswordManagerTrustedVaultWidget)}, - {"colorful-tab-group", flag_descriptions::kColorfulTabGroupName, - flag_descriptions::kColorfulTabGroupDescription, flags_ui::kOsIos, - FEATURE_VALUE_TYPE(kColorfulTabGroup)}, {"lens-load-aim-in-lens-result-page", flag_descriptions::kLensLoadAIMInLensResultPageName, flag_descriptions::kLensLoadAIMInLensResultPageDescription, @@ -2870,6 +2867,10 @@ {"page-context-anchor-tags", flag_descriptions::kPageContextAnchorTagsName, flag_descriptions::kPageContextAnchorTagsDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kPageContextAnchorTags)}, + {"cpe-passkey-largeblob-support", + flag_descriptions::kCredentialProviderPasskeyLargeBlobName, + flag_descriptions::kCredentialProviderPasskeyLargeBlobDescription, + flags_ui::kOsIos, FEATURE_VALUE_TYPE(kCredentialProviderPasskeyLargeBlob)}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index ccfc99a6..ca22392 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -318,10 +318,6 @@ "including features such as recent activity, dirty dots, and description " "action chips."; -const char kColorfulTabGroupName[] = "Colorful tab groups"; -const char kColorfulTabGroupDescription[] = - "Display the tab group colors in additional surfaces."; - const char kContainedTabGroupName[] = "Contained tab group"; const char kContainedTabGroupDescription[] = "When enabled the tab group in the tab grid is not presented fullscreen."; @@ -349,6 +345,12 @@ const char kCredentialProviderAutomaticPasskeyUpgradeDescription[] = "Enables automatic passkey upgrade in the Credential Provider Extension."; +const char kCredentialProviderPasskeyLargeBlobName[] = + "Credential Provider Large Blob support"; +const char kCredentialProviderPasskeyLargeBlobDescription[] = + "Enables support for the Large Blob extension for Passkeys in the " + "Credential Provider Extension."; + const char kCredentialProviderPasskeyPRFName[] = "Credential Provider PRF support"; const char kCredentialProviderPasskeyPRFDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 1d028b36..217b883 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -179,9 +179,6 @@ extern const char kCollaborationMessagingName[]; extern const char kCollaborationMessagingDescription[]; -extern const char kColorfulTabGroupName[]; -extern const char kColorfulTabGroupDescription[]; - extern const char kContainedTabGroupName[]; extern const char kContainedTabGroupDescription[]; @@ -200,6 +197,9 @@ extern const char kCredentialProviderAutomaticPasskeyUpgradeName[]; extern const char kCredentialProviderAutomaticPasskeyUpgradeDescription[]; +extern const char kCredentialProviderPasskeyLargeBlobName[]; +extern const char kCredentialProviderPasskeyLargeBlobDescription[]; + extern const char kCredentialProviderPasskeyPRFName[]; extern const char kCredentialProviderPasskeyPRFDescription[];
diff --git a/ios/chrome/browser/https_upgrades/model/typed_navigation_upgrade_tab_helper.h b/ios/chrome/browser/https_upgrades/model/typed_navigation_upgrade_tab_helper.h index e5dd1a72c..cbb08b7 100644 --- a/ios/chrome/browser/https_upgrades/model/typed_navigation_upgrade_tab_helper.h +++ b/ios/chrome/browser/https_upgrades/model/typed_navigation_upgrade_tab_helper.h
@@ -5,16 +5,15 @@ #ifndef IOS_CHROME_BROWSER_HTTPS_UPGRADES_MODEL_TYPED_NAVIGATION_UPGRADE_TAB_HELPER_H_ #define IOS_CHROME_BROWSER_HTTPS_UPGRADES_MODEL_TYPED_NAVIGATION_UPGRADE_TAB_HELPER_H_ -#import "base/memory/raw_ptr.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "base/timer/timer.h" #include "ios/web/public/web_state_observer.h" -#import "ios/web/public/web_state_user_data.h" +#include "ios/web/public/web_state_user_data.h" #include "url/gurl.h" class HttpsUpgradeService; -class PrerenderService; // A tab helper that handles the fallback and timeout logic for Omnibox HTTPS // upgrades. Omnibox HTTPS upgrades feature automatically upgrades navigations @@ -65,7 +64,6 @@ }; TypedNavigationUpgradeTabHelper(web::WebState* web_state, - PrerenderService* prerender_service, HttpsUpgradeService* service); // Called when the upgrade timer times out. @@ -84,7 +82,6 @@ base::OneShotTimer timer_; - raw_ptr<PrerenderService> prerender_service_; raw_ptr<HttpsUpgradeService> service_; };
diff --git a/ios/chrome/browser/https_upgrades/model/typed_navigation_upgrade_tab_helper.mm b/ios/chrome/browser/https_upgrades/model/typed_navigation_upgrade_tab_helper.mm index 261527c8..431001b 100644 --- a/ios/chrome/browser/https_upgrades/model/typed_navigation_upgrade_tab_helper.mm +++ b/ios/chrome/browser/https_upgrades/model/typed_navigation_upgrade_tab_helper.mm
@@ -10,7 +10,6 @@ #import "base/task/sequenced_task_runner.h" #import "components/security_interstitials/core/omnibox_https_upgrade_metrics.h" #import "ios/chrome/browser/https_upgrades/model/https_upgrade_service_impl.h" -#import "ios/chrome/browser/prerender/model/prerender_service.h" #import "ios/components/security_interstitials/https_only_mode/https_upgrade_service.h" #import "ios/web/public/navigation/https_upgrade_type.h" #import "ios/web/public/navigation/navigation_context.h" @@ -34,9 +33,8 @@ TypedNavigationUpgradeTabHelper::TypedNavigationUpgradeTabHelper( web::WebState* web_state, - PrerenderService* prerender_service, HttpsUpgradeService* service) - : prerender_service_(prerender_service), service_(service) { + : service_(service) { web_state->AddObserver(this); } @@ -86,10 +84,6 @@ if (navigation_context->IsSameDocument()) { return; } - if (prerender_service_ && - prerender_service_->IsWebStatePrerendered(web_state)) { - return; - } web::NavigationItem* item_pending = web_state->GetNavigationManager()->GetPendingItem(); @@ -123,10 +117,7 @@ if (navigation_context->IsSameDocument() || state_ == State::kNone) { return; } - if (prerender_service_ && - prerender_service_->IsWebStatePrerendered(web_state)) { - return; - } + timer_.Stop(); // Start a fallback navigation if the upgraded navigation failed.
diff --git a/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.h b/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.h index 53d9cba9..adf7d3f8 100644 --- a/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.h +++ b/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.h
@@ -8,6 +8,7 @@ #import <Foundation/Foundation.h> // Pref keys passed through setupModalViewControllerWithPrefs:. +extern NSString* const kCardCvcPrefKey; extern NSString* const kCardholderNamePrefKey; extern NSString* const kCardIssuerIconNamePrefKey; extern NSString* const kCardNetworkPrefKey;
diff --git a/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.mm b/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.mm index e15f824d..39e4673 100644 --- a/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.mm +++ b/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.mm
@@ -4,6 +4,7 @@ #import "ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_consumer.h" +NSString* const kCardCvcPrefKey = @"cardCvc"; NSString* const kCardholderNamePrefKey = @"cardholderName"; NSString* const kCardIssuerIconNamePrefKey = @"cardIssuerIconName"; NSString* const kCardNetworkPrefKey = @"cardNetwork";
diff --git a/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_delegate.h b/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_delegate.h index 9bf2405..0ea34b7 100644 --- a/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_delegate.h +++ b/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_modal_delegate.h
@@ -15,10 +15,13 @@ @protocol InfobarSaveCardModalDelegate <InfobarModalDelegate> // Saves the current card with using `cardholderName` as cardholder name, -// `month` as expiration month and `year` as expiration year. +// `month` as expiration month, `year` as expiration year, `cardCvc` as security +// code. The `cardCvc` is optional and should be an empty string if not provided +// by the user. - (void)saveCardWithCardholderName:(NSString*)cardholderName expirationMonth:(NSString*)month - expirationYear:(NSString*)year; + expirationYear:(NSString*)year + cardCvc:(NSString*)cardCvc; // Opens `linkURL` in a new tab and dismisses the Modal. - (void)dismissModalAndOpenURL:(const GURL&)linkURL;
diff --git a/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_table_view_controller.mm b/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_table_view_controller.mm index 13d36370..7f06a71e 100644 --- a/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_table_view_controller.mm +++ b/ios/chrome/browser/infobars/ui_bundled/modals/infobar_save_card_table_view_controller.mm
@@ -10,6 +10,7 @@ #import "base/metrics/user_metrics_action.h" #import "build/branding_buildflags.h" #import "components/autofill/core/common/autofill_features.h" +#import "components/autofill/core/common/autofill_payments_features.h" #import "components/strings/grit/components_strings.h" #import "ios/chrome/browser/autofill/model/message/save_card_message_with_links.h" #import "ios/chrome/browser/autofill/ui_bundled/save_card_infobar_metrics_recorder.h" @@ -49,6 +50,7 @@ ItemTypeCardHolderName, ItemTypeCardExpireMonth, ItemTypeCardExpireYear, + ItemTypeCardCvc, ItemTypeCardLegalMessage, ItemTypeCardSave, }; @@ -75,6 +77,8 @@ @property(nonatomic, copy) NSString* expirationMonth; // Card Expiration Year to be displayed. @property(nonatomic, copy) NSString* expirationYear; +// Card Security code to be displayed. +@property(nonatomic, strong) NSString* cardCvc; // Card related Legal Messages to be displayed. @property(nonatomic, copy) NSMutableArray<SaveCardMessageWithLinks*>* legalMessages; @@ -98,6 +102,8 @@ @property(nonatomic, strong) TableViewTextEditItem* expirationMonthItem; // Item for displaying and editing the expiration year. @property(nonatomic, strong) TableViewTextEditItem* expirationYearItem; +// Item for displaying and editing the security code. +@property(nonatomic, strong) TableViewTextEditItem* cardCvcItem; // Item for displaying the save card button . @property(nonatomic, strong) TableViewTextButtonItem* saveCardButtonItem; @end @@ -206,6 +212,17 @@ [model addItem:self.expirationYearItem toSectionWithIdentifier:SectionIdentifierContent]; + if (base::FeatureList::IsEnabled( + autofill::features::kAutofillEnableCvcStorageAndFilling)) { + self.cardCvcItem = + [self textEditItemWithType:ItemTypeCardCvc + fieldNameLabelText:l10n_util::GetNSString(IDS_IOS_AUTOFILL_CVC) + textFieldValue:self.cardCvc + textFieldEnabled:self.supportsEditing]; + [model addItem:self.cardCvcItem + toSectionWithIdentifier:SectionIdentifierContent]; + } + // Add a `TableViewTextLinkItem` for each legal message and add logo to the // last item. for (size_t index = 0; index < self.legalMessages.count; index++) { @@ -256,6 +273,7 @@ self.cardNumber = prefs[kCardNumberPrefKey]; self.expirationMonth = prefs[kExpirationMonthPrefKey]; self.expirationYear = prefs[kExpirationYearPrefKey]; + self.cardCvc = prefs[kCardCvcPrefKey]; self.legalMessages = prefs[kLegalMessagesPrefKey]; self.currentCardSaveAccepted = [prefs[kCurrentCardSaveAcceptedPrefKey] boolValue]; @@ -321,6 +339,17 @@ editCell.textField.delegate = self; break; } + case ItemTypeCardCvc: { + TableViewTextEditCell* editCell = + base::apple::ObjCCast<TableViewTextEditCell>(cell); + editCell.textField.keyboardType = UIKeyboardTypeNumberPad; + [editCell.textField addTarget:self + action:@selector(cvcDidChange:) + forControlEvents:UIControlEventEditingChanged]; + editCell.selectionStyle = UITableViewCellSelectionStyleNone; + editCell.textField.delegate = self; + break; + } case ItemTypeCardLegalMessage: { TableViewTextLinkCell* linkCell = base::apple::ObjCCast<TableViewTextLinkCell>(cell); @@ -383,7 +412,7 @@ [self reconfigureCellsForItems:@[ self.cardLastDigitsItem, self.cardholderNameItem, self.expirationMonthItem, - self.expirationYearItem, self.saveCardButtonItem + self.expirationYearItem, self.cardCvcItem, self.saveCardButtonItem ]]; } @@ -427,7 +456,8 @@ [self.saveCardModalDelegate saveCardWithCardholderName:self.cardholderNameItem.textFieldValue expirationMonth:self.expirationMonthItem.textFieldValue - expirationYear:self.expirationYearItem.textFieldValue]; + expirationYear:self.expirationYearItem.textFieldValue + cardCvc:self.cardCvcItem.textFieldValue]; } - (void)nameEditDidBegin { @@ -445,6 +475,11 @@ recordModalEvent:MobileMessagesSaveCardModalEvent::EditedExpirationYear]; } +- (void)cvcEditDidBegin { + [SaveCardInfobarMetricsRecorder + recordModalEvent:MobileMessagesSaveCardModalEvent::EditedCvc]; +} + - (void)nameDidChange:(UITextField*)textField { BOOL isNameValid = [self isCardholderNameValid:textField.text]; @@ -484,6 +519,10 @@ [self updateSaveCardButtonState]; } +- (void)cvcDidChange:(UITextField*)textField { + self.cardCvcItem.textFieldValue = textField.text; +} + - (void)dismissInfobarModal { base::RecordAction( base::UserMetricsAction("MobileMessagesModalCancelledTapped")); @@ -506,6 +545,9 @@ self.expirationYearItem.identifyingIconEnabled = NO; self.expirationYearItem.textFieldEnabled = NO; + + self.cardCvcItem.identifyingIconEnabled = NO; + self.cardCvcItem.textFieldEnabled = NO; } #pragma mark - Helpers
diff --git a/ios/chrome/browser/intelligence/bwg/ui/bwg_consent_view_controller.mm b/ios/chrome/browser/intelligence/bwg/ui/bwg_consent_view_controller.mm index ba8291e..415c94b 100644 --- a/ios/chrome/browser/intelligence/bwg/ui/bwg_consent_view_controller.mm +++ b/ios/chrome/browser/intelligence/bwg/ui/bwg_consent_view_controller.mm
@@ -409,6 +409,7 @@ titleLabel.text = titleText; titleLabel.font = PreferredFontForTextStyle(UIFontTextStyleHeadline, UIFontWeightSemibold); + titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader; titleLabel.numberOfLines = 0; [innerStackView addArrangedSubview:titleLabel]; @@ -447,6 +448,7 @@ titleLabel.text = titleText; titleLabel.font = PreferredFontForTextStyle(UIFontTextStyleHeadline, UIFontWeightSemibold); + titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader; titleLabel.numberOfLines = 0; [innerStackView addArrangedSubview:titleLabel];
diff --git a/ios/chrome/browser/intelligence/bwg/ui/bwg_promo_view_controller.mm b/ios/chrome/browser/intelligence/bwg/ui/bwg_promo_view_controller.mm index 762168b..bfe6c714 100644 --- a/ios/chrome/browser/intelligence/bwg/ui/bwg_promo_view_controller.mm +++ b/ios/chrome/browser/intelligence/bwg/ui/bwg_promo_view_controller.mm
@@ -235,6 +235,8 @@ mainTitleLabel.attributedText = attributedString; #endif + mainTitleLabel.accessibilityLabel = mainTitleString; + mainTitleLabel.accessibilityTraits |= UIAccessibilityTraitHeader; return mainTitleLabel; } @@ -373,6 +375,7 @@ titleLabel.textColor = [UIColor colorNamed:kTextPrimaryColor]; titleLabel.numberOfLines = 0; titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader; UILabel* bodyLabel = [[UILabel alloc] init]; bodyLabel.text = bodyText;
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn b/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn index 5f47715..95ea606 100644 --- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn +++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn
@@ -34,6 +34,8 @@ "//ios/chrome/browser/shared/model/profile", "//ios/chrome/browser/shared/model/web_state_list", "//ios/chrome/browser/shared/public/commands", + "//ios/chrome/browser/shared/ui/util", "//ios/chrome/browser/signin/model", + "//ios/web/public", ] }
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm index 768ccba..76e0db2 100644 --- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm +++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm
@@ -4,17 +4,13 @@ #import "ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.h" -#import "components/search/search.h" -#import "components/search_engines/template_url_service.h" #import "ios/chrome/browser/dom_distiller/model/distiller_service_factory.h" -#import "ios/chrome/browser/intelligence/bwg/model/bwg_service.h" #import "ios/chrome/browser/intelligence/bwg/model/bwg_service_factory.h" #import "ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h" #import "ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.h" #import "ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller_delegate.h" #import "ios/chrome/browser/intelligence/page_action_menu/utils/ai_hub_constants.h" #import "ios/chrome/browser/intelligence/page_action_menu/utils/ai_hub_metrics.h" -#import "ios/chrome/browser/lens_overlay/coordinator/lens_overlay_availability.h" #import "ios/chrome/browser/reader_mode/coordinator/reader_mode_options_mediator.h" #import "ios/chrome/browser/reader_mode/model/features.h" #import "ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.h" @@ -57,18 +53,20 @@ - (void)start { web::WebState* activeWebState = self.browser->GetWebStateList()->GetActiveWebState(); - BOOL readerModeActive = NO; - BOOL readerModeAvailable = NO; + + _viewController = [[PageActionMenuViewController alloc] init]; + ReaderModeTabHelper* readerModeTabHelper = ReaderModeTabHelper::FromWebState(activeWebState); - if (readerModeTabHelper) { - readerModeActive = readerModeTabHelper->IsActive(); - readerModeAvailable = - base::FeatureList::IsEnabled( - kEnableReaderModePageEligibilityForToolsMenu) - ? readerModeTabHelper->CurrentPageIsDistillable() - : readerModeTabHelper->CurrentPageIsEligibleForReaderMode(); + _mediator = [[PageActionMenuMediator alloc] + initWithWebState:activeWebState + profilePrefService:self.profile->GetPrefs() + templateURLService:ios::TemplateURLServiceFactory::GetForProfile( + self.profile) + BWGService:BwgServiceFactory::GetForProfile(self.profile) + readerModeTabHelper:readerModeTabHelper]; + if (readerModeTabHelper) { DistillerService* distillerService = DistillerServiceFactory::GetForProfile(self.profile); _readerModeOptionsMediator = [[ReaderModeOptionsMediator alloc] @@ -76,31 +74,17 @@ webStateList:self.browser->GetWebStateList()]; } - _viewController = [[PageActionMenuViewController alloc] - initWithReaderModeActive:readerModeActive]; _viewController.delegate = self; - _mediator = [[PageActionMenuMediator alloc] init]; - if (readerModeAvailable) { - _viewController.readerModeHandler = HandlerForProtocol( - self.browser->GetCommandDispatcher(), ReaderModeCommands); - } + _viewController.mutator = _mediator; + _viewController.readerModeHandler = HandlerForProtocol( + self.browser->GetCommandDispatcher(), ReaderModeCommands); _viewController.pageActionMenuHandler = HandlerForProtocol( self.browser->GetCommandDispatcher(), PageActionMenuCommands); - - BwgService* BWGService = BwgServiceFactory::GetForProfile(self.profile); - if (BWGService->IsBwgAvailableForWebState(activeWebState)) { - CHECK(BWGService->IsProfileEligibleForBwg()); - _viewController.BWGHandler = - HandlerForProtocol(self.browser->GetCommandDispatcher(), BWGCommands); - } - - if (IsLensOverlayAvailable(self.profile->GetPrefs()) && - search::DefaultSearchProviderIsGoogle( - ios::TemplateURLServiceFactory::GetForProfile(self.profile))) { - _viewController.lensOverlayHandler = HandlerForProtocol( - self.browser->GetCommandDispatcher(), LensOverlayCommands); - } + _viewController.BWGHandler = + HandlerForProtocol(self.browser->GetCommandDispatcher(), BWGCommands); + _viewController.lensOverlayHandler = HandlerForProtocol( + self.browser->GetCommandDispatcher(), LensOverlayCommands); _navigationController = [[UINavigationController alloc] initWithRootViewController:_viewController];
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h index 68676390..4776295 100644 --- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h +++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h
@@ -7,8 +7,29 @@ #import <Foundation/Foundation.h> +#import "ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h" + +class BwgService; +class PrefService; +class ReaderModeTabHelper; +class TemplateURLService; + +namespace web { +class WebState; +} + // The mediator for the page action menu. -@interface PageActionMenuMediator : NSObject +@interface PageActionMenuMediator : NSObject <PageActionMenuMutator> + +// Designated initializer for the mediator. +- (instancetype)initWithWebState:(web::WebState*)webState + profilePrefService:(PrefService*)profilePrefs + templateURLService:(TemplateURLService*)templateURLService + BWGService:(BwgService*)BWGService + readerModeTabHelper:(ReaderModeTabHelper*)readerModeTabHelper + NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; @end
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.mm b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.mm index 1db61cc..5d16ce1e3 100644 --- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.mm +++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.mm
@@ -4,6 +4,77 @@ #import "ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h" -@implementation PageActionMenuMediator +#import "components/prefs/pref_service.h" +#import "components/search/search.h" +#import "components/search_engines/template_url_service.h" +#import "ios/chrome/browser/intelligence/bwg/model/bwg_service.h" +#import "ios/chrome/browser/lens_overlay/coordinator/lens_overlay_availability.h" +#import "ios/chrome/browser/reader_mode/model/features.h" +#import "ios/chrome/browser/reader_mode/model/reader_mode_tab_helper.h" +#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" +#import "ios/web/public/web_state.h" + +@implementation PageActionMenuMediator { + // The web state referenced by this mediator. + raw_ptr<web::WebState> _webState; + + // The `PrefService` used to store reminder data. + raw_ptr<PrefService> _profilePrefs; + + // The service to retrieve default search engine URL. + raw_ptr<TemplateURLService> _templateURLService; + + // The service for the Gemini floaty. + raw_ptr<BwgService> _BWGService; + + // The tab helper for Reader mode. + raw_ptr<ReaderModeTabHelper> _readerModeTabHelper; +} + +- (instancetype)initWithWebState:(web::WebState*)webState + profilePrefService:(PrefService*)profilePrefs + templateURLService:(TemplateURLService*)templateURLService + BWGService:(BwgService*)BWGService + readerModeTabHelper:(ReaderModeTabHelper*)readerModeTabHelper { + self = [super init]; + if (self) { + _webState = webState; + _profilePrefs = profilePrefs; + _templateURLService = templateURLService; + _BWGService = BWGService; + _readerModeTabHelper = readerModeTabHelper; + } + return self; +} + +#pragma mark - PageActionMenuMutator + +- (BOOL)isLensAvailableForTraitCollection:(UITraitCollection*)traitCollection { + BOOL isLandscape = IsCompactHeight(traitCollection); + return IsLensOverlayAvailable(_profilePrefs) && + search::DefaultSearchProviderIsGoogle(_templateURLService) && + !isLandscape; +} + +- (BOOL)isGeminiAvailable { + return _BWGService->IsBwgAvailableForWebState(_webState); +} + +- (BOOL)isReaderModeAvailable { + if (!_readerModeTabHelper) { + return NO; + } + return base::FeatureList::IsEnabled( + kEnableReaderModePageEligibilityForToolsMenu) + ? _readerModeTabHelper->CurrentPageIsDistillable() + : _readerModeTabHelper->CurrentPageIsEligibleForReaderMode(); +} + +- (BOOL)isReaderModeActive { + if (!_readerModeTabHelper) { + return NO; + } + return _readerModeTabHelper->IsActive(); +} @end
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/BUILD.gn b/ios/chrome/browser/intelligence/page_action_menu/ui/BUILD.gn index 44cdccd..099bfc6b 100644 --- a/ios/chrome/browser/intelligence/page_action_menu/ui/BUILD.gn +++ b/ios/chrome/browser/intelligence/page_action_menu/ui/BUILD.gn
@@ -6,6 +6,7 @@ sources = [ "page_action_menu_entrypoint_view.h", "page_action_menu_entrypoint_view.mm", + "page_action_menu_mutator.h", "page_action_menu_view_controller.h", "page_action_menu_view_controller.mm", "page_action_menu_view_controller_delegate.h",
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h new file mode 100644 index 0000000..66c662b --- /dev/null +++ b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h
@@ -0,0 +1,27 @@ +// 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_CHROME_BROWSER_INTELLIGENCE_PAGE_ACTION_MENU_UI_PAGE_ACTION_MENU_MUTATOR_H_ +#define IOS_CHROME_BROWSER_INTELLIGENCE_PAGE_ACTION_MENU_UI_PAGE_ACTION_MENU_MUTATOR_H_ + +#import <UIKit/UIKit.h> + +// The mutator for the page action menu. +@protocol PageActionMenuMutator + +// Returns whether the Lens overlay is currently available. +- (BOOL)isLensAvailableForTraitCollection:(UITraitCollection*)traitCollection; + +// Returns whether the Gemini floaty is currently available. +- (BOOL)isGeminiAvailable; + +// Returns whether Reader mode is currently available. +- (BOOL)isReaderModeAvailable; + +// Returns whether Reader mode is currently active. +- (BOOL)isReaderModeActive; + +@end + +#endif // IOS_CHROME_BROWSER_INTELLIGENCE_PAGE_ACTION_MENU_UI_PAGE_ACTION_MENU_MUTATOR_H_
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.h b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.h index 8a76953bc..8857e0a 100644 --- a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.h +++ b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.h
@@ -12,6 +12,7 @@ @protocol BWGCommands; @protocol LensOverlayCommands; @protocol PageActionMenuCommands; +@protocol PageActionMenuMutator; @protocol PageActionMenuViewControllerDelegate; @protocol ReaderModeCommands; @@ -22,20 +23,13 @@ // The delegate for this view controller. @property(nonatomic, weak) id<PageActionMenuViewControllerDelegate> delegate; -// Initializes the view controller adapted to whether Reader Mode is currently -// active. -- (instancetype)initWithReaderModeActive:(BOOL)readerModeActive - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; -- (instancetype)initWithNibName:(NSString*)nibNameOrNil - bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE; - // Returns the appropriate detent value for a sheet presentation in `context`. - (CGFloat)resolveDetentValueForSheetPresentation: (id<UISheetPresentationControllerDetentResolutionContext>)context; +// The mutator for communicating with the mediator. +@property(nonatomic, weak) id<PageActionMenuMutator> mutator; + // The handler for sending BWG commands. @property(nonatomic, weak) id<BWGCommands> BWGHandler;
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm index 6b79c78..77bece3 100644 --- a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm +++ b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm
@@ -6,6 +6,7 @@ #import "build/branding_buildflags.h" #import "ios/chrome/browser/intelligence/bwg/utils/bwg_constants.h" +#import "ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h" #import "ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller_delegate.h" #import "ios/chrome/browser/intelligence/page_action_menu/utils/ai_hub_constants.h" #import "ios/chrome/browser/intelligence/page_action_menu/utils/ai_hub_metrics.h" @@ -74,9 +75,6 @@ @interface PageActionMenuViewController () -// Whether reader mode is currently active. -@property(nonatomic, assign) BOOL readerModeActive; - // Label of the Reader mode options button. Lazily created. @property(nonatomic, strong) UILabel* readerModeOptionsButtonSubtitleLabel; @@ -85,14 +83,9 @@ @implementation PageActionMenuViewController { // Stack view containing the menu's main content. UIStackView* _contentStackView; -} -- (instancetype)initWithReaderModeActive:(BOOL)readerModeActive { - self = [super initWithNibName:nil bundle:nil]; - if (self) { - _readerModeActive = readerModeActive; - } - return self; + // The entry point for the Lens overlay. + UIButton* _lensButton; } - (void)viewDidLoad { @@ -114,7 +107,7 @@ _contentStackView.translatesAutoresizingMaskIntoConstraints = NO; [self.view addSubview:_contentStackView]; - if (self.readerModeActive) { + if ([self.mutator isReaderModeActive]) { UIView* readerModeActiveSection = [self createReaderModeActiveSection]; [_contentStackView addArrangedSubview:readerModeActiveSection]; [_contentStackView setCustomSpacing:kStackViewMargins @@ -138,7 +131,7 @@ // If Reader Mode is available but inactive, we use a 3-button UI. Otherwise, // we just show the `buttonsStackView`, with an additional Reader mode section // (above) if Reader mode is available and active. - if (IsReaderModeAvailable() && !self.readerModeActive) { + if (IsReaderModeAvailable() && ![self.mutator isReaderModeActive]) { // Adds the large Gemini entry point button. UIButton* BWGButton = [self createBWGButton]; [_contentStackView addArrangedSubview:BWGButton]; @@ -165,6 +158,16 @@ [buttonsStackView.heightAnchor constraintGreaterThanOrEqualToConstant:kSmallButtonHeight], ]]; + + __weak PageActionMenuViewController* weakSelf = self; + NSArray<UITrait>* traits = TraitCollectionSetForTraits( + @[ UITraitHorizontalSizeClass.class, UITraitVerticalSizeClass.class ]); + [self registerForTraitChanges:traits + withHandler:^(id<UITraitEnvironment> traitEnvironment, + UITraitCollection* previousCollection) { + [weakSelf updateLensAvailability:traitEnvironment + .traitCollection]; + }]; } - (void)viewDidLayoutSubviews { @@ -415,18 +418,19 @@ stackView.translatesAutoresizingMaskIntoConstraints = NO; // Create the small buttons and add them to the stack view. - UIButton* lensButton = [self + _lensButton = [self createSmallButtonWithIcon:CustomSymbolWithPointSize(kCameraLensSymbol, kSmallButtonIconSize) title:l10n_util::GetNSString( IDS_IOS_AI_HUB_LENS_LABEL) - enabled:[self isLensAvailable]]; - [lensButton addTarget:self - action:@selector(handleLensEntryPointTapped:) - forControlEvents:UIControlEventTouchUpInside]; - [stackView addArrangedSubview:lensButton]; + enabled:[self.mutator isLensAvailableForTraitCollection: + self.traitCollection]]; + [_lensButton addTarget:self + action:@selector(handleLensEntryPointTapped:) + forControlEvents:UIControlEventTouchUpInside]; + [stackView addArrangedSubview:_lensButton]; - if (IsReaderModeAvailable() && !self.readerModeActive) { + if (IsReaderModeAvailable() && ![self.mutator isReaderModeActive]) { UIImage* readerModeImage = DefaultSymbolWithPointSize( GetReaderModeSymbolName(), kSmallButtonIconSize); @@ -436,7 +440,7 @@ UIButton* readerModeButton = [self createSmallButtonWithIcon:readerModeImage title:readerModeLabelText - enabled:[self isReaderModeAvailable]]; + enabled:[self.mutator isReaderModeAvailable]]; [readerModeButton addTarget:self action:@selector(handleReaderModeTapped:) forControlEvents:UIControlEventTouchUpInside]; @@ -446,7 +450,7 @@ [self createSmallButtonWithIcon:[self askGeminiIcon] title:l10n_util::GetNSString( IDS_IOS_AI_HUB_GEMINI_LABEL) - enabled:[self isGeminiAvailable]]; + enabled:[self.mutator isGeminiAvailable]]; [BWGSmallButton addTarget:self action:@selector(handleBWGTapped:) forControlEvents:UIControlEventTouchUpInside]; @@ -527,12 +531,6 @@ setObject:PreferredFontForTextStyle(UIFontTextStyleSubheadline, UIFontWeightRegular) forKey:NSFontAttributeName]; - // If the button is enabled, override the text color. Otherwise, inherit the - // disabled font color. - if (enabled) { - [titleAttributes setObject:[UIColor colorNamed:kTextPrimaryColor] - forKey:NSForegroundColorAttributeName]; - } NSMutableAttributedString* string = [[NSMutableAttributedString alloc] initWithString:title]; [string addAttributes:titleAttributes range:NSMakeRange(0, string.length)]; @@ -542,7 +540,7 @@ primaryAction:nil]; button.translatesAutoresizingMaskIntoConstraints = NO; - [button setEnabled:enabled]; + [self updateSmallButton:button enabled:enabled]; return button; } @@ -558,21 +556,6 @@ #endif } -// Whether Ask Gemini is currently available. -- (BOOL)isGeminiAvailable { - return self.BWGHandler != nil; -} - -// Whether the Reader mode is currently available. -- (BOOL)isReaderModeAvailable { - return self.readerModeHandler != nil; -} - -// Whether the Lens overlay is currently available. -- (BOOL)isLensAvailable { - return self.lensOverlayHandler != nil; -} - #pragma mark - Handlers // Dismisses this view controller and starts the BWG overlay. @@ -615,7 +598,7 @@ // Toggles the visibility of the Reading mode UI on the current page. - (void)toggleReaderModeVisibility { - if (self.readerModeActive) { + if ([self.mutator isReaderModeActive]) { [self.readerModeHandler hideReaderMode]; } else { [self.readerModeHandler @@ -623,4 +606,36 @@ } } +// Updates the availability of the Lens entry point. +- (void)updateLensAvailability:(UITraitCollection*)traitCollection { + [self + updateSmallButton:_lensButton + enabled:[self.mutator + isLensAvailableForTraitCollection:traitCollection]]; +} + +// Updates a `button` for whether it's `enabled`, modifying the tint and enabled +// property. +- (void)updateSmallButton:(UIButton*)button enabled:(BOOL)enabled { + [button setEnabled:enabled]; + + NSMutableAttributedString* attributedTitle = + [button.configuration.attributedTitle mutableCopy]; + NSRange titleRange = NSMakeRange(0, attributedTitle.length); + + if (enabled) { + // If enabled, add the custom color attribute to override the tint. + [attributedTitle addAttribute:NSForegroundColorAttributeName + value:[UIColor colorNamed:kTextPrimaryColor] + range:titleRange]; + } else { + // If disabled, remove the custom color attribute so it returns to its + // default tint. + [attributedTitle removeAttribute:NSForegroundColorAttributeName + range:titleRange]; + } + + [button setAttributedTitle:attributedTitle forState:UIControlStateNormal]; +} + @end
diff --git a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm index 834f56ac..2a736612 100644 --- a/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm +++ b/ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.mm
@@ -151,16 +151,17 @@ // The JavaScript to be executed in each WebFrame which gets all of a frame's // anchor tags and adds them to an array with their corresponding URL and -// innerText. Injected into the main script. +// textContent (which includes all text, including text that is not visually +// rendered). Injected into the main script. constexpr const char16_t* kAnchorTagsJavaScript = uR"DELIM( // Add all the frame's anchor tags to a links array with their HREF/URL and -// innerText. +// textContent. const linksArray = []; const anchorElements = node.querySelectorAll('a[href]'); anchorElements.forEach((anchor) => { linksArray.push({ href: anchor.href, - linkText: anchor.innerText + linkText: anchor.textContent }); }); @@ -434,18 +435,28 @@ maybeAnchorTagsJavaScript, nonceString}), nullptr); - // Execute the JavaScript on the main WebFrame first and pass in the callback - // (which executes the barrier when run) - mainFrame->ExecuteJavaScript( - script, - base::BindOnce(callback, weakSelf, annotatedPageContentBarrier, - /*isMainFrame=*/YES, mainFrame->GetSecurityOrigin())); + // If the page is not protected, execute the JavaScript on the main WebFrame + // first and pass in the callback (which executes the barrier when run). + if (ios::provider::IsProtectedUrl(mainFrame->GetUrl().spec())) { + _forceDetachPageContext = YES; + annotatedPageContentBarrier.Run(); + } else { + mainFrame->ExecuteJavaScript( + script, + base::BindOnce(callback, weakSelf, annotatedPageContentBarrier, + /*isMainFrame=*/YES, mainFrame->GetSecurityOrigin())); + } // Execute the JavaScript on each other WebFrame and pass in the callback // (which executes the barrier when run). for (web::WebFrame* webFrame : webFrames) { - // Skip the main frame since it was already processed above. - if (!webFrame || webFrame->IsMainFrame()) { + if (ios::provider::IsProtectedUrl(webFrame->GetUrl().spec())) { + _forceDetachPageContext = YES; + } + + // Skip if it's the main frame since it was already processed above, or if + // Page Context should already be force detached. + if (!webFrame || webFrame->IsMainFrame() || _forceDetachPageContext) { annotatedPageContentBarrier.Run(); continue; }
diff --git a/ios/chrome/browser/link_to_text/model/resources/link_to_text.ts b/ios/chrome/browser/link_to_text/model/resources/link_to_text.ts index ddf01a2e..2b88bc6 100644 --- a/ios/chrome/browser/link_to_text/model/resources/link_to_text.ts +++ b/ios/chrome/browser/link_to_text/model/resources/link_to_text.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {gCrWebLegacy} from '//ios/web/public/js_messaging/resources/gcrweb.js'; +import {CrWebApi, gCrWeb} from '//ios/web/public/js_messaging/resources/gcrweb.js'; import * as utils from '//third_party/text-fragments-polyfill/src/src/fragment-generation-utils.js'; /** @@ -42,4 +42,6 @@ }; } -gCrWebLegacy.linkToText = {getLinkToText}; +const linkToTextApi = new CrWebApi(); +linkToTextApi.addFunction('getLinkToText', getLinkToText); +gCrWeb.registerApi('linkToText', linkToTextApi);
diff --git a/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent_unittest.mm b/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent_unittest.mm index 4619fbe..ca228a5 100644 --- a/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent_unittest.mm +++ b/ios/chrome/browser/main/ui_bundled/default_browser_promo_scene_agent_unittest.mm
@@ -584,7 +584,7 @@ TestDefaultBrowserOffCyclePromoRegistration) { scoped_feature_list_.InitWithFeatures({kIOSDefaultBrowserOffCyclePromo}, {kEnableReaderModeDefaultBrowserPromo}); - if (@available(iOS 18.3, *)) { + if (IsDefaultBrowserOffCyclePromoEnabled()) { VerifyPromoRegistration({promos_manager::Promo::DefaultBrowserOffCycle}); EXPECT_CALL(*promos_manager_.get(), DeregisterPromo(promos_manager::Promo::DefaultBrowser))
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm index 6c84b2e..4988042 100644 --- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm +++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_coordinator.mm
@@ -26,6 +26,7 @@ #import "components/search/search.h" #import "components/search_engines/template_url_service.h" #import "components/signin/public/base/signin_metrics.h" +#import "components/signin/public/identity_manager/identity_manager.h" #import "components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h" #import "components/signin/public/identity_manager/tribool.h" #import "components/sync/service/sync_service.h" @@ -276,6 +277,8 @@ @end @implementation NewTabPageCoordinator { + // IdentityManager for the primary account info. + raw_ptr<signin::IdentityManager> _identityManager; // Coordinator for the AIM prototype. AIMPrototypeCoordinator* _aimPrototypeCoordinator; // Coordinator in charge of handling sharing use cases. @@ -363,11 +366,9 @@ } // Update the feed if the account is subject to parental controls. - signin::IdentityManager* identityManager = - IdentityManagerFactory::GetForProfile(self.profile); signin::Tribool capability = supervised_user::IsPrimaryAccountSubjectToParentalControls( - identityManager); + _identityManager); [self updateFeedWithIsSupervisedUser:(capability == signin::Tribool::kTrue)]; [self configureNTPMediator]; @@ -468,6 +469,8 @@ [_fakeboxLensIconBubblePresenter dismissAnimated:NO]; + _identityManager = nullptr; + self.started = NO; } @@ -625,6 +628,7 @@ // Gets all NTP services from the profile. - (void)initializeServices { ProfileIOS* profile = self.profile; + _identityManager = IdentityManagerFactory::GetForProfile(profile); self.authService = AuthenticationServiceFactory::GetForProfile(profile); self.templateURLService = ios::TemplateURLServiceFactory::GetForProfile(profile); @@ -638,16 +642,14 @@ DCHECK(self.headerViewController); // Start observing IdentityManager. - signin::IdentityManager* identityManager = - IdentityManagerFactory::GetForProfile(self.profile); _identityObserverBridge = - std::make_unique<signin::IdentityManagerObserverBridge>(identityManager, + std::make_unique<signin::IdentityManagerObserverBridge>(_identityManager, self); // Start observing Family Link user capabilities. _familyLinkUserCapabilitiesObserverBridge = std::make_unique< supervised_user::FamilyLinkUserCapabilitiesObserverBridge>( - identityManager, self); + _identityManager, self); // Start observing DiscoverFeedService. _discoverFeedObserverBridge = std::make_unique<DiscoverFeedObserverBridge>( @@ -917,7 +919,7 @@ [self dismissCustomizationMenu]; [self.NTPMetricsRecorder recordIdentityDiscTapped]; BOOL isSignedIn = - self.authService->HasPrimaryIdentity(signin::ConsentLevel::kSignin); + _identityManager->HasPrimaryAccount(signin::ConsentLevel::kSignin); if (![self isSignInAllowed]) { id<SettingsCommands> handler = HandlerForProtocol( self.browser->GetCommandDispatcher(), SettingsCommands); @@ -1083,8 +1085,8 @@ } - (BOOL)isFollowingFeedAvailable { - return IsWebChannelsEnabled() && self.authService && - self.authService->HasPrimaryIdentity(signin::ConsentLevel::kSignin); + return IsWebChannelsEnabled() && _identityManager && + _identityManager->HasPrimaryAccount(signin::ConsentLevel::kSignin); } - (NSUInteger)lastVisibleFeedCardIndex { @@ -1144,8 +1146,8 @@ - (void)showSignInUIFromSource:(FeedSignInPromoSource)source { // If the user is already signed in, do nothing. - if (self.authService && - self.authService->HasPrimaryIdentity(signin::ConsentLevel::kSignin)) { + if (_identityManager && + _identityManager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) { return; } // This flow shouldn't be offered if sign-in is disallowed. @@ -1642,9 +1644,7 @@ } - (bool)hasIdentitiesOnDevice { - return !IdentityManagerFactory::GetForProfile(self.profile) - ->GetAccountsOnDevice() - .empty(); + return !_identityManager->GetAccountsOnDevice().empty(); } // Update the state, to take into account that the signin coordinator
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm index 3ae608d..37ea5b2 100644 --- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm +++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm
@@ -752,6 +752,9 @@ self.miaAndVoiceDivider.alpha = percent; } + if (IsNTPBackgroundCustomizationEnabled()) { + [self applyBackgroundTheme]; + } _lastAnimationPercent = percent; }
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.mm index 3b82944..e57d0c6d 100644 --- a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.mm +++ b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/save_card/save_card_infobar_banner_overlay_mediator.mm
@@ -72,7 +72,7 @@ InfoBarIOS* infobar = GetOverlayRequestInfobar(self.request); infobar->set_accepted(delegate->UpdateAndAccept( delegate->cardholder_name(), delegate->expiration_date_month(), - delegate->expiration_date_year(), /*cvc=*/u"")); + delegate->expiration_date_year(), delegate->card_cvc())); // Create and show the snackbar message. MDCSnackbarMessage* message = [self createCardSavedSnackbarMessage];
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator.mm b/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator.mm index 2893584..e95c81c8 100644 --- a/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator.mm +++ b/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator.mm
@@ -120,6 +120,7 @@ NSString* cardNumber = [NSString stringWithFormat:@"•••• %@", base::SysUTF16ToNSString( delegate->card_last_four_digits())]; + NSString* cardCvc = base::SysUTF16ToNSString(delegate->card_cvc()); // Only allow editing if the card will be uploaded and it hasn't been // previously saved. @@ -135,6 +136,7 @@ base::SysUTF16ToNSString(delegate->expiration_date_month()), kExpirationYearPrefKey : base::SysUTF16ToNSString(delegate->expiration_date_year()), + kCardCvcPrefKey : cardCvc, kLegalMessagesPrefKey : [self legalMessages], kCurrentCardSaveAcceptedPrefKey : @(infobar->accepted()), kSupportsEditingPrefKey : @(supportsEditing), @@ -208,7 +210,8 @@ - (void)saveCardWithCardholderName:(NSString*)cardholderName expirationMonth:(NSString*)month - expirationYear:(NSString*)year { + expirationYear:(NSString*)year + cardCvc:(NSString*)cardCvc { autofill::AutofillSaveCardInfoBarDelegateIOS* delegate = self.saveCardDelegate; InfoBarIOS* infobar = GetOverlayRequestInfobar(self.request); @@ -219,7 +222,7 @@ infobar->set_accepted(delegate->UpdateAndAccept( base::SysNSStringToUTF16(cardholderName), base::SysNSStringToUTF16(month), - base::SysNSStringToUTF16(year), /*cvc=*/u"")); + base::SysNSStringToUTF16(year), base::SysNSStringToUTF16(cardCvc))); if (delegate->is_for_upload()) { autofill::autofill_metrics::LogCreditCardUploadLoadingViewShownMetric(
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator_unittest.mm b/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator_unittest.mm index 6fbb958..b9e6dc5 100644 --- a/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator_unittest.mm +++ b/ios/chrome/browser/overlays/ui_bundled/infobar_modal/save_card/save_card_infobar_modal_overlay_mediator_unittest.mm
@@ -53,6 +53,8 @@ NSString* kValidExpirationYear = base::SysUTF8ToNSString(autofill::test::NextYear()); +constexpr NSString* kCardCvc = @"123"; + constexpr char kSaveCreditCardPromptResultHistogramStringForLocalSave[] = "Autofill.SaveCreditCardPromptResult.IOS.Local.Modal.NumStrikes.0." "NoFixFlow"; @@ -159,7 +161,8 @@ void SaveCard() { [mediator_ saveCardWithCardholderName:kCardHolderName expirationMonth:kValidExpirationMonth - expirationYear:kValidExpirationYear]; + expirationYear:kValidExpirationYear + cardCvc:kCardCvc]; } protected: @@ -332,7 +335,7 @@ UpdateAndAccept(base::SysNSStringToUTF16(kCardHolderName), base::SysNSStringToUTF16(kValidExpirationMonth), base::SysNSStringToUTF16(kValidExpirationYear), - testing::IsEmpty())) + base::SysNSStringToUTF16(kCardCvc))) .WillByDefault(Return(true)); SaveCard(); histogramTester.ExpectBucketCount( @@ -406,7 +409,7 @@ UpdateAndAccept(base::SysNSStringToUTF16(kCardHolderName), base::SysNSStringToUTF16(kValidExpirationMonth), base::SysNSStringToUTF16(kValidExpirationYear), - testing::IsEmpty())); + base::SysNSStringToUTF16(kCardCvc))); SaveCard(); EXPECT_FALSE(consumer.inLoadingState); @@ -427,7 +430,7 @@ UpdateAndAccept(base::SysNSStringToUTF16(kCardHolderName), base::SysNSStringToUTF16(kValidExpirationMonth), base::SysNSStringToUTF16(kValidExpirationYear), - testing::IsEmpty())); + base::SysNSStringToUTF16(kCardCvc))); SaveCard(); EXPECT_TRUE(consumer.inLoadingState); @@ -637,3 +640,21 @@ "Autofill.CreditCardUpload.ConfirmationResult.CardUploaded", autofill::autofill_metrics::SaveCardPromptResult::kClosed, 0); } + +// Tests that the mediator correctly handles an empty CVC when the user saves. +TEST_F(SaveCardInfobarModalOverlayMediatorTest, OnSaveWithEmptyCVC) { + // Expect that the delegate's UpdateAndAccept method is called with an empty + // string for the CVC. + EXPECT_CALL(*delegate_, + UpdateAndAccept(base::SysNSStringToUTF16(kCardHolderName), + base::SysNSStringToUTF16(kValidExpirationMonth), + base::SysNSStringToUTF16(kValidExpirationYear), + testing::IsEmpty())); + + // Call the mediator's save method directly, passing an empty NSString for the + // CVC. + [mediator_ saveCardWithCardholderName:kCardHolderName + expirationMonth:kValidExpirationMonth + expirationYear:kValidExpirationYear + cardCvc:@""]; +}
diff --git a/ios/chrome/browser/policy/ui_bundled/idle/BUILD.gn b/ios/chrome/browser/policy/ui_bundled/idle/BUILD.gn index c05a05b..93abb7c 100644 --- a/ios/chrome/browser/policy/ui_bundled/idle/BUILD.gn +++ b/ios/chrome/browser/policy/ui_bundled/idle/BUILD.gn
@@ -26,8 +26,7 @@ "//ios/chrome/browser/shared/model/prefs:pref_names", "//ios/chrome/browser/shared/ui/util", "//ios/chrome/browser/shared/ui/util:snackbar_util", - "//ios/chrome/browser/signin/model:authentication_service", - "//ios/chrome/browser/signin/model:authentication_service_factory", + "//ios/chrome/browser/signin/model", "//ios/third_party/material_components_ios", "//ios/web/public", "//ui/base", @@ -118,6 +117,7 @@ "//ios/chrome/browser/shared/model/prefs:pref_names", "//ios/chrome/browser/shared/model/profile/test", "//ios/chrome/browser/shared/public/features", + "//ios/chrome/browser/signin/model", "//ios/chrome/browser/signin/model:authentication_service", "//ios/chrome/browser/signin/model:authentication_service_factory", "//ios/chrome/browser/signin/model:fake_system_identity",
diff --git a/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.mm b/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.mm index 2a6e70ea..bb8593e0 100644 --- a/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.mm +++ b/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_scene_agent.mm
@@ -13,6 +13,7 @@ #import "components/policy/core/common/policy_pref_names.h" #import "components/prefs/pref_service.h" #import "components/signin/public/base/signin_pref_names.h" +#import "components/signin/public/identity_manager/identity_manager.h" #import "ios/chrome/app/profile/profile_init_stage.h" #import "ios/chrome/app/profile/profile_state.h" #import "ios/chrome/browser/enterprise/model/idle/idle_service_observer_bridge.h" @@ -34,8 +35,7 @@ #import "ios/chrome/browser/shared/public/commands/snackbar_commands.h" #import "ios/chrome/browser/shared/ui/util/snackbar_util.h" #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" -#import "ios/chrome/browser/signin/model/authentication_service.h" -#import "ios/chrome/browser/signin/model/authentication_service_factory.h" +#import "ios/chrome/browser/signin/model/identity_manager_factory.h" #import "ios/chrome/grit/ios_strings.h" #import "ios/web/public/web_state.h" #import "ui/base/l10n/l10n_util.h" @@ -246,8 +246,8 @@ // crash is found. The crash is possibly related to BrowserSignin=2 also being // set, but it is not reproducible yet. if (!messageId) { - AuthenticationService* authenticationService = - AuthenticationServiceFactory::GetForProfile(_mainBrowser->GetProfile()); + signin::IdentityManager* identityManager = + IdentityManagerFactory::GetForProfile(_mainBrowser->GetProfile()); DUMP_WILL_BE_CHECK(messageId) << "The last IdleTimeout action set was empty. IdleTimeoutActions: " << _mainBrowser->GetProfile() @@ -258,8 +258,7 @@ << GetApplicationContext()->GetLocalState()->GetInteger( prefs::kBrowserSigninPolicy) << "Signin status: " - << authenticationService->HasPrimaryIdentity( - signin::ConsentLevel::kSignin); + << identityManager->HasPrimaryAccount(signin::ConsentLevel::kSignin); _idleService->OnIdleTimeoutSnackbarPresented(); return; }
diff --git a/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_utils_unittest.mm b/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_utils_unittest.mm index 071e981..0c01149a 100644 --- a/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_utils_unittest.mm +++ b/ios/chrome/browser/policy/ui_bundled/idle/idle_timeout_policy_utils_unittest.mm
@@ -9,6 +9,7 @@ #import "components/enterprise/idle/action_type.h" #import "components/enterprise/idle/idle_pref_names.h" #import "components/prefs/pref_service.h" +#import "components/signin/public/identity_manager/identity_manager.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h" #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h" #import "ios/chrome/browser/shared/public/features/features.h" @@ -17,6 +18,7 @@ #import "ios/chrome/browser/signin/model/fake_authentication_service_delegate.h" #import "ios/chrome/browser/signin/model/fake_system_identity.h" #import "ios/chrome/browser/signin/model/fake_system_identity_manager.h" +#import "ios/chrome/browser/signin/model/identity_manager_factory.h" #import "ios/chrome/grit/ios_branded_strings.h" #import "ios/chrome/grit/ios_strings.h" #import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" @@ -36,6 +38,7 @@ std::make_unique<FakeAuthenticationServiceDelegate>())); profile_ = std::move(builder).Build(); pref_service_ = profile_.get()->GetPrefs(); + identity_manager_ = IdentityManagerFactory::GetForProfile(profile_.get()); authentication_service_ = AuthenticationServiceFactory::GetForProfile(profile_.get()); } @@ -65,6 +68,7 @@ web::WebTaskEnvironment task_environment_; std::unique_ptr<TestProfileIOS> profile_; raw_ptr<PrefService> pref_service_; + raw_ptr<signin::IdentityManager> identity_manager_; raw_ptr<AuthenticationService> authentication_service_; IOSChromeScopedTestingLocalState scoped_testing_local_state_; }; @@ -73,7 +77,7 @@ SignIn(); SetIdleTimeoutActions({ActionType::kSignOut, ActionType::kCloseTabs, ActionType::kClearBrowsingHistory}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_TRUE(action_set.clear); EXPECT_TRUE(action_set.signout); EXPECT_TRUE(action_set.close); @@ -90,7 +94,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_AllTypes_UserSignedOut) { SetIdleTimeoutActions({ActionType::kSignOut, ActionType::kCloseTabs, ActionType::kClearBrowsingHistory}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_TRUE(action_set.clear); EXPECT_FALSE(action_set.signout); EXPECT_TRUE(action_set.close); @@ -107,7 +111,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_Signout_UserSignedIn) { SignIn(); SetIdleTimeoutActions({ActionType::kSignOut}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_FALSE(action_set.clear); EXPECT_TRUE(action_set.signout); EXPECT_FALSE(action_set.close); @@ -123,7 +127,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_Signout_UserSignedOut) { SetIdleTimeoutActions({ActionType::kSignOut}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_FALSE(action_set.clear); EXPECT_FALSE(action_set.signout); EXPECT_FALSE(action_set.close); @@ -135,7 +139,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, AllActionsToActionSet_CloseTabs) { SetIdleTimeoutActions({ActionType::kCloseTabs}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_FALSE(action_set.clear); EXPECT_FALSE(action_set.signout); EXPECT_TRUE(action_set.close); @@ -151,7 +155,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_ClearBrowsingHistory) { SetIdleTimeoutActions({ActionType::kClearBrowsingHistory}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_TRUE(action_set.clear); EXPECT_FALSE(action_set.signout); EXPECT_FALSE(action_set.close); @@ -168,7 +172,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_ClearCookiesAndOtherSiteData) { SetIdleTimeoutActions({ActionType::kClearCookiesAndOtherSiteData}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_TRUE(action_set.clear); EXPECT_FALSE(action_set.signout); EXPECT_FALSE(action_set.close); @@ -177,7 +181,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_ClearCachedImagesAndFiles) { SetIdleTimeoutActions({ActionType::kClearCookiesAndOtherSiteData}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_TRUE(action_set.clear); EXPECT_FALSE(action_set.signout); EXPECT_FALSE(action_set.close); @@ -185,7 +189,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_ClearPasswordSignin) { SetIdleTimeoutActions({ActionType::kClearPasswordSignin}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_TRUE(action_set.clear); EXPECT_FALSE(action_set.signout); EXPECT_FALSE(action_set.close); @@ -193,7 +197,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_ClearAutofill) { SetIdleTimeoutActions({ActionType::kClearAutofill}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_TRUE(action_set.clear); EXPECT_FALSE(action_set.signout); EXPECT_FALSE(action_set.close); @@ -203,7 +207,7 @@ SignIn(); SetIdleTimeoutActions( {ActionType::kSignOut, ActionType::kClearBrowsingHistory}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_TRUE(action_set.clear); EXPECT_TRUE(action_set.signout); EXPECT_FALSE(action_set.close); @@ -223,7 +227,7 @@ TEST_F(IdleTimeoutPolicyUtilsTest, ActionsToActionSet_SignoutAndCloseTabs) { SignIn(); SetIdleTimeoutActions({ActionType::kSignOut, ActionType::kCloseTabs}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_FALSE(action_set.clear); EXPECT_TRUE(action_set.signout); EXPECT_TRUE(action_set.close); @@ -245,7 +249,7 @@ // true in the `GetIdleTimeoutActionsSubtitleId` method under test below. SignIn(); SetIdleTimeoutActions({ActionType::kSignOut, ActionType::kCloseTabs}); - ActionSet action_set = GetActionSet(pref_service_, authentication_service_); + ActionSet action_set = GetActionSet(pref_service_, identity_manager_); EXPECT_FALSE(action_set.clear); EXPECT_TRUE(action_set.signout); EXPECT_TRUE(action_set.close);
diff --git a/ios/chrome/browser/providers/bwg/chromium_bwg.mm b/ios/chrome/browser/providers/bwg/chromium_bwg.mm index d9f297f..b157a81 100644 --- a/ios/chrome/browser/providers/bwg/chromium_bwg.mm +++ b/ios/chrome/browser/providers/bwg/chromium_bwg.mm
@@ -34,4 +34,8 @@ void ResetGemini() {} +bool IsProtectedUrl(std::string url) { + return false; +} + } // namespace ios::provider
diff --git a/ios/chrome/browser/reader_mode/model/reader_mode_distiller_page.h b/ios/chrome/browser/reader_mode/model/reader_mode_distiller_page.h index 8af6f0f..2c284027 100644 --- a/ios/chrome/browser/reader_mode/model/reader_mode_distiller_page.h +++ b/ios/chrome/browser/reader_mode/model/reader_mode_distiller_page.h
@@ -22,6 +22,7 @@ // dom_distiller::DistillerPage implementation. void DistillPageImpl(const GURL& url, const std::string& script) override; bool ShouldFetchOfflineData() override; + dom_distiller::DistillerType GetDistillerType() override; private: void HandleJavaScriptResult(const GURL& url, const base::Value* result);
diff --git a/ios/chrome/browser/reader_mode/model/reader_mode_distiller_page.mm b/ios/chrome/browser/reader_mode/model/reader_mode_distiller_page.mm index ffb992a..b8d26e4 100644 --- a/ios/chrome/browser/reader_mode/model/reader_mode_distiller_page.mm +++ b/ios/chrome/browser/reader_mode/model/reader_mode_distiller_page.mm
@@ -46,14 +46,25 @@ return false; } +dom_distiller::DistillerType ReaderModeDistillerPage::GetDistillerType() { + return dom_distiller::ShouldUseReadabilityDistiller() + ? dom_distiller::DistillerType::kReadability + : dom_distiller::DistillerType::kDOMDistiller; +} + void ReaderModeDistillerPage::HandleJavaScriptResult( const GURL& url, const base::Value* result) { - if (dom_distiller::ShouldUseReadabilityDistiller()) { - OnDistillationDone(url, result); - } else { - base::Value result_as_value = - dom_distiller::ParseValueFromScriptResult(result); - OnDistillationDone(url, &result_as_value); + switch (GetDistillerType()) { + case dom_distiller::DistillerType::kReadability: { + OnDistillationDone(url, result); + break; + } + case dom_distiller::DistillerType::kDOMDistiller: { + base::Value result_as_value = + dom_distiller::ParseValueFromScriptResult(result); + OnDistillationDone(url, &result_as_value); + break; + } } }
diff --git a/ios/chrome/browser/reading_list/model/reading_list_distiller_page.h b/ios/chrome/browser/reading_list/model/reading_list_distiller_page.h index 93c21ad3..8e4ff59 100644 --- a/ios/chrome/browser/reading_list/model/reading_list_distiller_page.h +++ b/ios/chrome/browser/reading_list/model/reading_list_distiller_page.h
@@ -62,6 +62,7 @@ // dom_distiller::DistillerPage implementation. bool ShouldFetchOfflineData() override; + dom_distiller::DistillerType GetDistillerType() override; protected: void DistillPageImpl(const GURL& url, const std::string& script) override;
diff --git a/ios/chrome/browser/reading_list/model/reading_list_distiller_page.mm b/ios/chrome/browser/reading_list/model/reading_list_distiller_page.mm index 50ce3af..5d6916d6 100644 --- a/ios/chrome/browser/reading_list/model/reading_list_distiller_page.mm +++ b/ios/chrome/browser/reading_list/model/reading_list_distiller_page.mm
@@ -84,6 +84,10 @@ return true; } +dom_distiller::DistillerType ReadingListDistillerPage::GetDistillerType() { + return dom_distiller::DistillerType::kDOMDistiller; +} + void ReadingListDistillerPage::DistillPageImpl(const GURL& url, const std::string& script) { std::unique_ptr<web::WebState> old_web_state = DetachWebState();
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.h b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.h index 44cc417..1e17c6b 100644 --- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.h +++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.h
@@ -66,10 +66,6 @@ /// Resets the mediator to the state before any file is selected or processed. - (void)reset; -/// Imports the items that are ready for import, and increments the import stage -/// . Should only be invoked when items are ready. -- (void)importItems; - /// List of password conflicts with the information retrieved from the source /// of import. Only available when passwords are ready. - (NSArray<PasswordImportItem*>*)conflictingPasswords;
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.mm b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.mm index 45750a6..1a283489 100644 --- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.mm +++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_mediator.mm
@@ -42,11 +42,10 @@ /// to be kept alive in the duration of the importer. std::unique_ptr<password_manager::SavedPasswordsPresenter> _savedPasswordsPresenter; - /// Whether we should allow the user to select a file. Workaround for file - /// picker latencies. - BOOL _disableFileSelection; /// Whether the mediator is disconnected. BOOL _disconnected; + /// The URL of the file being imported, which requires security-scoped access. + NSURL* _currentSecurityScopedURL; } - (instancetype) @@ -90,11 +89,10 @@ } - (void)reset { - _disableFileSelection = NO; -} - -- (void)importItems { - [self continueToImportPasswords:[NSArray array]]; + if (_currentSecurityScopedURL) { + [_currentSecurityScopedURL stopAccessingSecurityScopedResource]; + _currentSecurityScopedURL = nil; + } } - (NSArray<PasswordImportItem*>*)conflictingPasswords { @@ -145,16 +143,21 @@ - (void)documentPicker:(UIDocumentPickerViewController*)controller didPickDocumentsAtURLs:(NSArray<NSURL*>*)urls { - if (_disableFileSelection) { + // Early exit. Workaround for file picker latencies. + if (_currentSecurityScopedURL) { return; } - NSURL* file = urls.firstObject; - if (!file) { + _currentSecurityScopedURL = urls.firstObject; + if (!_currentSecurityScopedURL) { return; } - _disableFileSelection = YES; + if (![_currentSecurityScopedURL startAccessingSecurityScopedResource]) { + _currentSecurityScopedURL = nil; + return; + } [self setUpImportClient]; - _importer->PrepareImport(base::apple::NSURLToFilePath(file)); + _importer->PrepareImport( + base::apple::NSURLToFilePath(_currentSecurityScopedURL)); } - (void)documentPickerWasCancelled:(UIDocumentPickerViewController*)controller {
diff --git a/ios/chrome/browser/safari_data_import/ui/safari_data_import_import_view_controller.mm b/ios/chrome/browser/safari_data_import/ui/safari_data_import_import_view_controller.mm index 92d9b4f..dbde1e8 100644 --- a/ios/chrome/browser/safari_data_import/ui/safari_data_import_import_view_controller.mm +++ b/ios/chrome/browser/safari_data_import/ui/safari_data_import_import_view_controller.mm
@@ -74,6 +74,8 @@ break; case SafariDataImportStage::kImporting: self.primaryButtonEnabled = NO; + self.navigationItem.hidesBackButton = YES; + self.navigationItem.rightBarButtonItem = nil; [self.itemTableView notifyImportStart]; break; case SafariDataImportStage::kImported:
diff --git a/ios/chrome/browser/safari_data_import/ui/safari_data_item_table_view.mm b/ios/chrome/browser/safari_data_import/ui/safari_data_item_table_view.mm index 013b3c8c..46e72d8e 100644 --- a/ios/chrome/browser/safari_data_import/ui/safari_data_item_table_view.mm +++ b/ios/chrome/browser/safari_data_import/ui/safari_data_item_table_view.mm
@@ -252,7 +252,7 @@ CHECK(item); TableViewDetailIconCell* cell = DequeueTableViewCell<TableViewDetailIconCell>(self); - cell.backgroundColor = [UIColor colorNamed:kGroupedPrimaryBackgroundColor]; + cell.backgroundColor = [UIColor colorNamed:kSecondaryBackgroundColor]; cell.textLabel.text = GetTextForItemType(item.type); [self setupDescriptionForItem:item forCell:cell]; cell.textLayoutConstraintAxis = UILayoutConstraintAxisVertical;
diff --git a/ios/chrome/browser/safe_browsing/model/safe_browsing_egtest.mm b/ios/chrome/browser/safe_browsing/model/safe_browsing_egtest.mm index 731e1ff..5c35b73 100644 --- a/ios/chrome/browser/safe_browsing/model/safe_browsing_egtest.mm +++ b/ios/chrome/browser/safe_browsing/model/safe_browsing_egtest.mm
@@ -1147,6 +1147,11 @@ // Verifies that the Enteprise blocking interstitial is displayed for urls // blocked by Enterprise organizations. - (void)testEnterpriseBlockingPage { + // TODO(crbug.com/429137228): Test is flaky on iOS 18.2. Re-enable the test. + if (@available(iOS 18.2, *)) { + EARL_GREY_TEST_DISABLED(@"Fails on iOS 18.2."); + } + EnableEnterpriseUrlFilteringPrefs(); [ChromeEarlGrey loadURL:_safeURL1];
diff --git a/ios/chrome/browser/search_engine_choice/ui_bundled/search_engine_choice_ui_util.mm b/ios/chrome/browser/search_engine_choice/ui_bundled/search_engine_choice_ui_util.mm index 35fc996..f43e77d 100644 --- a/ios/chrome/browser/search_engine_choice/ui_bundled/search_engine_choice_ui_util.mm +++ b/ios/chrome/browser/search_engine_choice/ui_bundled/search_engine_choice_ui_util.mm
@@ -9,7 +9,6 @@ #import "base/strings/utf_string_conversions.h" #import "build/branding_buildflags.h" -#import "components/grit/components_scaled_resources.h" #import "components/regional_capabilities/regional_capabilities_service.h" #import "components/search_engines/template_url.h" #import "components/search_engines/template_url_service.h" @@ -42,15 +41,6 @@ if (resource_it != std::end(kSearchEnginesScaledResources)) { return resource_it->id; } - - if (resource_name == "IDR_SEARCH_ENGINE_GOOGLE_IMAGE") { - // Unlike the other logos which are in `kSearchEnginesScaledResources`, - // the Google logo is included via - // `components/resources/search_engine_choice_scaled_resources.grdp` - // TODO(crbug.com/422992330): Fix this discrepancy now that all OSE assets - // are restricted to branded builds. - return IDR_SEARCH_ENGINE_GOOGLE_IMAGE; - } #endif return IDR_DEFAULT_FAVICON;
diff --git a/ios/chrome/browser/settings/ui_bundled/bwg/ui/bwg_settings_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/bwg/ui/bwg_settings_view_controller.mm index de68e674..9cf646c 100644 --- a/ios/chrome/browser/settings/ui_bundled/bwg/ui/bwg_settings_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/bwg/ui/bwg_settings_view_controller.mm
@@ -208,6 +208,7 @@ l10n_util::GetNSString(IDS_IOS_BWG_SETTINGS_APP_ACTIVITY_TITLE); BWGAppActivityItem.accessorySymbol = TableViewDetailTextCellAccessorySymbolExternalLink; + BWGAppActivityItem.accessibilityTraits = UIAccessibilityTraitLink; return BWGAppActivityItem; }
diff --git a/ios/chrome/browser/settings/ui_bundled/default_browser/default_browser_settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/default_browser/default_browser_settings_table_view_controller.mm index 12e6ba86..e76d344 100644 --- a/ios/chrome/browser/settings/ui_bundled/default_browser/default_browser_settings_table_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/default_browser/default_browser_settings_table_view_controller.mm
@@ -12,6 +12,7 @@ #import "ios/chrome/browser/default_promo/ui_bundled/default_browser_instructions_view_controller.h" #import "ios/chrome/browser/intents/model/intents_donation_helper.h" #import "ios/chrome/browser/settings/ui_bundled/settings_table_view_controller_constants.h" +#import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" @@ -124,12 +125,15 @@ // Adds default browser video instructions view as a background view. - (void)addDefaultBrowserVideoInstructionsView { + BOOL useDefaultAppsDestination = + self.source == DefaultBrowserSettingsPageSource::kTipsNotification && + base::FeatureList::IsEnabled(kIOSOneTimeDefaultBrowserNotification); _instructionsViewController = [[DefaultBrowserInstructionsViewController alloc] initWithDismissButton:NO hasRemindMeLater:NO - useDefaultAppsDestination:NO - hasSteps:YES + useDefaultAppsDestination:useDefaultAppsDestination + hasSteps:!useDefaultAppsDestination actionHandler:self titleText:nil]; [self addChildViewController:_instructionsViewController];
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_manager_egtest.mm b/ios/chrome/browser/settings/ui_bundled/password/password_manager_egtest.mm index 251540d..d8b08e4 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_manager_egtest.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_manager_egtest.mm
@@ -3270,9 +3270,9 @@ performAction:grey_tap()]; } -// Tests that the save passwords in account section is hidden when not opted-in -// for account storage. -- (void)testSavePasswordsInAccountHiddenWhenNotOptedInToAccountStorage { +// Tests that the save passwords in account section is hidden when account +// storage disabled. +- (void)testSavePasswordsInAccountHiddenWhenAccountStorageDisabled { SavePasswordFormToProfileStore(); [PasswordSettingsAppInterface mockReauthenticationModuleExpectedResult: @@ -3284,7 +3284,7 @@ OpenSettingsSubmenu(); [ChromeEarlGreyUI waitForAppToIdle]; - // Opt out of account storage. + // Disable account storage. [SigninEarlGreyAppInterface setSelectedType:(syncer::UserSelectableType::kPasswords) enabled:NO];
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_sharing/family_promo_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_sharing/family_promo_view_controller.mm index 785253e..fc39df6 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_sharing/family_promo_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_sharing/family_promo_view_controller.mm
@@ -54,19 +54,9 @@ #pragma mark - UITextViewDelegate -#if !defined(__IPHONE_17_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_17_0 -- (BOOL)textView:(UITextView*)textView - shouldInteractWithURL:(NSURL*)URL - inRange:(NSRange)characterRange - interaction:(UITextItemInteraction)interaction { - [self.actionHandler createFamilyGroupLinkWasTapped]; - return NO; -} -#endif - - (UIAction*)textView:(UITextView*)textView primaryActionForTextItem:(UITextItem*)textItem - defaultAction:(UIAction*)defaultAction API_AVAILABLE(ios(17.0)) { + defaultAction:(UIAction*)defaultAction { __weak __typeof(self) weakSelf = self; return [UIAction actionWithHandler:^(UIAction* action) { [weakSelf.actionHandler createFamilyGroupLinkWasTapped];
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_sharing/password_sharing_first_run_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_sharing/password_sharing_first_run_view_controller.mm index 0578e493..25f9499 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_sharing/password_sharing_first_run_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_sharing/password_sharing_first_run_view_controller.mm
@@ -55,19 +55,9 @@ #pragma mark - UITextViewDelegate -#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_17_0 -- (BOOL)textView:(UITextView*)textView - shouldInteractWithURL:(NSURL*)URL - inRange:(NSRange)characterRange - interaction:(UITextItemInteraction)interaction { - [self.actionHandler learnMoreLinkWasTapped]; - return NO; -} -#endif - - (UIAction*)textView:(UITextView*)textView primaryActionForTextItem:(UITextItem*)textItem - defaultAction:(UIAction*)defaultAction API_AVAILABLE(ios(17.0)) { + defaultAction:(UIAction*)defaultAction { __weak __typeof(self) weakSelf = self; return [UIAction actionWithHandler:^(UIAction* action) { [weakSelf.actionHandler learnMoreLinkWasTapped];
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_sharing/sharing_status_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_sharing/sharing_status_view_controller.mm index e1f60e6..a85f300 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_sharing/sharing_status_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_sharing/sharing_status_view_controller.mm
@@ -244,19 +244,9 @@ #pragma mark - UITextViewDelegate -#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_17_0 -- (BOOL)textView:(UITextView*)textView - shouldInteractWithURL:(NSURL*)URL - inRange:(NSRange)characterRange - interaction:(UITextItemInteraction)interaction { - [self.delegate changePasswordLinkWasTapped]; - return NO; -} -#endif - - (UIAction*)textView:(UITextView*)textView primaryActionForTextItem:(UITextItem*)textItem - defaultAction:(UIAction*)defaultAction API_AVAILABLE(ios(17.0)) { + defaultAction:(UIAction*)defaultAction { __weak __typeof(self) weakSelf = self; return [UIAction actionWithHandler:^(UIAction* action) { [weakSelf.delegate changePasswordLinkWasTapped];
diff --git a/ios/chrome/browser/settings/ui_bundled/password/passwords_in_other_apps/passwords_in_other_apps_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/passwords_in_other_apps/passwords_in_other_apps_view_controller.mm index 42fcdb8..914ac59 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/passwords_in_other_apps/passwords_in_other_apps_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/passwords_in_other_apps/passwords_in_other_apps_view_controller.mm
@@ -276,12 +276,10 @@ imageHeightConstraint.priority = UILayoutPriorityDefaultHigh - 1; imageHeightConstraint.active = YES; - if (@available(iOS 17, *)) { - NSArray<UITrait>* traits = - TraitCollectionSetForTraits(@[ UITraitVerticalSizeClass.class ]); - [self registerForTraitChanges:traits - withAction:@selector(updateImageOnTraitChange)]; - } + NSArray<UITrait>* traits = + TraitCollectionSetForTraits(@[ UITraitVerticalSizeClass.class ]); + [self registerForTraitChanges:traits + withAction:@selector(updateImageOnTraitChange)]; } - (void)viewDidDisappear:(BOOL)animated { @@ -339,20 +337,6 @@ [self.navigationController setToolbarHidden:YES animated:YES]; } -#if !defined(__IPHONE_17_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_17_0 -- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection { - [super traitCollectionDidChange:previousTraitCollection]; - if (@available(iOS 17, *)) { - return; - } - - if (self.traitCollection.verticalSizeClass != - previousTraitCollection.verticalSizeClass) { - [self updateImageOnTraitChange]; - } -} -#endif - #pragma mark - Accessors - (UIScrollView*)scrollView { @@ -676,20 +660,9 @@ #pragma mark - UITextViewDelegate -#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_17_0 -- (BOOL)textView:(UITextView*)textView - shouldInteractWithURL:(NSURL*)URL - inRange:(NSRange)characterRange - interaction:(UITextItemInteraction)interaction { - [self didTapActionButton]; - // Return NO as the app is handling the opening of the settings page. - return NO; -} -#endif - - (UIAction*)textView:(UITextView*)textView primaryActionForTextItem:(UITextItem*)textItem - defaultAction:(UIAction*)defaultAction API_AVAILABLE(ios(17.0)) { + defaultAction:(UIAction*)defaultAction { __weak __typeof(self) weakSelf = self; return [UIAction actionWithHandler:^(UIAction* action) { [weakSelf didTapActionButton];
diff --git a/ios/chrome/browser/shared/public/features/features.h b/ios/chrome/browser/shared/public/features/features.h index 0f173bd7..a2ce4ea 100644 --- a/ios/chrome/browser/shared/public/features/features.h +++ b/ios/chrome/browser/shared/public/features/features.h
@@ -1040,12 +1040,6 @@ // Whether the feature associated with contained tab group is enabled. bool IsContainedTabGroupEnabled(); -// Feature flag to have more color for the tab groups. -BASE_DECLARE_FEATURE(kColorfulTabGroup); - -// Whether the feature associated with colorful tab group is enabled. -bool IsColorfulTabGroupEnabled(); - // Feature flag to highlight the app's features during the FRE. BASE_DECLARE_FEATURE(kBestOfAppFRE);
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm index 571e2ef9..8224c9f 100644 --- a/ios/chrome/browser/shared/public/features/features.mm +++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -1241,14 +1241,6 @@ return base::FeatureList::IsEnabled(kContainedTabGroup); } -BASE_FEATURE(kColorfulTabGroup, - "ColorfulTabGroup", - base::FEATURE_DISABLED_BY_DEFAULT); - -bool IsColorfulTabGroupEnabled() { - return base::FeatureList::IsEnabled(kColorfulTabGroup); -} - BASE_FEATURE(kBestOfAppFRE, "BestOfAppFRE", base::FEATURE_DISABLED_BY_DEFAULT); bool IsBestOfAppFREEnabled() {
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_groups_egtest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_groups_egtest.mm index e523db9..a006c944 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_groups_egtest.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_groups_egtest.mm
@@ -867,12 +867,6 @@ // Tests cancelling of the deletion of a group from the overflow menu in the // group view. - (void)testCancellingActionToGroupFromGroupView { -// TODO(crbug.com/429592748): Re-enable the test on iOS26. -#if defined(__IPHONE_26_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_26_0 - if (base::ios::IsRunningOnIOS26OrLater()) { - EARL_GREY_TEST_DISABLED(@"Test disabled on iOS 26."); - } -#endif // Create a tab cell with `Tab 1` as its title. [ChromeEarlGrey loadURL:GetQueryTitleURL(self.testServer, kTab1Title)]; [ChromeEarlGreyUI openTabGrid]; @@ -898,19 +892,21 @@ [[EarlGrey selectElementWithMatcher:DeleteGroupButton()] performAction:grey_tap()]; +#if defined(__IPHONE_26_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_26_0 + if (iOS26_OR_ABOVE()) { + [[EarlGrey + selectElementWithMatcher:GREYAccessibilityID(@"PopoverDismissRegion")] + performAction:grey_tap()]; + } else { + [[EarlGrey selectElementWithMatcher:CloseTabGroupButton()] + performAction:grey_tap()]; + } +#else // Cancel the action by tapping the close button (= outside the delete // button). We have a cancel button only on iPhones with iOS versions smaller // than iOS26. [[EarlGrey selectElementWithMatcher:CloseTabGroupButton()] performAction:grey_tap()]; - -#if defined(__IPHONE_26_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_26_0 - if (iOS26_OR_ABOVE()) { - // On iOS26 cancelling the action by tapping outside the popover is also - // clicking the button, for this reason, it is necessary to open again the - // tab group. - OpenTabGroupAtIndex(0); - } #endif // Check that `Tab 1` tab cell still exists in the group.
diff --git a/ios/chrome/browser/tabs/model/tab_helper_util.mm b/ios/chrome/browser/tabs/model/tab_helper_util.mm index a012cf0..6138959 100644 --- a/ios/chrome/browser/tabs/model/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/model/tab_helper_util.mm
@@ -330,10 +330,10 @@ HttpsUpgradeServiceFactory::GetForProfile(profile)); HttpsOnlyModeContainer::CreateForWebState(web_state); - if (base::FeatureList::IsEnabled(omnibox::kDefaultTypedNavigationsToHttps)) { + if (!for_prerender && + base::FeatureList::IsEnabled(omnibox::kDefaultTypedNavigationsToHttps)) { TypedNavigationUpgradeTabHelper::CreateForWebState( - web_state, PrerenderServiceFactory::GetForProfile(profile), - HttpsUpgradeServiceFactory::GetForProfile(profile)); + web_state, HttpsUpgradeServiceFactory::GetForProfile(profile)); } if (!is_off_the_record) {
diff --git a/ios/chrome/common/credential_provider/constants.h b/ios/chrome/common/credential_provider/constants.h index 24943a5d..8e10a048 100644 --- a/ios/chrome/common/credential_provider/constants.h +++ b/ios/chrome/common/credential_provider/constants.h
@@ -56,6 +56,10 @@ // currently enabled. NSString* AppGroupUserDefaulsCredentialProviderPasskeyPRFEnabled(); +// Key for the app group user defaults containing whether passkey Large Blob +// support is currently enabled. +NSString* AppGroupUserDefaulsCredentialProviderPasskeyLargeBlobEnabled(); + // Key for the app group user defaults containing whether signal API is // currently enabled. NSString* AppGroupUserDefaulsCredentialProviderSignalAPIEnabled();
diff --git a/ios/chrome/common/credential_provider/constants.mm b/ios/chrome/common/credential_provider/constants.mm index 10b93837..ab83a0a 100644 --- a/ios/chrome/common/credential_provider/constants.mm +++ b/ios/chrome/common/credential_provider/constants.mm
@@ -77,6 +77,11 @@ @"kUserDefaultsCredentialProviderPasskeyPRFSetting"; // Used to generate the key for the app group user defaults containing whether +// passkey Large Blob support is currently enabled. +NSString* const kUserDefaultsCredentialProviderPasskeyLargeBlobSetting = + @"kUserDefaultsCredentialProviderPasskeyLargeBlobSetting"; + +// Used to generate the key for the app group user defaults containing whether // signal API is currently enabled. NSString* const kUserDefaultsCredentialProviderSignalAPISetting = @"kUserDefaultsCredentialProviderSignalAPISetting"; @@ -182,6 +187,12 @@ stringByAppendingString:kUserDefaultsCredentialProviderPasskeyPRFSetting]; } +NSString* AppGroupUserDefaulsCredentialProviderPasskeyLargeBlobEnabled() { + return [AppGroupPrefix() + stringByAppendingString: + kUserDefaultsCredentialProviderPasskeyLargeBlobSetting]; +} + NSString* AppGroupUserDefaulsCredentialProviderSignalAPIEnabled() { return [AppGroupPrefix() stringByAppendingString:kUserDefaultsCredentialProviderSignalAPISetting];
diff --git a/ios/chrome/credential_provider_extension/ui/feature_flags.h b/ios/chrome/credential_provider_extension/ui/feature_flags.h index 65536bd..75505e8 100644 --- a/ios/chrome/credential_provider_extension/ui/feature_flags.h +++ b/ios/chrome/credential_provider_extension/ui/feature_flags.h
@@ -15,6 +15,9 @@ // Whether passkey PRF support is enabled. BOOL IsPasskeyPRFEnabled(); +// Whether passkey Large Blob support is enabled. +BOOL IsPasskeyLargeBlobEnabled(); + // Whether signal API is enabled. BOOL IsSignalAPIEnabled();
diff --git a/ios/chrome/credential_provider_extension/ui/feature_flags.mm b/ios/chrome/credential_provider_extension/ui/feature_flags.mm index d7d618e..2d436dd 100644 --- a/ios/chrome/credential_provider_extension/ui/feature_flags.mm +++ b/ios/chrome/credential_provider_extension/ui/feature_flags.mm
@@ -21,6 +21,13 @@ boolValue]; } +BOOL IsPasskeyLargeBlobEnabled() { + return [[app_group::GetGroupUserDefaults() + objectForKey: + AppGroupUserDefaulsCredentialProviderPasskeyLargeBlobEnabled()] + boolValue]; +} + BOOL IsSignalApiEnabled() { return [[app_group::GetGroupUserDefaults() objectForKey:AppGroupUserDefaulsCredentialProviderSignalAPIEnabled()]
diff --git a/ios/chrome/test/providers/bwg/test_bwg.mm b/ios/chrome/test/providers/bwg/test_bwg.mm index 8a21b62..ca33af2 100644 --- a/ios/chrome/test/providers/bwg/test_bwg.mm +++ b/ios/chrome/test/providers/bwg/test_bwg.mm
@@ -36,4 +36,8 @@ void ResetGemini() {} +bool IsProtectedUrl(std::string url) { + return false; +} + } // namespace ios::provider
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 index c4e004aa..47dfc9a 100644 --- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -25fbd0b684689f231b4cc3fe6421952de037a30c \ No newline at end of file +ff29dabb5255e7cf095a9067a5c778c26d41dc0b \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 index ec6da2a..94a70ff 100644 --- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@ -24cdd532e07c8f1d95315b9823a2500e51fe0731 \ No newline at end of file +53893664f194a6b731d3b8d0b49ccd961325bee1 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 index b17fa62d..b0f9478 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -49cb7383ac8a0b1c2852e16cce86a6ef157d418c \ No newline at end of file +de3785368cade9eb8d24ee0f7f453f8d7bbb147d \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 index fd518e4..43d2b86 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@ -ebaab3d469057eccd8f08de8fcf6be4263cab508 \ No newline at end of file +e2cc748b91454f1113de141ebaa063c325d02d16 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 index b326025..80a4076 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -90bdb13a8fbe29081707c5ed34a0cdf99a1821a4 \ No newline at end of file +7f6e4e6665513f860bfa0a0a3558489125b5f304 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 index 9afc83d..1e1d0ca5 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@ -e776df2eb746369ff2a42ef0c9505fec5d3162e7 \ No newline at end of file +719f5db3b594dd9becd5862c251e404fbef07989 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 index 2684e0f..e4026f3 100644 --- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -bb6a12f42d64c3dd64e02d86eba7257f94b33357 \ No newline at end of file +bb32be371cc1f6f3271da8c2a5a388b3435e60ea \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 index 9a680fae..183a56a 100644 --- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -56fe38b114c0d3adc0c2e862b8bcc781718b1474 \ No newline at end of file +44144342631f112d84ea4778cffcdf4aa15af106 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 index e05d861..9b8d095 100644 --- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -69db85cc8c9d686dd107fbdbb4ab50194457a6de \ No newline at end of file +619938772c37baad55703d9ec6c993e91e8bd35e \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 index 608fde0..fb81209 100644 --- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -5a13c5674f4ad5984717da801d401ce70ed52a0b \ No newline at end of file +dc7093e428b3ed67a218feff1826d744af4aa331 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index a11491a1..1baaa20 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -59db489c9401dc3ba8889b334849ec3b8836cac0 \ No newline at end of file +e1de5852e05ca357a8896b0a8236766579159443 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 index aa8fbc2..aa731ea3 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -49e6b01ac84eb8e7e8d9bb344474a3bbf7b0e5a2 \ No newline at end of file +1b51b1273406ef7220429892bd8dfea88338f916 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 2891c431..be9b131 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -3876b2478a7927aa32d32fb6e66c4d8442c6019b \ No newline at end of file +bd69a1e1bf0cf03a8d5e75d2e4bd426587104035 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 index 5ea42eb1e..f6a2ce6c 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -2627fd0a91331939966a10908b4c8db125f76f46 \ No newline at end of file +338e16778da670c8080c307dd686895f1745ab53 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index 02e8527..4ff138ee 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -835a2f6ba4eac095f7b7ec6f30363395bf5a047e \ No newline at end of file +eb3efbce17f96dc1b087c055f29f0b1b7b638099 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 index ffad65f43..24237a6 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -a9d4d163eab1c9b23279f825019c2d5fcb8d72b1 \ No newline at end of file +31a4523b12dfe4fe0989ecdc0b2adbdb99924e5b \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index cb79132..1847fe9 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -cfc7925e30c435f6bc6bc9715d9a691c9456e295 \ No newline at end of file +c8c0f7efb817c2dddb1d589fd8bf1350b076c5ab \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 index ea90e23..ae74310 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -b5bde3740b920923bc488942273a196fec198f96 \ No newline at end of file +99904c9536d1ed99d10b36e15e2707c8e4ecec5a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 index b50b5cb..557211d 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -6e123d41b4ed542ca6a8367505f215c60f6a0bf8 \ No newline at end of file +ca15a99b593f940bb8bb2e5301bc4d47e608e0c1 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 index 027693e..33cd2c7 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -15d06e6acb4fdcc4f264377bbbca242c13f129b9 \ No newline at end of file +23584618eec24ff9f917d13861a554fb794e76c2 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index 0f8b2fb6..fe66e63 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -a8a2b3802b94389e362c352474005d1eb5a67d2a \ No newline at end of file +6eeea0fcd038ae7302d431ce084e1c3cfc74e039 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 index d09e547..26d5730 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -4b7e544ccd39497b69eafff83c1a83c0196e966f \ No newline at end of file +1a25ff9bb7a931fb7317f49cb8c0f0ff6ed79f97 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index 5f12728..492eb439 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -a888fbd10851341e9f526c77c87efa278ccbf0de \ No newline at end of file +1ce76e74baf983a9981a0226d9fa52364cca9899 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 index 118169f..54ad65c 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -9b666ae141c0393a710c77de5e88dee275e27f7d \ No newline at end of file +b87e2498abbc751af3e31d3405758cf30519d3d0 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index c4e2329de..b907b4c 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -ee89d5f366083ceaa67fc71c9069756a127a7a15 \ No newline at end of file +e484c115739d254a59f3568ba7192cc293c46e29 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 index 5a13e80d..4cbd6b1 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@ -0c24b82a4e81a66bcb78a214134d950942f06214 \ No newline at end of file +d74b155276884e4ed36d6698cd9988910eb55ebe \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index d747b39..85b2de0 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -3d17e12e3d74710f5d60b1999d65c4732582294c \ No newline at end of file +bbf7e318f4fddd15831bc5c9cbc5f1538d681885 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 index 57e2386..81aa4d09 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@ -cc52a99eb876781bde54d1f5ac7ea7198f07808e \ No newline at end of file +897533a3fbfe5c6ff6fb7442a28a29740dd094fc \ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/bwg/bwg_api.h b/ios/public/provider/chrome/browser/bwg/bwg_api.h index baa14b24..b391501 100644 --- a/ios/public/provider/chrome/browser/bwg/bwg_api.h +++ b/ios/public/provider/chrome/browser/bwg/bwg_api.h
@@ -122,6 +122,9 @@ // Resets the Gemini instance by clearing its state. void ResetGemini(); +// Returns true if a URL is protected. +bool IsProtectedUrl(std::string url); + } // namespace ios::provider #endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_BWG_BWG_API_H_
diff --git a/ios/web/content/js_messaging/content_web_frame.h b/ios/web/content/js_messaging/content_web_frame.h index 8be4b7c..8c9f307 100644 --- a/ios/web/content/js_messaging/content_web_frame.h +++ b/ios/web/content/js_messaging/content_web_frame.h
@@ -44,6 +44,7 @@ std::string GetFrameId() const override; bool IsMainFrame() const override; url::Origin GetSecurityOrigin() const override; + GURL GetUrl() const override; BrowserState* GetBrowserState() override; base::WeakPtr<WebFrame> AsWeakPtr() override;
diff --git a/ios/web/content/js_messaging/content_web_frame.mm b/ios/web/content/js_messaging/content_web_frame.mm index c0e0c80..3646afc 100644 --- a/ios/web/content/js_messaging/content_web_frame.mm +++ b/ios/web/content/js_messaging/content_web_frame.mm
@@ -71,6 +71,10 @@ return render_frame_host_->GetLastCommittedOrigin(); } +GURL ContentWebFrame::GetUrl() const { + return render_frame_host_->GetLastCommittedURL(); +} + BrowserState* ContentWebFrame::GetBrowserState() { return content_web_state_->GetBrowserState(); ;
diff --git a/ios/web/js_messaging/web_frame_impl.h b/ios/web/js_messaging/web_frame_impl.h index d74ccb8..af688f1 100644 --- a/ios/web/js_messaging/web_frame_impl.h +++ b/ios/web/js_messaging/web_frame_impl.h
@@ -5,20 +5,20 @@ #ifndef IOS_WEB_JS_MESSAGING_WEB_FRAME_IMPL_H_ #define IOS_WEB_JS_MESSAGING_WEB_FRAME_IMPL_H_ -#include <map> -#include <string> +#import <map> +#import <string> -#include "base/cancelable_callback.h" +#import "base/cancelable_callback.h" #import "base/memory/raw_ptr.h" #import "base/memory/weak_ptr.h" -#include "base/values.h" -#include "ios/web/js_messaging/web_frame_internal.h" +#import "base/values.h" +#import "ios/web/js_messaging/web_frame_internal.h" #import "ios/web/public/js_messaging/content_world.h" -#include "ios/web/public/js_messaging/web_frame.h" +#import "ios/web/public/js_messaging/web_frame.h" #import "ios/web/public/web_state.h" -#include "ios/web/public/web_state_observer.h" -#include "url/gurl.h" -#include "url/origin.h" +#import "ios/web/public/web_state_observer.h" +#import "url/gurl.h" +#import "url/origin.h" @class WKFrameInfo; @@ -51,6 +51,7 @@ std::string GetFrameId() const override; bool IsMainFrame() const override; url::Origin GetSecurityOrigin() const override; + GURL GetUrl() const override; BrowserState* GetBrowserState() override; bool CallJavaScriptFunction(const std::string& name,
diff --git a/ios/web/js_messaging/web_frame_impl.mm b/ios/web/js_messaging/web_frame_impl.mm index 46597ad..9cabe26 100644 --- a/ios/web/js_messaging/web_frame_impl.mm +++ b/ios/web/js_messaging/web_frame_impl.mm
@@ -27,6 +27,7 @@ #import "ios/web/public/js_messaging/web_view_js_utils.h" #import "ios/web/public/thread/web_task_traits.h" #import "ios/web/public/thread/web_thread.h" +#import "net/base/apple/url_conversions.h" #import "url/gurl.h" namespace { @@ -121,6 +122,10 @@ return security_origin_; } +GURL WebFrameImpl::GetUrl() const { + return net::GURLWithNSURL(frame_info_.request.URL); +} + BrowserState* WebFrameImpl::GetBrowserState() { return GetWebState()->GetBrowserState(); }
diff --git a/ios/web/js_messaging/web_frame_impl_unittest.mm b/ios/web/js_messaging/web_frame_impl_unittest.mm index cb0c3f6..3d78d9b 100644 --- a/ios/web/js_messaging/web_frame_impl_unittest.mm +++ b/ios/web/js_messaging/web_frame_impl_unittest.mm
@@ -4,6 +4,7 @@ #import "ios/web/js_messaging/web_frame_impl.h" +#import <Foundation/Foundation.h> #import <WebKit/WebKit.h> #import "base/functional/bind.h" @@ -25,6 +26,8 @@ const char kFrameId[] = "1effd8f52a067c8d3a01762d3c41dfd8"; +const char kFrameInfoRequestUrl[] = "https://test.com"; + } // namespace namespace web { @@ -32,6 +35,7 @@ class WebFrameImplTest : public web::WebTest { protected: WebFrameImplTest() { + mock_ns_url_request_ = OCMClassMock([NSURLRequest class]); mock_frame_info_ = OCMClassMock([WKFrameInfo class]); mock_web_view_ = OCMClassMock([WKWebView class]); @@ -45,6 +49,10 @@ [invocation getArgument:&last_received_content_world_ atIndex:4]; }); OCMStub([mock_frame_info_ webView]).andReturn(mock_web_view_); + NSURL* url = [[NSURL alloc] + initWithString:base::SysUTF8ToNSString(kFrameInfoRequestUrl)]; + OCMStub([mock_ns_url_request_ URL]).andReturn(url); + OCMStub([mock_frame_info_ request]).andReturn(mock_ns_url_request_); } void SetUp() override { @@ -59,6 +67,7 @@ id mock_frame_info_; id mock_web_view_; + id mock_ns_url_request_; NSString* last_received_script_; WKContentWorld* last_received_content_world_; @@ -68,13 +77,14 @@ // Tests creation of a WebFrame for the main frame. TEST_F(WebFrameImplTest, CreateWebFrameForMainFrame) { - WebFrameImpl web_frame([[WKFrameInfo alloc] init], kFrameId, + WebFrameImpl web_frame(mock_frame_info_, kFrameId, /*is_main_frame=*/true, security_origin_, &fake_web_state_, ContentWorld::kPageContentWorld); EXPECT_EQ(&fake_web_state_, web_frame.GetWebState()); EXPECT_TRUE(web_frame.IsMainFrame()); EXPECT_EQ(security_origin_, web_frame.GetSecurityOrigin()); + EXPECT_EQ(web_frame.GetUrl(), GURL(kFrameInfoRequestUrl)); EXPECT_EQ(kFrameId, web_frame.GetFrameId()); }
diff --git a/ios/web/public/js_messaging/web_frame.h b/ios/web/public/js_messaging/web_frame.h index b979266..94c4442 100644 --- a/ios/web/public/js_messaging/web_frame.h +++ b/ios/web/public/js_messaging/web_frame.h
@@ -37,6 +37,10 @@ virtual bool IsMainFrame() const = 0; // The security origin associated with this frame. virtual url::Origin GetSecurityOrigin() const = 0; + // The URL associated with this frame. Important: for security-relevant + // decisions, do not use this function. Instead, use `GetSecurityOrigin()`. A + // `GURL` and an `Origin` are not interchangeable. + virtual GURL GetUrl() const = 0; // Returns the BrowserState associated with this WebFrame. virtual BrowserState* GetBrowserState() = 0;
diff --git a/ios/web/test/fakes/fake_web_frame_impl.h b/ios/web/test/fakes/fake_web_frame_impl.h index 14610a3..7a9782ec 100644 --- a/ios/web/test/fakes/fake_web_frame_impl.h +++ b/ios/web/test/fakes/fake_web_frame_impl.h
@@ -30,6 +30,7 @@ std::string GetFrameId() const override; bool IsMainFrame() const override; url::Origin GetSecurityOrigin() const override; + GURL GetUrl() const override; BrowserState* GetBrowserState() override; bool CallJavaScriptFunction(const std::string& name, const base::Value::List& parameters) override;
diff --git a/ios/web/test/fakes/fake_web_frame_impl.mm b/ios/web/test/fakes/fake_web_frame_impl.mm index 7bb724c..67bba0d 100644 --- a/ios/web/test/fakes/fake_web_frame_impl.mm +++ b/ios/web/test/fakes/fake_web_frame_impl.mm
@@ -107,13 +107,19 @@ std::string FakeWebFrameImpl::GetFrameId() const { return frame_id_; } + bool FakeWebFrameImpl::IsMainFrame() const { return is_main_frame_; } + url::Origin FakeWebFrameImpl::GetSecurityOrigin() const { return security_origin_; } +GURL FakeWebFrameImpl::GetUrl() const { + return GURL(); +} + BrowserState* FakeWebFrameImpl::GetBrowserState() { return browser_state_; }
diff --git a/ios_internal b/ios_internal index 17f7253..11c9522 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 17f72536aae764cb30b113ed93602009f43baca9 +Subproject commit 11c95229a646ddfa592300ac5b7b566bd2f9466b
diff --git a/media/base/audio_buffer.cc b/media/base/audio_buffer.cc index 7ae2f3a..6d4fcbb 100644 --- a/media/base/audio_buffer.cc +++ b/media/base/audio_buffer.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/audio_buffer.h" #include <cmath> #include "base/bits.h" +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/functional/callback_helpers.h" #include "base/logging.h" @@ -20,8 +16,8 @@ #include "base/numerics/safe_conversions.h" #include "base/types/pass_key.h" #include "media/base/audio_bus.h" -#include "media/base/limits.h" #include "media/base/audio_sample_types.h" +#include "media/base/limits.h" #include "media/base/timestamp_constants.h" namespace media { @@ -38,12 +34,12 @@ class SelfOwnedMemory : public AudioBuffer::ExternalMemory { public: explicit SelfOwnedMemory(size_t size) - : heap_array_( + : heap_array_(UNSAFE_TODO( base::HeapArray<uint8_t, base::AlignedFreeDeleter>:: FromOwningPointer( static_cast<uint8_t*>( base::AlignedAlloc(size, AudioBus::kChannelAlignment)), - size)) { + size))) { span_ = heap_array_.as_span(); } @@ -74,7 +70,7 @@ std::unique_ptr<uint8_t, base::AlignedFreeDeleter> memory, size_t size) : memory_(std::move(memory)), pool_(pool) { - span_ = {memory_.get(), size}; + span_ = UNSAFE_TODO({memory_.get(), size}); } AudioBufferMemoryPool::ExternalMemoryFromPool::~ExternalMemoryFromPool() { @@ -109,7 +105,7 @@ // for VideoFrames we need to zero out the memory. https://crbug.com/1144070. auto memory = std::unique_ptr<uint8_t, base::AlignedFreeDeleter>( static_cast<uint8_t*>(base::AlignedAlloc(size, GetChannelAlignment()))); - memset(memory.get(), 0, size); + UNSAFE_TODO(memset(memory.get(), 0, size)); return std::make_unique<ExternalMemoryFromPool>( ExternalMemoryFromPool(this, std::move(memory), size)); } @@ -178,7 +174,8 @@ // Note: `data_size` is the external data size, not `data_size_`. auto [data_portion, zero_portion] = data_->span().split_at(data_size); - data_portion.copy_from_nonoverlapping(base::span(data[0], data_size)); + data_portion.copy_from_nonoverlapping( + UNSAFE_TODO(base::span(data[0], data_size))); needs_zeroing = zero_portion; } @@ -202,10 +199,10 @@ // Copy each channel's data into the appropriate spot. for (int i = 0; i < channel_count_; ++i) { - channel_data_.push_back(data_->span().data() + - i * block_size_per_channel); + channel_data_.push_back( + UNSAFE_TODO(data_->span().data() + i * block_size_per_channel)); if (data) { - memcpy(channel_data_[i], data[i], data_size_per_channel); + UNSAFE_TODO(memcpy(channel_data_[i], data[i], data_size_per_channel)); } } return; @@ -224,7 +221,7 @@ data_ = pool_ ? pool_->CreateBuffer(data_size_) : AllocateMemory(data_size_); channel_data_.push_back(data_->span().data()); if (data) { - memcpy(data_->span().data(), data[0], data_size_); + UNSAFE_TODO(memcpy(data_->span().data(), data[0], data_size_)); } } @@ -275,10 +272,11 @@ channel_data_.reserve(channel_count_); // Set each channel's data pointer into the appropriate spot. for (int i = 0; i < channel_count_; ++i) { - channel_data_.push_back(data_->span().data() + i * data_size_per_channel); + channel_data_.push_back( + UNSAFE_TODO(data_->span().data() + i * data_size_per_channel)); CHECK_LE(data_->span().data(), channel_data_.back()); - CHECK_GE(data_->span().data() + data_->span().size(), - channel_data_.back() + data_size_per_channel); + UNSAFE_TODO(CHECK_GE(data_->span().data() + data_->span().size(), + channel_data_.back() + data_size_per_channel)); } } else { NOTREACHED() << sample_format; @@ -457,8 +455,9 @@ for (int ch = 0; ch < channels; ++ch) { audio_bus->SetChannelData( - ch, base::span(reinterpret_cast<float*>(buffer->channel_data()[ch]), - base::checked_cast<size_t>(buffer->frame_count()))); + ch, UNSAFE_TODO(base::span( + reinterpret_cast<float*>(buffer->channel_data()[ch]), + base::checked_cast<size_t>(buffer->frame_count())))); } // Keep |buffer| alive as long as |audio_bus|. @@ -513,7 +512,7 @@ auto dest_span = dest->bitstream_data().subspan(dest_size, data_size()); dest_span.copy_from_nonoverlapping( - base::span(channel_data_[0], data_size())); + UNSAFE_TODO(base::span(channel_data_[0], data_size()))); dest->SetBitstreamFrames(dest_frame_offset + frame_count()); return; @@ -533,10 +532,11 @@ for (int ch = 0; ch < channel_count_; ++ch) { auto dest_data = dest->channel_span(ch).subspan(dest_offset); const float* source_data = - reinterpret_cast<const float*>(channel_data_[ch]) + - source_frame_offset; + UNSAFE_TODO(reinterpret_cast<const float*>(channel_data_[ch]) + + source_frame_offset); for (int i = 0; i < frames_to_copy; ++i) - dest_data[i] = Float32SampleTypeTraits::FromFloat(source_data[i]); + dest_data[i] = + Float32SampleTypeTraits::FromFloat(UNSAFE_TODO(source_data[i])); } return; } @@ -544,10 +544,12 @@ // Format is planar unsigned 8. Convert each value into float and insert // into output channel data. for (int ch = 0; ch < channel_count_; ++ch) { - const uint8_t* source_data = channel_data_[ch] + source_frame_offset; + const uint8_t* source_data = + UNSAFE_TODO(channel_data_[ch] + source_frame_offset); auto dest_data = dest->channel_span(ch).subspan(dest_offset); for (int i = 0; i < frames_to_copy; ++i) - dest_data[i] = UnsignedInt8SampleTypeTraits::ToFloat(source_data[i]); + dest_data[i] = + UnsignedInt8SampleTypeTraits::ToFloat(UNSAFE_TODO(source_data[i])); } return; } @@ -557,11 +559,12 @@ // output channel data. for (int ch = 0; ch < channel_count_; ++ch) { const int16_t* source_data = - reinterpret_cast<const int16_t*>(channel_data_[ch]) + - source_frame_offset; + UNSAFE_TODO(reinterpret_cast<const int16_t*>(channel_data_[ch]) + + source_frame_offset); auto dest_data = dest->channel_span(ch).subspan(dest_offset); for (int i = 0; i < frames_to_copy; ++i) - dest_data[i] = SignedInt16SampleTypeTraits::ToFloat(source_data[i]); + dest_data[i] = + SignedInt16SampleTypeTraits::ToFloat(UNSAFE_TODO(source_data[i])); } return; } @@ -571,11 +574,12 @@ // output channel data. for (int ch = 0; ch < channel_count_; ++ch) { const int32_t* source_data = - reinterpret_cast<const int32_t*>(channel_data_[ch]) + - source_frame_offset; + UNSAFE_TODO(reinterpret_cast<const int32_t*>(channel_data_[ch]) + + source_frame_offset); auto dest_data = dest->channel_span(ch).subspan(dest_offset); for (int i = 0; i < frames_to_copy; ++i) - dest_data[i] = SignedInt32SampleTypeTraits::ToFloat(source_data[i]); + dest_data[i] = + SignedInt32SampleTypeTraits::ToFloat(UNSAFE_TODO(source_data[i])); } return; } @@ -583,7 +587,7 @@ const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); const int frame_size = channel_count_ * bytes_per_channel; const uint8_t* source_data = - data_->span().data() + source_frame_offset * frame_size; + UNSAFE_TODO(data_->span().data() + source_frame_offset * frame_size); if (sample_format_ == kSampleFormatF32) { dest->FromInterleavedPartial<Float32SampleTypeTraits>( @@ -656,9 +660,9 @@ case kSampleFormatPlanarS32: // Planar data must be shifted per channel. for (int ch = 0; ch < channel_count_; ++ch) { - memmove(channel_data_[ch] + start * bytes_per_channel, - channel_data_[ch] + end * bytes_per_channel, - bytes_per_channel * frames_to_copy); + UNSAFE_TODO(memmove(channel_data_[ch] + start * bytes_per_channel, + channel_data_[ch] + end * bytes_per_channel, + bytes_per_channel * frames_to_copy)); } break; case kSampleFormatU8: @@ -668,9 +672,9 @@ case kSampleFormatF32: { // Interleaved data can be shifted all at once. const int frame_size = channel_count_ * bytes_per_channel; - memmove(channel_data_[0] + start * frame_size, - channel_data_[0] + end * frame_size, - frame_size * frames_to_copy); + UNSAFE_TODO(memmove(channel_data_[0] + start * frame_size, + channel_data_[0] + end * frame_size, + frame_size * frames_to_copy)); break; } case kUnknownSampleFormat:
diff --git a/media/base/audio_buffer_converter.cc b/media/base/audio_buffer_converter.cc index 377d1b2..ddf29d1 100644 --- a/media/base/audio_buffer_converter.cc +++ b/media/base/audio_buffer_converter.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/audio_buffer_converter.h" #include <algorithm> @@ -14,6 +9,7 @@ #include <memory> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/numerics/safe_conversions.h" #include "media/base/audio_bus.h" #include "media/base/audio_decoder_config.h" @@ -216,9 +212,9 @@ // can fill it. output_bus->set_frames(frames_this_iteration); for (int ch = 0; ch < output_buffer->channel_count(); ++ch) { - AudioBus::Channel output_channel = base::span( + AudioBus::Channel output_channel = UNSAFE_TODO(base::span( reinterpret_cast<float*>(output_buffer->channel_data()[ch]), - base::checked_cast<size_t>(output_buffer->frame_count())); + base::checked_cast<size_t>(output_buffer->frame_count()))); output_bus->SetChannelData( ch, output_channel.subspan(
diff --git a/media/base/audio_buffer_unittest.cc b/media/base/audio_buffer_unittest.cc index 1eddbc8f..bded699 100644 --- a/media/base/audio_buffer_unittest.cc +++ b/media/base/audio_buffer_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/audio_buffer.h" #include <stdint.h> @@ -14,6 +9,7 @@ #include <limits> #include <memory> +#include "base/compiler_specific.h" #include "base/memory/scoped_refptr.h" #include "base/test/gtest_util.h" #include "base/time/time.h" @@ -50,7 +46,8 @@ public: explicit TestExternalMemory(std::vector<uint8_t> contents) : contents_(std::move(contents)) { - span_ = base::span<uint8_t>(contents_.data(), contents_.size()); + span_ = + UNSAFE_TODO(base::span<uint8_t>(contents_.data(), contents_.size())); } private: @@ -229,7 +226,7 @@ audio_buffer_from_bus->channel_data()[ch]); for (int i = 0; i < kFrameCount; ++i) - EXPECT_EQ(buffer_data[i], bus_data[i]); + UNSAFE_TODO(EXPECT_EQ(buffer_data[i], bus_data[i])); } } @@ -308,7 +305,7 @@ test_data.insert(test_data.end(), kFrameCount, 1); test_data.insert(test_data.end(), kFrameCount, 2); uint8_t* first_channel_ptr = test_data.data(); - uint8_t* second_channel_ptr = test_data.data() + kFrameCount; + uint8_t* second_channel_ptr = UNSAFE_TODO(test_data.data() + kFrameCount); auto external_memory = std::make_unique<TestExternalMemory>(std::move(test_data)); @@ -675,7 +672,7 @@ // Set some data to confirm the overwrite. std::vector<float*> wrapped_channels = WrapChannelsAsVector(bus.get()); for (float* wrapped_channel : wrapped_channels) - memset(wrapped_channel, 123, frames * sizeof(float)); + UNSAFE_TODO(memset(wrapped_channel, 123, frames * sizeof(float))); } TEST(AudioBufferTest, TrimEmptyBuffer) { @@ -818,7 +815,7 @@ // Mark pool for destruction and ensure buffer is still valid. pool = nullptr; - memset(b2->channel_data()[0], 0, b2->frame_count()); + UNSAFE_TODO(memset(b2->channel_data()[0], 0, b2->frame_count())); // Destruct final frame after pool; hope nothing explodes. b2 = nullptr; @@ -891,7 +888,7 @@ // Mark pool for destruction and ensure buffer is still valid. pool = nullptr; - memset(b1->channel_data()[0], 0, b1->frame_count()); + UNSAFE_TODO(memset(b1->channel_data()[0], 0, b1->frame_count())); // Destruct final frame after pool; hope nothing explodes. b1 = nullptr;
diff --git a/media/base/audio_bus.cc b/media/base/audio_bus.cc index 0ecab4e..60bbf2c 100644 --- a/media/base/audio_bus.cc +++ b/media/base/audio_bus.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/audio_bus.h" #include <stddef.h> @@ -18,6 +13,7 @@ #include "base/bits.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/memory/aligned_memory.h" #include "base/memory/ptr_util.h" @@ -85,12 +81,13 @@ } AudioBus::AudioBus(int channels, int frames, float* data) - : AudioBus( - channels, - frames, - // Per interface contract, `data` must have a size of at least - // CalculateMemorySizeInternal(). - base::span(data, CalculateMemorySizeInternal(channels, frames))) {} + : AudioBus(channels, + frames, + // Per interface contract, `data` must have a size of at least + // CalculateMemorySizeInternal(). + UNSAFE_TODO(base::span( + data, + CalculateMemorySizeInternal(channels, frames)))) {} AudioBus::AudioBus(int channels, int frames, base::span<float> data) : frames_(base::checked_cast<size_t>(frames)) {
diff --git a/media/base/audio_bus_unittest.cc b/media/base/audio_bus_unittest.cc index 621a7f3..500f9e6 100644 --- a/media/base/audio_bus_unittest.cc +++ b/media/base/audio_bus_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/audio_bus.h" #include <stddef.h> @@ -16,6 +11,7 @@ #include <limits> #include <memory> +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/memory/aligned_memory.h" #include "base/memory/raw_ptr.h" @@ -310,8 +306,9 @@ const float* backing_memory_end = backing_memory_start.subspan(total_frame_count).data(); EXPECT_GE(bus->channel_span(0).data(), backing_memory_start.data()); - EXPECT_LT(bus->channel_span(bus->channels() - 1).data() + bus->frames(), - backing_memory_end); + UNSAFE_TODO( + EXPECT_LT(bus->channel_span(bus->channels() - 1).data() + bus->frames(), + backing_memory_end)); } // Simulate a shared memory transfer and verify results. @@ -516,8 +513,8 @@ SCOPED_TRACE("SignedInt32SampleTypeTraits"); bus->Zero(); bus->FromInterleavedPartial<SignedInt32SampleTypeTraits>( - kTestVectorInt32 + kPartialStart * bus->channels(), kPartialStart, - kPartialFrames); + UNSAFE_TODO(kTestVectorInt32 + kPartialStart * bus->channels()), + kPartialStart, kPartialFrames); VerifyAreEqual(bus.get(), expected.get()); } } @@ -535,15 +532,15 @@ SCOPED_TRACE("UnsignedInt8SampleTypeTraits"); uint8_t test_array[std::size(kTestVectorUint8)]; bus->ToInterleaved<UnsignedInt8SampleTypeTraits>(bus->frames(), test_array); - ASSERT_EQ(0, - memcmp(test_array, kTestVectorUint8, sizeof(kTestVectorUint8))); + UNSAFE_TODO(ASSERT_EQ( + 0, memcmp(test_array, kTestVectorUint8, sizeof(kTestVectorUint8)))); } { SCOPED_TRACE("SignedInt16SampleTypeTraits"); int16_t test_array[std::size(kTestVectorInt16)]; bus->ToInterleaved<SignedInt16SampleTypeTraits>(bus->frames(), test_array); - ASSERT_EQ(0, - memcmp(test_array, kTestVectorInt16, sizeof(kTestVectorInt16))); + UNSAFE_TODO(ASSERT_EQ( + 0, memcmp(test_array, kTestVectorInt16, sizeof(kTestVectorInt16)))); } { SCOPED_TRACE("SignedInt32SampleTypeTraits"); @@ -553,23 +550,23 @@ // Some compilers get better precision than others on the half-max test, so // let the test pass with an off by one check on the half-max. int32_t alternative_acceptable_result[std::size(kTestVectorInt32)]; - memcpy(alternative_acceptable_result, kTestVectorInt32, - sizeof(kTestVectorInt32)); + UNSAFE_TODO(memcpy(alternative_acceptable_result, kTestVectorInt32, + sizeof(kTestVectorInt32))); ASSERT_EQ(alternative_acceptable_result[4], std::numeric_limits<int32_t>::max() / 2); alternative_acceptable_result[4]++; - ASSERT_TRUE( + UNSAFE_TODO(ASSERT_TRUE( memcmp(test_array, kTestVectorInt32, sizeof(kTestVectorInt32)) == 0 || memcmp(test_array, alternative_acceptable_result, - sizeof(alternative_acceptable_result)) == 0); + sizeof(alternative_acceptable_result)) == 0)); } { SCOPED_TRACE("Float32SampleTypeTraits"); float test_array[std::size(kTestVectorFloat32)]; bus->ToInterleaved<Float32SampleTypeTraits>(bus->frames(), test_array); - ASSERT_EQ( - 0, memcmp(test_array, kTestVectorFloat32, sizeof(kTestVectorFloat32))); + UNSAFE_TODO(ASSERT_EQ( + 0, memcmp(test_array, kTestVectorFloat32, sizeof(kTestVectorFloat32)))); } } @@ -583,7 +580,7 @@ std::array<float, std::size(kTestVectorFloat32Sanitized)> test_array; bus->ToInterleaved<Float32SampleTypeTraits>(bus->frames(), test_array.data()); for (size_t i = 0; i < std::size(kTestVectorFloat32Sanitized); ++i) - ASSERT_EQ(kTestVectorFloat32Sanitized[i], test_array[i]); + UNSAFE_TODO(ASSERT_EQ(kTestVectorFloat32Sanitized[i], test_array[i])); // Verify that Float32SampleTypeTraitsNoClip applied no sanity. Note: We don't // use memcmp() here since the NaN type may change on x86 platforms in certain @@ -592,9 +589,9 @@ test_array.data()); for (int i = 0; i < kTestVectorSize; ++i) { if (std::isnan(test_array[i])) - EXPECT_TRUE(std::isnan(kTestVectorFloat32Invalid[i])); + UNSAFE_TODO(EXPECT_TRUE(std::isnan(kTestVectorFloat32Invalid[i]))); else - EXPECT_FLOAT_EQ(test_array[i], kTestVectorFloat32Invalid[i]); + UNSAFE_TODO(EXPECT_FLOAT_EQ(test_array[i], kTestVectorFloat32Invalid[i])); } } @@ -644,10 +641,11 @@ float test_array[std::size(kTestVectorFloat32)]; expected->ToInterleavedPartial<Float32SampleTypeTraits>( kPartialStart, kPartialFrames, test_array); - ASSERT_EQ(0, memcmp(test_array, kTestVectorFloat32 + - kPartialStart * kTestVectorChannelCount, - kPartialFrames * sizeof(*kTestVectorFloat32) * - kTestVectorChannelCount)); + UNSAFE_TODO(ASSERT_EQ( + 0, memcmp(test_array, + kTestVectorFloat32 + kPartialStart * kTestVectorChannelCount, + kPartialFrames * sizeof(*kTestVectorFloat32) * + kTestVectorChannelCount))); } }
diff --git a/media/base/channel_mixer.cc b/media/base/channel_mixer.cc index e15a5b0d..b5fb74e 100644 --- a/media/base/channel_mixer.cc +++ b/media/base/channel_mixer.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/base/channel_mixer.h" #include <stddef.h>
diff --git a/media/base/container_names.cc b/media/base/container_names.cc index e852289..08ded38 100644 --- a/media/base/container_names.cc +++ b/media/base/container_names.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/container_names.h" #include <stddef.h> @@ -16,6 +11,7 @@ #include <limits> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/numerics/safe_conversions.h" #include "media/base/bit_reader.h" #include "third_party/abseil-cpp/absl/strings/ascii.h" @@ -40,22 +36,24 @@ // Helper function to read 2 bytes (16 bits, big endian) from a buffer. static int Read16(const uint8_t* p) { - return p[0] << 8 | p[1]; + return p[0] << 8 | UNSAFE_TODO(p[1]); } // Helper function to read 3 bytes (24 bits, big endian) from a buffer. static uint32_t Read24(const uint8_t* p) { - return p[0] << 16 | p[1] << 8 | p[2]; + return p[0] << 16 | UNSAFE_TODO(p[1]) << 8 | UNSAFE_TODO(p[2]); } // Helper function to read 4 bytes (32 bits, big endian) from a buffer. static uint32_t Read32(const uint8_t* p) { - return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + return p[0] << 24 | UNSAFE_TODO(p[1]) << 16 | UNSAFE_TODO(p[2]) << 8 | + UNSAFE_TODO(p[3]); } // Helper function to read 4 bytes (32 bits, little endian) from a buffer. static uint32_t Read32LE(const uint8_t* p) { - return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; + return UNSAFE_TODO(p[3]) << 24 | UNSAFE_TODO(p[2]) << 16 | + UNSAFE_TODO(p[1]) << 8 | p[0]; } // Helper function to do buffer comparisons with a string without going off the @@ -65,7 +63,7 @@ const char* prefix) { size_t prefix_size = strlen(prefix); return (prefix_size <= buffer_size && - memcmp(buffer, prefix, prefix_size) == 0); + UNSAFE_TODO(memcmp(buffer, prefix, prefix_size)) == 0); } // Helper function to do buffer comparisons with another buffer (to allow for @@ -75,7 +73,7 @@ const uint8_t* prefix, size_t prefix_size) { return (prefix_size <= buffer_size && - memcmp(buffer, prefix, prefix_size) == 0); + UNSAFE_TODO(memcmp(buffer, prefix, prefix_size)) == 0); } // Helper function to read up to 64 bits from a bit stream. @@ -101,7 +99,7 @@ int offset = 0; while (offset + 6 < buffer_size) { - BitReader reader(buffer + offset, 6); + BitReader reader(UNSAFE_TODO(buffer + offset), 6); // Syncword must be 0xfff. RCHECK(ReadBits(&reader, 12) == 0xfff); @@ -159,7 +157,7 @@ int offset = 0; while (offset + 6 < buffer_size) { - BitReader reader(buffer + offset, 6); + BitReader reader(UNSAFE_TODO(buffer + offset), 6); // Check syncinfo. RCHECK(ReadBits(&reader, 16) == kAc3SyncWord); @@ -194,7 +192,7 @@ int offset = 0; while (offset + 6 < buffer_size) { - BitReader reader(buffer + offset, 6); + BitReader reader(UNSAFE_TODO(buffer + offset), 6); // Check syncinfo. RCHECK(ReadBits(&reader, 16) == kAc3SyncWord); @@ -227,24 +225,24 @@ RCHECK(buffer_size >= 44); // Verify number of frames specified. - RCHECK(Read32LE(buffer + 8) > 0); + UNSAFE_TODO(RCHECK(Read32LE(buffer + 8) > 0)); // Verify width in range. - int width = Read32LE(buffer + 20); + int width = Read32LE(UNSAFE_TODO(buffer + 20)); RCHECK(width > 0 && width <= 32767); // Verify height in range. - int height = Read32LE(buffer + 24); + int height = Read32LE(UNSAFE_TODO(buffer + 24)); RCHECK(height > 0 && height <= 32767); // Verify frames per second specified. - RCHECK(Read32LE(buffer + 28) > 0); + UNSAFE_TODO(RCHECK(Read32LE(buffer + 28) > 0)); // Verify video frames per second specified. - RCHECK(Read32LE(buffer + 32) > 0); + UNSAFE_TODO(RCHECK(Read32LE(buffer + 32) > 0)); // Number of audio tracks must be 256 or less. - return (Read32LE(buffer + 40) <= 256); + return (Read32LE(UNSAFE_TODO(buffer + 40)) <= 256); } // Additional checks for a CAF container. @@ -289,7 +287,7 @@ int offset = 0; while (offset + 11 < buffer_size) { - BitReader reader(buffer + offset, 11); + BitReader reader(UNSAFE_TODO(buffer + offset), 11); // Verify sync word. RCHECK(ReadBits(&reader, 32) == 0x7ffe8001); @@ -356,7 +354,7 @@ int current_sequence_number = -1; std::array<int, 6> last_block_number = {}; while (offset + 11 < buffer_size) { - BitReader reader(buffer + offset, 11); + BitReader reader(UNSAFE_TODO(buffer + offset), 11); // Decode ID data. Sections 5, 6, and 7 are reserved. int section = ReadBits(&reader, 3); @@ -420,7 +418,7 @@ int offset = 0; while (offset < buffer_size) { // First 4 bits of each block are xD. - RCHECK((buffer[offset] & 0xf0) == 0xd0); + UNSAFE_TODO(RCHECK((buffer[offset] & 0xf0) == 0xd0)); offset += 33; } return true; @@ -444,7 +442,7 @@ uint32_t bits_to_shift = 24 - num_bits; uint32_t mask = (1 << num_bits) - 1; while (*offset + bytes_needed < buffer_size) { - uint32_t next = Read24(buffer + *offset); + uint32_t next = Read24(UNSAFE_TODO(buffer + *offset)); if (((next >> bits_to_shift) & mask) == start_code) return true; ++(*offset); @@ -470,7 +468,7 @@ // Now verify the block. AdvanceToStartCode() made sure that there are // at least 4 bytes remaining in the buffer. - BitReader reader(buffer + offset, buffer_size - offset); + BitReader reader(UNSAFE_TODO(buffer + offset), buffer_size - offset); RCHECK(ReadBits(&reader, 20) == 0x10); // Skip the temporal reference and PTYPE. @@ -519,7 +517,7 @@ // Now verify the block. AdvanceToStartCode() made sure that there are // at least 9 bytes remaining in the buffer. - BitReader reader(buffer + offset, 9); + BitReader reader(UNSAFE_TODO(buffer + offset), 9); RCHECK(ReadBits(&reader, 22) == 0x20); // Skip the temporal reference. @@ -587,7 +585,7 @@ // Now verify the block. AdvanceToStartCode() made sure that there are // at least 4 bytes remaining in the buffer. - BitReader reader(buffer + offset, 4); + BitReader reader(UNSAFE_TODO(buffer + offset), 4); RCHECK(ReadBits(&reader, 24) == 1); // Verify forbidden_zero_bit. @@ -637,10 +635,13 @@ // (http://en.wikipedia.org/wiki/M3U). int offset = strlen(kHlsSignature); while (offset < buffer_size) { - if (buffer[offset] == '#') { - if (StartsWith(buffer + offset, buffer_size - offset, kHls1) || - StartsWith(buffer + offset, buffer_size - offset, kHls2) || - StartsWith(buffer + offset, buffer_size - offset, kHls3)) { + if (UNSAFE_TODO(buffer[offset]) == '#') { + if (StartsWith(UNSAFE_TODO(buffer + offset), buffer_size - offset, + kHls1) || + StartsWith(UNSAFE_TODO(buffer + offset), buffer_size - offset, + kHls2) || + StartsWith(UNSAFE_TODO(buffer + offset), buffer_size - offset, + kHls3)) { return true; } } @@ -661,8 +662,8 @@ int num_codes = 0; while (offset + 5 < buffer_size) { // Marker codes are always a two byte code with the first byte xFF. - RCHECK(buffer[offset] == 0xff); - uint8_t code = buffer[offset + 1]; + UNSAFE_TODO(RCHECK(buffer[offset] == 0xff)); + uint8_t code = UNSAFE_TODO(buffer[offset + 1]); RCHECK(code >= 0xc0 || code == 1); // Skip sequences of xFF. @@ -688,20 +689,22 @@ offset += 2; } else { // All remaining marker codes are followed by a length of the header. - int length = Read16(buffer + offset + 2) + 2; + int length = Read16(UNSAFE_TODO(buffer + offset + 2)) + 2; // Special handling of SOS (start of scan) marker since the entropy // coded data follows the SOS. Any xFF byte in the data block must be // followed by x00 in the data. if (code == 0xda) { - int number_components = buffer[offset + 4]; + int number_components = UNSAFE_TODO(buffer[offset + 4]); RCHECK(length == 8 + 2 * number_components); // Advance to the next marker. offset += length; while (offset + 2 < buffer_size) { - if (buffer[offset] == 0xff && buffer[offset + 1] != 0) + if (UNSAFE_TODO(buffer[offset]) == 0xff && + UNSAFE_TODO(buffer[offset + 1]) != 0) { break; + } ++offset; } } else { @@ -726,7 +729,7 @@ int offset = 0; while (offset + 14 < buffer_size) { - BitReader reader(buffer + offset, 14); + BitReader reader(UNSAFE_TODO(buffer + offset), 14); // Must start with pack_start_code. RCHECK(ReadBits(&reader, 24) == 1); @@ -789,9 +792,10 @@ } // Check for system headers and PES_packets. - while (offset + 6 < buffer_size && Read24(buffer + offset) == 1) { + while (offset + 6 < buffer_size && + Read24(UNSAFE_TODO(buffer + offset)) == 1) { // Next 8 bits determine stream type. - int stream_id = buffer[offset + 3]; + int stream_id = UNSAFE_TODO(buffer[offset + 3]); // Some stream types are reserved and shouldn't occur. if (mpeg_version == 0) @@ -805,7 +809,7 @@ if (stream_id == PROGRAM_END_CODE) // end of stream. return true; - int pes_length = Read16(buffer + offset + 4); + int pes_length = Read16(UNSAFE_TODO(buffer + offset + 4)); RCHECK(pes_length > 0); offset = offset + 6 + pes_length; } @@ -828,13 +832,13 @@ int offset = 0; int packet_length = -1; - while (buffer[offset] != kMpeg2SyncWord && offset < 20) { + while (UNSAFE_TODO(buffer[offset]) != kMpeg2SyncWord && offset < 20) { // Skip over any header in the first 20 bytes. ++offset; } while (offset + 6 < buffer_size) { - BitReader reader(buffer + offset, 6); + BitReader reader(UNSAFE_TODO(buffer + offset), 6); // Must start with sync byte. RCHECK(ReadBits(&reader, 8) == kMpeg2SyncWord); @@ -869,13 +873,13 @@ // Attempt to determine the packet length on the first packet. if (packet_length < 0) { - if (buffer[offset + 188] == kMpeg2SyncWord) + if (UNSAFE_TODO(buffer[offset + 188]) == kMpeg2SyncWord) { packet_length = 188; - else if (buffer[offset + 192] == kMpeg2SyncWord) + } else if (UNSAFE_TODO(buffer[offset + 192]) == kMpeg2SyncWord) { packet_length = 192; - else if (buffer[offset + 204] == kMpeg2SyncWord) + } else if (UNSAFE_TODO(buffer[offset + 204]) == kMpeg2SyncWord) { packet_length = 204; - else + } else packet_length = 208; } offset += packet_length; @@ -912,7 +916,7 @@ // Now verify the block. AdvanceToStartCode() made sure that there are // at least 6 bytes remaining in the buffer. - BitReader reader(buffer + offset, 6); + BitReader reader(UNSAFE_TODO(buffer + offset), 6); RCHECK(ReadBits(&reader, 24) == 1); int start_code = ReadBits(&reader, 8); @@ -975,8 +979,8 @@ int offset = 0; int valid_top_level_boxes = 0; while (offset + 8 < buffer_size) { - uint32_t atomsize = Read32(buffer + offset); - uint32_t atomtype = Read32(buffer + offset + 4); + uint32_t atomsize = Read32(UNSAFE_TODO(buffer + offset)); + uint32_t atomtype = Read32(UNSAFE_TODO(buffer + offset + 4)); // Only need to check for atoms that are valid at the top level. However, // "Boxes with an unrecognized type shall be ignored and skipped." So @@ -1007,9 +1011,10 @@ // Indicates that the length is the next 64bits. if (offset + 16 > buffer_size) break; - if (Read32(buffer + offset + 8) != 0) + if (Read32(UNSAFE_TODO(buffer + offset + 8)) != 0) { break; // Offset is way past buffer size. - atomsize = Read32(buffer + offset + 12); + } + atomsize = Read32(UNSAFE_TODO(buffer + offset + 12)); } if (atomsize == 0 || atomsize > static_cast<size_t>(buffer_size)) break; // Indicates the last atom or length too big. @@ -1121,13 +1126,14 @@ int offset = 0; // Skip over any padding (0's). - while (offset < buffer_size && buffer[offset] == 0) + while (offset < buffer_size && UNSAFE_TODO(buffer[offset]) == 0) { ++offset; + } while (offset + 3 < buffer_size) { int framesize; - RCHECK(ValidMpegAudioFrameHeader( - buffer + offset, buffer_size - offset, &framesize)); + UNSAFE_TODO(RCHECK(ValidMpegAudioFrameHeader( + buffer + offset, buffer_size - offset, &framesize))); // Have we seen enough valid headers? if (++numSeen > 10) @@ -1149,14 +1155,15 @@ RCHECK(*offset < buffer_size); // Skip over any leading space. - while (absl::ascii_isspace(buffer[*offset])) { + while (absl::ascii_isspace(UNSAFE_TODO(buffer[*offset]))) { ++(*offset); RCHECK(*offset < buffer_size); } // Need to process up to max_digits digits. int numSeen = 0; - while (--max_digits >= 0 && absl::ascii_isdigit(buffer[*offset])) { + while (--max_digits >= 0 && + absl::ascii_isdigit(UNSAFE_TODO(buffer[*offset]))) { ++numSeen; ++(*offset); if (*offset >= buffer_size) @@ -1176,7 +1183,7 @@ char c1, char c2) { RCHECK(*offset < buffer_size); - char c = static_cast<char>(buffer[(*offset)++]); + char c = static_cast<char>(UNSAFE_TODO(buffer[(*offset)++])); return (c == c1 || (c == c2 && c2 != 0)); } @@ -1333,11 +1340,10 @@ RCHECK(buffer_size >= 24); // First check for Bitstream Metadata Serialization (Annex L) - if (buffer[0] == 0xc5 && - Read32(buffer + 4) == 0x04 && - Read32(buffer + 20) == 0x0c) { + if (buffer[0] == 0xc5 && Read32(UNSAFE_TODO(buffer + 4)) == 0x04 && + Read32(UNSAFE_TODO(buffer + 20)) == 0x0c) { // Verify settings in STRUCT_C and STRUCT_A - BitReader reader(buffer + 8, 12); + BitReader reader(UNSAFE_TODO(buffer + 8), 12); int profile = ReadBits(&reader, 4); if (profile == 0 || profile == 4) { // simple or main @@ -1392,7 +1398,7 @@ // Now verify the block. AdvanceToStartCode() made sure that there are // at least 5 bytes remaining in the buffer. - BitReader reader(buffer + offset, 5); + BitReader reader(UNSAFE_TODO(buffer + offset), 5); RCHECK(ReadBits(&reader, 24) == 1); // Keep track of the number of certain types received. @@ -1478,8 +1484,9 @@ break; case TAG('.','R','M','F'): - if (buffer[4] == 0 && buffer[5] == 0) + if (UNSAFE_TODO(buffer[4]) == 0 && UNSAFE_TODO(buffer[5]) == 0) { return MediaContainerName::kContainerRM; + } break; case TAG('.','r','a','\xfd'): @@ -1501,16 +1508,16 @@ break; case TAG('D','E','X','A'): - if (buffer_size > 15 && - Read16(buffer + 11) <= 2048 && - Read16(buffer + 13) <= 2048) { + if (buffer_size > 15 && Read16(UNSAFE_TODO(buffer + 11)) <= 2048 && + Read16(UNSAFE_TODO(buffer + 13)) <= 2048) { return MediaContainerName::kContainerDXA; } break; case TAG('D','T','S','H'): - if (Read32(buffer + 4) == TAG('D','H','D','R')) + if (Read32(UNSAFE_TODO(buffer + 4)) == TAG('D', 'H', 'D', 'R')) { return MediaContainerName::kContainerDTSHD; + } break; case 0x64a30100: @@ -1520,8 +1527,10 @@ case 0x0001a364: case 0x0002a364: case 0x0003a364: - if (Read32(buffer + 4) != 0 && Read32(buffer + 8) != 0) + if (Read32(UNSAFE_TODO(buffer + 4)) != 0 && + Read32(UNSAFE_TODO(buffer + 8)) != 0) { return MediaContainerName::kContainerIRCAM; + } break; case TAG('f','L','a','C'): @@ -1532,12 +1541,13 @@ case TAG('F','L','V',2): case TAG('F','L','V',3): case TAG('F','L','V',4): - if (buffer[5] == 0 && Read32(buffer + 5) > 8) + if (UNSAFE_TODO(buffer[5]) == 0 && Read32(UNSAFE_TODO(buffer + 5)) > 8) { return MediaContainerName::kContainerFLV; + } break; case TAG('F','O','R','M'): - switch (Read32(buffer + 8)) { + switch (Read32(UNSAFE_TODO(buffer + 8))) { case TAG('A','I','F','F'): case TAG('A','I','F','C'): return MediaContainerName::kContainerAIFF; @@ -1548,22 +1558,26 @@ return MediaContainerName::kContainerAPE; case TAG('O','N','2',' '): - if (Read32(buffer + 8) == TAG('O','N','2','f')) + if (Read32(UNSAFE_TODO(buffer + 8)) == TAG('O', 'N', '2', 'f')) { return MediaContainerName::kContainerAVI; + } break; case TAG('O','g','g','S'): - if (buffer[5] <= 7) + if (UNSAFE_TODO(buffer[5]) <= 7) { return MediaContainerName::kContainerOgg; + } break; case TAG('R','F','6','4'): - if (buffer_size > 16 && Read32(buffer + 12) == TAG('d','s','6','4')) + if (buffer_size > 16 && + Read32(UNSAFE_TODO(buffer + 12)) == TAG('d', 's', '6', '4')) { return MediaContainerName::kContainerWAV; + } break; case TAG('R','I','F','F'): - switch (Read32(buffer + 8)) { + switch (Read32(UNSAFE_TODO(buffer + 8))) { case TAG('A','V','I',' '): case TAG('A','V','I','X'): case TAG('A','V','I','\x19'): @@ -1683,10 +1697,12 @@ // so scan for a start code. int offset = 1; // No need to start at byte 0 due to First4 check. if (AdvanceToStartCode(buffer, buffer_size, &offset, 4, 16, kAc3SyncWord)) { - if (CheckAc3(buffer + offset, buffer_size - offset)) + if (CheckAc3(UNSAFE_TODO(buffer + offset), buffer_size - offset)) { return MediaContainerName::kContainerAC3; - if (CheckEac3(buffer + offset, buffer_size - offset)) + } + if (CheckEac3(UNSAFE_TODO(buffer + offset), buffer_size - offset)) { return MediaContainerName::kContainerEAC3; + } } return MediaContainerName::kContainerUnknown;
diff --git a/media/base/container_names_unittest.cc b/media/base/container_names_unittest.cc index dee21a37..73c201fe 100644 --- a/media/base/container_names_unittest.cc +++ b/media/base/container_names_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/base/container_names.h" #include <stdint.h> #include <optional> +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "media/base/test_data_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -53,11 +49,11 @@ // Try a large buffer all zeros. char buffer3[4096]; - memset(buffer3, 0, sizeof(buffer3)); + UNSAFE_TODO(memset(buffer3, 0, sizeof(buffer3))); VERIFY(buffer3, MediaContainerName::kContainerUnknown); // Reuse buffer, but all \n this time. - memset(buffer3, '\n', sizeof(buffer3)); + UNSAFE_TODO(memset(buffer3, '\n', sizeof(buffer3))); VERIFY(buffer3, MediaContainerName::kContainerUnknown); }
diff --git a/media/base/decoder_buffer_unittest.cc b/media/base/decoder_buffer_unittest.cc index 7c41924..74c4a9e 100644 --- a/media/base/decoder_buffer_unittest.cc +++ b/media/base/decoder_buffer_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/decoder_buffer.h" #include <stdint.h> @@ -15,6 +10,7 @@ #include <memory> #include <variant> +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/scoped_refptr.h" @@ -103,7 +99,7 @@ auto region = base::UnsafeSharedMemoryRegion::Create(kDataSize); auto mapping = region.Map(); ASSERT_TRUE(mapping.IsValid()); - memcpy(mapping.GetMemoryAs<uint8_t>(), kData, kDataSize); + UNSAFE_TODO(memcpy(mapping.GetMemoryAs<uint8_t>(), kData, kDataSize)); scoped_refptr<DecoderBuffer> buffer( DecoderBuffer::FromSharedMemoryRegion(std::move(region), 0, kDataSize)); @@ -122,7 +118,7 @@ auto region = base::UnsafeSharedMemoryRegion::Create(kDataSize); auto mapping = region.Map(); ASSERT_TRUE(mapping.IsValid()); - memcpy(mapping.GetMemoryAs<uint8_t>(), kData, kDataSize); + UNSAFE_TODO(memcpy(mapping.GetMemoryAs<uint8_t>(), kData, kDataSize)); scoped_refptr<DecoderBuffer> buffer(DecoderBuffer::FromSharedMemoryRegion( std::move(region), kDataOffset, kDataSize - kDataOffset)); @@ -140,7 +136,7 @@ auto region = base::UnsafeSharedMemoryRegion::Create(kDataSize); auto mapping = region.Map(); ASSERT_TRUE(mapping.IsValid()); - memcpy(mapping.memory(), kData, kDataSize); + UNSAFE_TODO(memcpy(mapping.memory(), kData, kDataSize)); scoped_refptr<DecoderBuffer> buffer( DecoderBuffer::FromSharedMemoryRegion(std::move(region), 0, 0)); @@ -153,7 +149,8 @@ auto mapping_region = base::ReadOnlySharedMemoryRegion::Create(kDataSize); ASSERT_TRUE(mapping_region.IsValid()); - memcpy(mapping_region.mapping.GetMemoryAs<uint8_t>(), kData, kDataSize); + UNSAFE_TODO( + memcpy(mapping_region.mapping.GetMemoryAs<uint8_t>(), kData, kDataSize)); scoped_refptr<DecoderBuffer> buffer(DecoderBuffer::FromSharedMemoryRegion( std::move(mapping_region.region), 0, kDataSize)); @@ -171,7 +168,8 @@ auto mapping_region = base::ReadOnlySharedMemoryRegion::Create(kDataSize); ASSERT_TRUE(mapping_region.IsValid()); - memcpy(mapping_region.mapping.GetMemoryAs<uint8_t>(), kData, kDataSize); + UNSAFE_TODO( + memcpy(mapping_region.mapping.GetMemoryAs<uint8_t>(), kData, kDataSize)); scoped_refptr<DecoderBuffer> buffer(DecoderBuffer::FromSharedMemoryRegion( std::move(mapping_region.region), kDataOffset, kDataSize - kDataOffset)); @@ -188,7 +186,8 @@ const size_t kDataSize = std::size(kData); auto mapping_region = base::ReadOnlySharedMemoryRegion::Create(kDataSize); - memcpy(mapping_region.mapping.GetMemoryAs<uint8_t>(), kData, kDataSize); + UNSAFE_TODO( + memcpy(mapping_region.mapping.GetMemoryAs<uint8_t>(), kData, kDataSize)); scoped_refptr<DecoderBuffer> buffer(DecoderBuffer::FromSharedMemoryRegion( std::move(mapping_region.region), 0, 0)); @@ -201,7 +200,7 @@ constexpr size_t kDataSize = std::size(kData); auto external_memory = std::make_unique<ExternalMemoryAdapterForTesting>( - base::span(kData, kDataSize)); + UNSAFE_TODO(base::span(kData, kDataSize))); auto buffer = DecoderBuffer::FromExternalMemory(std::move(external_memory)); ASSERT_TRUE(buffer.get()); EXPECT_EQ(buffer->size(), kDataSize); @@ -220,7 +219,7 @@ uint8_t* data = buffer->writable_data(); ASSERT_TRUE(data); ASSERT_EQ(kDataSize, buffer->size()); - base::span(data, buffer->size()).copy_from(kData); + UNSAFE_TODO(base::span(data, buffer->size())).copy_from(kData); const uint8_t* read_only_data = base::span(*buffer).data(); ASSERT_EQ(data, read_only_data); EXPECT_EQ(base::span(*buffer), base::span(kData));
diff --git a/media/base/djb2.cc b/media/base/djb2.cc index 8b50ef4..bd11991 100644 --- a/media/base/djb2.cc +++ b/media/base/djb2.cc
@@ -2,18 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/djb2.h" +#include "base/compiler_specific.h" + uint32_t DJB2Hash(const void* buf, size_t len, uint32_t seed) { const uint8_t* src = reinterpret_cast<const uint8_t*>(buf); uint32_t hash = seed; for (size_t i = 0; i < len; ++i) { - hash = hash * 33 + src[i]; + hash = hash * 33 + UNSAFE_TODO(src[i]); } return hash; }
diff --git a/media/base/frame_buffer_pool_unittest.cc b/media/base/frame_buffer_pool_unittest.cc index 8641c0d3..eaef72b 100644 --- a/media/base/frame_buffer_pool_unittest.cc +++ b/media/base/frame_buffer_pool_unittest.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/frame_buffer_pool.h" +#include "base/compiler_specific.h" #include "base/test/simple_test_tick_clock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -23,7 +19,7 @@ auto buf1 = pool->GetFrameBuffer(kBufferSize, &priv1); ASSERT_FALSE(buf1.empty()); ASSERT_TRUE(priv1); - memset(buf1.data(), 0, kBufferSize); + UNSAFE_TODO(memset(buf1.data(), 0, kBufferSize)); void* priv2 = nullptr; auto buf2 = pool->GetFrameBuffer(kBufferSize, &priv2); @@ -31,13 +27,13 @@ ASSERT_FALSE(buf2.empty()); EXPECT_NE(priv1, priv2); EXPECT_NE(buf1.data(), buf2.data()); - memset(buf2.data(), 0, kBufferSize); + UNSAFE_TODO(memset(buf2.data(), 0, kBufferSize)); auto alpha = pool->AllocateAlphaPlaneForFrameBuffer(kBufferSize, priv1); ASSERT_FALSE(alpha.empty()); EXPECT_NE(alpha.data(), buf1.data()); EXPECT_NE(alpha.data(), buf2.data()); - memset(alpha.data(), 0, kBufferSize); + UNSAFE_TODO(memset(alpha.data(), 0, kBufferSize)); EXPECT_EQ(2u, pool->get_pool_size_for_testing()); @@ -52,8 +48,8 @@ pool->Shutdown(); EXPECT_EQ(1u, pool->get_pool_size_for_testing()); - memset(buf1.data(), 0, kBufferSize); - memset(alpha.data(), 0, kBufferSize); + UNSAFE_TODO(memset(buf1.data(), 0, kBufferSize)); + UNSAFE_TODO(memset(alpha.data(), 0, kBufferSize)); // This will release all memory since we're in the shutdown state. std::move(frame_release_cb).Run();
diff --git a/media/base/limiting_audio_queue_unittest.cc b/media/base/limiting_audio_queue_unittest.cc index d4cee0d..0545ca8 100644 --- a/media/base/limiting_audio_queue_unittest.cc +++ b/media/base/limiting_audio_queue_unittest.cc
@@ -6,6 +6,7 @@ #include <algorithm> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/location.h" @@ -16,11 +17,6 @@ #include "media/base/audio_timestamp_helper.h" #include "testing/gtest/include/gtest/gtest.h" -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/41494069): Update these tests once AudioBus is spanified.. -#pragma allow_unsafe_buffers -#endif - namespace media { namespace { @@ -45,7 +41,8 @@ const size_t kSpanSize = sizeof(float) * static_cast<size_t>(number_frames); base::span<const uint8_t> input_span(base::as_byte_span( base::allow_nonunique_obj, expected_data->channel_span(ch))); - base::span<uint8_t> output_span(buffer->channel_data()[ch], kSpanSize); + base::span<uint8_t> UNSAFE_TODO( + output_span(buffer->channel_data()[ch], kSpanSize)); EXPECT_EQ(input_span, output_span); } } @@ -156,7 +153,8 @@ const float* channel_data = reinterpret_cast<const float*>(buffer->channel_data()[0]); for (int i = 0; i < buffer->frame_count(); ++i) { - has_values_from_first_buffer |= channel_data[i] == kGuardValue; + has_values_from_first_buffer |= + UNSAFE_TODO(channel_data[i]) == kGuardValue; } second_bufer_emitted = true; })); @@ -202,7 +200,7 @@ const float* channel_data = reinterpret_cast<const float*>(buffer->channel_data()[ch]); for (int i = 0; i < kBufferSize; ++i) { - has_out_of_range_value |= std::abs(channel_data[i]) > 1.0f; + has_out_of_range_value |= std::abs(UNSAFE_TODO(channel_data[i])) > 1.0f; } }
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index c0c4996..08272269 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -1124,6 +1124,11 @@ "AutoPictureInPictureAndroid", base::FEATURE_DISABLED_BY_DEFAULT); +// Enables Picture-in-Picture menu item on the video context menu on Android. +BASE_FEATURE(kContextMenuPictureInPictureAndroid, + "ContextMenuPictureInPictureAndroid", + base::FEATURE_DISABLED_BY_DEFAULT); + // Enables block model (LinearBlock) on supported devices. BASE_FEATURE(kMediaCodecBlockModel, "MediaCodecBlockModel", @@ -1762,6 +1767,9 @@ BASE_FEATURE(kD3D12VideoEncodeAccelerator, "D3D12VideoEncodeAccelerator", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kD3D12VideoEncodeAcceleratorL1T3, + "D3D12VideoEncodeAcceleratorL1T3", + base::FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64)
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 3d3ab044..720737e 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -395,6 +395,7 @@ #if BUILDFLAG(IS_ANDROID) MEDIA_EXPORT BASE_DECLARE_FEATURE(kAllowNonSecureOverlays); MEDIA_EXPORT BASE_DECLARE_FEATURE(kAutoPictureInPictureAndroid); +MEDIA_EXPORT BASE_DECLARE_FEATURE(kContextMenuPictureInPictureAndroid); MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaCodecBlockModel); MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaCodecCodedSizeGuessing); MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaCodecElideEOS); @@ -525,6 +526,7 @@ #if BUILDFLAG(IS_WIN) MEDIA_EXPORT BASE_DECLARE_FEATURE(kD3D12VideoDecoder); MEDIA_EXPORT BASE_DECLARE_FEATURE(kD3D12VideoEncodeAccelerator); +MEDIA_EXPORT BASE_DECLARE_FEATURE(kD3D12VideoEncodeAcceleratorL1T3); MEDIA_EXPORT extern const base::FeatureParam<double> kAudioOffloadBufferTimeMs; MEDIA_EXPORT BASE_DECLARE_FEATURE(kAudioOffload);
diff --git a/media/base/multi_channel_resampler.cc b/media/base/multi_channel_resampler.cc index 1e49c92..6d02d13 100644 --- a/media/base/multi_channel_resampler.cc +++ b/media/base/multi_channel_resampler.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/multi_channel_resampler.h" #include <algorithm> #include <memory> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/numerics/safe_conversions.h" @@ -96,7 +92,7 @@ int frames, float* destination) { const size_t frames_to_provide = base::checked_cast<size_t>(frames); - auto dest_span = base::span(destination, frames_to_provide); + auto dest_span = UNSAFE_TODO(base::span(destination, frames_to_provide)); // Get the data from the multi-channel provider when the first channel asks // for it. For subsequent channels, we can just dish out the channel data
diff --git a/media/base/silent_sink_suspender_unittest.cc b/media/base/silent_sink_suspender_unittest.cc index 9853436..134ae7f5 100644 --- a/media/base/silent_sink_suspender_unittest.cc +++ b/media/base/silent_sink_suspender_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/base/silent_sink_suspender.h" #include "base/memory/scoped_refptr.h"
diff --git a/media/base/sinc_resampler_unittest.cc b/media/base/sinc_resampler_unittest.cc index 7edec05..12e33e5 100644 --- a/media/base/sinc_resampler_unittest.cc +++ b/media/base/sinc_resampler_unittest.cc
@@ -2,21 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif +#include "media/base/sinc_resampler.h" #include <memory> #include <numbers> +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "build/build_config.h" -#include "media/base/sinc_resampler.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,14 +30,14 @@ }; ACTION(ClearBuffer) { - memset(arg1, 0, arg0 * sizeof(float)); + UNSAFE_TODO(memset(arg1, 0, arg0 * sizeof(float))); } ACTION(FillBuffer) { // Value chosen arbitrarily such that SincResampler resamples it to something // easily representable on all platforms; e.g., using kSampleRateRatio this // becomes 1.81219. - memset(arg1, 64, arg0 * sizeof(float)); + UNSAFE_TODO(memset(arg1, 64, arg0 * sizeof(float))); } // Test requesting multiples of ChunkSize() frames results in the proper number @@ -188,11 +185,11 @@ // Test Convolve() w/ unaligned input pointer. result = resampler.Convolve_C( - resampler.KernelSize(), resampler.kernel_storage_.get() + 1, + resampler.KernelSize(), UNSAFE_TODO(resampler.kernel_storage_.get() + 1), resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), kKernelInterpolationFactor); result2 = resampler.convolve_proc_( - resampler.KernelSize(), resampler.kernel_storage_.get() + 1, + resampler.KernelSize(), UNSAFE_TODO(resampler.kernel_storage_.get() + 1), resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), kKernelInterpolationFactor); EXPECT_NEAR(result2, result, kEpsilon); @@ -225,13 +222,13 @@ for (int i = 0; i < frames; ++i, ++current_index_) { // Filter out frequencies higher than Nyquist. if (Frequency(current_index_) > 0.5 * sample_rate_) { - destination[i] = 0; + UNSAFE_TODO(destination[i]) = 0; } else { // Calculate time in seconds. double t = static_cast<double>(current_index_) / sample_rate_; // Sinusoidal linear chirp. - destination[i] = + UNSAFE_TODO(destination[i]) = sin(2 * std::numbers::pi * (kMinFrequency * t + (k_ / 2) * t * t)); } } @@ -298,14 +295,16 @@ // Force an update to the sample rate ratio to ensure dynamic sample rate // changes are working correctly. auto kernel = base::HeapArray<float>::Uninit(kernel_storage_size); - memcpy(kernel.data(), resampler.get_kernel_for_testing(), - kernel_storage_size_in_bytes); + UNSAFE_TODO(memcpy(kernel.data(), resampler.get_kernel_for_testing(), + kernel_storage_size_in_bytes)); resampler.SetRatio(std::numbers::pi); - ASSERT_NE(0, memcmp(kernel.data(), resampler.get_kernel_for_testing(), - kernel_storage_size_in_bytes)); + UNSAFE_TODO( + ASSERT_NE(0, memcmp(kernel.data(), resampler.get_kernel_for_testing(), + kernel_storage_size_in_bytes))); resampler.SetRatio(io_ratio); - ASSERT_EQ(0, memcmp(kernel.data(), resampler.get_kernel_for_testing(), - kernel_storage_size_in_bytes)); + UNSAFE_TODO( + ASSERT_EQ(0, memcmp(kernel.data(), resampler.get_kernel_for_testing(), + kernel_storage_size_in_bytes))); // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes. @@ -393,14 +392,16 @@ // Force an update to the sample rate ratio to ensure dynamic sample rate // changes are working correctly. auto kernel = base::HeapArray<float>::Uninit(kernel_storage_size); - memcpy(kernel.data(), resampler.get_kernel_for_testing(), - kernel_storage_size_in_bytes); + UNSAFE_TODO(memcpy(kernel.data(), resampler.get_kernel_for_testing(), + kernel_storage_size_in_bytes)); resampler.SetRatio(std::numbers::pi); - ASSERT_NE(0, memcmp(kernel.data(), resampler.get_kernel_for_testing(), - kernel_storage_size_in_bytes)); + UNSAFE_TODO( + ASSERT_NE(0, memcmp(kernel.data(), resampler.get_kernel_for_testing(), + kernel_storage_size_in_bytes))); resampler.SetRatio(io_ratio); - ASSERT_EQ(0, memcmp(kernel.data(), resampler.get_kernel_for_testing(), - kernel_storage_size_in_bytes)); + UNSAFE_TODO( + ASSERT_EQ(0, memcmp(kernel.data(), resampler.get_kernel_for_testing(), + kernel_storage_size_in_bytes))); // TODO(dalecurtis): If we switch to AVX/SSE optimization, we'll need to // allocate these on 32-byte boundaries and ensure they're sized % 32 bytes.
diff --git a/media/base/status_unittest.cc b/media/base/status_unittest.cc index c081c02..4831581 100644 --- a/media/base/status_unittest.cc +++ b/media/base/status_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/base/status.h" #include <algorithm>
diff --git a/media/base/stream_parser_unittest.cc b/media/base/stream_parser_unittest.cc index 5fbebbbf..3768564 100644 --- a/media/base/stream_parser_unittest.cc +++ b/media/base/stream_parser_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/stream_parser.h" #include <stddef.h>
diff --git a/media/base/svc_scalability_mode.cc b/media/base/svc_scalability_mode.cc index 9ea68e9..9ba4919 100644 --- a/media/base/svc_scalability_mode.cc +++ b/media/base/svc_scalability_mode.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/svc_scalability_mode.h" #include <algorithm> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/notreached.h" namespace media { @@ -52,7 +48,7 @@ sizeof(kSVCScalabilityModeMap) / sizeof(SVCScalabilityMode); std::vector<SVCScalabilityMode> supported_svcs( &kSVCScalabilityModeMap[0][0][0], - (&kSVCScalabilityModeMap[0][0][0]) + kSVCMapSize); + UNSAFE_TODO((&kSVCScalabilityModeMap[0][0][0]) + kSVCMapSize)); std::sort(supported_svcs.begin(), supported_svcs.end()); supported_svcs.erase( std::unique(supported_svcs.begin(), supported_svcs.end()), @@ -70,9 +66,8 @@ CHECK(0 < num_temporal_layers && num_temporal_layers <= 3); CHECK(static_cast<int>(inter_layer_pred) >= 0 && static_cast<int>(inter_layer_pred) < 3); - auto mode = - kSVCScalabilityModeMap[static_cast<int>(inter_layer_pred)] - [num_spatial_layers - 1][num_temporal_layers - 1]; + auto mode = UNSAFE_TODO(kSVCScalabilityModeMap[static_cast<int>( + inter_layer_pred)][num_spatial_layers - 1][num_temporal_layers - 1]); CHECK_NE(mode, kInvalid); return mode; }
diff --git a/media/base/test_helpers.cc b/media/base/test_helpers.cc index 5d3a2f2..0952f0e0 100644 --- a/media/base/test_helpers.cc +++ b/media/base/test_helpers.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/test_helpers.h" #include <stdint.h> @@ -15,6 +10,7 @@ #include <optional> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" @@ -73,15 +69,15 @@ << VideoPixelFormatToString(dest_frame->format()); // Write known full size planes first. - libyuv::SetPlane(dest_frame->GetWritableVisibleData(VideoFrame::Plane::kY) + - y * dest_frame->stride(VideoFrame::Plane::kY) + x, - dest_frame->stride(VideoFrame::Plane::kY), width, height, - value_y); + libyuv::SetPlane( + UNSAFE_TODO(dest_frame->GetWritableVisibleData(VideoFrame::Plane::kY) + + y * dest_frame->stride(VideoFrame::Plane::kY) + x), + dest_frame->stride(VideoFrame::Plane::kY), width, height, value_y); if (num_planes == 4) { - libyuv::SetPlane(dest_frame->GetWritableVisibleData(VideoFrame::Plane::kA) + - y * dest_frame->stride(VideoFrame::Plane::kA) + x, - dest_frame->stride(VideoFrame::Plane::kA), width, height, - value_a); + libyuv::SetPlane( + UNSAFE_TODO(dest_frame->GetWritableVisibleData(VideoFrame::Plane::kA) + + y * dest_frame->stride(VideoFrame::Plane::kA) + x), + dest_frame->stride(VideoFrame::Plane::kA), width, height, value_a); } // Adjust rect start and offset. @@ -92,15 +88,17 @@ // Write variable sized planes. libyuv::SetPlane( - dest_frame->GetWritableVisibleData(VideoFrame::Plane::kU) + - start_xy.height() * dest_frame->stride(VideoFrame::Plane::kU) + - start_xy.width(), + UNSAFE_TODO(dest_frame->GetWritableVisibleData(VideoFrame::Plane::kU) + + start_xy.height() * + dest_frame->stride(VideoFrame::Plane::kU) + + start_xy.width()), dest_frame->stride(VideoFrame::Plane::kU), uv_size.width(), uv_size.height(), value_u); libyuv::SetPlane( - dest_frame->GetWritableVisibleData(VideoFrame::Plane::kV) + - start_xy.height() * dest_frame->stride(VideoFrame::Plane::kV) + - start_xy.width(), + UNSAFE_TODO(dest_frame->GetWritableVisibleData(VideoFrame::Plane::kV) + + start_xy.height() * + dest_frame->stride(VideoFrame::Plane::kV) + + start_xy.width()), dest_frame->stride(VideoFrame::Plane::kV), uv_size.width(), uv_size.height(), value_v); } @@ -582,7 +580,7 @@ reinterpret_cast<T*>(output->channel_data()[is_planar ? ch : 0]); const T v = static_cast<T>(start + ch * frames * increment); for (size_t i = 0; i < frames; ++i) { - buffer[is_planar ? i : ch + i * channels] = + UNSAFE_TODO(buffer[is_planar ? i : ch + i * channels]) = static_cast<T>(v + i * increment); } } @@ -620,7 +618,7 @@ reinterpret_cast<float*>(output->channel_data()[is_planar ? ch : 0]); const float v = static_cast<float>(start + ch * frames * increment); for (size_t i = 0; i < frames; ++i) { - buffer[is_planar ? i : ch + i * channels] = + UNSAFE_TODO(buffer[is_planar ? i : ch + i * channels]) = static_cast<float>(v + i * increment) / std::numeric_limits<uint16_t>::max(); } @@ -649,7 +647,7 @@ // start + 2 * increment, ... uint8_t* buffer = reinterpret_cast<uint8_t*>(output->channel_data()[0]); for (size_t i = 0; i < data_size; ++i) { - buffer[i] = static_cast<uint8_t>(start + i * increment); + UNSAFE_TODO(buffer[i]) = static_cast<uint8_t>(start + i * increment); } return output;
diff --git a/media/base/video_bitrate_allocation.cc b/media/base/video_bitrate_allocation.cc index 1dfb491..25d98375 100644 --- a/media/base/video_bitrate_allocation.cc +++ b/media/base/video_bitrate_allocation.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "video_bitrate_allocation.h" #include <array> @@ -16,6 +11,7 @@ #include <sstream> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/numerics/checked_math.h" #include "media/base/bitrate.h" @@ -176,9 +172,9 @@ if (sum_bitrate_ != other.sum_bitrate_) { return false; } - return memcmp(bitrates_.data(), other.bitrates_.data(), - (bitrates_.size() * sizeof(decltype(bitrates_)::value_type))) == - 0; + return UNSAFE_TODO(memcmp(bitrates_.data(), other.bitrates_.data(), + (bitrates_.size() * + sizeof(decltype(bitrates_)::value_type)))) == 0; } } // namespace media
diff --git a/media/base/video_codec_string_parsers.cc b/media/base/video_codec_string_parsers.cc index be76c193..da1f0a48 100644 --- a/media/base/video_codec_string_parsers.cc +++ b/media/base/video_codec_string_parsers.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/video_codec_string_parsers.h" #include <array> #include <string_view> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/notreached.h" #include "base/strings/string_number_conversions.h" @@ -681,9 +677,9 @@ } std::array<uint8_t, 6> constraint_flags; - memset(constraint_flags.data(), 0, - (constraint_flags.size() * - sizeof(decltype(constraint_flags)::value_type))); + UNSAFE_TODO(memset(constraint_flags.data(), 0, + (constraint_flags.size() * + sizeof(decltype(constraint_flags)::value_type)))); if (elem.size() > 10) { DVLOG(4) << __func__ << ": unexpected number of trailing bytes in HEVC "
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index b84ff34f..72b870c 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h
@@ -647,6 +647,18 @@ return data_[plane]; } + std::optional<base::span<uint8_t>> writable_span(size_t plane) { + if (storage_type_ == STORAGE_SHMEM || + storage_type_ == STORAGE_UNOWNED_MEMORY) { + return std::nullopt; + } + auto const_span = data_span(plane); + // SAFETY: We take data() and size() from another span, which supposedly + // refers to a valid range in memory. + return UNSAFE_BUFFERS( + base::span(const_cast<uint8_t*>(const_span.data()), const_span.size())); + } + uint8_t* writable_data(size_t plane) { // TODO(crbug.com/40265179): Also CHECK that the storage type isn't // STORAGE_UNOWNED_MEMORY once non-compliant usages are fixed.
diff --git a/media/base/video_frame_converter_unittest.cc b/media/base/video_frame_converter_unittest.cc index ce97e02..ac6d2fb 100644 --- a/media/base/video_frame_converter_unittest.cc +++ b/media/base/video_frame_converter_unittest.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/video_frame_converter.h" +#include "base/compiler_specific.h" #include "base/logging.h" #include "media/base/test_helpers.h" #include "media/base/video_frame.h" @@ -94,8 +90,8 @@ auto plane_size = VideoFrame::PlaneSize(frame.format(), i, frame.visible_rect().size()); for (int y = 0; y < plane_size.height(); ++y) { - fwrite(frame.visible_data(i) + y * frame.stride(i), 1, plane_size.width(), - f); + UNSAFE_TODO(fwrite(frame.visible_data(i) + y * frame.stride(i), 1, + plane_size.width(), f)); } } fclose(f);
diff --git a/media/base/video_frame_pool_unittest.cc b/media/base/video_frame_pool_unittest.cc index bf58016..c352812 100644 --- a/media/base/video_frame_pool_unittest.cc +++ b/media/base/video_frame_pool_unittest.cc
@@ -2,19 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif +#include "media/base/video_frame_pool.h" #include <stddef.h> #include <stdint.h> + #include <memory> #include <tuple> #include "base/bits.h" +#include "base/compiler_specific.h" #include "base/test/simple_test_tick_clock.h" -#include "media/base/video_frame_pool.h" #include "testing/gmock/include/gmock/gmock.h" namespace media { @@ -126,9 +124,9 @@ // Write to the Y plane. The memory tools should detect a // use-after-free if the storage was actually removed by pool destruction. - memset(frame->writable_data(VideoFrame::Plane::kY), 0xff, - frame->rows(VideoFrame::Plane::kY) * - frame->stride(VideoFrame::Plane::kY)); + UNSAFE_TODO(memset(frame->writable_data(VideoFrame::Plane::kY), 0xff, + frame->rows(VideoFrame::Plane::kY) * + frame->stride(VideoFrame::Plane::kY))); } TEST_F(VideoFramePoolTest, StaleFramesAreExpired) {
diff --git a/media/base/video_transformation.cc b/media/base/video_transformation.cc index 463c9da..0fa26f8 100644 --- a/media/base/video_transformation.cc +++ b/media/base/video_transformation.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/video_transformation.h" #include <math.h> @@ -15,6 +10,7 @@ #include <array> #include <cmath> +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/logging.h" #include "base/notreached.h" @@ -56,9 +52,9 @@ const int32_t* matrix3x3) { const int32_t matrix2x2[4] = { matrix3x3[0], - matrix3x3[1], - matrix3x3[3], - matrix3x3[4], + UNSAFE_TODO(matrix3x3[1]), + UNSAFE_TODO(matrix3x3[3]), + UNSAFE_TODO(matrix3x3[4]), }; return VideoTransformation(matrix2x2); }
diff --git a/media/base/video_util.cc b/media/base/video_util.cc index a7840af..716e5de 100644 --- a/media/base/video_util.cc +++ b/media/base/video_util.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/video_util.h" #include <array> @@ -14,6 +9,7 @@ #include "base/bits.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/logging.h" #include "base/notreached.h" @@ -51,24 +47,27 @@ const gfx::Size& visible_size) { if (visible_size.IsEmpty()) { if (!coded_size.IsEmpty()) - memset(data, 0, coded_size.height() * stride); + UNSAFE_TODO(memset(data, 0, coded_size.height() * stride)); return; } const int coded_width = coded_size.width(); if (visible_size.width() < coded_width) { const int pad_length = coded_width - visible_size.width(); - uint8_t* dst = data + visible_size.width(); - for (int i = 0; i < visible_size.height(); ++i, dst += stride) - memset(dst, *(dst - 1), pad_length); + uint8_t* dst = UNSAFE_TODO(data + visible_size.width()); + for (int i = 0; i < visible_size.height(); + ++i, UNSAFE_TODO(dst += stride)) { + UNSAFE_TODO(memset(dst, *(dst - 1), pad_length)); + } } if (visible_size.height() < coded_size.height()) { - uint8_t* dst = data + visible_size.height() * stride; - uint8_t* src = dst - stride; + uint8_t* dst = UNSAFE_TODO(data + visible_size.height() * stride); + uint8_t* src = UNSAFE_TODO(dst - stride); for (int i = visible_size.height(); i < coded_size.height(); - ++i, dst += stride) - memcpy(dst, src, coded_width); + ++i, UNSAFE_TODO(dst += stride)) { + UNSAFE_TODO(memcpy(dst, src, coded_width)); + } } } @@ -116,7 +115,7 @@ if (view_area_in_bytes.y() > 0) { libyuv::SetPlane(ptr, stride, row_bytes, view_area_in_bytes.y(), fill_byte); - ptr += stride * view_area_in_bytes.y(); + UNSAFE_TODO(ptr += stride * view_area_in_bytes.y()); } if (view_area_in_bytes.width() < row_bytes) { @@ -125,13 +124,13 @@ view_area_in_bytes.height(), fill_byte); } if (view_area_in_bytes.right() < row_bytes) { - libyuv::SetPlane(ptr + view_area_in_bytes.right(), stride, + libyuv::SetPlane(UNSAFE_TODO(ptr + view_area_in_bytes.right()), stride, row_bytes - view_area_in_bytes.right(), view_area_in_bytes.height(), fill_byte); } } - ptr += stride * view_area_in_bytes.height(); + UNSAFE_TODO(ptr += stride * view_area_in_bytes.height()); if (view_area_in_bytes.bottom() < rows) { libyuv::SetPlane(ptr, stride, row_bytes, rows - view_area_in_bytes.bottom(), @@ -351,21 +350,21 @@ if (flip_vert) { // Rotation 180. dest_row_step = -width; - dest += height * width - 1; + UNSAFE_TODO(dest += height * width - 1); } else { - dest += width - 1; + UNSAFE_TODO(dest += width - 1); } } else { if (flip_vert) { // Fast copy by rows. - dest += width * (height - 1); + UNSAFE_TODO(dest += width * (height - 1)); for (int row = 0; row < height; ++row) { - memcpy(dest, src, width); - src += width; - dest -= width; + UNSAFE_TODO(memcpy(dest, src, width)); + UNSAFE_TODO(src += width); + UNSAFE_TODO(dest -= width); } } else { - memcpy(dest, src, width * height); + UNSAFE_TODO(memcpy(dest, src, width * height)); } return; } @@ -373,11 +372,11 @@ int offset; if (width > height) { offset = (width - height) / 2; - src += offset; + UNSAFE_TODO(src += offset); num_rows = num_cols = height; } else { offset = (height - width) / 2; - src += width * offset; + UNSAFE_TODO(src += width * offset); num_rows = num_cols = width; } @@ -385,18 +384,18 @@ dest_row_step = (flip_horiz ? 1 : -1); if (flip_horiz) { if (flip_vert) { - dest += (width > height ? width * (height - 1) + offset : - width * (height - offset - 1)); + UNSAFE_TODO(dest += (width > height ? width * (height - 1) + offset + : width * (height - offset - 1))); } else { - dest += (width > height ? offset : width * offset); + UNSAFE_TODO(dest += (width > height ? offset : width * offset)); } } else { if (flip_vert) { - dest += (width > height ? width * height - offset - 1 : - width * (height - offset) - 1); + UNSAFE_TODO(dest += (width > height ? width * height - offset - 1 + : width * (height - offset) - 1)); } else { - dest += (width > height ? width - offset - 1 : - width * (offset + 1) - 1); + UNSAFE_TODO(dest += (width > height ? width - offset - 1 + : width * (offset + 1) - 1)); } } } else { @@ -408,11 +407,11 @@ const uint8_t* src_ptr = src; uint8_t* dest_ptr = dest; for (int col = 0; col < num_cols; ++col) { - *dest_ptr = *src_ptr++; - dest_ptr += dest_col_step; + *dest_ptr = *UNSAFE_TODO(src_ptr++); + UNSAFE_TODO(dest_ptr += dest_col_step); } - src += src_stride; - dest += dest_row_step; + UNSAFE_TODO(src += src_stride); + UNSAFE_TODO(dest += dest_row_step); } }
diff --git a/media/base/video_util_unittest.cc b/media/base/video_util_unittest.cc index 57824d9..dfa3ccd 100644 --- a/media/base/video_util_unittest.cc +++ b/media/base/video_util_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/base/video_util.h" #include <stdint.h> @@ -14,6 +9,7 @@ #include <cmath> #include <memory> +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/containers/span.h" #include "base/memory/raw_ptr_exclusion.h" @@ -32,9 +28,9 @@ uint32_t val = 0; uint8_t* src = data; - for (int i = 0; i < visible_size.height(); ++i, src += stride) { + for (int i = 0; i < visible_size.height(); ++i, UNSAFE_TODO(src += stride)) { for (int j = 0; j < visible_size.width(); ++j, ++val) - src[j] = val & 0xff; + UNSAFE_TODO(src[j]) = val & 0xff; } } @@ -90,19 +86,22 @@ return false; const uint8_t *src_ptr = src, *dst_ptr = dst; - for (size_t i = 0; i < src_height; - ++i, src_ptr += src_stride, dst_ptr += dst_stride) { - if (memcmp(src_ptr, dst_ptr, src_width)) + for (size_t i = 0; i < src_height; ++i, UNSAFE_TODO(src_ptr += src_stride), + UNSAFE_TODO(dst_ptr += dst_stride)) { + if (UNSAFE_TODO(memcmp(src_ptr, dst_ptr, src_width))) { return false; + } for (size_t j = src_width; j < dst_width; ++j) { - if (src_ptr[src_width - 1] != dst_ptr[j]) + if (UNSAFE_TODO(src_ptr[src_width - 1]) != UNSAFE_TODO(dst_ptr[j])) { return false; + } } } if (src_height < dst_height) { - src_ptr = dst + (src_height - 1) * dst_stride; - if (memcmp(src_ptr, dst_ptr, dst_width)) + src_ptr = UNSAFE_TODO(dst + (src_height - 1) * dst_stride); + if (UNSAFE_TODO(memcmp(src_ptr, dst_ptr, dst_width))) { return false; + } } return true; } @@ -335,7 +334,7 @@ RotatePlaneByPixels(GetParam().src, dest.data(), GetParam().width, GetParam().height, rotation, GetParam().flip_vert, GetParam().flip_horiz); - auto expected = base::span(GetParam().target, dest.size()); + auto expected = UNSAFE_TODO(base::span(GetParam().target, dest.size())); EXPECT_EQ(dest, expected); } @@ -550,17 +549,20 @@ x < view_area.x() + view_area.width() && y >= view_area.y() && y < view_area.y() + view_area.height(); - EXPECT_EQ(frame->data(VideoFrame::Plane::kY) - [y * frame->stride(VideoFrame::Plane::kY) + x], - inside ? 0x01 : 0x00); - EXPECT_EQ(frame->data(VideoFrame::Plane::kU) - [(y / 2) * frame->stride(VideoFrame::Plane::kU) + - (x / 2)], - inside ? 0x02 : 0x80); - EXPECT_EQ(frame->data(VideoFrame::Plane::kV) - [(y / 2) * frame->stride(VideoFrame::Plane::kV) + - (x / 2)], - inside ? 0x03 : 0x80); + UNSAFE_TODO( + EXPECT_EQ(frame->data(VideoFrame::Plane::kY) + [y * frame->stride(VideoFrame::Plane::kY) + x], + inside ? 0x01 : 0x00)); + UNSAFE_TODO(EXPECT_EQ( + frame->data(VideoFrame::Plane::kU) + [(y / 2) * frame->stride(VideoFrame::Plane::kU) + + (x / 2)], + inside ? 0x02 : 0x80)); + UNSAFE_TODO(EXPECT_EQ( + frame->data(VideoFrame::Plane::kV) + [(y / 2) * frame->stride(VideoFrame::Plane::kV) + + (x / 2)], + inside ? 0x03 : 0x80)); } } } @@ -623,7 +625,8 @@ // ASAN. src_frame.reset(); for (auto plane : planes) - memset(dst_frame->writable_data(plane), 1, dst_frame->stride(plane)); + UNSAFE_TODO( + memset(dst_frame->writable_data(plane), 1, dst_frame->stride(plane))); } } // namespace media
diff --git a/media/capabilities/bucket_utility.cc b/media/capabilities/bucket_utility.cc index 0361416..ee54e52 100644 --- a/media/capabilities/bucket_utility.cc +++ b/media/capabilities/bucket_utility.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/capabilities/bucket_utility.h" #include <algorithm> @@ -15,6 +10,7 @@ #include <iterator> #include "base/check_op.h" +#include "base/compiler_specific.h" namespace { @@ -78,9 +74,9 @@ // If no bucket is larger than the raw dimension, just use the last bucket. if (width_bound == std::end(kSizeBuckets)) - --width_bound; + UNSAFE_TODO(--width_bound); if (height_bound == std::end(kSizeBuckets)) - --height_bound; + UNSAFE_TODO(--height_bound); return gfx::Size(*width_bound, *height_bound); } @@ -95,14 +91,14 @@ // If no bucket is larger than |rounded_fps|, just used the last bucket; if (upper_bound == std::end(kFrameRateBuckets)) - return *(upper_bound - 1); + return *(UNSAFE_TODO(upper_bound - 1)); // Return early if its the first bucket. if (upper_bound == std::begin(kFrameRateBuckets)) return *upper_bound; int higher_bucket = *upper_bound; - int previous_bucket = *(upper_bound - 1); + int previous_bucket = *(UNSAFE_TODO(upper_bound - 1)); if (std::abs(previous_bucket - rounded_fps) < std::abs(higher_bucket - rounded_fps)) { return previous_bucket; @@ -129,4 +125,4 @@ return pixels_bucket_index; } -} // namespace media \ No newline at end of file +} // namespace media
diff --git a/media/capabilities/webrtc_video_stats_db.cc b/media/capabilities/webrtc_video_stats_db.cc index 1dc4c9eb..20450ec 100644 --- a/media/capabilities/webrtc_video_stats_db.cc +++ b/media/capabilities/webrtc_video_stats_db.cc
@@ -2,14 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/capabilities/webrtc_video_stats_db.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/format_macros.h" #include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" @@ -106,9 +102,10 @@ last_separator_index >= kMinimumIndexOfLastSeparator && (last_separator_index + 1) < key.size()) { int parsed_pixels; - if (base::StringToInt(&key.c_str()[last_separator_index + 1], - &parsed_pixels)) + if (base::StringToInt(&UNSAFE_TODO(key.c_str()[last_separator_index + 1]), + &parsed_pixels)) { return parsed_pixels; + } } return std::nullopt; }
diff --git a/media/capture/content/smooth_event_sampler_unittest.cc b/media/capture/content/smooth_event_sampler_unittest.cc index 0d7b1be..b5f4b3aa 100644 --- a/media/capture/content/smooth_event_sampler_unittest.cc +++ b/media/capture/content/smooth_event_sampler_unittest.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/capture/content/smooth_event_sampler.h" #include <stddef.h> #include <stdint.h> +#include "base/compiler_specific.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" @@ -285,12 +281,13 @@ base::TimeTicks t = InitialTestTimeTicks(); for (size_t i = 0; i < num_data_points; ++i) { t += base::Microseconds( - static_cast<int64_t>(data_points[i].increment_ms * 1000)); - ASSERT_EQ(data_points[i].should_capture, - AddEventAndConsiderSampling(sampler, t)) + static_cast<int64_t>(UNSAFE_TODO(data_points[i]).increment_ms * 1000)); + UNSAFE_TODO(ASSERT_EQ(data_points[i].should_capture, + AddEventAndConsiderSampling(sampler, t))) << "at data_points[" << i << ']'; - if (data_points[i].should_capture) + if (UNSAFE_TODO(data_points[i]).should_capture) { sampler->RecordSample(); + } } }
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc index 9fabc9d..513f515 100644 --- a/media/capture/video/fake_video_capture_device_unittest.cc +++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/capture/video/fake_video_capture_device.h" #include <stddef.h> @@ -18,6 +13,7 @@ #include <utility> #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_refptr.h" @@ -46,7 +42,7 @@ bool operator==(const FakePhotoDeviceConfig& lhs, const FakePhotoDeviceConfig& rhs) { - return std::memcmp(&lhs, &rhs, sizeof(lhs)) == 0; + return UNSAFE_TODO(std::memcmp(&lhs, &rhs, sizeof(lhs))) == 0; } namespace {
diff --git a/media/capture/video/file_video_capture_device.cc b/media/capture/video/file_video_capture_device.cc index 6142cb2..6879f651 100644 --- a/media/capture/video/file_video_capture_device.cc +++ b/media/capture/video/file_video_capture_device.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/capture/video/file_video_capture_device.h" #include <stddef.h> @@ -17,6 +12,7 @@ #include <string_view> #include <utility> +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/functional/bind.h" #include "base/location.h" @@ -218,7 +214,7 @@ } std::string header(kY4MHeaderMaxSize, '\0'); - file_->Read(0, &header[0], header.size()); + UNSAFE_TODO(file_->Read(0, &header[0], header.size())); const size_t header_end = header.find(kY4MSimpleFrameDelimiter); CHECK_NE(header_end, header.npos); @@ -358,12 +354,12 @@ std::make_unique<uint8_t[]>(i420_buffer_size); uint8_t* dst_yp = jpeg_to_i420_buffer_.get(); - uint8_t* dst_up = + uint8_t* dst_up = UNSAFE_TODO( dst_yp + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, frame_size) - .GetArea(); - uint8_t* dst_vp = + .GetArea()); + uint8_t* dst_vp = UNSAFE_TODO( dst_up + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 1, frame_size) - .GetArea(); + .GetArea()); int dst_yp_stride = frame_size.width(); int dst_up_stride = dst_yp_stride / 2; int dst_vp_stride = dst_yp_stride / 2; @@ -408,12 +404,12 @@ std::vector<uint8_t> crop_frame(crop_buffer_size); uint8_t* crop_yp = crop_frame.data(); - uint8_t* crop_up = + uint8_t* crop_up = UNSAFE_TODO( crop_yp + - VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, crop_size).GetArea(); - uint8_t* crop_vp = + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, crop_size).GetArea()); + uint8_t* crop_vp = UNSAFE_TODO( crop_up + - VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 1, crop_size).GetArea(); + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 1, crop_size).GetArea()); int crop_yp_stride = crop_width; int crop_up_stride = crop_yp_stride / 2; int crop_vp_stride = crop_yp_stride / 2; @@ -437,12 +433,12 @@ std::vector<uint8_t> scale_frame(scale_buffer_size); uint8_t* scale_yp = scale_frame.data(); - uint8_t* scale_up = + uint8_t* scale_up = UNSAFE_TODO( scale_yp + - VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, scale_size).GetArea(); - uint8_t* scale_vp = + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, scale_size).GetArea()); + uint8_t* scale_vp = UNSAFE_TODO( scale_up + - VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 1, scale_size).GetArea(); + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 1, scale_size).GetArea()); int scale_yp_stride = scale_size.width(); int scale_up_stride = scale_yp_stride / 2; int scale_vp_stride = scale_yp_stride / 2; @@ -682,32 +678,31 @@ } const uint8_t* src_y_plane = ptz_frame.data(); - const uint8_t* src_u_plane = + const uint8_t* src_u_plane = UNSAFE_TODO( ptz_frame.data() + - VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, buffer_size).GetArea(); - const uint8_t* src_v_plane = + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, buffer_size).GetArea()); + const uint8_t* src_v_plane = UNSAFE_TODO( ptz_frame.data() + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, buffer_size).GetArea() + - VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 1, buffer_size).GetArea(); - auto scoped_mapping = shared_image->Map(); - libyuv::I420ToNV12( - src_y_plane, buffer_size.width(), src_u_plane, - buffer_size.width() / 2, src_v_plane, buffer_size.width() / 2, - scoped_mapping->GetMemoryForPlane(0).data(), - scoped_mapping->Stride(0), - scoped_mapping->GetMemoryForPlane(1).data(), - scoped_mapping->Stride(1), buffer_size.width(), buffer_size.height()); + VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 1, buffer_size).GetArea()); + auto scoped_mapping = shared_image->Map(); + libyuv::I420ToNV12( + src_y_plane, buffer_size.width(), src_u_plane, buffer_size.width() / 2, + src_v_plane, buffer_size.width() / 2, + scoped_mapping->GetMemoryForPlane(0).data(), scoped_mapping->Stride(0), + scoped_mapping->GetMemoryForPlane(1).data(), scoped_mapping->Stride(1), + buffer_size.width(), buffer_size.height()); - // When mappable buffer is used, the frame data is opaque to the CPU for - // most of the time. Currently the only supported underlying format is - // NV12. - VideoCaptureFormat buffer_format = ptz_format; - buffer_format.pixel_format = PIXEL_FORMAT_NV12; - client_->OnIncomingCapturedBuffer( - std::move(capture_buffer), buffer_format, current_time, - current_time - first_ref_time_, - /*capture_begin_timestamp=*/std::nullopt, - /*metadata=*/std::nullopt); + // When mappable buffer is used, the frame data is opaque to the CPU for + // most of the time. Currently the only supported underlying format is + // NV12. + VideoCaptureFormat buffer_format = ptz_format; + buffer_format.pixel_format = PIXEL_FORMAT_NV12; + client_->OnIncomingCapturedBuffer(std::move(capture_buffer), buffer_format, + current_time, + current_time - first_ref_time_, + /*capture_begin_timestamp=*/std::nullopt, + /*metadata=*/std::nullopt); } else { // Leave the color space unset for compatibility purposes but this // information should be retrieved from the container when possible.
diff --git a/media/capture/video/linux/v4l2_capture_delegate_gpu_helper.cc b/media/capture/video/linux/v4l2_capture_delegate_gpu_helper.cc index c071fa6..0af842ed 100644 --- a/media/capture/video/linux/v4l2_capture_delegate_gpu_helper.cc +++ b/media/capture/video/linux/v4l2_capture_delegate_gpu_helper.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/capture/video/linux/v4l2_capture_delegate_gpu_helper.h" +#include "base/compiler_specific.h" #include "base/numerics/safe_conversions.h" #include "base/trace_event/trace_event.h" #include "components/viz/common/resources/shared_image_format.h" @@ -215,14 +211,14 @@ } uint8_t* i420_y = i420_buffer_.data(); - uint8_t* i420_u = + uint8_t* i420_u = UNSAFE_TODO( i420_y + VideoFrame::PlaneSize(VideoPixelFormat::PIXEL_FORMAT_I420, VideoFrame::Plane::kY, dimensions) - .GetArea(); - uint8_t* i420_v = + .GetArea()); + uint8_t* i420_v = UNSAFE_TODO( i420_u + VideoFrame::PlaneSize(VideoPixelFormat::PIXEL_FORMAT_I420, VideoFrame::Plane::kU, dimensions) - .GetArea(); + .GetArea()); std::vector<size_t> i420_strides = VideoFrame::ComputeStrides( VideoPixelFormat::PIXEL_FORMAT_I420, dimensions); const int i420_stride_y = @@ -261,7 +257,7 @@ int dst_stride_uv) { const int src_width = capture_format.frame_size.width(); const int src_height = capture_format.frame_size.height(); - const uint8_t* src_uv = sample + (src_width * src_height); + const uint8_t* src_uv = UNSAFE_TODO(sample + (src_width * src_height)); const libyuv::FourCC fourcc = VideoCaptureFormatToLibyuvFourcc(capture_format);
diff --git a/media/capture/video/linux/v4l2_capture_delegate_gpu_helper_unittest.cc b/media/capture/video/linux/v4l2_capture_delegate_gpu_helper_unittest.cc index c44cf4d..2e082b0 100644 --- a/media/capture/video/linux/v4l2_capture_delegate_gpu_helper_unittest.cc +++ b/media/capture/video/linux/v4l2_capture_delegate_gpu_helper_unittest.cc
@@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "media/capture/video/linux/v4l2_capture_delegate_gpu_helper.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/test/bind.h" #include "base/test/task_environment.h" #include "gpu/command_buffer/client/test_shared_image_interface.h" @@ -162,7 +159,7 @@ size_t size = ftell(fp); sample->resize(size); fseek(fp, 0, SEEK_SET); - size_t read_size = fread(sample->data(), 1, size, fp); + size_t read_size = UNSAFE_TODO(fread(sample->data(), 1, size, fp)); EXPECT_EQ(size, read_size); fclose(fp); } @@ -209,7 +206,7 @@ // corrupt the sample data uint8_t* data = sample->data(); for (size_t i = 0; i < 0xff && i < sample->size(); i++) { - data[i] = 0xff; + UNSAFE_TODO(data[i]) = 0xff; } }
diff --git a/media/cast/encoding/av1_encoder.cc b/media/cast/encoding/av1_encoder.cc index ebdfabc..ff08a9c 100644 --- a/media/cast/encoding/av1_encoder.cc +++ b/media/cast/encoding/av1_encoder.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/cast/encoding/av1_encoder.h" +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/strings/strcat.h" #include "media/base/video_encoder_metrics_provider.h" @@ -292,10 +288,10 @@ encoded_frame->rtp_timestamp = ToRtpTimeTicks(video_frame->timestamp(), kVideoFrequency); encoded_frame->reference_time = reference_time; - encoded_frame->data = - base::HeapArray<uint8_t>::CopiedFrom(base::span<const uint8_t>( + encoded_frame->data = base::HeapArray<uint8_t>::CopiedFrom( + UNSAFE_TODO(base::span<const uint8_t>( static_cast<const uint8_t*>(pkt->data.frame.buf), - pkt->data.frame.sz)); + pkt->data.frame.sz))); break; // Done, since all data is provided in one CX_FRAME_PKT packet. } if (encoded_frame->data.empty()) {
diff --git a/media/cast/encoding/external_video_encoder.cc b/media/cast/encoding/external_video_encoder.cc index 9d37ce5..0b43baa 100644 --- a/media/cast/encoding/external_video_encoder.cc +++ b/media/cast/encoding/external_video_encoder.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/cast/encoding/external_video_encoder.h" #include <array> @@ -16,6 +11,7 @@ #include <utility> #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/logging.h" @@ -443,8 +439,9 @@ std::string data = stream_header_.str(); std::ostringstream().swap(stream_header_); data.append(output_buffer_memory, metadata.payload_size_bytes); - encoded_frame->data = base::HeapArray<uint8_t>::CopiedFrom(base::span( - reinterpret_cast<const uint8_t*>(data.c_str()), data.size())); + encoded_frame->data = + base::HeapArray<uint8_t>::CopiedFrom(UNSAFE_TODO(base::span( + reinterpret_cast<const uint8_t*>(data.c_str()), data.size()))); // If FRAME_DURATION metadata was provided in the source VideoFrame, // compute the utilization metrics. @@ -912,11 +909,13 @@ const int row_skip = size.height() / rows_in_subset; int y = 0; for (int i = 0; i < rows_in_subset; ++i, y += row_skip) { - const uint8_t* const row_begin = frame.visible_data(VideoFrame::Plane::kY) + - y * frame.stride(VideoFrame::Plane::kY); - const uint8_t* const row_end = row_begin + size.width(); + const uint8_t* const row_begin = + UNSAFE_TODO(frame.visible_data(VideoFrame::Plane::kY) + + y * frame.stride(VideoFrame::Plane::kY)); + const uint8_t* const row_end = UNSAFE_TODO(row_begin + size.width()); int left_hand_pixel_value = static_cast<int>(*row_begin); - for (const uint8_t* p = row_begin + 1; p < row_end; ++p) { + for (const uint8_t* p = UNSAFE_TODO(row_begin + 1); p < row_end; + UNSAFE_TODO(++p)) { const int right_hand_pixel_value = static_cast<int>(*p); const int difference = right_hand_pixel_value - left_hand_pixel_value; const int histogram_index = difference + 255; @@ -926,8 +925,8 @@ // Copy the row of pixels into the buffer. This will be used when // generating histograms for future delta frames. - memcpy(last_frame_pixel_buffer_.get() + i * size.width(), row_begin, - size.width()); + UNSAFE_TODO(memcpy(last_frame_pixel_buffer_.get() + i * size.width(), + row_begin, size.width())); } // Estimate a quantizer value depending on the difference data in the @@ -959,13 +958,14 @@ const int row_skip = size.height() / rows_in_subset; int y = 0; for (int i = 0; i < rows_in_subset; ++i, y += row_skip) { - const uint8_t* const row_begin = frame.visible_data(VideoFrame::Plane::kY) + - y * frame.stride(VideoFrame::Plane::kY); - const uint8_t* const row_end = row_begin + size.width(); + const uint8_t* const row_begin = + UNSAFE_TODO(frame.visible_data(VideoFrame::Plane::kY) + + y * frame.stride(VideoFrame::Plane::kY)); + const uint8_t* const row_end = UNSAFE_TODO(row_begin + size.width()); uint8_t* const last_frame_row_begin = - last_frame_pixel_buffer_.get() + i * size.width(); + UNSAFE_TODO(last_frame_pixel_buffer_.get() + i * size.width()); for (const uint8_t *p = row_begin, *q = last_frame_row_begin; p < row_end; - ++p, ++q) { + UNSAFE_TODO(++p), UNSAFE_TODO(++q)) { const int difference = static_cast<int>(*p) - static_cast<int>(*q); const int histogram_index = difference + 255; ++histogram[histogram_index]; @@ -973,7 +973,7 @@ // Copy the row of pixels into the buffer. This will be used when // generating histograms for future delta frames. - memcpy(last_frame_row_begin, row_begin, size.width()); + UNSAFE_TODO(memcpy(last_frame_row_begin, row_begin, size.width())); } // Estimate a quantizer value depending on the difference data in the @@ -997,7 +997,8 @@ DCHECK_LT(0, num_samples); double entropy = 0.0; for (size_t i = 0; i < histogram_size; ++i) { - const double probability = static_cast<double>(histogram[i]) / num_samples; + const double probability = + static_cast<double>(UNSAFE_TODO(histogram[i])) / num_samples; if (probability > 0.0) { entropy = entropy - probability * std::log2(probability); }
diff --git a/media/cast/encoding/external_video_encoder_unittest.cc b/media/cast/encoding/external_video_encoder_unittest.cc index 7f077fc..0502a1cde 100644 --- a/media/cast/encoding/external_video_encoder_unittest.cc +++ b/media/cast/encoding/external_video_encoder_unittest.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/cast/encoding/external_video_encoder.h" #include <stdint.h> +#include "base/compiler_specific.h" #include "build/build_config.h" #include "media/base/video_frame.h" #include "testing/gtest/include/gtest/gtest.h" @@ -24,9 +20,9 @@ scoped_refptr<VideoFrame> result = VideoFrame::CreateFrame( PIXEL_FORMAT_I420, size, gfx::Rect(size), size, base::TimeDelta()); for (int y = 0, y_end = size.height(); y < y_end; ++y) { - memcpy(result->GetWritableVisibleData(VideoFrame::Plane::kY) + - y * result->stride(VideoFrame::Plane::kY), - y_plane_data + y * size.width(), size.width()); + UNSAFE_TODO(memcpy(result->GetWritableVisibleData(VideoFrame::Plane::kY) + + y * result->stride(VideoFrame::Plane::kY), + y_plane_data + y * size.width(), size.width())); } return result; } @@ -39,7 +35,7 @@ const gfx::Size frame_size(320, 180); const auto black_frame_data = std::make_unique<uint8_t[]>(frame_size.GetArea()); - memset(black_frame_data.get(), 0, frame_size.GetArea()); + UNSAFE_TODO(memset(black_frame_data.get(), 0, frame_size.GetArea())); const scoped_refptr<VideoFrame> black_frame = CreateFrame(black_frame_data.get(), frame_size); @@ -55,7 +51,7 @@ const auto checkerboard_frame_data = std::make_unique<uint8_t[]>(frame_size.GetArea()); for (int i = 0, end = frame_size.GetArea(); i < end; ++i) { - checkerboard_frame_data.get()[i] = (((i % 2) == 0) ? 0 : 255); + UNSAFE_TODO(checkerboard_frame_data.get()[i]) = (((i % 2) == 0) ? 0 : 255); } const scoped_refptr<VideoFrame> checkerboard_frame = CreateFrame(checkerboard_frame_data.get(), frame_size); @@ -74,7 +70,8 @@ std::make_unique<uint8_t[]>(frame_size.GetArea()); for (int j = 0, end = frame_size.GetArea(); j < end; ++j) { rand_seed = (1103515245u * rand_seed + 12345u) % (1u << 31); - random_frame_data.get()[j] = static_cast<uint8_t>(rand_seed & 0xff); + UNSAFE_TODO(random_frame_data.get()[j]) = + static_cast<uint8_t>(rand_seed & 0xff); } const scoped_refptr<VideoFrame> random_frame = CreateFrame(random_frame_data.get(), frame_size);
diff --git a/media/cast/encoding/vpx_encoder.cc b/media/cast/encoding/vpx_encoder.cc index 53b7e160..7226784 100644 --- a/media/cast/encoding/vpx_encoder.cc +++ b/media/cast/encoding/vpx_encoder.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/cast/encoding/vpx_encoder.h" +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/strings/strcat.h" #include "media/base/media_switches.h" @@ -278,7 +274,8 @@ // with the same stride, shifted by one byte. vpx_image.planes[VPX_PLANE_U] = const_cast<uint8_t*>( video_frame->visible_data(VideoFrame::Plane::kUV)); - vpx_image.planes[VPX_PLANE_V] = vpx_image.planes[VPX_PLANE_U] + 1; + vpx_image.planes[VPX_PLANE_V] = + UNSAFE_TODO(vpx_image.planes[VPX_PLANE_U] + 1); vpx_image.stride[VPX_PLANE_Y] = video_frame->stride(VideoFrame::Plane::kY); vpx_image.stride[VPX_PLANE_U] = @@ -349,8 +346,9 @@ encoded_frame->rtp_timestamp = ToRtpTimeTicks(video_frame->timestamp(), kVideoFrequency); encoded_frame->reference_time = reference_time; - encoded_frame->data = base::HeapArray<uint8_t>::CopiedFrom(base::span( - static_cast<const uint8_t*>(pkt->data.frame.buf), pkt->data.frame.sz)); + encoded_frame->data = base::HeapArray<uint8_t>::CopiedFrom( + UNSAFE_TODO(base::span(static_cast<const uint8_t*>(pkt->data.frame.buf), + pkt->data.frame.sz))); break; // Done, since all data is provided in one CX_FRAME_PKT packet. } if (encoded_frame->data.empty()) {
diff --git a/media/cast/openscreen/remoting_proto_utils_unittest.cc b/media/cast/openscreen/remoting_proto_utils_unittest.cc index 6a248ca..b4d9375 100644 --- a/media/cast/openscreen/remoting_proto_utils_unittest.cc +++ b/media/cast/openscreen/remoting_proto_utils_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/cast/openscreen/remoting_proto_utils.h" #include <memory> @@ -14,6 +9,7 @@ #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/memory/ref_counted.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" @@ -162,13 +158,13 @@ // NOTE: fields will all be initialized with 0xcd. Forcing the conversion to // properly assigned them. Since nested structs have strings, memsetting must // be done infividually for them. - memset(&converted, 0xcd, - sizeof(converted) - sizeof(media::AudioPipelineInfo) - - sizeof(media::VideoPipelineInfo)); - memset(&converted.audio_pipeline_info, 0xcd, - sizeof(media::AudioPipelineInfo)); - memset(&converted.video_pipeline_info, 0xcd, - sizeof(media::VideoPipelineInfo)); + UNSAFE_TODO(memset(&converted, 0xcd, + sizeof(converted) - sizeof(media::AudioPipelineInfo) - + sizeof(media::VideoPipelineInfo))); + UNSAFE_TODO(memset(&converted.audio_pipeline_info, 0xcd, + sizeof(media::AudioPipelineInfo))); + UNSAFE_TODO(memset(&converted.video_pipeline_info, 0xcd, + sizeof(media::VideoPipelineInfo))); ConvertProtoToPipelineStatistics(pb_stats, &converted);
diff --git a/media/cdm/aes_decryptor_fuzztests.cc b/media/cdm/aes_decryptor_fuzztests.cc index 0304376..1d8f3e7e 100644 --- a/media/cdm/aes_decryptor_fuzztests.cc +++ b/media/cdm/aes_decryptor_fuzztests.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include <algorithm> #include <cstdint> #include <string> #include <vector> +#include "base/compiler_specific.h" #include "base/functional/callback_helpers.h" #include "base/memory/scoped_refptr.h" #include "base/test/bind.h" @@ -255,7 +251,8 @@ // encrypted buffer. auto encrypted_buffer = base::MakeRefCounted<media::DecoderBuffer>(data.size()); - memcpy(encrypted_buffer->writable_data(), data.data(), data.size()); + UNSAFE_TODO( + memcpy(encrypted_buffer->writable_data(), data.data(), data.size())); std::string key_id_string(std::begin(key_id), std::end(key_id)); std::string iv_string(std::begin(kIv), std::end(kIv)); encrypted_buffer->set_decrypt_config(media::DecryptConfig::CreateCencConfig(
diff --git a/media/cdm/cdm_adapter.cc b/media/cdm/cdm_adapter.cc index 5dd26aa..2e8ca52 100644 --- a/media/cdm/cdm_adapter.cc +++ b/media/cdm/cdm_adapter.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/cdm/cdm_adapter.h" #include <stddef.h> @@ -742,7 +737,7 @@ CdmKeysInfo keys; keys.reserve(keys_info_count); for (uint32_t i = 0; i < keys_info_count; ++i) { - const auto& info = keys_info[i]; + const auto& info = UNSAFE_TODO(keys_info[i]); keys.push_back(std::make_unique<CdmKeyInformation>( info.key_id, info.key_id_size, ToMediaKeyStatus(info.status), info.system_code)); @@ -780,7 +775,7 @@ CdmKeysInfo keys; keys.reserve(keys_info_count); for (uint32_t i = 0; i < keys_info_count; ++i) { - const auto& info = keys_info[i]; + const auto& info = UNSAFE_TODO(keys_info[i]); keys.push_back(std::make_unique<CdmKeyInformation>( info.key_id, info.key_id_size, ToMediaKeyStatus(info.status), info.system_code)); @@ -906,7 +901,8 @@ const uint8_t* message_ptr = reinterpret_cast<const uint8_t*>(message); session_message_cb_.Run( session_id_str, ToMediaMessageType(message_type), - std::vector<uint8_t>(message_ptr, message_ptr + message_size)); + std::vector<uint8_t>(message_ptr, + UNSAFE_TODO(message_ptr + message_size))); } void CdmAdapter::OnExpirationChange(const char* session_id, @@ -1189,9 +1185,10 @@ if (bytes_left < kHeaderSize) return false; - memcpy(×tamp, data, sizeof(timestamp)); - memcpy(&frame_size, data + sizeof(timestamp), sizeof(frame_size)); - data += kHeaderSize; + UNSAFE_TODO(memcpy(×tamp, data, sizeof(timestamp))); + UNSAFE_TODO( + memcpy(&frame_size, data + sizeof(timestamp), sizeof(frame_size))); + UNSAFE_TODO(data += kHeaderSize); bytes_left -= kHeaderSize; // We should *not* have empty frames in the list. @@ -1204,7 +1201,7 @@ // one in the case of interleaved data. const int size_per_channel = frame_size / audio_channel_count; for (int i = 0; i < audio_channel_count; ++i) - channel_ptrs[i] = data + i * size_per_channel; + channel_ptrs[i] = UNSAFE_TODO(data + i * size_per_channel); const int frame_count = frame_size / audio_bytes_per_frame; scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom( @@ -1213,7 +1210,7 @@ base::Microseconds(timestamp), pool_); result_frames->push_back(frame); - data += frame_size; + UNSAFE_TODO(data += frame_size); bytes_left -= frame_size; } while (bytes_left > 0);
diff --git a/media/cdm/library_cdm/clear_key_cdm/cdm_file_adapter.cc b/media/cdm/library_cdm/clear_key_cdm/cdm_file_adapter.cc index 383b3c9..f20350b 100644 --- a/media/cdm/library_cdm/clear_key_cdm/cdm_file_adapter.cc +++ b/media/cdm/library_cdm/clear_key_cdm/cdm_file_adapter.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/cdm/library_cdm/clear_key_cdm/cdm_file_adapter.h" #include <memory> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/logging.h" #include "media/cdm/library_cdm/cdm_host_proxy.h" @@ -72,7 +68,7 @@ uint32_t data_size) { std::move(read_cb_).Run( status == FileIOClient::Status::kSuccess && data_size > 0, - std::vector<uint8_t>(data, data + data_size)); + std::vector<uint8_t>(data, UNSAFE_TODO(data + data_size))); } void CdmFileAdapter::OnWriteComplete(cdm::FileIOClient::Status status) {
diff --git a/media/cdm/library_cdm/clear_key_cdm/cdm_file_io_test.cc b/media/cdm/library_cdm/clear_key_cdm/cdm_file_io_test.cc index 11b19a4..31b01eb2 100644 --- a/media/cdm/library_cdm/clear_key_cdm/cdm_file_io_test.cc +++ b/media/cdm/library_cdm/clear_key_cdm/cdm_file_io_test.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/cdm/library_cdm/clear_key_cdm/cdm_file_io_test.h" #include <algorithm> #include <limits> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/logging.h" @@ -615,10 +611,10 @@ // If |a| specifies a data2, compare it first. If the size matches, compare // the contents. if (a.data2 && b.data_size == a.data2_size) - return std::equal(a.data2, a.data2 + a.data2_size, b.data); + return std::equal(a.data2, UNSAFE_TODO(a.data2 + a.data2_size), b.data); return (a.data_size == b.data_size && - std::equal(a.data, a.data + a.data_size, b.data)); + std::equal(a.data, UNSAFE_TODO(a.data + a.data_size), b.data)); } void FileIOTest::RunNextStep() {
diff --git a/media/cdm/library_cdm/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc b/media/cdm/library_cdm/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc index 2718a98..0213ea3 100644 --- a/media/cdm/library_cdm/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc +++ b/media/cdm/library_cdm/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/cdm/library_cdm/clear_key_cdm/ffmpeg_cdm_audio_decoder.h" #include <stddef.h> @@ -14,6 +9,7 @@ #include <algorithm> #include <memory> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" @@ -85,9 +81,10 @@ codec_context->extradata_size = config.extra_data_size; codec_context->extradata = reinterpret_cast<uint8_t*>( av_malloc(config.extra_data_size + AV_INPUT_BUFFER_PADDING_SIZE)); - memcpy(codec_context->extradata, config.extra_data, config.extra_data_size); - memset(codec_context->extradata + config.extra_data_size, '\0', - AV_INPUT_BUFFER_PADDING_SIZE); + UNSAFE_TODO(memcpy(codec_context->extradata, config.extra_data, + config.extra_data_size)); + UNSAFE_TODO(memset(codec_context->extradata + config.extra_data_size, '\0', + AV_INPUT_BUFFER_PADDING_SIZE)); } else { codec_context->extradata = nullptr; codec_context->extradata_size = 0; @@ -123,16 +120,16 @@ case cdm::kAudioFormatS16: case cdm::kAudioFormatS32: case cdm::kAudioFormatF32: - memcpy(output_buffer, av_frame.data[0], decoded_audio_size); + UNSAFE_TODO(memcpy(output_buffer, av_frame.data[0], decoded_audio_size)); break; case cdm::kAudioFormatPlanarS16: case cdm::kAudioFormatPlanarF32: { const int decoded_size_per_channel = decoded_audio_size / av_frame.ch_layout.nb_channels; for (int i = 0; i < av_frame.ch_layout.nb_channels; ++i) { - memcpy(output_buffer, av_frame.extended_data[i], - decoded_size_per_channel); - output_buffer += decoded_size_per_channel; + UNSAFE_TODO(memcpy(output_buffer, av_frame.extended_data[i], + decoded_size_per_channel)); + UNSAFE_TODO(output_buffer += decoded_size_per_channel); } break; } @@ -285,9 +282,9 @@ uint8_t* output_buffer = decoded_frames->FrameBuffer()->Data(); SerializeInt64(output_timestamp_helper_->GetTimestamp().InMicroseconds(), output_buffer); - output_buffer += sizeof(int64_t); + UNSAFE_TODO(output_buffer += sizeof(int64_t)); SerializeInt64(total_size, output_buffer); - output_buffer += sizeof(int64_t); + UNSAFE_TODO(output_buffer += sizeof(int64_t)); output_timestamp_helper_->AddFrames(total_size / bytes_per_frame_); for (auto& frame : audio_frames) { @@ -314,7 +311,7 @@ << "Decoder didn't output full frames"; CopySamples(cdm_format, decoded_audio_size, *frame, output_buffer); - output_buffer += decoded_audio_size; + UNSAFE_TODO(output_buffer += decoded_audio_size); } return cdm::kSuccess; @@ -344,7 +341,7 @@ } void FFmpegCdmAudioDecoder::SerializeInt64(int64_t value, uint8_t* dest) { - memcpy(dest, &value, sizeof(value)); + UNSAFE_TODO(memcpy(dest, &value, sizeof(value))); } } // namespace media
diff --git a/media/filters/audio_file_reader.cc b/media/filters/audio_file_reader.cc index 70a8ea6..503e0887 100644 --- a/media/filters/audio_file_reader.cc +++ b/media/filters/audio_file_reader.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/audio_file_reader.h" #include <stddef.h> @@ -15,6 +10,7 @@ #include <memory> #include <vector> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/logging.h" @@ -72,7 +68,7 @@ codec_context_.reset(); bool found_stream = false; for (size_t i = 0; i < format_context->nb_streams; ++i) { - if (format_context->streams[i]->codecpar->codec_type == + if (UNSAFE_TODO(format_context->streams[i])->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { stream_index_ = i; found_stream = true; @@ -84,8 +80,8 @@ return false; // Get the codec context. - codec_context_ = - AVStreamToAVCodecContext(format_context->streams[stream_index_]); + codec_context_ = AVStreamToAVCodecContext( + UNSAFE_TODO(format_context->streams[stream_index_])); if (!codec_context_) return false; @@ -232,10 +228,11 @@ // MP3 packets may be zero-padded according to ffmpeg, so trim until we // have the packet. - uint8_t* packet_end = output_packet->data + output_packet->size; + uint8_t* packet_end = + UNSAFE_TODO(output_packet->data + output_packet->size); uint8_t* header_start = output_packet->data; while (header_start < packet_end && !*header_start) { - ++header_start; + UNSAFE_TODO(++header_start); } if (packet_end - header_start < MPEG1AudioStreamParser::kHeaderSize || @@ -279,7 +276,7 @@ // adjust the duration downward by however much exists before zero. if (audio_codec_ == AudioCodec::kAAC && frame->duration) { const base::TimeDelta pkt_duration = ConvertFromTimeBase( - glue_->format_context()->streams[stream_index_]->time_base, + UNSAFE_TODO(glue_->format_context()->streams[stream_index_])->time_base, frame->duration + std::min(static_cast<int64_t>(0), frame->pts)); const base::TimeDelta frame_duration = base::Seconds(frames_read / static_cast<double>(sample_rate_)); @@ -308,9 +305,9 @@ reinterpret_cast<float*>(frame->data[0]), frames_read); } else if (codec_context_->sample_fmt == AV_SAMPLE_FMT_FLTP) { for (int ch = 0; ch < audio_bus->channels(); ++ch) { - audio_bus->channel_span(ch).copy_from_nonoverlapping( + audio_bus->channel_span(ch).copy_from_nonoverlapping(UNSAFE_TODO( base::span(reinterpret_cast<float*>(frame->extended_data[ch]), - static_cast<size_t>(frames_read))); + static_cast<size_t>(frames_read)))); } } else { int bytes_per_sample = av_get_bytes_per_sample(codec_context_->sample_fmt); @@ -352,7 +349,7 @@ } const AVStream* AudioFileReader::GetAVStreamForTesting() const { - return glue_->format_context()->streams[stream_index_]; + return UNSAFE_TODO(glue_->format_context()->streams[stream_index_]); } } // namespace media
diff --git a/media/filters/audio_renderer_algorithm.cc b/media/filters/audio_renderer_algorithm.cc index f74d59b..f2fadc2 100644 --- a/media/filters/audio_renderer_algorithm.cc +++ b/media/filters/audio_renderer_algorithm.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/audio_renderer_algorithm.h" #include <algorithm> #include <cmath> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" @@ -525,16 +521,17 @@ continue; const float* const ch_opt_frame = optimal_block_->channel_span(k).data(); - float* ch_output = - wsola_output_->channel_span(k).data() + num_complete_frames_; + float* ch_output = UNSAFE_TODO(wsola_output_->channel_span(k).data() + + num_complete_frames_); for (int n = 0; n < ola_hop_size_; ++n) { - ch_output[n] = ch_output[n] * ola_window_[ola_hop_size_ + n] + - ch_opt_frame[n] * ola_window_[n]; + UNSAFE_TODO(ch_output[n]) = + UNSAFE_TODO(ch_output[n]) * ola_window_[ola_hop_size_ + n] + + UNSAFE_TODO(ch_opt_frame[n]) * ola_window_[n]; } // Copy the second half to the output. - memcpy(&ch_output[ola_hop_size_], &ch_opt_frame[ola_hop_size_], - sizeof(*ch_opt_frame) * ola_hop_size_); + UNSAFE_TODO(memcpy(&ch_output[ola_hop_size_], &ch_opt_frame[ola_hop_size_], + sizeof(*ch_opt_frame) * ola_hop_size_)); } num_complete_frames_ += ola_hop_size_; @@ -584,7 +581,8 @@ if (!channel_mask_[k]) continue; float* ch = wsola_output_->channel_span(k).data(); - memmove(ch, &ch[rendered_frames], sizeof(*ch) * frames_to_move); + UNSAFE_TODO( + memmove(ch, &ch[rendered_frames], sizeof(*ch) * frames_to_move)); } num_complete_frames_ -= rendered_frames; return rendered_frames; @@ -642,8 +640,10 @@ float* ch_opt = optimal_block_->channel_span(k).data(); const float* const ch_target = target_block_->channel_span(k).data(); for (int n = 0; n < ola_window_size_; ++n) { - ch_opt[n] = ch_opt[n] * transition_window_[n] + - ch_target[n] * transition_window_[ola_window_size_ + n]; + UNSAFE_TODO(ch_opt[n]) = + UNSAFE_TODO(ch_opt[n]) * transition_window_[n] + + UNSAFE_TODO(ch_target[n]) * + transition_window_[ola_window_size_ + n]; } } }
diff --git a/media/filters/audio_renderer_algorithm_unittest.cc b/media/filters/audio_renderer_algorithm_unittest.cc index 2ca53d09..2c940e7 100644 --- a/media/filters/audio_renderer_algorithm_unittest.cc +++ b/media/filters/audio_renderer_algorithm_unittest.cc
@@ -8,11 +8,6 @@ // correct rate. We always pass in a very large destination buffer with the // expectation that FillBuffer() will fill as much as it can but no more. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/audio_renderer_algorithm.h" #include <stddef.h> @@ -24,6 +19,7 @@ #include <memory> #include <vector> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "media/base/audio_buffer.h" @@ -55,7 +51,7 @@ pulse = -pulse; k = 0; } - data[n] = pulse; + UNSAFE_TODO(data[n]) = pulse; } // Fill forward from |offset| towards the end, starting with 1, alternating @@ -66,7 +62,7 @@ pulse = -pulse; k = 0; } - data[n] = pulse; + UNSAFE_TODO(data[n]) = pulse; } } @@ -203,7 +199,7 @@ bool VerifyAudioData(AudioBus* bus, int offset, int frames, float value) { for (int ch = 0; ch < bus->channels(); ++ch) { for (int i = offset; i < offset + frames; ++i) { - if (bus->channel(ch)[i] != value) { + if (UNSAFE_TODO(bus->channel(ch)[i]) != value) { return false; } } @@ -422,9 +418,10 @@ // Because of overlap-and-add we might have round off error. for (int k = 0; k < kPulseWidthSamples; ++k) { - ASSERT_NEAR(reinterpret_cast<float*>(channel_data[m])[k], - pulse_ch[k], kTolerance) << " loop " << n - << " channel/sample " << m << "/" << k; + UNSAFE_TODO( + ASSERT_NEAR(reinterpret_cast<float*>(channel_data[m])[k], + pulse_ch[k], kTolerance)) + << " loop " << n << " channel/sample " << m << "/" << k; } } } @@ -706,8 +703,8 @@ // Fill up both channels. for (int n = 0; n < kFrames; ++n) { - ch_left[n] = n; - ch_right[n] = kFrames - 1 - n; + UNSAFE_TODO(ch_left[n]) = n; + UNSAFE_TODO(ch_right[n]) = kFrames - 1 - n; } internal::MultiChannelMovingBlockEnergies(a.get(), kFramesPerBlock, @@ -717,14 +714,16 @@ for (int n = 0; n < kNumBlocks; ++n) { float expected_energy = 0; for (int k = 0; k < kFramesPerBlock; ++k) - expected_energy += ch_left[n + k] * ch_left[n + k]; + expected_energy += + UNSAFE_TODO(ch_left[n + k]) * UNSAFE_TODO(ch_left[n + k]); // Left (first) channel. EXPECT_FLOAT_EQ(expected_energy, energies[2 * n]); expected_energy = 0; for (int k = 0; k < kFramesPerBlock; ++k) - expected_energy += ch_right[n + k] * ch_right[n + k]; + expected_energy += + UNSAFE_TODO(ch_right[n + k]) * UNSAFE_TODO(ch_right[n + k]); // Second (right) channel. EXPECT_FLOAT_EQ(expected_energy, energies[2 * n + 1]); @@ -744,9 +743,9 @@ std::unique_ptr<AudioBus> search_region = AudioBus::Create(kChannels, kFramesInSearchRegion); float* ch = search_region->channel(0); - memcpy(ch, ch_0, sizeof(float) * kFramesInSearchRegion); + UNSAFE_TODO(memcpy(ch, ch_0, sizeof(float) * kFramesInSearchRegion)); ch = search_region->channel(1); - memcpy(ch, ch_1, sizeof(float) * kFramesInSearchRegion); + UNSAFE_TODO(memcpy(ch, ch_1, sizeof(float) * kFramesInSearchRegion)); const int kFramePerBlock = 4; float target_0[] = { 1.0f, 1.0f, 1.0f, 0.0f }; @@ -758,9 +757,9 @@ std::unique_ptr<AudioBus> target = AudioBus::Create(kChannels, kFramePerBlock); ch = target->channel(0); - memcpy(ch, target_0, sizeof(float) * kFramePerBlock); + UNSAFE_TODO(memcpy(ch, target_0, sizeof(float) * kFramePerBlock)); ch = target->channel(1); - memcpy(ch, target_1, sizeof(float) * kFramePerBlock); + UNSAFE_TODO(memcpy(ch, target_1, sizeof(float) * kFramePerBlock)); auto energy_target = std::make_unique<float[]>(kChannels); @@ -907,7 +906,7 @@ for (int ch = 0; ch < bus->channels(); ++ch) { double sum = 0; for (int i = 0; i < bus->frames(); ++i) - sum += bus->channel(ch)[i]; + sum += UNSAFE_TODO(bus->channel(ch)[i]); if (ch % 2 == 1) ASSERT_EQ(sum, 0); else @@ -923,7 +922,7 @@ for (int ch = 0; ch < bus->channels(); ++ch) { double sum = 0; for (int i = 0; i < bus->frames(); ++i) - sum += bus->channel(ch)[i]; + sum += UNSAFE_TODO(bus->channel(ch)[i]); ASSERT_NE(sum, 0); } }
diff --git a/media/filters/blocking_url_protocol.cc b/media/filters/blocking_url_protocol.cc index d76e7b32..08ae2e1f 100644 --- a/media/filters/blocking_url_protocol.cc +++ b/media/filters/blocking_url_protocol.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/blocking_url_protocol.h" #include <stddef.h> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread_restrictions.h" @@ -77,8 +73,9 @@ index = base::WaitableEvent::WaitMany(events, std::size(events)); } - if (events[index] == &aborted_) + if (UNSAFE_TODO(events[index]) == &aborted_) { return AVERROR(EIO); + } if (last_read_bytes_ == DataSource::kReadError) { aborted_.Signal();
diff --git a/media/filters/dav1d_video_decoder_unittest.cc b/media/filters/dav1d_video_decoder_unittest.cc index 710daa8..6ec51c5 100644 --- a/media/filters/dav1d_video_decoder_unittest.cc +++ b/media/filters/dav1d_video_decoder_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/filters/dav1d_video_decoder.h" #include <memory> @@ -14,6 +9,7 @@ #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/run_loop.h" @@ -349,9 +345,10 @@ // Write to the Y plane. The memory tools should detect a // use-after-free if the storage was actually removed by pool destruction. - memset(output_frames_.front()->writable_data(VideoFrame::Plane::kY), 0xff, - output_frames_.front()->rows(VideoFrame::Plane::kY) * - output_frames_.front()->stride(VideoFrame::Plane::kY)); + UNSAFE_TODO( + memset(output_frames_.front()->writable_data(VideoFrame::Plane::kY), 0xff, + output_frames_.front()->rows(VideoFrame::Plane::kY) * + output_frames_.front()->stride(VideoFrame::Plane::kY))); } } // namespace media
diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc index 2fd213d..7726bda 100644 --- a/media/filters/ffmpeg_audio_decoder.cc +++ b/media/filters/ffmpeg_audio_decoder.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/ffmpeg_audio_decoder.h" #include <stdint.h> @@ -14,6 +9,7 @@ #include <functional> #include <memory> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/task/bind_post_task.h" @@ -463,7 +459,7 @@ if (number_of_planes <= AV_NUM_DATA_POINTERS) { DCHECK_EQ(frame->extended_data, frame->data); for (int i = 0; i < number_of_planes; ++i) - frame->data[i] = buffer->channel_data()[i]; + UNSAFE_TODO(frame->data[i]) = buffer->channel_data()[i]; } else { // There are more channels than can fit into data[], so allocate // extended_data[] and fill appropriately. @@ -471,9 +467,10 @@ av_malloc(number_of_planes * sizeof(*frame->extended_data))); int i = 0; for (; i < AV_NUM_DATA_POINTERS; ++i) - frame->extended_data[i] = frame->data[i] = buffer->channel_data()[i]; + UNSAFE_TODO(frame->extended_data[i]) = UNSAFE_TODO(frame->data[i]) = + buffer->channel_data()[i]; for (; i < number_of_planes; ++i) - frame->extended_data[i] = buffer->channel_data()[i]; + UNSAFE_TODO(frame->extended_data[i]) = buffer->channel_data()[i]; } // Now create an AVBufferRef for the data just allocated. It will own the
diff --git a/media/filters/file_data_source.cc b/media/filters/file_data_source.cc index a853dbb..6bf39e7 100644 --- a/media/filters/file_data_source.cc +++ b/media/filters/file_data_source.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/file_data_source.h" #include <algorithm> #include <utility> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/functional/callback.h" namespace media { @@ -57,7 +53,7 @@ int64_t clamped_size = std::min(static_cast<int64_t>(size), file_size - position); - memcpy(data, file_.data() + position, clamped_size); + UNSAFE_TODO(memcpy(data, file_.data() + position, clamped_size)); bytes_read_ += clamped_size; std::move(read_cb).Run(clamped_size); }
diff --git a/media/filters/frame_processor_unittest.cc b/media/filters/frame_processor_unittest.cc index d599065..a8c4c326 100644 --- a/media/filters/frame_processor_unittest.cc +++ b/media/filters/frame_processor_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/filters/frame_processor.h" #include <stddef.h>
diff --git a/media/filters/h26x_annex_b_bitstream_builder_unittest.cc b/media/filters/h26x_annex_b_bitstream_builder_unittest.cc index 2eabf37..534dca1a 100644 --- a/media/filters/h26x_annex_b_bitstream_builder_unittest.cc +++ b/media/filters/h26x_annex_b_bitstream_builder_unittest.cc
@@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif +#include "media/filters/h26x_annex_b_bitstream_builder.h" #include <stdint.h> #include "base/bits.h" -#include "media/filters/h26x_annex_b_bitstream_builder.h" +#include "base/compiler_specific.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -24,7 +21,7 @@ got |= (*ptr & 0xff); num_bits -= 8; got <<= (num_bits > 8 ? 8 : num_bits); - ptr++; + UNSAFE_TODO(ptr++); } if (num_bits > 0) { uint64_t temp = (*ptr & 0xff);
diff --git a/media/filters/in_memory_url_protocol.cc b/media/filters/in_memory_url_protocol.cc index 351ef4b..775d649 100644 --- a/media/filters/in_memory_url_protocol.cc +++ b/media/filters/in_memory_url_protocol.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/filters/in_memory_url_protocol.h" +#include "base/compiler_specific.h" #include "media/ffmpeg/ffmpeg_common.h" namespace media { @@ -35,8 +31,9 @@ size = available_bytes; if (size > 0) { - memcpy(data, data_.subspan(base::checked_cast<size_t>(position_)).data(), - size); + UNSAFE_TODO(memcpy( + data, data_.subspan(base::checked_cast<size_t>(position_)).data(), + size)); position_ += size; }
diff --git a/media/filters/in_memory_url_protocol_unittest.cc b/media/filters/in_memory_url_protocol_unittest.cc index cec1deb..f62f6ea4 100644 --- a/media/filters/in_memory_url_protocol_unittest.cc +++ b/media/filters/in_memory_url_protocol_unittest.cc
@@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif +#include "media/filters/in_memory_url_protocol.h" #include <stdint.h> +#include "base/compiler_specific.h" #include "media/ffmpeg/ffmpeg_common.h" -#include "media/filters/in_memory_url_protocol.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -22,7 +19,7 @@ uint8_t out[sizeof(kData)]; EXPECT_EQ(4, protocol.Read(sizeof(out), out)); - EXPECT_EQ(0, memcmp(out, kData.data(), sizeof(out))); + UNSAFE_TODO(EXPECT_EQ(0, memcmp(out, kData.data(), sizeof(out)))); } TEST(InMemoryUrlProtocolTest, ReadWithNegativeSize) {
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc index 218ab67f..8aeb7bc 100644 --- a/media/filters/source_buffer_stream.cc +++ b/media/filters/source_buffer_stream.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/filters/source_buffer_stream.h" #include <algorithm> @@ -15,6 +10,7 @@ #include <sstream> #include <string> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/trace_event/trace_event.h" #include "media/base/demuxer_memory_limit.h" @@ -342,7 +338,7 @@ } else if (itr != buffers.begin()) { // Copy the first key frame and everything after it into // |trimmed_buffers|. - trimmed_buffers.assign(itr, buffers.end()); + UNSAFE_TODO(trimmed_buffers.assign(itr, buffers.end())); buffers_for_new_range = &trimmed_buffers; }
diff --git a/media/formats/hls/media_segment.cc b/media/formats/hls/media_segment.cc index 826026f2..ca47532 100644 --- a/media/formats/hls/media_segment.cc +++ b/media/formats/hls/media_segment.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/hls/media_segment.h" +#include "base/compiler_specific.h" #include "base/numerics/byte_conversions.h" #include "base/strings/string_util.h" #include "base/time/time.h" @@ -56,8 +52,8 @@ std::tie(msb, lsb) = iv.value(); msb = base::ByteSwap(msb); lsb = base::ByteSwap(lsb); - memcpy(write_buffer, &msb, 8); - memcpy(&write_buffer[8], &lsb, 8); + UNSAFE_TODO(memcpy(write_buffer, &msb, 8)); + UNSAFE_TODO(memcpy(&write_buffer[8], &lsb, 8)); return str; }
diff --git a/media/formats/mp4/box_reader.cc b/media/formats/mp4/box_reader.cc index 4aed08a7..5f8fe4f1 100644 --- a/media/formats/mp4/box_reader.cc +++ b/media/formats/mp4/box_reader.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/mp4/box_reader.h" #include <stddef.h> @@ -15,6 +10,7 @@ #include <algorithm> #include <set> +#include "base/compiler_specific.h" #include "base/numerics/byte_conversions.h" #include "media/formats/mp4/box_definitions.h" @@ -231,7 +227,7 @@ bool BoxReader::ReadDisplayMatrix(DisplayMatrix matrix) { for (int i = 0; i < kDisplayMatrixDimension; i++) { - if (!Read4s(&matrix[i])) { + if (!Read4s(&UNSAFE_TODO(matrix[i]))) { return false; } }
diff --git a/media/formats/mp4/es_descriptor.cc b/media/formats/mp4/es_descriptor.cc index 4f581e2f..fc2fc775 100644 --- a/media/formats/mp4/es_descriptor.cc +++ b/media/formats/mp4/es_descriptor.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/mp4/es_descriptor.h" #include <stddef.h> +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "media/base/bit_reader.h" #include "media/formats/mp4/rcheck.h" @@ -84,7 +80,7 @@ #pragma pack(pop) std::vector<uint8_t> esds_data(sizeof(EsDescriptor) + aac_extra_data.size()); - auto* esds = reinterpret_cast<EsDescriptor*>(esds_data.data()); + auto* esds = UNSAFE_TODO(reinterpret_cast<EsDescriptor*>(esds_data.data())); esds->tag = kESDescrTag; EncodeDescriptorSize(
diff --git a/media/formats/mpeg/mpeg1_audio_stream_parser.cc b/media/formats/mpeg/mpeg1_audio_stream_parser.cc index e5f6f5d..4920a715 100644 --- a/media/formats/mpeg/mpeg1_audio_stream_parser.cc +++ b/media/formats/mpeg/mpeg1_audio_stream_parser.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/mpeg/mpeg1_audio_stream_parser.h" #include <array> +#include "base/compiler_specific.h" #include "media/base/media_log.h" namespace media { @@ -260,7 +256,8 @@ // If we don't have enough data available to check, return 0 so frame parsing // will be retried once more data is available. - BitReader reader(data + header_bytes_read, size - header_bytes_read); + BitReader reader(UNSAFE_TODO(data + header_bytes_read), + size - header_bytes_read); if (!reader.SkipBits(xing_header_index * 8) || !reader.ReadBits(sizeof(tag) * 8, &tag)) { return 0;
diff --git a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc b/media/formats/mpeg/mpeg_audio_stream_parser_base.cc index f898450c..e8cb85c 100644 --- a/media/formats/mpeg/mpeg_audio_stream_parser_base.cc +++ b/media/formats/mpeg/mpeg_audio_stream_parser_base.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/mpeg/mpeg_audio_stream_parser_base.h" #include <memory> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/numerics/checked_math.h" @@ -44,7 +40,7 @@ bool was_lf = false; char last_c = '\0'; for (; i < buf_len; ++i) { - char c = buf[i]; + char c = UNSAFE_TODO(buf[i]); if (c == '\n') { if (was_lf) return i + 1; @@ -184,8 +180,8 @@ if (data_size < 4) break; - uint32_t start_code = - data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3]; + uint32_t start_code = data[0] << 24 | UNSAFE_TODO(data[1]) << 16 | + UNSAFE_TODO(data[2]) << 8 | UNSAFE_TODO(data[3]); int bytes_read = 0; bool parsed_metadata = true; if ((start_code & start_code_mask_) == start_code_mask_) { @@ -226,7 +222,7 @@ CHECK_GE(data_size, bytes_read); data_size -= bytes_read; - data += bytes_read; + UNSAFE_TODO(data += bytes_read); bytes_to_pop += bytes_read; end_of_segment = true; } @@ -321,7 +317,8 @@ // TODO(wolenetz/acolwell): Validate and use a common cross-parser TrackId // type and allow multiple audio tracks, if applicable. See // https://crbug.com/341581. - auto data_span = base::span(data, base::checked_cast<size_t>(frame_size)); + auto data_span = + UNSAFE_TODO(base::span(data, base::checked_cast<size_t>(frame_size))); scoped_refptr<StreamParserBuffer> buffer = StreamParserBuffer::CopyFrom( data_span, true, DemuxerStream::AUDIO, kMpegAudioTrackId); buffer->set_timestamp(timestamp_helper_->GetTimestamp()); @@ -340,8 +337,9 @@ if (size < 4) return 0; - if (memcmp("ICY ", data, 4)) + if (UNSAFE_TODO(memcmp("ICY ", data, 4))) { return -1; + } int locate_size = std::min(size, kMaxIcecastHeaderSize); int offset = LocateEndOfHeaders(data, locate_size, 4); @@ -363,7 +361,8 @@ if (size < 4) return 0; - int needed_size = !memcmp(data, "TAG+", 4) ? kID3v1ExtendedSize : kID3v1Size; + int needed_size = + !UNSAFE_TODO(memcmp(data, "TAG+", 4)) ? kID3v1ExtendedSize : kID3v1Size; return (size < needed_size) ? 0 : needed_size; } @@ -421,12 +420,12 @@ int MPEGAudioStreamParserBase::FindNextValidStartCode(const uint8_t* data, int size) { const uint8_t* start = data; - const uint8_t* end = data + size; + const uint8_t* end = UNSAFE_TODO(data + size); while (start < end) { int bytes_left = end - start; - const uint8_t* candidate_start_code = - static_cast<const uint8_t*>(memchr(start, 0xff, bytes_left)); + const uint8_t* candidate_start_code = static_cast<const uint8_t*>( + UNSAFE_TODO(memchr(start, 0xff, bytes_left))); if (!candidate_start_code) return 0; @@ -448,7 +447,7 @@ DCHECK_LE(sync_bytes, sync_size); // Skip over this frame so we can check the next one. - sync += frame_size; + UNSAFE_TODO(sync += frame_size); // Make sure the next frame starts inside the buffer. if (sync >= end) @@ -464,7 +463,7 @@ // One of the frame header parses failed so |candidate_start_code| // did not point to the start of a real frame. Move |start| forward // so we can find the next candidate. - start = candidate_start_code + 1; + start = UNSAFE_TODO(candidate_start_code + 1); continue; }
diff --git a/media/formats/webm/cluster_builder.cc b/media/formats/webm/cluster_builder.cc index a309bd03..9d81423 100644 --- a/media/formats/webm/cluster_builder.cc +++ b/media/formats/webm/cluster_builder.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/cluster_builder.h" #include <memory> #include <utility> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "media/base/data_buffer.h" #include "media/formats/webm/webm_constants.h" @@ -80,9 +76,9 @@ cluster_timecode_ = cluster_timecode; // Write the timecode into the header. - uint8_t* buf = buffer_.data() + kClusterTimecodeOffset; + uint8_t* buf = UNSAFE_TODO(buffer_.data() + kClusterTimecodeOffset); for (int i = 7; i >= 0; --i) { - buf[i] = cluster_timecode & 0xff; + UNSAFE_TODO(buf[i]) = cluster_timecode & 0xff; cluster_timecode >>= 8; } } @@ -98,11 +94,11 @@ ExtendBuffer(bytes_needed); } - uint8_t* buf = buffer_.data() + bytes_used_; + uint8_t* buf = UNSAFE_TODO(buffer_.data() + bytes_used_); int block_offset = bytes_used_; - memcpy(buf, kSimpleBlockHeader, sizeof(kSimpleBlockHeader)); + UNSAFE_TODO(memcpy(buf, kSimpleBlockHeader, sizeof(kSimpleBlockHeader))); UpdateUInt64(block_offset + kSimpleBlockSizeOffset, block_size); - buf += sizeof(kSimpleBlockHeader); + UNSAFE_TODO(buf += sizeof(kSimpleBlockHeader)); WriteBlock(buf, track_num, timecode, flags, data, size); @@ -155,20 +151,20 @@ ExtendBuffer(bytes_needed); } - uint8_t* buf = buffer_.data() + bytes_used_; + uint8_t* buf = UNSAFE_TODO(buffer_.data() + bytes_used_); int block_group_offset = bytes_used_; if (include_block_duration) { - memcpy(buf, kBlockGroupHeader, sizeof(kBlockGroupHeader)); + UNSAFE_TODO(memcpy(buf, kBlockGroupHeader, sizeof(kBlockGroupHeader))); UpdateUInt64(block_group_offset + kBlockGroupDurationOffset, duration); UpdateUInt64(block_group_offset + kBlockGroupBlockSizeOffset, block_size); - buf += sizeof(kBlockGroupHeader); + UNSAFE_TODO(buf += sizeof(kBlockGroupHeader)); } else { - memcpy(buf, kBlockGroupHeaderWithoutBlockDuration, - sizeof(kBlockGroupHeaderWithoutBlockDuration)); + UNSAFE_TODO(memcpy(buf, kBlockGroupHeaderWithoutBlockDuration, + sizeof(kBlockGroupHeaderWithoutBlockDuration))); UpdateUInt64( block_group_offset + kBlockGroupWithoutBlockDurationBlockSizeOffset, block_size); - buf += sizeof(kBlockGroupHeaderWithoutBlockDuration); + UNSAFE_TODO(buf += sizeof(kBlockGroupHeaderWithoutBlockDuration)); } UpdateUInt64(block_group_offset + kBlockGroupSizeOffset, block_group_size); @@ -178,10 +174,11 @@ flags &= 0x0f; WriteBlock(buf, track_num, timecode, flags, data, size); - buf += size + 4; + UNSAFE_TODO(buf += size + 4); if (!is_key_frame) { - memcpy(buf, kBlockGroupReferenceBlock, sizeof(kBlockGroupReferenceBlock)); + UNSAFE_TODO(memcpy(buf, kBlockGroupReferenceBlock, + sizeof(kBlockGroupReferenceBlock))); } bytes_used_ += bytes_needed; @@ -206,10 +203,10 @@ DCHECK_LE(timecode_delta, 32767); buf[0] = 0x80 | (track_num & 0x7F); - buf[1] = (timecode_delta >> 8) & 0xff; - buf[2] = timecode_delta & 0xff; - buf[3] = flags & 0xff; - memcpy(buf + 4, data, size); + UNSAFE_TODO(buf[1]) = (timecode_delta >> 8) & 0xff; + UNSAFE_TODO(buf[2]) = timecode_delta & 0xff; + UNSAFE_TODO(buf[3]) = flags & 0xff; + UNSAFE_TODO(memcpy(buf + 4, data, size)); } std::unique_ptr<Cluster> ClusterBuilder::Finish() { @@ -234,7 +231,7 @@ void ClusterBuilder::Reset() { buffer_ = base::HeapArray<uint8_t>::Uninit(kInitialBufferSize); - memcpy(buffer_.data(), kClusterHeader, sizeof(kClusterHeader)); + UNSAFE_TODO(memcpy(buffer_.data(), kClusterHeader, sizeof(kClusterHeader))); bytes_used_ = sizeof(kClusterHeader); cluster_timecode_ = -1; } @@ -247,17 +244,17 @@ auto new_buffer = base::HeapArray<uint8_t>::Uninit(new_buffer_size); - memcpy(new_buffer.data(), buffer_.data(), bytes_used_); + UNSAFE_TODO(memcpy(new_buffer.data(), buffer_.data(), bytes_used_)); buffer_ = std::move(new_buffer); } void ClusterBuilder::UpdateUInt64(int offset, int64_t value) { DCHECK_LE(offset + 7u, buffer_.size()); - uint8_t* buf = buffer_.data() + offset; + uint8_t* buf = UNSAFE_TODO(buffer_.data() + offset); // Fill the last 7 bytes of size field in big-endian order. for (int i = 7; i > 0; i--) { - buf[i] = value & 0xff; + UNSAFE_TODO(buf[i]) = value & 0xff; value >>= 8; } }
diff --git a/media/formats/webm/tracks_builder.cc b/media/formats/webm/tracks_builder.cc index 89c3b11..c84579cdb 100644 --- a/media/formats/webm/tracks_builder.cc +++ b/media/formats/webm/tracks_builder.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/tracks_builder.h" #include <cstring> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "media/formats/webm/webm_constants.h" namespace media { @@ -80,7 +76,7 @@ int& buf_size = *buf_size_ptr; for (int idx = 1; idx <= size; ++idx) { - *buf++ = static_cast<uint8_t>(value >> ((size - idx) * 8)); + *UNSAFE_TODO(buf++) = static_cast<uint8_t>(value >> ((size - idx) * 8)); --buf_size; } } @@ -150,8 +146,8 @@ const uint64_t size = value.length(); WriteUInt(&buf, &buf_size, size); - memcpy(buf, value.data(), size); - buf += size; + UNSAFE_TODO(memcpy(buf, value.data(), size)); + UNSAFE_TODO(buf += size); buf_size -= size; }
diff --git a/media/formats/webm/webm_cluster_parser.cc b/media/formats/webm/webm_cluster_parser.cc index b2642639..017b6b3 100644 --- a/media/formats/webm/webm_cluster_parser.cc +++ b/media/formats/webm/webm_cluster_parser.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_cluster_parser.h" #include <memory> #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/logging.h" #include "base/numerics/byte_conversions.h" @@ -518,14 +514,15 @@ // type with remapped bytestream track numbers and allow multiple tracks as // applicable. See https://crbug.com/341581. auto data_span = - base::span(data.data(), spanification_suspected_redundant_size) + UNSAFE_TODO( + base::span(data.data(), spanification_suspected_redundant_size)) .subspan(data_offset); auto buffer = StreamParserBuffer::CopyFrom(data_span, is_keyframe, buffer_type, track_num); if (additional_size) { buffer->WritableSideData().alpha_data = - base::HeapArray<uint8_t>::CopiedFrom( - base::span<const uint8_t>(additional, additional_size)); + base::HeapArray<uint8_t>::CopiedFrom(UNSAFE_TODO( + base::span<const uint8_t>(additional, additional_size))); } if (decrypt_config) {
diff --git a/media/formats/webm/webm_cluster_parser_unittest.cc b/media/formats/webm/webm_cluster_parser_unittest.cc index b5f6efcc..458c8a4 100644 --- a/media/formats/webm/webm_cluster_parser_unittest.cc +++ b/media/formats/webm/webm_cluster_parser_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_cluster_parser.h" #include <stddef.h> @@ -19,6 +14,7 @@ #include <string> #include <vector> +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/functional/bind.h" #include "base/logging.h" @@ -515,7 +511,7 @@ parse_size = default_parse_size; - data += result; + UNSAFE_TODO(data += result); size -= result; } ASSERT_TRUE(VerifyBuffers(
diff --git a/media/formats/webm/webm_crypto_helpers_unittest.cc b/media/formats/webm/webm_crypto_helpers_unittest.cc index ad37a47..02cbbe43 100644 --- a/media/formats/webm/webm_crypto_helpers_unittest.cc +++ b/media/formats/webm/webm_crypto_helpers_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_crypto_helpers.h" #include <array>
diff --git a/media/formats/webm/webm_info_parser.cc b/media/formats/webm/webm_info_parser.cc index d22cf4e0..86032217 100644 --- a/media/formats/webm/webm_info_parser.cc +++ b/media/formats/webm/webm_info_parser.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_info_parser.h" +#include "base/compiler_specific.h" #include "base/logging.h" #include "media/formats/webm/webm_constants.h" @@ -87,7 +83,7 @@ int64_t date_in_nanoseconds = 0; for (int i = 0; i < size; ++i) - date_in_nanoseconds = (date_in_nanoseconds << 8) | data[i]; + date_in_nanoseconds = (date_in_nanoseconds << 8) | UNSAFE_TODO(data[i]); static constexpr base::Time::Exploded kExplodedEpoch = { .year = 2001, .month = 1, .day_of_week = 1, .day_of_month = 1};
diff --git a/media/formats/webm/webm_parser.cc b/media/formats/webm/webm_parser.cc index 1f641d9a..427265b 100644 --- a/media/formats/webm/webm_parser.cc +++ b/media/formats/webm/webm_parser.cc
@@ -9,11 +9,6 @@ // WebM Container Guidelines is at https://www.webmproject.org/docs/container/ // WebM Encryption spec is at: https://www.webmproject.org/docs/webm-encryption/ -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_parser.h" #include <stddef.h> @@ -25,6 +20,7 @@ #include <limits> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" @@ -505,7 +501,7 @@ int bytes_used = 1; for (int i = 0; i < extra_bytes; ++i) { - ch = buf[bytes_used++]; + ch = UNSAFE_TODO(buf[bytes_used++]); all_ones &= (ch == 0xff); *num = (*num << 8) | ch; } @@ -544,7 +540,7 @@ *id = static_cast<int>(tmp); int num_size_bytes = ParseWebMElementHeaderField( - buf + num_id_bytes, size - num_id_bytes, 8, true, &tmp); + UNSAFE_TODO(buf + num_id_bytes), size - num_id_bytes, 8, true, &tmp); if (num_size_bytes <= 0) { return num_size_bytes; @@ -609,7 +605,7 @@ // Read in the big-endian integer. uint64_t value = 0; for (int i = 0; i < size; ++i) { - value = (value << 8) | buf[i]; + value = (value << 8) | UNSAFE_TODO(buf[i]); } // We use int64_t in place of uint64_t everywhere for convenience. See this @@ -639,7 +635,7 @@ // Read the bytes from big-endian form into a native endian integer. int64_t tmp = 0; for (int i = 0; i < size; ++i) { - tmp = (tmp << 8) | buf[i]; + tmp = (tmp << 8) | UNSAFE_TODO(buf[i]); } // Use a union to convert the integer bit pattern into a floating point @@ -680,7 +676,8 @@ int size, int id, WebMParserClient* client) { - const uint8_t* end = static_cast<const uint8_t*>(memchr(buf, '\0', size)); + const uint8_t* end = + static_cast<const uint8_t*>(UNSAFE_TODO(memchr(buf, '\0', size))); int length = (end != nullptr) ? static_cast<int>(end - buf) : size; std::string str(reinterpret_cast<const char*>(buf), length); return client->OnString(id, str) ? size : -1; @@ -826,7 +823,7 @@ case INSIDE_LIST: { int header_size = result; - const uint8_t* element_data = cur + header_size; + const uint8_t* element_data = UNSAFE_TODO(cur + header_size); int element_data_size = cur_size - header_size; if (element_size < element_data_size) { @@ -855,7 +852,7 @@ break; } - cur += result; + UNSAFE_TODO(cur += result); cur_size -= result; bytes_parsed += result; }
diff --git a/media/formats/webm/webm_parser_unittest.cc b/media/formats/webm/webm_parser_unittest.cc index 2e79631..58f39f52 100644 --- a/media/formats/webm/webm_parser_unittest.cc +++ b/media/formats/webm/webm_parser_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_parser.h" #include <stddef.h> @@ -15,6 +10,7 @@ #include <array> #include <memory> +#include "base/compiler_specific.h" #include "media/formats/webm/cluster_builder.h" #include "media/formats/webm/webm_constants.h" #include "testing/gmock/include/gmock/gmock.h" @@ -263,7 +259,7 @@ parse_size = default_parse_size; - data += result; + UNSAFE_TODO(data += result); size -= result; EXPECT_EQ((size == 0), parser.IsParsingComplete());
diff --git a/media/formats/webm/webm_stream_parser.cc b/media/formats/webm/webm_stream_parser.cc index 8729d26b..a0718e6 100644 --- a/media/formats/webm/webm_stream_parser.cc +++ b/media/formats/webm/webm_stream_parser.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_stream_parser.h" #include <memory> #include <string> +#include "base/compiler_specific.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" #include "base/logging.h" @@ -171,7 +167,7 @@ break; DCHECK_GE(result, 0); - cur += result; + UNSAFE_TODO(cur += result); cur_size -= result; bytes_parsed += result; } @@ -250,7 +246,7 @@ if (result <= 0) return result; - cur += result; + UNSAFE_TODO(cur += result); cur_size -= result; bytes_parsed += result;
diff --git a/media/formats/webm/webm_tracks_parser.cc b/media/formats/webm/webm_tracks_parser.cc index 5237c426..2fa44a5 100644 --- a/media/formats/webm/webm_tracks_parser.cc +++ b/media/formats/webm/webm_tracks_parser.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_tracks_parser.h" #include <memory> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -292,7 +288,7 @@ << "Multiple CodecPrivate fields in a track."; return false; } - codec_private_.assign(data, data + size); + codec_private_.assign(data, UNSAFE_TODO(data + size)); return true; } return true;
diff --git a/media/formats/webm/webm_webvtt_parser.cc b/media/formats/webm/webm_webvtt_parser.cc index ec78312..49268ff 100644 --- a/media/formats/webm/webm_webvtt_parser.cc +++ b/media/formats/webm/webm_webvtt_parser.cc
@@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/377326291): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_webvtt_parser.h" +#include "base/compiler_specific.h" + namespace media { void WebMWebVTTParser::Parse(const uint8_t* payload, @@ -21,7 +18,7 @@ } WebMWebVTTParser::WebMWebVTTParser(const uint8_t* payload, int payload_size) - : ptr_(payload), ptr_end_(payload + payload_size) {} + : ptr_(payload), ptr_end_(UNSAFE_TODO(payload + payload_size)) {} void WebMWebVTTParser::Parse(std::string* id, std::string* settings, @@ -35,12 +32,12 @@ if (ptr_ >= ptr_end_) return false; // indicates end-of-stream - *byte = *ptr_++; + *byte = *UNSAFE_TODO(ptr_++); return true; } void WebMWebVTTParser::UngetByte() { - --ptr_; + UNSAFE_TODO(--ptr_); } void WebMWebVTTParser::ParseLine(std::string* line) {
diff --git a/media/formats/webm/webm_webvtt_parser_unittest.cc b/media/formats/webm/webm_webvtt_parser_unittest.cc index dad92cfb..786b750 100644 --- a/media/formats/webm/webm_webvtt_parser_unittest.cc +++ b/media/formats/webm/webm_webvtt_parser_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/formats/webm/webm_webvtt_parser.h" #include <stdint.h>
diff --git a/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.cc b/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.cc index f10e9bf..32c070c 100644 --- a/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.cc +++ b/media/gpu/chromeos/generic_dmabuf_video_frame_mapper.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/chromeos/generic_dmabuf_video_frame_mapper.h" #include <sys/mman.h> @@ -15,6 +10,7 @@ #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/containers/span.h" #include "base/functional/bind.h" @@ -174,7 +170,7 @@ chunks.emplace_back(mapped_addr, mapped_size); for (size_t j = i; j < next_buf; ++j) - plane_addrs[j] = mapped_addr + planes[j].offset; + plane_addrs[j] = UNSAFE_TODO(mapped_addr + planes[j].offset); i = next_buf; }
diff --git a/media/gpu/chromeos/perf_test_util.cc b/media/gpu/chromeos/perf_test_util.cc index 0e43140..1dbfd165 100644 --- a/media/gpu/chromeos/perf_test_util.cc +++ b/media/gpu/chromeos/perf_test_util.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/chromeos/perf_test_util.h" +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/json/json_writer.h" #include "base/logging.h" @@ -39,8 +35,8 @@ base::File metrics_output_file( base::FilePath(metrics_file_path), base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE); - const int bytes_written = metrics_output_file.WriteAtCurrentPos( - metrics_str.data(), metrics_str.length()); + const int bytes_written = UNSAFE_TODO(metrics_output_file.WriteAtCurrentPos( + metrics_str.data(), metrics_str.length())); ASSERT_EQ(bytes_written, static_cast<int>(metrics_str.length())); LOG(INFO) << "Wrote performance metrics to: " << metrics_file_path; }
diff --git a/media/gpu/h264_builder_unittest.cc b/media/gpu/h264_builder_unittest.cc index 98a7ae7..7bfb85de 100644 --- a/media/gpu/h264_builder_unittest.cc +++ b/media/gpu/h264_builder_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/gpu/h264_builder.h" #include "base/logging.h"
diff --git a/media/gpu/h264_dpb.cc b/media/gpu/h264_dpb.cc index 708e267..ed2cd2c 100644 --- a/media/gpu/h264_dpb.cc +++ b/media/gpu/h264_dpb.cc
@@ -2,18 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif +#include "media/gpu/h264_dpb.h" #include <string.h> #include <algorithm> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/notreached.h" -#include "media/gpu/h264_dpb.h" namespace media { @@ -48,7 +45,7 @@ long_term_reference_flag(false), adaptive_ref_pic_marking_mode_flag(false), dpb_position(0) { - memset(&ref_pic_marking, 0, sizeof(ref_pic_marking)); + UNSAFE_TODO(memset(&ref_pic_marking, 0, sizeof(ref_pic_marking))); } H264Picture::~H264Picture() = default;
diff --git a/media/gpu/test/image_quality_metrics.cc b/media/gpu/test/image_quality_metrics.cc index 6142e890..069549c 100644 --- a/media/gpu/test/image_quality_metrics.cc +++ b/media/gpu/test/image_quality_metrics.cc
@@ -2,15 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <math.h> + #include <algorithm> #include <utility> +#include "base/compiler_specific.h" #include "base/logging.h" #include "media/base/video_frame.h" #include "media/base/video_types.h" @@ -54,9 +51,9 @@ // Read 16 bits and store it in a 32 bits value to avoid overflow in the // following calculations. const uint32_t a = static_cast<uint32_t>( - *reinterpret_cast<const uint16_t*>(src_a + 2 * j)); + *reinterpret_cast<const uint16_t*>(UNSAFE_TODO(src_a + 2 * j))); const uint32_t b = static_cast<uint32_t>( - *reinterpret_cast<const uint16_t*>(src_b + 2 * j)); + *reinterpret_cast<const uint16_t*>(UNSAFE_TODO(src_b + 2 * j))); sum_a += a; sum_b += b; sum_sq_a += a * a; @@ -64,8 +61,8 @@ sum_axb += a * b; } - src_a += stride_a; - src_b += stride_b; + UNSAFE_TODO(src_a += stride_a); + UNSAFE_TODO(src_b += stride_b); } constexpr int64_t count = 64; @@ -100,13 +97,13 @@ for (int i = 0; i < height - 8; i += 4) { for (int j = 0; j < width - 8; j += 4) { // Double |j| because the color depth is 16 bits. - ssim_total += - SSIM16BitPlane8x8(src_a + 2 * j, stride_a, src_b + 2 * j, stride_b); + ssim_total += SSIM16BitPlane8x8(UNSAFE_TODO(src_a + 2 * j), stride_a, + UNSAFE_TODO(src_b + 2 * j), stride_b); samples++; } // |stride_a| and |stride_b| are bytes. No need to double them. - src_a += stride_a * 4; - src_b += stride_b * 4; + UNSAFE_TODO(src_a += stride_a * 4); + UNSAFE_TODO(src_b += stride_b * 4); } ssim_total /= samples; @@ -219,7 +216,7 @@ for (int i = 0; i < kJointDistributionDim; i++) { for (int j = 0; j < kJointDistributionDim; j++) { for (int k = 0; k < kJointDistributionDim; k++) { - log_joint_distribution[i][j][k] = kMinProbabilityValue; + UNSAFE_TODO(log_joint_distribution[i][j][k]) = kMinProbabilityValue; } } } @@ -230,12 +227,13 @@ const uint8_t* row_ptr = frame.visible_data(0); for (int y = 0; y < frame.visible_rect().height(); y++) { for (int x = 0; x < frame.visible_rect().width(); x++) { - log_joint_distribution[row_ptr[4 * x + 1] >> kJointDistributionBitDepth] - [row_ptr[4 * x + 2] >> kJointDistributionBitDepth] - [row_ptr[4 * x + 3] >> - kJointDistributionBitDepth] += 1.0; + UNSAFE_TODO(log_joint_distribution + [row_ptr[4 * x + 1] >> kJointDistributionBitDepth] + [row_ptr[4 * x + 2] >> kJointDistributionBitDepth] + [row_ptr[4 * x + 3] >> kJointDistributionBitDepth]) += + 1.0; } - row_ptr += frame.stride(0); + UNSAFE_TODO(row_ptr += frame.stride(0)); } // Normalize the joint distribution so that it sums to 1.0 and then take the @@ -243,8 +241,9 @@ for (int i = 0; i < kJointDistributionDim; i++) { for (int j = 0; j < kJointDistributionDim; j++) { for (int k = 0; k < kJointDistributionDim; k++) { - log_joint_distribution[i][j][k] /= normalization_factor; - log_joint_distribution[i][j][k] = log(log_joint_distribution[i][j][k]); + UNSAFE_TODO(log_joint_distribution[i][j][k]) /= normalization_factor; + UNSAFE_TODO(log_joint_distribution[i][j][k]) = + log(UNSAFE_TODO(log_joint_distribution[i][j][k])); } } } @@ -263,12 +262,13 @@ const uint8_t* row_ptr = frame.visible_data(0); for (int y = 0; y < frame.visible_rect().height(); y++) { for (int x = 0; x < frame.visible_rect().width(); x++) { - ret += log_joint_distribution - [row_ptr[4 * x + 1] >> kJointDistributionBitDepth] - [row_ptr[4 * x + 2] >> kJointDistributionBitDepth] - [row_ptr[4 * x + 3] >> kJointDistributionBitDepth]; + ret += + UNSAFE_TODO(log_joint_distribution + [row_ptr[4 * x + 1] >> kJointDistributionBitDepth] + [row_ptr[4 * x + 2] >> kJointDistributionBitDepth] + [row_ptr[4 * x + 3] >> kJointDistributionBitDepth]); } - row_ptr += frame.stride(0); + UNSAFE_TODO(row_ptr += frame.stride(0)); } return ret; @@ -302,8 +302,8 @@ const int row_bytes = VideoFrame::RowBytes(i, format, visible_size.width()); for (size_t r = 0; r < rows; ++r) { for (int c = 0; c < row_bytes; c++) { - uint8_t b1 = data1[(stride1 * r) + c]; - uint8_t b2 = data2[(stride2 * r) + c]; + uint8_t b1 = UNSAFE_TODO(data1[(stride1 * r) + c]); + uint8_t b2 = UNSAFE_TODO(data2[(stride2 * r) + c]); uint8_t diff = std::max(b1, b2) - std::min(b1, b2); diff_cnt += diff > tolerance; } @@ -361,8 +361,8 @@ for (size_t y = 0; y < height; y++) { for (size_t x = 0; x < width; x++) { - const uint32_t pixel1 = frame1_data[y * frame1_stride + x]; - const uint32_t pixel2 = frame2_data[y * frame2_stride + x]; + const uint32_t pixel1 = UNSAFE_TODO(frame1_data[y * frame1_stride + x]); + const uint32_t pixel2 = UNSAFE_TODO(frame2_data[y * frame2_stride + x]); const int32_t r1 = (pixel1 >> 20) & 0x3FF; const int32_t g1 = (pixel1 >> 10) & 0x3FF; const int32_t b1 = pixel1 & 0x3FF;
diff --git a/media/gpu/test/video_bitstream.cc b/media/gpu/test/video_bitstream.cc index 35d3c17..4e0ea8e 100644 --- a/media/gpu/test/video_bitstream.cc +++ b/media/gpu/test/video_bitstream.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/test/video_bitstream.h" #include <optional> +#include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/files/file_util.h" #include "base/files/memory_mapped_file.h" @@ -204,8 +200,8 @@ base::span<const uint8_t> VideoBitstream::Data() const { CHECK(memory_mapped_file_ && memory_mapped_file_->IsValid()); - return base::span<const uint8_t>(memory_mapped_file_->data(), - memory_mapped_file_->length()); + return UNSAFE_TODO(base::span<const uint8_t>(memory_mapped_file_->data(), + memory_mapped_file_->length())); } // static base::FilePath VideoBitstream::test_data_path_;
diff --git a/media/gpu/test/video_encoder/bitstream_file_writer.cc b/media/gpu/test/video_encoder/bitstream_file_writer.cc index 08e6f713..2f1c86fa 100644 --- a/media/gpu/test/video_encoder/bitstream_file_writer.cc +++ b/media/gpu/test/video_encoder/bitstream_file_writer.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/test/video_encoder/bitstream_file_writer.h" #include <algorithm> +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/logging.h" @@ -35,8 +31,8 @@ } // For H.264. LOG_ASSERT(output_file_.IsValid()); - return output_file_.WriteAtCurrentPos(reinterpret_cast<const char*>(data), - data_size) == + return UNSAFE_TODO(output_file_.WriteAtCurrentPos( + reinterpret_cast<const char*>(data), data_size)) == static_cast<int>(data_size); }
diff --git a/media/gpu/vaapi/test/av1_decoder.cc b/media/gpu/vaapi/test/av1_decoder.cc index e122202..f614fcc 100644 --- a/media/gpu/vaapi/test/av1_decoder.cc +++ b/media/gpu/vaapi/test/av1_decoder.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/test/av1_decoder.h" #include <va/va.h> @@ -14,6 +9,7 @@ #include <bitset> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/notreached.h" @@ -56,15 +52,17 @@ "Invalid feature array size"); for (size_t i = 0; i < libgav1::kMaxSegments; ++i) { for (size_t j = 0; j < libgav1::kSegmentFeatureMax; ++j) - va_seg_info.feature_data[i][j] = segmentation.feature_data[i][j]; + UNSAFE_TODO(va_seg_info.feature_data[i][j]) = + UNSAFE_TODO(segmentation.feature_data[i][j]); } for (size_t i = 0; i < libgav1::kMaxSegments; ++i) { uint8_t feature_mask = 0; for (size_t j = 0; j < libgav1::kSegmentFeatureMax; ++j) { - if (segmentation.feature_enabled[i][j]) + if (UNSAFE_TODO(segmentation.feature_enabled[i][j])) { feature_mask |= 1 << j; + } } - va_seg_info.feature_mask[i] = feature_mask; + UNSAFE_TODO(va_seg_info.feature_mask[i]) = feature_mask; } } @@ -124,19 +122,21 @@ COPY_FILM_GRAIN_FIELD3(grain_seed); COPY_FILM_GRAIN_FIELD3(num_y_points); for (uint8_t i = 0; i < film_grain_params.num_y_points; ++i) { - COPY_FILM_GRAIN_FIELD3(point_y_value[i]); - COPY_FILM_GRAIN_FIELD3(point_y_scaling[i]); + UNSAFE_TODO(COPY_FILM_GRAIN_FIELD3(point_y_value[i])); + UNSAFE_TODO(COPY_FILM_GRAIN_FIELD3(point_y_scaling[i])); } #undef COPY_FILM_GRAIN_FIELD3 COPY_FILM_GRAIN_FIELD2(num_cb_points, num_u_points); for (uint8_t i = 0; i < film_grain_params.num_u_points; ++i) { - COPY_FILM_GRAIN_FIELD2(point_cb_value[i], point_u_value[i]); - COPY_FILM_GRAIN_FIELD2(point_cb_scaling[i], point_u_scaling[i]); + UNSAFE_TODO(COPY_FILM_GRAIN_FIELD2(point_cb_value[i], point_u_value[i])); + UNSAFE_TODO( + COPY_FILM_GRAIN_FIELD2(point_cb_scaling[i], point_u_scaling[i])); } COPY_FILM_GRAIN_FIELD2(num_cr_points, num_v_points); for (uint8_t i = 0; i < film_grain_params.num_v_points; ++i) { - COPY_FILM_GRAIN_FIELD2(point_cr_value[i], point_v_value[i]); - COPY_FILM_GRAIN_FIELD2(point_cr_scaling[i], point_v_scaling[i]); + UNSAFE_TODO(COPY_FILM_GRAIN_FIELD2(point_cr_value[i], point_v_value[i])); + UNSAFE_TODO( + COPY_FILM_GRAIN_FIELD2(point_cr_scaling[i], point_v_scaling[i])); } constexpr size_t kAutoRegressionCoeffYSize = 24; @@ -160,7 +160,8 @@ if (film_grain_params.num_y_points > 0) { DCHECK_LE(num_pos_y, kAutoRegressionCoeffYSize); for (size_t i = 0; i < num_pos_y; ++i) - COPY_FILM_GRAIN_FIELD2(ar_coeffs_y[i], auto_regression_coeff_y[i]); + UNSAFE_TODO( + COPY_FILM_GRAIN_FIELD2(ar_coeffs_y[i], auto_regression_coeff_y[i])); } if (film_grain_params.chroma_scaling_from_luma || film_grain_params.num_u_points > 0 || @@ -169,11 +170,13 @@ for (size_t i = 0; i < num_pos_uv; ++i) { if (film_grain_params.chroma_scaling_from_luma || film_grain_params.num_u_points > 0) { - COPY_FILM_GRAIN_FIELD2(ar_coeffs_cb[i], auto_regression_coeff_u[i]); + UNSAFE_TODO(COPY_FILM_GRAIN_FIELD2(ar_coeffs_cb[i], + auto_regression_coeff_u[i])); } if (film_grain_params.chroma_scaling_from_luma || film_grain_params.num_v_points > 0) { - COPY_FILM_GRAIN_FIELD2(ar_coeffs_cr[i], auto_regression_coeff_v[i]); + UNSAFE_TODO(COPY_FILM_GRAIN_FIELD2(ar_coeffs_cr[i], + auto_regression_coeff_v[i])); } } } @@ -202,29 +205,30 @@ auto gm = global_motion[i + 1]; switch (gm.type) { case libgav1::kGlobalMotionTransformationTypeIdentity: - va_warped_motion[i].wmtype = VAAV1TransformationIdentity; + UNSAFE_TODO(va_warped_motion[i]).wmtype = VAAV1TransformationIdentity; break; case libgav1::kGlobalMotionTransformationTypeTranslation: - va_warped_motion[i].wmtype = VAAV1TransformationTranslation; + UNSAFE_TODO(va_warped_motion[i]).wmtype = + VAAV1TransformationTranslation; break; case libgav1::kGlobalMotionTransformationTypeRotZoom: - va_warped_motion[i].wmtype = VAAV1TransformationRotzoom; + UNSAFE_TODO(va_warped_motion[i]).wmtype = VAAV1TransformationRotzoom; break; case libgav1::kGlobalMotionTransformationTypeAffine: - va_warped_motion[i].wmtype = VAAV1TransformationAffine; + UNSAFE_TODO(va_warped_motion[i]).wmtype = VAAV1TransformationAffine; break; default: NOTREACHED() << "Invalid global motion transformation type, " - << va_warped_motion[i].wmtype; + << UNSAFE_TODO(va_warped_motion[i]).wmtype; } static_assert(ARRAY_SIZE(va_warped_motion[i].wmmat) == 8 && ARRAY_SIZE(gm.params) == 6, "Invalid size of warp motion parameters"); for (size_t j = 0; j < 6; ++j) - va_warped_motion[i].wmmat[j] = gm.params[j]; - va_warped_motion[i].wmmat[6] = 0; - va_warped_motion[i].wmmat[7] = 0; - va_warped_motion[i].invalid = !libgav1::SetupShear(&gm); + UNSAFE_TODO(va_warped_motion[i].wmmat[j]) = UNSAFE_TODO(gm.params[j]); + UNSAFE_TODO(va_warped_motion[i]).wmmat[6] = 0; + UNSAFE_TODO(va_warped_motion[i]).wmmat[7] = 0; + UNSAFE_TODO(va_warped_motion[i]).invalid = !libgav1::SetupShear(&gm); } } @@ -253,16 +257,20 @@ const int tile_columns = std::min(kVaSizeOfTileWidthAndHeightArray, tile_info.tile_columns); for (int i = 0; i < tile_columns; i++) { - if (!base::CheckSub<int>(tile_info.tile_column_width_in_superblocks[i], 1) - .AssignIfValid(&va_pic_param.width_in_sbs_minus_1[i])) { + if (!base::CheckSub<int>( + UNSAFE_TODO(tile_info.tile_column_width_in_superblocks[i]), 1) + .AssignIfValid( + &UNSAFE_TODO(va_pic_param.width_in_sbs_minus_1[i]))) { return false; } } const int tile_rows = std::min(kVaSizeOfTileWidthAndHeightArray, tile_info.tile_rows); for (int i = 0; i < tile_rows; i++) { - if (!base::CheckSub<int>(tile_info.tile_row_height_in_superblocks[i], 1) - .AssignIfValid(&va_pic_param.height_in_sbs_minus_1[i])) { + if (!base::CheckSub<int>( + UNSAFE_TODO(tile_info.tile_row_height_in_superblocks[i]), 1) + .AssignIfValid( + &UNSAFE_TODO(va_pic_param.height_in_sbs_minus_1[i]))) { return false; } } @@ -308,9 +316,9 @@ libgav1::kLoopFilterMaxModeDeltas, "Invalid size of mode deltas array"); for (size_t i = 0; i < libgav1::kNumReferenceFrameTypes; i++) - va_pic_param.ref_deltas[i] = loop_filter.ref_deltas[i]; + UNSAFE_TODO(va_pic_param.ref_deltas[i]) = loop_filter.ref_deltas[i]; for (size_t i = 0; i < libgav1::kLoopFilterMaxModeDeltas; i++) - va_pic_param.mode_deltas[i] = loop_filter.mode_deltas[i]; + UNSAFE_TODO(va_pic_param.mode_deltas[i]) = loop_filter.mode_deltas[i]; } void FillQuantizationInfo(VADecPictureParameterBufferAV1& va_pic_param, @@ -371,22 +379,26 @@ DCHECK_LE(num_cdef_strengths, static_cast<size_t>(libgav1::kMaxCdefStrengths)); for (size_t i = 0; i < num_cdef_strengths; ++i) { - const uint8_t prim_strength = cdef.y_primary_strength[i] >> coeff_shift; - uint8_t sec_strength = cdef.y_secondary_strength[i] >> coeff_shift; + const uint8_t prim_strength = + UNSAFE_TODO(cdef.y_primary_strength[i]) >> coeff_shift; + uint8_t sec_strength = + UNSAFE_TODO(cdef.y_secondary_strength[i]) >> coeff_shift; DCHECK_LE(sec_strength, 4u); if (sec_strength == 4) sec_strength--; - va_pic_param.cdef_y_strengths[i] = + UNSAFE_TODO(va_pic_param.cdef_y_strengths[i]) = ((prim_strength & 0xf) << 2) | (sec_strength & 0x03); } for (size_t i = 0; i < num_cdef_strengths; ++i) { - const uint8_t prim_strength = cdef.uv_primary_strength[i] >> coeff_shift; - uint8_t sec_strength = cdef.uv_secondary_strength[i] >> coeff_shift; + const uint8_t prim_strength = + UNSAFE_TODO(cdef.uv_primary_strength[i]) >> coeff_shift; + uint8_t sec_strength = + UNSAFE_TODO(cdef.uv_secondary_strength[i]) >> coeff_shift; DCHECK_LE(sec_strength, 4u); if (sec_strength == 4) sec_strength--; - va_pic_param.cdef_uv_strengths[i] = + UNSAFE_TODO(va_pic_param.cdef_uv_strengths[i]) = ((prim_strength & 0xf) << 2) | (sec_strength & 0x03); } } @@ -443,10 +455,10 @@ const size_t num_planes = libgav1::kMaxPlanes; const bool use_loop_restoration = std::find_if(std::begin(loop_restoration.type), - std::begin(loop_restoration.type) + num_planes, + UNSAFE_TODO(std::begin(loop_restoration.type) + num_planes), [](const auto type) { return type != libgav1::kLoopRestorationTypeNone; - }) != (loop_restoration.type + num_planes); + }) != (UNSAFE_TODO(loop_restoration.type + num_planes)); if (!use_loop_restoration) return; static_assert(libgav1::kPlaneY == 0u && libgav1::kPlaneU == 1u, @@ -472,7 +484,7 @@ va_slice_params.resize(num_tiles); for (uint16_t tile = 0; tile < num_tiles; ++tile) { VASliceParameterBufferAV1& va_tile_param = va_slice_params[tile]; - memset(&va_tile_param, 0, sizeof(VASliceParameterBufferAV1)); + UNSAFE_TODO(memset(&va_tile_param, 0, sizeof(VASliceParameterBufferAV1))); va_tile_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL; va_tile_param.tile_row = tile / base::checked_cast<uint16_t>(tile_columns); va_tile_param.tile_column = @@ -725,7 +737,7 @@ // Create surfaces for decode. VASurfaceAttrib attribute; - memset(&attribute, 0, sizeof(VASurfaceAttrib)); + UNSAFE_TODO(memset(&attribute, 0, sizeof(VASurfaceAttrib))); attribute.type = VASurfaceAttribUsageHint; attribute.flags = VA_SURFACE_ATTRIB_SETTABLE; attribute.value.type = VAGenericValueTypeInteger; @@ -735,7 +747,8 @@ // Set up buffer for pic parameters VADecPictureParameterBufferAV1 pic_parameters; - memset(&pic_parameters, 0, sizeof(VADecPictureParameterBufferAV1)); + UNSAFE_TODO( + memset(&pic_parameters, 0, sizeof(VADecPictureParameterBufferAV1))); pic_parameters.profile = base::strict_cast<uint8_t>(current_sequence_header_->profile); @@ -804,7 +817,7 @@ pic_parameters.frame_height_minus1 = current_frame_header.height - 1; for (size_t i = 0; i < kAv1NumRefFrames; ++i) { - pic_parameters.ref_frame_map[i] = + UNSAFE_TODO(pic_parameters.ref_frame_map[i]) = ref_frames_[i] ? ref_frames_[i]->id() : VA_INVALID_SURFACE; } @@ -812,10 +825,12 @@ // frames (it can be left zero initialized). if (!libgav1::IsIntraFrame(current_frame_header.frame_type)) { for (size_t i = 0; i < libgav1::kNumInterReferenceFrameTypes; ++i) { - const int8_t index = current_frame_header.reference_frame_index[i]; + const int8_t index = + UNSAFE_TODO(current_frame_header.reference_frame_index[i]); CHECK_GE(index, 0); CHECK_LT(static_cast<size_t>(index), kAv1NumRefFrames); - pic_parameters.ref_frame_idx[i] = base::checked_cast<uint8_t>(index); + UNSAFE_TODO(pic_parameters.ref_frame_idx[i]) = + base::checked_cast<uint8_t>(index); } } pic_parameters.primary_ref_frame = @@ -885,7 +900,8 @@ const size_t tile_columns = current_frame_header.tile_info.tile_columns; const bool slice_parameters_success = FillAV1SliceParameters( obu_parser_->tile_buffers(), tile_columns, - base::span(ivf_frame_data_.get(), ivf_frame_header_.frame_size), + UNSAFE_TODO( + base::span(ivf_frame_data_.get(), ivf_frame_header_.frame_size)), slice_params); LOG_ASSERT(slice_parameters_success) << "Failed to fill slice parameters for current frame.";
diff --git a/media/gpu/vaapi/test/fake_libva_driver/fake_buffer.cc b/media/gpu/vaapi/test/fake_libva_driver/fake_buffer.cc index 372f7f94..6f2295cc 100644 --- a/media/gpu/vaapi/test/fake_libva_driver/fake_buffer.cc +++ b/media/gpu/vaapi/test/fake_libva_driver/fake_buffer.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/gpu/vaapi/test/fake_libva_driver/fake_buffer.h" #include <string.h> +#include "base/compiler_specific.h" #include "base/numerics/checked_math.h" namespace { @@ -39,7 +35,7 @@ data_size_(CalculateDataSize(size_per_element, num_elements)), data_(std::make_unique<uint8_t[]>(data_size_)) { if (data) { - memcpy(data_.get(), data, data_size_); + UNSAFE_TODO(memcpy(data_.get(), data, data_size_)); } }
diff --git a/media/gpu/vaapi/test/fake_libva_driver/fake_image.cc b/media/gpu/vaapi/test/fake_libva_driver/fake_image.cc index bbedb69..1147b1cc 100644 --- a/media/gpu/vaapi/test/fake_libva_driver/fake_image.cc +++ b/media/gpu/vaapi/test/fake_libva_driver/fake_image.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/test/fake_libva_driver/fake_image.h" +#include "base/compiler_specific.h" #include "base/memory/ptr_util.h" #include "base/numerics/checked_math.h" #include "media/gpu/vaapi/test/fake_libva_driver/fake_buffer.h" @@ -57,7 +53,7 @@ uv_offset.ValueOrDie<unsigned int>()); data_size += uv_size.ValueOrDie<unsigned int>(); - memset(va_image, 0, sizeof(VAImage)); + UNSAFE_TODO(memset(va_image, 0, sizeof(VAImage))); va_image->image_id = id; va_image->format = format;
diff --git a/media/gpu/vaapi/test/fake_libva_driver/h264_decoder_delegate.cc b/media/gpu/vaapi/test/fake_libva_driver/h264_decoder_delegate.cc index 00e9b61..4e891be2 100644 --- a/media/gpu/vaapi/test/fake_libva_driver/h264_decoder_delegate.cc +++ b/media/gpu/vaapi/test/fake_libva_driver/h264_decoder_delegate.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/test/fake_libva_driver/h264_decoder_delegate.h" #include "base/bits.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/logging.h" #include "base/notreached.h" @@ -555,9 +551,9 @@ for (const auto& slice_data_buffer : slice_data_buffers_) { // Add the H264 start code for each slice. bitstream_builder.AppendBits(32, 0x00000001); - const base::span<const uint8_t> data( - reinterpret_cast<uint8_t*>(slice_data_buffer->GetData()), - slice_data_buffer->GetDataSize()); + const base::span<const uint8_t> UNSAFE_TODO( + data(reinterpret_cast<uint8_t*>(slice_data_buffer->GetData()), + slice_data_buffer->GetDataSize())); for (size_t i = 0; i < slice_data_buffer->GetDataSize(); i++) { bitstream_builder.AppendBits<uint8_t>(8, data[i]); } @@ -567,7 +563,7 @@ unsigned char* pData[3]; SBufferInfo sDstBufInfo; - memset(&sDstBufInfo, 0, sizeof(SBufferInfo)); + UNSAFE_TODO(memset(&sDstBufInfo, 0, sizeof(SBufferInfo))); sDstBufInfo.uiInBsTimeStamp = current_ts_++; CHECK_EQ(svc_decoder_->DecodeFrameNoDelay(bitstream_builder.data(), bitstream_builder.BytesInBuffer(), @@ -582,7 +578,7 @@ svc_decoder_->GetOption(DECODER_OPTION_NUM_OF_FRAMES_REMAINING_IN_BUFFER, &num_of_frames_in_buffer); for (int32_t i = 0; i < num_of_frames_in_buffer; i++) { - memset(&sDstBufInfo, 0, sizeof(SBufferInfo)); + UNSAFE_TODO(memset(&sDstBufInfo, 0, sizeof(SBufferInfo))); svc_decoder_->FlushFrame(pData, &sDstBufInfo); OnFrameReady(pData, &sDstBufInfo); } @@ -607,10 +603,10 @@ /*src_y=*/static_cast<uint8_t*>(pData[0]), /*src_stride_y=*/ base::checked_cast<int>(pDstInfo->UsrData.sSystemBuffer.iStride[0]), - /*src_u=*/static_cast<uint8_t*>(pData[1]), + /*src_u=*/static_cast<uint8_t*>(UNSAFE_TODO(pData[1])), /*src_stride_u=*/ base::checked_cast<int>(pDstInfo->UsrData.sSystemBuffer.iStride[1]), - /*src_v=*/static_cast<uint8_t*>(pData[2]), + /*src_v=*/static_cast<uint8_t*>(UNSAFE_TODO(pData[2])), /*src_stride_v=*/ base::checked_cast<int>(pDstInfo->UsrData.sSystemBuffer.iStride[1]), /*dst_y=*/mapped_bo.GetData(0),
diff --git a/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.cc b/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.cc index e1563e2..7b944bbb 100644 --- a/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.cc +++ b/media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/gpu/vaapi/test/fake_libva_driver/scoped_bo_mapping_factory.h" #include <linux/dma-buf.h> @@ -14,6 +9,7 @@ #include <sys/mman.h> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/notreached.h" #include "base/posix/eintr_wrapper.h" @@ -23,7 +19,7 @@ : mapping_(mapping) { for (const auto& plane : mapping_->planes_) { struct dma_buf_sync sync_start; - memset(&sync_start, 0, sizeof(sync_start)); + UNSAFE_TODO(memset(&sync_start, 0, sizeof(sync_start))); sync_start.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW; // This will fail for the fake GBM backend, so ignore the return result. We @@ -36,7 +32,7 @@ ScopedBOMapping::ScopedAccess::~ScopedAccess() { for (const auto& plane : mapping_->planes_) { struct dma_buf_sync sync_end; - memset(&sync_end, 0, sizeof(sync_end)); + UNSAFE_TODO(memset(&sync_end, 0, sizeof(sync_end))); sync_end.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW; HANDLE_EINTR(ioctl(plane.prime_fd.get(), DMA_BUF_IOCTL_SYNC, &sync_end)); }
diff --git a/media/gpu/vaapi/test/h264_decoder.cc b/media/gpu/vaapi/test/h264_decoder.cc index 9a5d0d0..7c596ee0 100644 --- a/media/gpu/vaapi/test/h264_decoder.cc +++ b/media/gpu/vaapi/test/h264_decoder.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/test/h264_decoder.h" #include <va/va.h> #include <algorithm> +#include "base/compiler_specific.h" #include "base/notreached.h" #include "media/base/subsample_entry.h" #include "media/gpu/macros.h" @@ -1020,7 +1016,7 @@ break; } - ++list_mod; + UNSAFE_TODO(++list_mod); } // Per NOTE 2 in 8.2.4.3.2, the ref_pic_listx size in the above loop is
diff --git a/media/gpu/vaapi/test/h264_vaapi_wrapper.cc b/media/gpu/vaapi/test/h264_vaapi_wrapper.cc index 539f967..bbfe6a7 100644 --- a/media/gpu/vaapi/test/h264_vaapi_wrapper.cc +++ b/media/gpu/vaapi/test/h264_vaapi_wrapper.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/test/h264_vaapi_wrapper.h" #include <va/va.h> @@ -15,6 +10,7 @@ #include <array> #include <memory> +#include "base/compiler_specific.h" #include "base/memory/scoped_refptr.h" #include "base/trace_event/trace_event.h" #include "media/gpu/macros.h" @@ -69,7 +65,7 @@ } void InitVAPicture(VAPictureH264* va_pic) { - memset(va_pic, 0, sizeof(*va_pic)); + UNSAFE_TODO(memset(va_pic, 0, sizeof(*va_pic))); va_pic->picture_id = VA_INVALID_ID; va_pic->flags = VA_PICTURE_H264_INVALID; } @@ -145,7 +141,7 @@ const H264Picture::Vector& ref_pic_listb1, scoped_refptr<H264Picture> pic) { VAPictureParameterBufferH264 pic_param; - memset(&pic_param, 0, sizeof(pic_param)); + UNSAFE_TODO(memset(&pic_param, 0, sizeof(pic_param))); #define FROM_SPS_TO_PP(a) pic_param.a = sps->a #define FROM_SPS_TO_PP2(a, b) pic_param.b = sps->a @@ -205,40 +201,41 @@ // Init reference pictures' array. for (int i = 0; i < 16; ++i) - InitVAPicture(&pic_param.ReferenceFrames[i]); + InitVAPicture(&UNSAFE_TODO(pic_param.ReferenceFrames[i])); // And fill it with our reference frames. for (size_t i = 0; i < ref_pic_listp0.size(); i++) { - FillVAPicture(pic_param.ReferenceFrames + i, ref_pic_listp0[i]); + FillVAPicture(UNSAFE_TODO(pic_param.ReferenceFrames + i), + ref_pic_listp0[i]); } pic_param.num_ref_frames = sps->max_num_ref_frames; VAIQMatrixBufferH264 iq_matrix_buf; - memset(&iq_matrix_buf, 0, sizeof(iq_matrix_buf)); + UNSAFE_TODO(memset(&iq_matrix_buf, 0, sizeof(iq_matrix_buf))); if (pps->pic_scaling_matrix_present_flag) { for (int i = 0; i < 6; ++i) { for (int j = 0; j < 16; ++j) - iq_matrix_buf.ScalingList4x4[i][kZigzagScan4x4[j]] = + UNSAFE_TODO(iq_matrix_buf.ScalingList4x4[i][kZigzagScan4x4[j]]) = pps->scaling_list4x4[i][j]; } for (int i = 0; i < 2; ++i) { for (int j = 0; j < 64; ++j) - iq_matrix_buf.ScalingList8x8[i][kZigzagScan8x8[j]] = + UNSAFE_TODO(iq_matrix_buf.ScalingList8x8[i][kZigzagScan8x8[j]]) = pps->scaling_list8x8[i][j]; } } else { for (int i = 0; i < 6; ++i) { for (int j = 0; j < 16; ++j) - iq_matrix_buf.ScalingList4x4[i][kZigzagScan4x4[j]] = + UNSAFE_TODO(iq_matrix_buf.ScalingList4x4[i][kZigzagScan4x4[j]]) = sps->scaling_list4x4[i][j]; } for (int i = 0; i < 2; ++i) { for (int j = 0; j < 64; ++j) - iq_matrix_buf.ScalingList8x8[i][kZigzagScan8x8[j]] = + UNSAFE_TODO(iq_matrix_buf.ScalingList8x8[i][kZigzagScan8x8[j]]) = sps->scaling_list8x8[i][j]; } } @@ -266,7 +263,7 @@ size_t size, const std::vector<SubsampleEntry>& subsamples) { VASliceParameterBufferH264 slice_param; - memset(&slice_param, 0, sizeof(slice_param)); + UNSAFE_TODO(memset(&slice_param, 0, sizeof(slice_param))); slice_param.slice_data_size = slice_hdr->nalu_size; slice_param.slice_data_offset = 0; @@ -299,30 +296,30 @@ SHDRToSP(chroma_weight_l1_flag); for (int i = 0; i <= slice_param.num_ref_idx_l0_active_minus1; ++i) { - slice_param.luma_weight_l0[i] = + UNSAFE_TODO(slice_param.luma_weight_l0[i]) = slice_hdr->pred_weight_table_l0.luma_weight[i]; - slice_param.luma_offset_l0[i] = + UNSAFE_TODO(slice_param.luma_offset_l0[i]) = slice_hdr->pred_weight_table_l0.luma_offset[i]; for (int j = 0; j < 2; ++j) { - slice_param.chroma_weight_l0[i][j] = + UNSAFE_TODO(slice_param.chroma_weight_l0[i][j]) = slice_hdr->pred_weight_table_l0.chroma_weight[i][j]; - slice_param.chroma_offset_l0[i][j] = + UNSAFE_TODO(slice_param.chroma_offset_l0[i][j]) = slice_hdr->pred_weight_table_l0.chroma_offset[i][j]; } } if (slice_hdr->IsBSlice()) { for (int i = 0; i <= slice_param.num_ref_idx_l1_active_minus1; ++i) { - slice_param.luma_weight_l1[i] = + UNSAFE_TODO(slice_param.luma_weight_l1[i]) = slice_hdr->pred_weight_table_l1.luma_weight[i]; - slice_param.luma_offset_l1[i] = + UNSAFE_TODO(slice_param.luma_offset_l1[i]) = slice_hdr->pred_weight_table_l1.luma_offset[i]; for (int j = 0; j < 2; ++j) { - slice_param.chroma_weight_l1[i][j] = + UNSAFE_TODO(slice_param.chroma_weight_l1[i][j]) = slice_hdr->pred_weight_table_l1.chroma_weight[i][j]; - slice_param.chroma_offset_l1[i][j] = + UNSAFE_TODO(slice_param.chroma_offset_l1[i][j]) = slice_hdr->pred_weight_table_l1.chroma_offset[i][j]; } } @@ -334,25 +331,25 @@ "Invalid RefPicList sizes"); for (size_t i = 0; i < std::size(slice_param.RefPicList0); ++i) { - InitVAPicture(&slice_param.RefPicList0[i]); - InitVAPicture(&slice_param.RefPicList1[i]); + InitVAPicture(&UNSAFE_TODO(slice_param.RefPicList0[i])); + InitVAPicture(&UNSAFE_TODO(slice_param.RefPicList1[i])); } for (size_t i = 0; i < ref_pic_list0.size() && i < std::size(slice_param.RefPicList0); ++i) { if (ref_pic_list0[i]) - FillVAPicture(&slice_param.RefPicList0[i], ref_pic_list0[i]); + FillVAPicture(&UNSAFE_TODO(slice_param.RefPicList0[i]), ref_pic_list0[i]); } for (size_t i = 0; i < ref_pic_list1.size() && i < std::size(slice_param.RefPicList1); ++i) { if (ref_pic_list1[i]) - FillVAPicture(&slice_param.RefPicList1[i], ref_pic_list1[i]); + FillVAPicture(&UNSAFE_TODO(slice_param.RefPicList1[i]), ref_pic_list1[i]); } pic->slice_data_buffers.emplace_back(std::make_unique<uint8_t[]>(size)); - memcpy(pic->slice_data_buffers.back().get(), data, size); + UNSAFE_TODO(memcpy(pic->slice_data_buffers.back().get(), data, size)); VABufferID buffer_id; VAStatus va_res = vaCreateBuffer(
diff --git a/media/gpu/vaapi/test/shared_va_surface.cc b/media/gpu/vaapi/test/shared_va_surface.cc index 7e0bc47..ffc9bff 100644 --- a/media/gpu/vaapi/test/shared_va_surface.cc +++ b/media/gpu/vaapi/test/shared_va_surface.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/test/shared_va_surface.h" +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/hash/md5.h" #include "base/memory/scoped_refptr.h" @@ -169,9 +165,9 @@ DCHECK(fourcc == VA_FOURCC_NV12 || fourcc == VA_FOURCC_P010); if (fourcc == VA_FOURCC_NV12) { - convert_res = libyuv::NV12ToARGB(image_data + image.offsets[0], + convert_res = libyuv::NV12ToARGB(UNSAFE_TODO(image_data + image.offsets[0]), base::checked_cast<int>(image.pitches[0]), - image_data + image.offsets[1], + UNSAFE_TODO(image_data + image.offsets[1]), base::checked_cast<int>(image.pitches[1]), argb_data.get(), base::checked_cast<int>(argb_stride), @@ -181,24 +177,27 @@ LOG_ASSERT(image.width * 2 <= image.pitches[0]); LOG_ASSERT(4 * ((image.width + 1) / 2) <= image.pitches[1]); - uint8_t* y_8b = image_data + image.offsets[0]; + uint8_t* y_8b = UNSAFE_TODO(image_data + image.offsets[0]); std::vector<uint16_t> y_plane; for (uint32_t row = 0u; row < image.height; row++) { for (uint32_t col = 0u; col < image.width * 2; col += 2) { - y_plane.push_back(JoinUint8(y_8b[col], y_8b[col + 1])); + y_plane.push_back( + JoinUint8(UNSAFE_TODO(y_8b[col]), UNSAFE_TODO(y_8b[col + 1]))); } - y_8b += image.pitches[0]; + UNSAFE_TODO(y_8b += image.pitches[0]); } // Split the interleaved UV plane. - uint8_t* uv_8b = image_data + image.offsets[1]; + uint8_t* uv_8b = UNSAFE_TODO(image_data + image.offsets[1]); std::vector<uint16_t> u_plane, v_plane; for (uint32_t row = 0u; row < (image.height + 1) / 2; row++) { for (uint32_t col = 0u; col < 4 * ((image.width + 1) / 2); col += 4) { - u_plane.push_back(JoinUint8(uv_8b[col], uv_8b[col + 1])); - v_plane.push_back(JoinUint8(uv_8b[col + 2], uv_8b[col + 3])); + u_plane.push_back( + JoinUint8(UNSAFE_TODO(uv_8b[col]), UNSAFE_TODO(uv_8b[col + 1]))); + v_plane.push_back(JoinUint8(UNSAFE_TODO(uv_8b[col + 2]), + UNSAFE_TODO(uv_8b[col + 3]))); } - uv_8b += image.pitches[1]; + UNSAFE_TODO(uv_8b += image.pitches[1]); } convert_res = libyuv::H010ToARGB( @@ -247,28 +246,30 @@ // I420 still needs to be packed. LOG_ASSERT(image.num_planes == 3u); convert_res = libyuv::I420Copy( - image_data + image.offsets[0], + UNSAFE_TODO(image_data + image.offsets[0]), base::checked_cast<int>(image.pitches[0]), - image_data + image.offsets[1], + UNSAFE_TODO(image_data + image.offsets[1]), base::checked_cast<int>(image.pitches[1]), - image_data + image.offsets[2], + UNSAFE_TODO(image_data + image.offsets[2]), base::checked_cast<int>(image.pitches[2]), i420_data.data(), - base::strict_cast<int>(image.width), i420_data.data() + luma_plane_size, + base::strict_cast<int>(image.width), + UNSAFE_TODO(i420_data.data() + luma_plane_size), base::checked_cast<int>((image.width + 1) / 2), - i420_data.data() + luma_plane_size + chroma_plane_size, + UNSAFE_TODO(i420_data.data() + luma_plane_size + chroma_plane_size), base::checked_cast<int>((image.width + 1) / 2), base::strict_cast<int>(image.width), base::strict_cast<int>(image.height)); } else if (fourcc == VA_FOURCC_NV12) { LOG_ASSERT(image.num_planes == 2u); convert_res = libyuv::NV12ToI420( - image_data + image.offsets[0], + UNSAFE_TODO(image_data + image.offsets[0]), base::checked_cast<int>(image.pitches[0]), - image_data + image.offsets[1], + UNSAFE_TODO(image_data + image.offsets[1]), base::checked_cast<int>(image.pitches[1]), i420_data.data(), - base::strict_cast<int>(image.width), i420_data.data() + luma_plane_size, + base::strict_cast<int>(image.width), + UNSAFE_TODO(i420_data.data() + luma_plane_size), base::checked_cast<int>((image.width + 1) / 2), - i420_data.data() + luma_plane_size + chroma_plane_size, + UNSAFE_TODO(i420_data.data() + luma_plane_size + chroma_plane_size), base::checked_cast<int>((image.width + 1) / 2), base::strict_cast<int>(image.width), base::strict_cast<int>(image.height));
diff --git a/media/gpu/vaapi/test/vp8_decoder.cc b/media/gpu/vaapi/test/vp8_decoder.cc index 1703e73..eaf714b 100644 --- a/media/gpu/vaapi/test/vp8_decoder.cc +++ b/media/gpu/vaapi/test/vp8_decoder.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/test/vp8_decoder.h" #include <va/va.h> @@ -14,6 +9,7 @@ #include <algorithm> #include <memory> +#include "base/compiler_specific.h" #include "media/gpu/vaapi/test/macros.h" #include "media/parsers/ivf_parser.h" #include "media/parsers/vp8_parser.h" @@ -29,7 +25,7 @@ static_assert(std::is_array<From>::value, "Second parameter must be an array"); static_assert(sizeof(to) == sizeof(from), "arrays must be of same size"); - memcpy(&to, &from, sizeof(to)); + UNSAFE_TODO(memcpy(&to, &from, sizeof(to))); } } // namespace @@ -94,19 +90,24 @@ if (sgmnt_hdr.segmentation_enabled) { if (sgmnt_hdr.segment_feature_mode == Vp8SegmentationHeader::FEATURE_MODE_ABSOLUTE) { - q = sgmnt_hdr.quantizer_update_value[i]; + q = UNSAFE_TODO(sgmnt_hdr.quantizer_update_value[i]); } else { - q += sgmnt_hdr.quantizer_update_value[i]; + q += UNSAFE_TODO(sgmnt_hdr.quantizer_update_value[i]); } } #define CLAMP_Q(q) std::clamp(q, 0, 127) - iq_matrix_buf.quantization_index[i][0] = CLAMP_Q(q); - iq_matrix_buf.quantization_index[i][1] = CLAMP_Q(q + quant_hdr.y_dc_delta); - iq_matrix_buf.quantization_index[i][2] = CLAMP_Q(q + quant_hdr.y2_dc_delta); - iq_matrix_buf.quantization_index[i][3] = CLAMP_Q(q + quant_hdr.y2_ac_delta); - iq_matrix_buf.quantization_index[i][4] = CLAMP_Q(q + quant_hdr.uv_dc_delta); - iq_matrix_buf.quantization_index[i][5] = CLAMP_Q(q + quant_hdr.uv_ac_delta); + UNSAFE_TODO(iq_matrix_buf.quantization_index[i])[0] = CLAMP_Q(q); + UNSAFE_TODO(iq_matrix_buf.quantization_index[i]) + [1] = CLAMP_Q(q + quant_hdr.y_dc_delta); + UNSAFE_TODO(iq_matrix_buf.quantization_index[i]) + [2] = CLAMP_Q(q + quant_hdr.y2_dc_delta); + UNSAFE_TODO(iq_matrix_buf.quantization_index[i]) + [3] = CLAMP_Q(q + quant_hdr.y2_ac_delta); + UNSAFE_TODO(iq_matrix_buf.quantization_index[i]) + [4] = CLAMP_Q(q + quant_hdr.uv_dc_delta); + UNSAFE_TODO(iq_matrix_buf.quantization_index[i]) + [5] = CLAMP_Q(q + quant_hdr.uv_ac_delta); #undef CLAMP_Q } @@ -154,13 +155,13 @@ if (sgmnt_hdr.segmentation_enabled) { if (sgmnt_hdr.segment_feature_mode == Vp8SegmentationHeader::FEATURE_MODE_ABSOLUTE) { - lf_level = sgmnt_hdr.lf_update_value[i]; + lf_level = UNSAFE_TODO(sgmnt_hdr.lf_update_value[i]); } else { - lf_level += sgmnt_hdr.lf_update_value[i]; + lf_level += UNSAFE_TODO(sgmnt_hdr.lf_update_value[i]); } } - pic_param.loop_filter_level[i] = std::clamp(lf_level, 0, 63); + UNSAFE_TODO(pic_param.loop_filter_level[i]) = std::clamp(lf_level, 0, 63); } static_assert( @@ -174,8 +175,10 @@ std::extent<decltype(lf_hdr.mb_mode_delta)>(), "loop filter deltas arrays size mismatch"); for (size_t i = 0; i < std::size(lf_hdr.ref_frame_delta); ++i) { - pic_param.loop_filter_deltas_ref_frame[i] = lf_hdr.ref_frame_delta[i]; - pic_param.loop_filter_deltas_mode[i] = lf_hdr.mb_mode_delta[i]; + UNSAFE_TODO(pic_param.loop_filter_deltas_ref_frame[i]) = + UNSAFE_TODO(lf_hdr.ref_frame_delta[i]); + UNSAFE_TODO(pic_param.loop_filter_deltas_mode[i]) = + UNSAFE_TODO(lf_hdr.mb_mode_delta[i]); } #define FHDR_TO_PP(a) pic_param.a = frame_hdr.a @@ -206,7 +209,8 @@ frame_hdr.first_part_size - ((frame_hdr.macroblock_bit_offset + 7) / 8); for (size_t i = 0; i < frame_hdr.num_of_dct_partitions; ++i) - slice_param.partition_size[i + 1] = frame_hdr.dct_partition_sizes[i]; + UNSAFE_TODO(slice_param.partition_size[i + 1]) = + UNSAFE_TODO(frame_hdr.dct_partition_sizes[i]); } // Based on update_reference_frames() in libvpx: vp8/encoder/onyx_if.c @@ -315,7 +319,7 @@ void* iq_matrix_data; res = vaMapBuffer(va_device_->display(), iq_matrix_id, &iq_matrix_data); VA_LOG_ASSERT(res, "vaMapBuffer"); - memcpy(iq_matrix_data, &iq_matrix_buf, sizeof(iq_matrix_buf)); + UNSAFE_TODO(memcpy(iq_matrix_data, &iq_matrix_buf, sizeof(iq_matrix_buf))); buffers.push_back(iq_matrix_id); VABufferID prob_buffer_id; @@ -326,7 +330,7 @@ void* prob_buffer_data; res = vaMapBuffer(va_device_->display(), prob_buffer_id, &prob_buffer_data); VA_LOG_ASSERT(res, "vaMapBuffer"); - memcpy(prob_buffer_data, &prob_buf, sizeof(prob_buf)); + UNSAFE_TODO(memcpy(prob_buffer_data, &prob_buf, sizeof(prob_buf))); buffers.push_back(prob_buffer_id); VABufferID picture_params_id; @@ -338,7 +342,7 @@ res = vaMapBuffer(va_device_->display(), picture_params_id, &picture_params_data); VA_LOG_ASSERT(res, "vaMapBuffer"); - memcpy(picture_params_data, &pic_param, sizeof(pic_param)); + UNSAFE_TODO(memcpy(picture_params_data, &pic_param, sizeof(pic_param))); buffers.push_back(picture_params_id); VABufferID slice_params_id; @@ -349,7 +353,7 @@ void* slice_params_data; res = vaMapBuffer(va_device_->display(), slice_params_id, &slice_params_data); VA_LOG_ASSERT(res, "vaMapBuffer"); - memcpy(slice_params_data, &slice_param, sizeof(pic_param)); + UNSAFE_TODO(memcpy(slice_params_data, &slice_param, sizeof(pic_param))); buffers.push_back(slice_params_id); VABufferID encoded_data_id; @@ -360,7 +364,7 @@ void* encoded_data; res = vaMapBuffer(va_device_->display(), encoded_data_id, &encoded_data); VA_LOG_ASSERT(res, "vaMapBuffer"); - memcpy(encoded_data, frame_hdr.data, frame_hdr.frame_size); + UNSAFE_TODO(memcpy(encoded_data, frame_hdr.data, frame_hdr.frame_size)); buffers.push_back(encoded_data_id); // Time to render!
diff --git a/media/gpu/vaapi/test/vp9_decoder.cc b/media/gpu/vaapi/test/vp9_decoder.cc index 3a0f7519..9fdd6b2 100644 --- a/media/gpu/vaapi/test/vp9_decoder.cc +++ b/media/gpu/vaapi/test/vp9_decoder.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/test/vp9_decoder.h" #include <va/va.h> #include <bitset> +#include "base/compiler_specific.h" #include "base/numerics/safe_conversions.h" #include "media/gpu/macros.h" #include "media/gpu/vaapi/test/macros.h" @@ -172,7 +168,7 @@ CHECK_EQ(kVp9NumRefFrames, std::size(pic_param.reference_frames)); CHECK_EQ(kVp9NumRefFrames, ref_frames_.size()); for (size_t i = 0; i < std::size(pic_param.reference_frames); ++i) { - pic_param.reference_frames[i] = + UNSAFE_TODO(pic_param.reference_frames[i]) = ref_frames_[i] ? ref_frames_[i]->id() : VA_INVALID_SURFACE; } @@ -237,7 +233,7 @@ slice_param.slice_data_flag = VA_SLICE_DATA_FLAG_ALL; for (size_t i = 0; i < std::size(slice_param.seg_param); ++i) { - VASegmentParameterVP9& seg_param = slice_param.seg_param[i]; + VASegmentParameterVP9& seg_param = UNSAFE_TODO(slice_param.seg_param[i]); #define SEG_TO_SP_SF(a, b) seg_param.segment_flags.fields.a = b SEG_TO_SP_SF( segment_reference_enabled, @@ -248,12 +244,12 @@ seg.FeatureEnabled(i, Vp9SegmentationParams::SEG_LVL_SKIP)); #undef SEG_TO_SP_SF - SafeArrayMemcpy(seg_param.filter_level, lf.lvl[i]); + SafeArrayMemcpy(seg_param.filter_level, UNSAFE_TODO(lf.lvl[i])); - seg_param.luma_dc_quant_scale = seg.y_dequant[i][0]; - seg_param.luma_ac_quant_scale = seg.y_dequant[i][1]; - seg_param.chroma_dc_quant_scale = seg.uv_dequant[i][0]; - seg_param.chroma_ac_quant_scale = seg.uv_dequant[i][1]; + seg_param.luma_dc_quant_scale = UNSAFE_TODO(seg.y_dequant[i])[0]; + seg_param.luma_ac_quant_scale = UNSAFE_TODO(seg.y_dequant[i])[1]; + seg_param.chroma_dc_quant_scale = UNSAFE_TODO(seg.uv_dequant[i])[0]; + seg_param.chroma_ac_quant_scale = UNSAFE_TODO(seg.uv_dequant[i])[1]; } res = vaCreateBuffer(
diff --git a/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc b/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc index 3da001d2..792da69 100644 --- a/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc +++ b/media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/vaapi_dmabuf_video_frame_mapper.h" #include <sys/mman.h> #include <array> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/memory/ptr_util.h" @@ -62,10 +58,11 @@ std::vector<ColorPlaneLayout> planes(kNumPlanes); std::array<uint8_t*, VideoFrame::kMaxPlanes> addrs = {}; for (size_t i = 0; i < kNumPlanes; i++) { - planes[i].stride = va_image->image()->pitches[i]; - planes[i].offset = va_image->image()->offsets[i]; - addrs[i] = static_cast<uint8_t*>(va_image->va_buffer()->data()) + - va_image->image()->offsets[i]; + planes[i].stride = UNSAFE_TODO(va_image->image()->pitches[i]); + planes[i].offset = UNSAFE_TODO(va_image->image()->offsets[i]); + addrs[i] = + UNSAFE_TODO(static_cast<uint8_t*>(va_image->va_buffer()->data()) + + va_image->image()->offsets[i]); } // The size of each plane is not given by VAImage. We compute the size to be
diff --git a/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.cc b/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.cc index e59ab01..01ab696 100644 --- a/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.cc +++ b/media/gpu/vaapi/vaapi_image_decode_accelerator_worker.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/gpu/vaapi/vaapi_image_decode_accelerator_worker.h" #include <utility> +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/feature_list.h" #include "base/functional/bind.h" @@ -42,7 +38,7 @@ bool IsJpegImage(base::span<const uint8_t> encoded_data) { if (encoded_data.size() < 3u) return false; - return memcmp("\xFF\xD8\xFF", encoded_data.data(), 3u) == 0; + return UNSAFE_TODO(memcmp("\xFF\xD8\xFF", encoded_data.data(), 3u)) == 0; } } // namespace
diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc index 7ea0d00..e4377aa 100644 --- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc +++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h" #include <va/va.h> @@ -16,6 +11,7 @@ #include <numeric> #include "base/bits.h" +#include "base/compiler_specific.h" #include "base/memory/ref_counted_memory.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" @@ -113,21 +109,22 @@ rc_cfg.ss_number_layers = num_spatial_layers; rc_cfg.ts_number_layers = num_temporal_layers; for (size_t tid = 0; tid < num_temporal_layers; ++tid) { - rc_cfg.ts_rate_decimator[tid] = 1u << (num_temporal_layers - tid - 1); + UNSAFE_TODO(rc_cfg.ts_rate_decimator[tid]) = + 1u << (num_temporal_layers - tid - 1); } for (size_t sid = 0; sid < num_spatial_layers; ++sid) { int gcd = std::gcd(encode_size.height(), spatial_layer_resolutions[sid].height()); - rc_cfg.scaling_factor_num[sid] = + UNSAFE_TODO(rc_cfg.scaling_factor_num[sid]) = spatial_layer_resolutions[sid].height() / gcd; - rc_cfg.scaling_factor_den[sid] = encode_size.height() / gcd; + UNSAFE_TODO(rc_cfg.scaling_factor_den[sid]) = encode_size.height() / gcd; int bitrate_sum = 0; for (size_t tid = 0; tid < num_temporal_layers; ++tid) { size_t idx = sid * num_temporal_layers + tid; - rc_cfg.max_quantizers[idx] = rc_cfg.max_quantizer; - rc_cfg.min_quantizers[idx] = rc_cfg.min_quantizer; + UNSAFE_TODO(rc_cfg.max_quantizers[idx]) = rc_cfg.max_quantizer; + UNSAFE_TODO(rc_cfg.min_quantizers[idx]) = rc_cfg.min_quantizer; bitrate_sum += bitrate_allocation.GetBitrateBps(sid, tid); - rc_cfg.layer_target_bitrate[idx] = bitrate_sum / 1000; + UNSAFE_TODO(rc_cfg.layer_target_bitrate[idx]) = bitrate_sum / 1000; } } return rc_cfg; @@ -550,7 +547,7 @@ for (size_t i = 0; i < picture_param.reference_frame_indices.size(); ++i) { (*ref_frames_used)[i] = true; - picture->frame_hdr->ref_frame_idx[i] = + UNSAFE_TODO(picture->frame_hdr->ref_frame_idx[i]) = picture_param.reference_frame_indices[i]; } } else { @@ -656,7 +653,7 @@ for (size_t i = 0; i < kVp9NumRefFrames; i++) { auto ref_pic = ref_frames.GetFrame(i); - pic_param.reference_frames[i] = + UNSAFE_TODO(pic_param.reference_frames[i]) = ref_pic ? ref_pic->AsVaapiVP9Picture()->va_surface_id() : VA_INVALID_ID; } @@ -677,14 +674,17 @@ CHECK_LT(first_used_ref_frame, 3u); pic_param.ref_flags.bits.ref_last_idx = - ref_frames_used[0] ? frame_header->ref_frame_idx[0] - : frame_header->ref_frame_idx[first_used_ref_frame]; + ref_frames_used[0] + ? frame_header->ref_frame_idx[0] + : UNSAFE_TODO(frame_header->ref_frame_idx[first_used_ref_frame]); pic_param.ref_flags.bits.ref_gf_idx = - ref_frames_used[1] ? frame_header->ref_frame_idx[1] - : frame_header->ref_frame_idx[first_used_ref_frame]; + ref_frames_used[1] + ? frame_header->ref_frame_idx[1] + : UNSAFE_TODO(frame_header->ref_frame_idx[first_used_ref_frame]); pic_param.ref_flags.bits.ref_arf_idx = - ref_frames_used[2] ? frame_header->ref_frame_idx[2] - : frame_header->ref_frame_idx[first_used_ref_frame]; + ref_frames_used[2] + ? frame_header->ref_frame_idx[2] + : UNSAFE_TODO(frame_header->ref_frame_idx[first_used_ref_frame]); } pic_param.pic_flags.bits.frame_type = frame_header->frame_type;
diff --git a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc index 549e4af..8d90927 100644 --- a/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc +++ b/media/gpu/vaapi/vp9_vaapi_video_encoder_delegate_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/gpu/vaapi/vp9_vaapi_video_encoder_delegate.h" #include <va/va.h> @@ -19,6 +14,7 @@ #include <optional> #include <tuple> +#include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" @@ -106,7 +102,8 @@ } { - *temporal_layer_id = kTemporalLayerPattern[1][frame_num % 4]; + *temporal_layer_id = + UNSAFE_TODO(kTemporalLayerPattern[1][frame_num % 4]); *ref_frames_used = kRefFramesUsedForInterFrameInTemporalLayer; } break; @@ -118,7 +115,8 @@ } { - *temporal_layer_id = kTemporalLayerPattern[2][frame_num % 4]; + *temporal_layer_id = + UNSAFE_TODO(kTemporalLayerPattern[2][frame_num % 4]); *ref_frames_used = kRefFramesUsedForInterFrameInTemporalLayer; } break; @@ -202,14 +200,17 @@ for (size_t tid = 0; tid < num_temporal_layers; ++tid) { size_t idx = sid * num_temporal_layers + tid; bitrate_sum += bitrate_allocation.GetBitrateBps(sid, tid); - if (arg.layer_target_bitrate[idx] != bitrate_sum / 1000) + if (UNSAFE_TODO(arg.layer_target_bitrate[idx]) != bitrate_sum / 1000) { return false; - if (arg.ts_rate_decimator[tid] != (1 << (num_temporal_layers - tid - 1))) + } + if (UNSAFE_TODO(arg.ts_rate_decimator[tid]) != + (1 << (num_temporal_layers - tid - 1))) { return false; + } } - if (arg.scaling_factor_num[sid] != 1 || - arg.scaling_factor_den[sid] != + if (UNSAFE_TODO(arg.scaling_factor_num[sid]) != 1 || + UNSAFE_TODO(arg.scaling_factor_den[sid]) != kSpatialLayersResolutionScaleDenom[num_spatial_layers - 1][sid]) { return false; } @@ -588,19 +589,19 @@ DefaultVideoEncodeAcceleratorConfig().bitrate.target_bps(); const uint32_t kFramerate = DefaultVideoEncodeAcceleratorConfig().framerate; const uint8_t* expected_temporal_ids = - kTemporalLayerPattern[num_temporal_layers - 1]; + UNSAFE_TODO(kTemporalLayerPattern[num_temporal_layers - 1]); // Call UpdateRates before Encode. update_rates_and_encode(true, expected_temporal_ids[0], kBitrate / 2, kFramerate); // Bitrate change only. - update_rates_and_encode(false, expected_temporal_ids[1], kBitrate, - kFramerate); + update_rates_and_encode(false, UNSAFE_TODO(expected_temporal_ids[1]), + kBitrate, kFramerate); // Framerate change only. - update_rates_and_encode(false, expected_temporal_ids[2], kBitrate, - kFramerate + 2); + update_rates_and_encode(false, UNSAFE_TODO(expected_temporal_ids[2]), + kBitrate, kFramerate + 2); // Bitrate + Frame changes. - update_rates_and_encode(false, expected_temporal_ids[3], kBitrate * 3 / 4, - kFramerate - 5); + update_rates_and_encode(false, UNSAFE_TODO(expected_temporal_ids[3]), + kBitrate * 3 / 4, kFramerate - 5); } struct VP9VaapiVideoEncoderDelegateTestParam {
diff --git a/media/gpu/windows/d3d12_video_encode_accelerator.cc b/media/gpu/windows/d3d12_video_encode_accelerator.cc index 7213ae3..6109cdd 100644 --- a/media/gpu/windows/d3d12_video_encode_accelerator.cc +++ b/media/gpu/windows/d3d12_video_encode_accelerator.cc
@@ -11,6 +11,8 @@ #include "base/check_is_test.h" #include "base/logging.h" #include "base/no_destructor.h" +#include "base/strings/strcat.h" +#include "base/strings/stringprintf.h" #include "base/synchronization/waitable_event.h" #include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" @@ -26,11 +28,11 @@ #include "media/base/media_switches.h" #include "media/base/video_util.h" #include "media/gpu/command_buffer_helper.h" +#include "media/gpu/gpu_video_encode_accelerator_helpers.h" #include "media/gpu/macros.h" #include "media/gpu/windows/d3d12_video_encode_av1_delegate.h" #include "media/gpu/windows/d3d12_video_encode_delegate.h" #include "media/gpu/windows/d3d12_video_encode_h264_delegate.h" -#include "media/gpu/windows/format_utils.h" #include "third_party/microsoft_dxheaders/src/include/directx/d3dx12_core.h" #include "ui/gfx/gpu_memory_buffer_handle.h" @@ -357,9 +359,21 @@ return {EncoderStatus::Codes::kEncoderInitializationError}; } - if (config.HasSpatialLayer() || config.HasTemporalLayer()) { - MEDIA_LOG(ERROR, media_log_) << "Only L1T1 mode is supported"; - return {EncoderStatus::Codes::kEncoderInitializationError}; + if (config.HasSpatialLayer()) { + MEDIA_LOG(ERROR, media_log_) + << "D3D12VideoEncodeAccelerator don't support spatial layers"; + return {EncoderStatus::Codes::kEncoderUnsupportedConfig}; + } + uint8_t num_of_temporal_layers = + config.spatial_layers.empty() + ? 1 + : config.spatial_layers[0].num_of_temporal_layers; + CHECK_GT(num_of_temporal_layers, 0u); + if (num_of_temporal_layers > 3) { + MEDIA_LOG(ERROR, media_log_) << base::StringPrintf( + "D3D12VideoEncodeAccelerator don't support %u temporal layers", + num_of_temporal_layers); + return {EncoderStatus::Codes::kEncoderUnsupportedConfig}; } SupportedProfiles profiles = GetSupportedProfiles(); @@ -370,6 +384,15 @@ << GetProfileName(config.output_profile); return {EncoderStatus::Codes::kEncoderUnsupportedProfile}; } + SVCScalabilityMode scalability_mode = GetSVCScalabilityMode( + 1, num_of_temporal_layers, SVCInterLayerPredMode::kOff); + if (std::ranges::find(profile->scalability_modes, scalability_mode) == + std::ranges::end(profile->scalability_modes)) { + MEDIA_LOG(ERROR, media_log_) + << base::StrCat({"Unsupported scalability mode ", + GetScalabilityModeName(scalability_mode)}); + return {EncoderStatus::Codes::kEncoderUnsupportedConfig}; + } if (config.input_visible_size.width() > profile->max_resolution.width() || config.input_visible_size.height() > profile->max_resolution.height() || @@ -428,6 +451,7 @@ DVLOGF(2); DCHECK_CALLED_ON_VALID_SEQUENCE(child_sequence_checker_); + destroy_requested_ = true; child_weak_this_factory_.InvalidateWeakPtrs(); // We're destroying; cancel all callbacks. @@ -482,13 +506,14 @@ BindOnce(&Client::RequireBitstreamBuffers, client_, num_frames_in_flight_, config.input_visible_size, bitstream_buffer_size_)); - // TODO(crbug.com/40275246): This needs to be populated when temporal layers - // support is implemented. - constexpr uint8_t kFullFramerate = 255; - encoder_info_.fps_allocation[0] = {kFullFramerate}; + // Set the fps allocation for the first spatial layer + encoder_info_.fps_allocation[0] = + GetFpsAllocation(encoder_->GetNumTemporalLayers()); encoder_info_.reports_average_qp = encoder_->ReportsAverageQp(); encoder_info_.requested_resolution_alignment = 2; encoder_info_.apply_alignment_to_all_simulcast_layers = true; + encoder_info_.number_of_manual_reference_buffers = + encoder_->GetMaxNumOfRefFrames(); child_task_runner_->PostTask( FROM_HERE, @@ -504,7 +529,7 @@ } bitstream_buffers_.push(std::move(buffer)); - TryEncodeNextFrame(); + TryEncodeFrames(); } void D3D12VideoEncodeAccelerator::RequestEncodingParametersChangeTask( @@ -647,29 +672,35 @@ {std::move(frame), options, /*resolving_shared_image=*/false}); } if (!bitstream_buffers_.empty()) { - TryEncodeNextFrame(); + TryEncodeFrames(); } } -void D3D12VideoEncodeAccelerator::TryEncodeNextFrame() { +void D3D12VideoEncodeAccelerator::TryEncodeFrames() { DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_); - if (input_frames_queue_.empty() || bitstream_buffers_.empty()) { - return; + + while (!input_frames_queue_.empty() && !bitstream_buffers_.empty()) { + auto& next_input = input_frames_queue_.front(); + if (next_input.resolving_shared_image || + (!next_input.frame->HasMappableGpuBuffer() && + next_input.frame->HasSharedImage() && !next_input.resolved_resource)) { + // D3D12 VEA encodes frames one-by-one, so we will not try following + // frames. + break; + } + + DoEncodeTask(next_input.frame, next_input.resolved_resource, + next_input.options, bitstream_buffers_.front()); + input_frames_queue_.pop_front(); + bitstream_buffers_.pop(); } - auto& next_input = input_frames_queue_.front(); - if (next_input.resolving_shared_image || - (!next_input.frame->HasMappableGpuBuffer() && - next_input.frame->HasSharedImage() && !next_input.resolved_resource)) { - // D3D12 VEA encodes frames one-by-one, so we will not try following - // frames. - return; + if (flush_requested_ && input_frames_queue_.empty()) { + flush_requested_ = false; + child_task_runner_->PostTask( + FROM_HERE, BindOnce(&D3D12VideoEncodeAccelerator::NotifyFlushDone, + child_weak_this_, /*succeed=*/true)); } - - DoEncodeTask(next_input.frame, next_input.resolved_resource, - next_input.options, bitstream_buffers_.front()); - input_frames_queue_.pop_front(); - bitstream_buffers_.pop(); } void D3D12VideoEncodeAccelerator::DoEncodeTask( @@ -810,8 +841,8 @@ it->resolving_shared_image = false; it->resolved_resource = std::move(input_texture); - // Check if we can encode the front frame now. - TryEncodeNextFrame(); + // Check if we can encode the front frames now. + TryEncodeFrames(); } void D3D12VideoEncodeAccelerator::ResolveQueuedSharedImages() { @@ -836,4 +867,42 @@ } } +bool D3D12VideoEncodeAccelerator::IsFlushSupported() { + return true; +} + +void D3D12VideoEncodeAccelerator::Flush(FlushCallback flush_callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(child_sequence_checker_); + + if (destroy_requested_) { + std::move(flush_callback).Run(/*succeed=*/false); + return; + } + + flush_callback_ = std::move(flush_callback); + encoder_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&D3D12VideoEncodeAccelerator::FlushTask, + encoder_weak_this_)); +} + +void D3D12VideoEncodeAccelerator::FlushTask() { + DCHECK_CALLED_ON_VALID_SEQUENCE(encoder_sequence_checker_); + + if (!encoder_) { + child_task_runner_->PostTask( + FROM_HERE, BindOnce(&D3D12VideoEncodeAccelerator::NotifyFlushDone, + child_weak_this_, /*succeed=*/false)); + return; + } + + flush_requested_ = true; + TryEncodeFrames(); +} + +void D3D12VideoEncodeAccelerator::NotifyFlushDone(bool succeed) { + DCHECK_CALLED_ON_VALID_SEQUENCE(child_sequence_checker_); + + std::move(flush_callback_).Run(succeed); +} + } // namespace media
diff --git a/media/gpu/windows/d3d12_video_encode_accelerator.h b/media/gpu/windows/d3d12_video_encode_accelerator.h index 805f953..4211185 100644 --- a/media/gpu/windows/d3d12_video_encode_accelerator.h +++ b/media/gpu/windows/d3d12_video_encode_accelerator.h
@@ -72,6 +72,8 @@ uint32_t framerate, const std::optional<gfx::Size>& size) override; void Destroy() override; + void Flush(FlushCallback flush_callback) override; + bool IsFlushSupported() override; void SetCommandBufferHelperCB( base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> command_buffer_helper_cb, @@ -113,12 +115,16 @@ const VideoEncoder::EncodeOptions& options, const BitstreamBuffer& bitstream_buffer); - void TryEncodeNextFrame(); + void TryEncodeFrames(); void ResolveQueuedSharedImages(); void DestroyTask(); + void FlushTask(); + + void NotifyFlushDone(bool succeed); + void NotifyError(EncoderStatus status); // Invoked when the CommandBufferHelper is available. @@ -163,6 +169,12 @@ bool error_occurred_ = false; + // True if Destroy() has been called. + bool destroy_requested_ GUARDED_BY_CONTEXT(child_sequence_checker_) = false; + + // True if a flush request is pending. + bool flush_requested_ GUARDED_BY_CONTEXT(encoder_sequence_checker_) = false; + // The accelerator has acquired the command buffer helper that // would be used for accessing incoming shared images. bool acquired_command_buffer_ = false; @@ -179,6 +191,9 @@ // Used for frame format conversion. VideoFrameConverter frame_converter_; + // Invoked once flush is completed. + FlushCallback flush_callback_; + struct InputFrameRef; base::circular_deque<InputFrameRef> input_frames_queue_
diff --git a/media/gpu/windows/d3d12_video_encode_accelerator_unittest.cc b/media/gpu/windows/d3d12_video_encode_accelerator_unittest.cc index 4dc30bf..4a80bda 100644 --- a/media/gpu/windows/d3d12_video_encode_accelerator_unittest.cc +++ b/media/gpu/windows/d3d12_video_encode_accelerator_unittest.cc
@@ -4,6 +4,7 @@ #include "media/gpu/windows/d3d12_video_encode_accelerator.h" +#include "base/strings/stringprintf.h" #include "base/test/task_environment.h" #include "components/viz/common/resources/shared_image_format.h" #include "gpu/command_buffer/client/test_shared_image_interface.h" @@ -103,6 +104,7 @@ EXPECT_TRUE(video_device); VideoEncodeAccelerator::SupportedProfile profile(kSupportedProfile, kSupportedSize, 30, 1); + profile.scalability_modes.push_back(SVCScalabilityMode::kL1T1); profile.gpu_supported_pixel_formats.push_back(PIXEL_FORMAT_NV12); return {profile}; } @@ -209,13 +211,29 @@ for (const auto& profile : d3d12_video_encode_accelerator->GetSupportedProfiles()) { auto config = SupportedProfileToConfig(profile); - EXPECT_TRUE(d3d12_video_encode_accelerator - ->Initialize(config, client_.get(), media_log_->Clone()) - .is_ok()); - EXPECT_CALL(*client_, NotifyEncoderInfoChange(_)).Times(1); - EXPECT_CALL(*client_, NotifyErrorStatus(_)).Times(0); - WaitForEncoderTasksToComplete(); - Mock::VerifyAndClearExpectations(&client_); + for (SVCScalabilityMode svc_mode : profile.scalability_modes) { + SCOPED_TRACE(base::StringPrintf("Testing profile %s, scalability mode %s", + GetProfileName(profile.profile).c_str(), + GetScalabilityModeName(svc_mode))); + ASSERT_GE(svc_mode, SVCScalabilityMode::kL1T1); + ASSERT_LE(svc_mode, SVCScalabilityMode::kL1T3); + config.spatial_layers = {{ + .width = config.input_visible_size.width(), + .height = config.input_visible_size.height(), + .bitrate_bps = config.bitrate.target_bps(), + .framerate = config.framerate, + .num_of_temporal_layers = static_cast<uint8_t>( + static_cast<int>(svc_mode) - + static_cast<int>(SVCScalabilityMode::kL1T1) + 1u), + }}; + EXPECT_TRUE(d3d12_video_encode_accelerator + ->Initialize(config, client_.get(), media_log_->Clone()) + .is_ok()); + EXPECT_CALL(*client_, NotifyEncoderInfoChange(_)).Times(1); + EXPECT_CALL(*client_, NotifyErrorStatus(_)).Times(0); + WaitForEncoderTasksToComplete(); + Mock::VerifyAndClearExpectations(&client_); + } } } @@ -251,10 +269,28 @@ WaitForEncoderTasksToComplete(); Mock::VerifyAndClearExpectations(&client_); } + + // Unsupported number of temporal layers. + auto bad_config = supported_config; + bad_config.spatial_layers = {{ + .width = supported_config.input_visible_size.width(), + .height = supported_config.input_visible_size.height(), + .bitrate_bps = supported_config.bitrate.target_bps(), + .framerate = supported_config.framerate, + .num_of_temporal_layers = 4, // Unsupported number of temporal layers. + }}; + + EXPECT_FALSE(d3d12_video_encode_accelerator + ->Initialize(bad_config, client_.get(), media_log_->Clone()) + .is_ok()); + EXPECT_CALL(*client_, NotifyEncoderInfoChange(_)).Times(0); + EXPECT_CALL(*client_, NotifyErrorStatus(_)).Times(0); + WaitForEncoderTasksToComplete(); + Mock::VerifyAndClearExpectations(&client_); } TEST_F(D3D12VideoEncodeAcceleratorTest, - InputFramesQueueAndBitstreamBuffersAreEitherEmpty) { + InputFramesQueueAndBitstreamBuffersAreEitherEmptyForGMBEncoding) { auto* d3d12_video_encode_accelerator = static_cast<D3D12VideoEncodeAccelerator*>( video_encode_accelerator_.get()); @@ -299,4 +335,57 @@ } } +TEST_F(D3D12VideoEncodeAcceleratorTest, FlushEncoder) { + auto* d3d12_video_encode_accelerator = + static_cast<D3D12VideoEncodeAccelerator*>( + video_encode_accelerator_.get()); + auto supported_profiles = + d3d12_video_encode_accelerator->GetSupportedProfiles(); + EXPECT_FALSE(supported_profiles.empty()); + auto profile = supported_profiles.front(); + auto supported_config = SupportedProfileToConfig(profile); + + unsigned bitstream_buffer_count = 0; + size_t bitstream_buffer_size = 0; + EXPECT_CALL(*client_, RequireBitstreamBuffers(_, _, _)) + .WillOnce(Invoke( + [&](unsigned int count, const gfx::Size& size, size_t size_in_bytes) { + bitstream_buffer_count = count; + bitstream_buffer_size = size_in_bytes; + })); + EXPECT_TRUE( + d3d12_video_encode_accelerator + ->Initialize(supported_config, client_.get(), media_log_->Clone()) + .is_ok()); + WaitForEncoderTasksToComplete(); + Mock::VerifyAndClearExpectations(&client_); + + // Add a few bitstream buffers + for (unsigned i = 0; i < 4; ++i) { + BitstreamBuffer bitstream_buffer( + i, base::UnsafeSharedMemoryRegion::Create(bitstream_buffer_size), + bitstream_buffer_size); + d3d12_video_encode_accelerator->UseOutputBitstreamBuffer( + std::move(bitstream_buffer)); + } + + // Add a few frames to encode + for (unsigned i = 0; i < 3; ++i) { + d3d12_video_encode_accelerator->Encode(CreateTestVideoFrame(), false); + } + + EXPECT_TRUE(d3d12_video_encode_accelerator->IsFlushSupported()); + + bool flush_done = false; + d3d12_video_encode_accelerator->Flush(base::BindOnce( + [](bool* flush_done, bool success) { + *flush_done = true; + EXPECT_TRUE(success); + }, + &flush_done)); + + WaitForEncoderTasksToComplete(); + EXPECT_TRUE(flush_done); +} + } // namespace media
diff --git a/media/gpu/windows/d3d12_video_encode_delegate.cc b/media/gpu/windows/d3d12_video_encode_delegate.cc index 523fafa..ea13248 100644 --- a/media/gpu/windows/d3d12_video_encode_delegate.cc +++ b/media/gpu/windows/d3d12_video_encode_delegate.cc
@@ -125,8 +125,13 @@ : VideoEncodeAccelerator::kNoMode) | (cqp.IsSupported ? VideoEncodeAccelerator::kExternalMode : VideoEncodeAccelerator::kNoMode); - // TODO(crbug.com/40275246): support L1T2/L1T3. - supported_profile.scalability_modes.push_back(SVCScalabilityMode::kL1T1); + supported_profile.scalability_modes = { + SVCScalabilityMode::kL1T1, + SVCScalabilityMode::kL1T2, + }; + if (base::FeatureList::IsEnabled(kD3D12VideoEncodeAcceleratorL1T3)) { + supported_profile.scalability_modes.push_back(SVCScalabilityMode::kL1T3); + } supported_profile.is_software_codec = false; std::vector<std::pair<VideoCodecProfile, std::vector<VideoPixelFormat>>> @@ -190,8 +195,12 @@ output_profile_ = config.output_profile; - CHECK(!config.HasSpatialLayer() && !config.HasTemporalLayer()) - << "D3D12VideoEncoder only support L1T1 mode."; + svc_layers_.emplace( + SVCLayers::Config({config.input_visible_size}, 0, 1, + config.spatial_layers.empty() + ? 1 + : config.spatial_layers[0].num_of_temporal_layers, + SVCInterLayerPredMode::kOff)); input_size_.Width = config.input_visible_size.width(); input_size_.Height = config.input_visible_size.height(); @@ -215,6 +224,8 @@ return EncoderStatus::Codes::kEncoderInitializationError; } + config_ = config; + return InitializeVideoEncoder(config); } @@ -232,6 +243,8 @@ return false; } + config_.bitrate = bitrate; + config_.framerate = framerate; rate_control_ = rate_control; return true; } @@ -300,6 +313,11 @@ return encode_result; } +uint8_t D3D12VideoEncodeDelegate::GetNumTemporalLayers() const { + return svc_layers_.has_value() ? svc_layers_->config().num_temporal_layers + : 1; +} + D3D12VideoEncodeDelegate::D3D12VideoEncoderRateControl:: D3D12VideoEncoderRateControl() = default;
diff --git a/media/gpu/windows/d3d12_video_encode_delegate.h b/media/gpu/windows/d3d12_video_encode_delegate.h index 126488c6..2949674 100644 --- a/media/gpu/windows/d3d12_video_encode_delegate.h +++ b/media/gpu/windows/d3d12_video_encode_delegate.h
@@ -14,6 +14,7 @@ #include "media/base/bitstream_buffer.h" #include "media/base/encoder_status.h" #include "media/gpu/media_gpu_export.h" +#include "media/gpu/svc_layers.h" #include "media/gpu/windows/d3d12_video_encoder_wrapper.h" #include "media/gpu/windows/d3d12_video_helpers.h" #include "media/gpu/windows/d3d12_video_processor_wrapper.h" @@ -64,6 +65,8 @@ const VideoEncoder::EncodeOptions& options, const gfx::ColorSpace& input_color_space) = 0; + uint8_t GetNumTemporalLayers() const; + void SetFactoriesForTesting( base::RepeatingCallback<decltype(CreateD3D12VideoEncoderWrapper)> video_encoder_wrapper_factory, @@ -141,6 +144,10 @@ Microsoft::WRL::ComPtr<ID3D12Device> device_; Microsoft::WRL::ComPtr<ID3D12VideoDevice3> video_device_; + // The current used config. Used for reconstructing bitrate allocation when + // rate control is updated. + VideoEncodeAccelerator::Config config_; + // The the size and format for the input of the D3D12VideoEncoder. The format // may be different to input frame, in which case we do internal conversion. D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC input_size_{}; @@ -158,6 +165,8 @@ base::BindRepeating(&CreateD3D12VideoEncoderWrapper); std::unique_ptr<D3D12VideoEncoderWrapper> video_encoder_wrapper_; + std::optional<SVCLayers> svc_layers_; + private: // The video processor factory that may be changed for testing. base::RepeatingCallback<
diff --git a/media/gpu/windows/d3d12_video_encode_h264_delegate.cc b/media/gpu/windows/d3d12_video_encode_h264_delegate.cc index 96cd1de0..30ba1d8 100644 --- a/media/gpu/windows/d3d12_video_encode_h264_delegate.cc +++ b/media/gpu/windows/d3d12_video_encode_h264_delegate.cc
@@ -7,7 +7,10 @@ #include "base/bits.h" #include "base/containers/fixed_flat_map.h" #include "base/strings/stringprintf.h" +#include "media/gpu/gpu_video_encode_accelerator_helpers.h" #include "media/gpu/h264_builder.h" +#include "media/gpu/h264_rate_control_util.h" +#include "media/gpu/macros.h" #include "media/gpu/windows/d3d12_video_helpers.h" #include "media/gpu/windows/format_utils.h" #include "media/gpu/windows/mf_video_encoder_util.h" @@ -252,6 +255,7 @@ .DataSize = sizeof(pic_params_), .pH264PicData = &pic_params_, }; + metadata_.h264.emplace(); } D3D12VideoEncodeH264Delegate::~D3D12VideoEncodeH264Delegate() = default; @@ -278,28 +282,49 @@ return false; } + config_.bitrate = bitrate; + config_.framerate = framerate; + VideoBitrateAllocation bitrate_allocation = + AllocateBitrateForDefaultEncoding(config_); + if (bitrate_allocation.GetSumBps() == 0) { + return false; + } + float peak_target_ratio = + 1.f * bitrate_allocation.GetPeakBps() / bitrate_allocation.GetSumBps(); + uint32_t sum_bitrate = 0; if (framerate != rate_controller_settings_.frame_rate_max) { // Frame rate has changed, resetting the rate controller. rate_controller_settings_.frame_rate_max = framerate; CHECK_GT(framerate, 0u); rate_controller_settings_.gop_max_duration = base::Seconds((gop_structure_.GOPLength + framerate - 1) / framerate); - H264RateControllerLayerSettings& layer_settings = - rate_controller_settings_.layer_settings[0]; - layer_settings.avg_bitrate = bitrate.target_bps(); - // Bitrate::Mode::kConstant only has target_bps. Using the target_bps for - // peak_bitrate. - layer_settings.peak_bitrate = bitrate.mode() == Bitrate::Mode::kConstant - ? bitrate.target_bps() - : bitrate.peak_bps(); - layer_settings.frame_rate = framerate; + for (size_t i = 0; i < rate_controller_settings_.layer_settings.size(); + i++) { + H264RateControllerLayerSettings& layer_settings = + rate_controller_settings_.layer_settings[i]; + sum_bitrate += bitrate_allocation.GetBitrateBps(0, i); + layer_settings.avg_bitrate = sum_bitrate; + layer_settings.peak_bitrate = + bitrate.mode() == Bitrate::Mode::kConstant + ? sum_bitrate + : base::saturated_cast<uint32_t>(sum_bitrate * + peak_target_ratio); + layer_settings.frame_rate = framerate / static_cast<float>(1u << i); + } software_rate_controller_.emplace(rate_controller_settings_); } else { // Frame rate has not changed, updating the bitrate. - software_rate_controller_->temporal_layers(0).SetBufferParameters( - rate_controller_settings_.layer_settings[0].hrd_buffer_size, - bitrate.target_bps(), bitrate.target_bps(), - rate_controller_settings_.ease_hrd_reduction); + for (size_t i = 0; i < GetNumTemporalLayers(); i++) { + sum_bitrate += bitrate_allocation.GetBitrateBps(0, i); + software_rate_controller_->temporal_layers(i).SetBufferParameters( + rate_controller_settings_.layer_settings[i].hrd_buffer_size, + sum_bitrate, + bitrate.mode() == Bitrate::Mode::kConstant + ? sum_bitrate + : base::saturated_cast<uint32_t>(sum_bitrate * + peak_target_ratio), + rate_controller_settings_.ease_hrd_reduction); + } } return true; } @@ -325,16 +350,40 @@ pic_params_.FrameDecodingOrderNumber * 2; bool is_keyframe = pic_params_.FrameDecodingOrderNumber == 0; - // TODO(crbug.com/40275246): Support multiple temporal layers. absl::InlinedVector<uint8_t, 4> reference_buffers; std::optional<uint8_t> update_buffer; std::optional<uint8_t> destroy_buffer; - if (!is_keyframe) { - reference_buffers.push_back(0); - } - update_buffer = 0; - if (destroy_buffer.value_or(0) > 0) { - destroy_buffer = destroy_buffer.value() + 1; + if (svc_layers_) { + if (is_keyframe) { + svc_layers_->Reset(); + } + SVCLayers::PictureParam pic_param; + SVCGenericMetadata metadata{}; + svc_layers_->GetPictureParamAndMetadata(pic_param, &metadata); + metadata_.h264->temporal_idx = metadata.temporal_idx; + CHECK_LE(pic_param.reference_frame_indices.size(), 1u); + if (!pic_param.reference_frame_indices.empty()) { + reference_buffers.push_back(pic_param.reference_frame_indices[0]); + } + if (is_keyframe) { + // SVCLayers returns 0xff for AV1, we only need one at zero slot for H26x. + pic_param.refresh_frame_flags = 1; + } + CHECK_LE(std::popcount(pic_param.refresh_frame_flags), 1); + if (pic_param.refresh_frame_flags) { + update_buffer = std::countr_zero(pic_param.refresh_frame_flags); + } + // In L1T3 SVC mode, the slot 1 is not used for reference once it is used + // at the last frame of each 4 frames, so we need to manually remove it. + // In L1Tx, The slot 0 is always replaced by the current frame when it is + // referenced for the last time, so we don't need to explicitly remove it. + if (GetNumTemporalLayers() == 3 && + pic_params_.FrameDecodingOrderNumber % 4 == 3) { + destroy_buffer = 1; + } + } else { + reference_buffers = options.reference_buffers; + update_buffer = options.update_buffer; } if (update_buffer.has_value() && @@ -442,16 +491,19 @@ // Rate control. int qp = -1; if (software_rate_controller_) { - software_rate_controller_->temporal_layers(0).ShrinkHRDBuffer( - rate_controller_timestamp_); + CHECK(metadata_.h264); + software_rate_controller_->temporal_layers(metadata_.h264->temporal_idx) + .ShrinkHRDBuffer(rate_controller_timestamp_); if (is_keyframe) { software_rate_controller_->EstimateIntraFrameQP( rate_controller_timestamp_); } else { software_rate_controller_->EstimateInterFrameQP( - 0, rate_controller_timestamp_); + metadata_.h264->temporal_idx, rate_controller_timestamp_); } - qp = software_rate_controller_->temporal_layers(0).curr_frame_qp(); + qp = + software_rate_controller_->temporal_layers(metadata_.h264->temporal_idx) + .curr_frame_qp(); } else if (options.quantizer.has_value()) { qp = options.quantizer.value(); } @@ -498,6 +550,7 @@ } reference_frame_manager_.ProcessMemoryManagementControlOperation(pic_params_); + svc_layers_->PostEncode(0); metadata_.key_frame = is_keyframe; metadata_.qp = qp; @@ -530,17 +583,22 @@ "D3D12VideoEncoder doesn't support long term reference for H264"}; } - max_num_ref_frames_ = 1; - if (picture_control_support_h264.MaxDPBCapacity < max_num_ref_frames_) { - return { - EncoderStatus::Codes::kEncoderUnsupportedConfig, - base::StringPrintf( - "D3D12VideoEncoder only support DPB capacity %u, got %u", - picture_control_support_h264.MaxDPBCapacity, max_num_ref_frames_)}; + if (svc_layers_.has_value()) { + max_num_ref_frames_ = GetNumTemporalLayers() == 3 ? 2 : 1; + if (picture_control_support_h264.MaxDPBCapacity < max_num_ref_frames_) { + return {EncoderStatus::Codes::kEncoderUnsupportedConfig, + base::StringPrintf( + "D3D12VideoEncoder only support DPB capacity %u, got %u", + picture_control_support_h264.MaxDPBCapacity, + max_num_ref_frames_)}; + } + } else { + max_num_ref_frames_ = picture_control_support_h264.MaxDPBCapacity; } - if (config.bitrate.mode() == Bitrate::Mode::kConstant || - config.bitrate.mode() == Bitrate::Mode::kVariable) { + if ((config.bitrate.mode() == Bitrate::Mode::kConstant || + config.bitrate.mode() == Bitrate::Mode::kVariable) && + GetNumTemporalLayers() <= h264_rate_control_util::kMaxNumTemporalLayers) { constexpr uint32_t kDefaultQp = 26; rate_control_ = D3D12VideoEncoderRateControl::CreateCqp( kDefaultQp, kDefaultQp, kDefaultQp); @@ -551,21 +609,32 @@ (config.gop_length.value() + config.framerate - 1) / config.framerate); rate_controller_settings_.fixed_delta_qp = false; rate_controller_settings_.ease_hrd_reduction = false; - rate_controller_settings_.num_temporal_layers = 1; + rate_controller_settings_.num_temporal_layers = GetNumTemporalLayers(); H264RateControllerLayerSettings layer_settings; - layer_settings.avg_bitrate = config.bitrate.target_bps(); - // Bitrate::Mode::kConstant only has target_bps. Using the target_bps for - // peak_bitrate. - layer_settings.peak_bitrate = - config.bitrate.mode() == Bitrate::Mode::kConstant - ? config.bitrate.target_bps() - : config.bitrate.peak_bps(); constexpr size_t kHRDBufferSize = 40000; layer_settings.hrd_buffer_size = kHRDBufferSize; layer_settings.min_qp = kH264MinQuantizer; layer_settings.max_qp = kH264MaxQuantizer; - layer_settings.frame_rate = config.framerate; - rate_controller_settings_.layer_settings.push_back(layer_settings); + VideoBitrateAllocation bitrate_allocation = + AllocateBitrateForDefaultEncoding(config); + if (bitrate_allocation.GetSumBps() == 0) { + return {EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Bitrate is zero"}; + } + float peak_target_ratio = + 1.f * bitrate_allocation.GetPeakBps() / bitrate_allocation.GetSumBps(); + uint32_t sum_bitrate = 0; + for (size_t i = 0; i < rate_controller_settings_.num_temporal_layers; i++) { + sum_bitrate += bitrate_allocation.GetBitrateBps(0, i); + layer_settings.avg_bitrate = sum_bitrate; + layer_settings.peak_bitrate = + config.bitrate.mode() == Bitrate::Mode::kConstant + ? sum_bitrate + : base::saturated_cast<uint32_t>(sum_bitrate * peak_target_ratio); + layer_settings.frame_rate = + config.framerate / static_cast<float>(1u << i); + rate_controller_settings_.layer_settings.push_back(layer_settings); + } software_rate_controller_.emplace(rate_controller_settings_); } @@ -748,8 +817,9 @@ software_rate_controller_->FinishIntraFrame(payload_size, rate_controller_timestamp_); } else { - software_rate_controller_->FinishInterFrame(0, payload_size, - rate_controller_timestamp_); + software_rate_controller_->FinishInterFrame( + metadata_.h264 ? metadata_.h264->temporal_idx : 0, payload_size, + rate_controller_timestamp_); } // The next frame should be decoded at (1 / frame_rate) seconds later. rate_controller_timestamp_ += @@ -793,6 +863,7 @@ sps.log2_max_pic_order_cnt_lsb_minus4 = gop_structure_.log2_max_pic_order_cnt_lsb_minus4; sps.max_num_ref_frames = max_num_ref_frames_; + sps.gaps_in_frame_num_value_allowed_flag = svc_layers_.has_value(); constexpr int kMbSize = 16; sps.pic_width_in_mbs_minus1 = (input_size_.Width + kMbSize - 1) / kMbSize - 1; sps.pic_height_in_map_units_minus1 =
diff --git a/media/gpu/windows/d3d12_video_encode_h265_delegate.cc b/media/gpu/windows/d3d12_video_encode_h265_delegate.cc index 91808e7..4425a1f 100644 --- a/media/gpu/windows/d3d12_video_encode_h265_delegate.cc +++ b/media/gpu/windows/d3d12_video_encode_h265_delegate.cc
@@ -9,6 +9,8 @@ #include "base/bits.h" #include "base/containers/fixed_flat_map.h" #include "base/strings/stringprintf.h" +#include "media/gpu/gpu_video_encode_accelerator_helpers.h" +#include "media/gpu/h264_rate_control_util.h" #include "media/gpu/h265_builder.h" #include "media/gpu/windows/d3d12_video_helpers.h" #include "media/gpu/windows/format_utils.h" @@ -209,28 +211,49 @@ return false; } + config_.bitrate = bitrate; + config_.framerate = framerate; + VideoBitrateAllocation bitrate_allocation = + AllocateBitrateForDefaultEncoding(config_); + if (bitrate_allocation.GetSumBps() == 0) { + return false; + } + float peak_target_ratio = + 1.f * bitrate_allocation.GetPeakBps() / bitrate_allocation.GetSumBps(); + uint32_t sum_bitrate = 0; if (framerate != rate_controller_settings_.frame_rate_max) { // Frame rate has changed, resetting the rate controller. rate_controller_settings_.frame_rate_max = framerate; CHECK_GT(framerate, 0u); rate_controller_settings_.gop_max_duration = base::Seconds((gop_structure_.GOPLength + framerate - 1) / framerate); - H264RateControllerLayerSettings& layer_settings = - rate_controller_settings_.layer_settings[0]; - layer_settings.avg_bitrate = bitrate.target_bps(); - // Bitrate::Mode::kConstant only has target_bps. Using the target_bps for - // peak_bitrate. - layer_settings.peak_bitrate = bitrate.mode() == Bitrate::Mode::kConstant - ? bitrate.target_bps() - : bitrate.peak_bps(); - layer_settings.frame_rate = framerate; + for (size_t i = 0; i < rate_controller_settings_.layer_settings.size(); + i++) { + H264RateControllerLayerSettings& layer_settings = + rate_controller_settings_.layer_settings[i]; + sum_bitrate += bitrate_allocation.GetBitrateBps(0, i); + layer_settings.avg_bitrate = sum_bitrate; + layer_settings.peak_bitrate = + bitrate.mode() == Bitrate::Mode::kConstant + ? sum_bitrate + : base::saturated_cast<uint32_t>(sum_bitrate * + peak_target_ratio); + layer_settings.frame_rate = framerate / static_cast<float>(1u << i); + } software_rate_controller_.emplace(rate_controller_settings_); } else { // Frame rate has not changed, updating the bitrate. - software_rate_controller_->temporal_layers(0).SetBufferParameters( - rate_controller_settings_.layer_settings[0].hrd_buffer_size, - bitrate.target_bps(), bitrate.target_bps(), - rate_controller_settings_.ease_hrd_reduction); + for (size_t i = 0; i < GetNumTemporalLayers(); i++) { + sum_bitrate += bitrate_allocation.GetBitrateBps(0, i); + software_rate_controller_->temporal_layers(i).SetBufferParameters( + rate_controller_settings_.layer_settings[i].hrd_buffer_size, + sum_bitrate, + bitrate.mode() == Bitrate::Mode::kConstant + ? sum_bitrate + : base::saturated_cast<uint32_t>(sum_bitrate * + peak_target_ratio), + rate_controller_settings_.ease_hrd_reduction); + } } return true; } @@ -256,10 +279,37 @@ absl::InlinedVector<uint8_t, 4> reference_buffers; std::optional<uint8_t> update_buffer; std::optional<uint8_t> destroy_buffer; - if (!is_keyframe) { - reference_buffers.push_back(0); + if (svc_layers_) { + if (is_keyframe) { + svc_layers_->Reset(); + } + SVCLayers::PictureParam pic_param; + svc_layers_->GetPictureParamAndMetadata(pic_param, &*metadata_.svc_generic); + CHECK_LE(pic_param.reference_frame_indices.size(), 1u); + if (!pic_param.reference_frame_indices.empty()) { + reference_buffers.push_back(pic_param.reference_frame_indices[0]); + } + if (is_keyframe) { + // SVCLayers returns 0xff for AV1, we only need one at zero slot for H26x. + pic_param.refresh_frame_flags = 1; + } + CHECK_LE(std::popcount(pic_param.refresh_frame_flags), 1); + if (pic_param.refresh_frame_flags) { + update_buffer = std::countr_zero(pic_param.refresh_frame_flags); + } + // In L1T3 SVC mode, the slot 1 is not used for reference once it is used + // at the last frame of each 4 frames, so we need to manually remove it. + // In L1Tx, The slot 0 is always replaced by the current frame when it is + // referenced for the last time, so we don't need to explicitly remove it. + if (GetNumTemporalLayers() == 3 && + pic_params_.PictureOrderCountNumber % 4 == 3) { + destroy_buffer = 1; + } + } else { + reference_buffers = options.reference_buffers; + update_buffer = options.update_buffer; } - update_buffer = 0; + if (update_buffer.has_value() && update_buffer.value() >= max_num_ref_frames_) { return {EncoderStatus::Codes::kBadReferenceBuffer, @@ -332,16 +382,19 @@ // Rate control. int qp = -1; if (software_rate_controller_) { - software_rate_controller_->temporal_layers(0).ShrinkHRDBuffer( - rate_controller_timestamp_); + software_rate_controller_ + ->temporal_layers(metadata_.svc_generic->temporal_idx) + .ShrinkHRDBuffer(rate_controller_timestamp_); if (is_keyframe) { software_rate_controller_->EstimateIntraFrameQP( rate_controller_timestamp_); } else { software_rate_controller_->EstimateInterFrameQP( - 0, rate_controller_timestamp_); + metadata_.svc_generic->temporal_idx, rate_controller_timestamp_); } - qp = software_rate_controller_->temporal_layers(0).curr_frame_qp(); + qp = software_rate_controller_ + ->temporal_layers(metadata_.svc_generic->temporal_idx) + .curr_frame_qp(); } else if (options.quantizer.has_value()) { qp = options.quantizer.value(); } @@ -395,6 +448,8 @@ pic_params_.PictureOrderCountNumber, update_buffer.value(), false); } + svc_layers_->PostEncode(0); + metadata_.key_frame = is_keyframe; metadata_.qp = qp; return metadata_; @@ -426,17 +481,22 @@ "D3D12VideoEncoder doesn't support long term reference for HEVC"}; } - max_num_ref_frames_ = 1; - if (picture_control_support_h265.MaxDPBCapacity < max_num_ref_frames_) { - return { - EncoderStatus::Codes::kEncoderUnsupportedConfig, - base::StringPrintf( - "D3D12VideoEncoder only support DPB capacity %u, got %u", - picture_control_support_h265.MaxDPBCapacity, max_num_ref_frames_)}; + if (svc_layers_.has_value()) { + max_num_ref_frames_ = GetNumTemporalLayers() == 3 ? 2 : 1; + if (picture_control_support_h265.MaxDPBCapacity < max_num_ref_frames_) { + return {EncoderStatus::Codes::kEncoderUnsupportedConfig, + base::StringPrintf( + "D3D12VideoEncoder only support DPB capacity %u, got %u", + picture_control_support_h265.MaxDPBCapacity, + max_num_ref_frames_)}; + } + } else { + max_num_ref_frames_ = picture_control_support_h265.MaxDPBCapacity; } - if (config.bitrate.mode() == Bitrate::Mode::kConstant || - config.bitrate.mode() == Bitrate::Mode::kVariable) { + if ((config.bitrate.mode() == Bitrate::Mode::kConstant || + config.bitrate.mode() == Bitrate::Mode::kVariable) && + GetNumTemporalLayers() <= h264_rate_control_util::kMaxNumTemporalLayers) { constexpr uint32_t kDefaultQp = 26; rate_control_ = D3D12VideoEncoderRateControl::CreateCqp( kDefaultQp, kDefaultQp, kDefaultQp); @@ -447,21 +507,32 @@ (config.gop_length.value() + config.framerate - 1) / config.framerate); rate_controller_settings_.fixed_delta_qp = false; rate_controller_settings_.ease_hrd_reduction = false; - rate_controller_settings_.num_temporal_layers = 1; + rate_controller_settings_.num_temporal_layers = GetNumTemporalLayers(); H264RateControllerLayerSettings layer_settings; - layer_settings.avg_bitrate = config.bitrate.target_bps(); - // Bitrate::Mode::kConstant only has target_bps. Using the target_bps for - // peak_bitrate. - layer_settings.peak_bitrate = - config.bitrate.mode() == Bitrate::Mode::kConstant - ? config.bitrate.target_bps() - : config.bitrate.peak_bps(); constexpr size_t kHRDBufferSize = 40000; layer_settings.hrd_buffer_size = kHRDBufferSize; layer_settings.min_qp = kH265MinQuantizer; layer_settings.max_qp = kH265MaxQuantizer; - layer_settings.frame_rate = config.framerate; - rate_controller_settings_.layer_settings.push_back(layer_settings); + VideoBitrateAllocation bitrate_allocation = + AllocateBitrateForDefaultEncoding(config); + if (bitrate_allocation.GetSumBps() == 0) { + return {EncoderStatus::Codes::kEncoderUnsupportedConfig, + "Bitrate is zero"}; + } + float peak_target_ratio = + 1.f * bitrate_allocation.GetPeakBps() / bitrate_allocation.GetSumBps(); + uint32_t sum_bitrate = 0; + for (size_t i = 0; i < rate_controller_settings_.num_temporal_layers; i++) { + sum_bitrate += bitrate_allocation.GetBitrateBps(0, i); + layer_settings.avg_bitrate = sum_bitrate; + layer_settings.peak_bitrate = + config.bitrate.mode() == Bitrate::Mode::kConstant + ? sum_bitrate + : base::saturated_cast<uint32_t>(sum_bitrate * peak_target_ratio); + layer_settings.frame_rate = + config.framerate / static_cast<float>(1u << i); + rate_controller_settings_.layer_settings.push_back(layer_settings); + } software_rate_controller_.emplace(rate_controller_settings_); } @@ -585,6 +656,11 @@ input_arguments_.SequenceControlDesc.RateControl = current_rate_control_.GetD3D12VideoEncoderRateControl(); input_arguments_.SequenceControlDesc.PictureTargetResolution = input_size_; + + if (svc_layers_) { + metadata_.svc_generic.emplace(SVCGenericMetadata{.follow_svc_spec = true}); + } + return EncoderStatus::Codes::kOk; } @@ -622,8 +698,9 @@ software_rate_controller_->FinishIntraFrame(payload_size, rate_controller_timestamp_); } else { - software_rate_controller_->FinishInterFrame(0, payload_size, - rate_controller_timestamp_); + software_rate_controller_->FinishInterFrame( + metadata_.svc_generic ? metadata_.svc_generic->temporal_idx : 0, + payload_size, rate_controller_timestamp_); } // The next frame should be decoded at (1 / frame_rate) seconds later. rate_controller_timestamp_ +=
diff --git a/media/midi/message_util_unittest.cc b/media/midi/message_util_unittest.cc index e94d770..c31a958 100644 --- a/media/midi/message_util_unittest.cc +++ b/media/midi/message_util_unittest.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/midi/message_util.h" #include <stdint.h> +#include "base/compiler_specific.h" #include "testing/gtest/include/gtest/gtest.h" namespace midi { @@ -44,13 +40,13 @@ template <typename T, size_t N> const std::vector<T> AsVector(const T (&data)[N]) { std::vector<T> buffer; - buffer.insert(buffer.end(), data, data + N); + buffer.insert(buffer.end(), data, UNSAFE_TODO(data + N)); return buffer; } template <typename T, size_t N> void PushToVector(const T (&data)[N], std::vector<T>* buffer) { - buffer->insert(buffer->end(), data, data + N); + buffer->insert(buffer->end(), data, UNSAFE_TODO(data + N)); } TEST(MidiMessageUtilTest, GetMessageLength) {
diff --git a/media/midi/midi_manager_alsa.cc b/media/midi/midi_manager_alsa.cc index 0a2de92..1dac8a8 100644 --- a/media/midi/midi_manager_alsa.cc +++ b/media/midi/midi_manager_alsa.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/midi/midi_manager_alsa.h" #include <errno.h> @@ -19,6 +14,7 @@ #include <string_view> #include <utility> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/json/json_writer.h" #include "base/logging.h" @@ -234,7 +230,7 @@ // Subscribe to the announce port. snd_seq_port_subscribe_t* subs; - snd_seq_port_subscribe_alloca(&subs); + UNSAFE_TODO(snd_seq_port_subscribe_alloca(&subs)); snd_seq_addr_t announce_sender; snd_seq_addr_t announce_dest; announce_sender.client = SND_SEQ_CLIENT_SYSTEM; @@ -811,7 +807,7 @@ ScopedSndMidiEventPtr encoder = CreateScopedSndMidiEventPtr(kSendBufferSize); for (const auto datum : data) { snd_seq_event_t event; - snd_seq_ev_clear(&event); + UNSAFE_TODO(snd_seq_ev_clear(&event)); int result = snd_midi_event_encode_byte(encoder.get(), datum, &event); if (result == 1) { // Full event, send it. @@ -950,7 +946,7 @@ return; snd_seq_client_info_t* client_info; - snd_seq_client_info_alloca(&client_info); + UNSAFE_TODO(snd_seq_client_info_alloca(&client_info)); int err = snd_seq_get_any_client_info(in_client_.get(), client_id, client_info); if (err != 0) @@ -971,7 +967,7 @@ void MidiManagerAlsa::ProcessPortStartEvent(const snd_seq_addr_t& addr) { snd_seq_port_info_t* port_info; - snd_seq_port_info_alloca(&port_info); + UNSAFE_TODO(snd_seq_port_info_alloca(&port_info)); int err = snd_seq_get_any_port_info(in_client_.get(), addr.client, addr.port, port_info); if (err != 0) @@ -1025,11 +1021,11 @@ if (!action) action = kUdevActionChange; - if (strcmp(action, kUdevActionChange) == 0) { + if (UNSAFE_TODO(strcmp(action, kUdevActionChange)) == 0) { AddCard(dev); // Generate Web MIDI events. UpdatePortStateAndGenerateEvents(); - } else if (strcmp(action, kUdevActionRemove) == 0) { + } else if (UNSAFE_TODO(strcmp(action, kUdevActionRemove)) == 0) { RemoveCard(GetCardNumber(dev)); // Generate Web MIDI events. UpdatePortStateAndGenerateEvents(); @@ -1045,8 +1041,8 @@ snd_ctl_card_info_t* card; snd_hwdep_info_t* hwdep; - snd_ctl_card_info_alloca(&card); - snd_hwdep_info_alloca(&hwdep); + UNSAFE_TODO(snd_ctl_card_info_alloca(&card)); + UNSAFE_TODO(snd_hwdep_info_alloca(&hwdep)); const std::string id = base::StringPrintf("hw:CARD=%i", number); snd_ctl_t* handle; int err = snd_ctl_open(&handle, id.c_str(), 0); @@ -1211,9 +1207,9 @@ // TODO(agoode): return false on failure. void MidiManagerAlsa::EnumerateAlsaPorts() { snd_seq_client_info_t* client_info; - snd_seq_client_info_alloca(&client_info); + UNSAFE_TODO(snd_seq_client_info_alloca(&client_info)); snd_seq_port_info_t* port_info; - snd_seq_port_info_alloca(&port_info); + UNSAFE_TODO(snd_seq_port_info_alloca(&port_info)); // Enumerate clients. snd_seq_client_info_set_client(client_info, -1); @@ -1286,7 +1282,7 @@ // Activate port subscription. snd_seq_port_subscribe_t* subs; - snd_seq_port_subscribe_alloca(&subs); + UNSAFE_TODO(snd_seq_port_subscribe_alloca(&subs)); snd_seq_addr_t sender; sender.client = out_client_id_; sender.port = out_port; @@ -1330,7 +1326,7 @@ int port_id) { // Activate port subscription. snd_seq_port_subscribe_t* subs; - snd_seq_port_subscribe_alloca(&subs); + UNSAFE_TODO(snd_seq_port_subscribe_alloca(&subs)); snd_seq_addr_t sender; sender.client = client_id; sender.port = port_id;
diff --git a/media/midi/midi_message_queue.cc b/media/midi/midi_message_queue.cc index 9dc6e54..b04de98 100644 --- a/media/midi/midi_message_queue.cc +++ b/media/midi/midi_message_queue.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/midi/midi_message_queue.h" #include <algorithm> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/notreached.h" #include "media/midi/message_util.h" @@ -27,7 +23,7 @@ } void MidiMessageQueue::Add(const uint8_t* data, size_t length) { - queue_.insert(queue_.end(), data, data + length); + queue_.insert(queue_.end(), data, UNSAFE_TODO(data + length)); } void MidiMessageQueue::Get(std::vector<uint8_t>* message) {
diff --git a/media/midi/midi_message_queue_unittest.cc b/media/midi/midi_message_queue_unittest.cc index a1315f9..bc96905 100644 --- a/media/midi/midi_message_queue_unittest.cc +++ b/media/midi/midi_message_queue_unittest.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/midi/midi_message_queue.h" #include <stddef.h> #include <stdint.h> +#include "base/compiler_specific.h" #include "testing/gtest/include/gtest/gtest.h" namespace midi { @@ -64,7 +60,7 @@ << ", actual: " << ::testing::PrintToString(actual); } for (size_t i = 0; i < N; ++i) { - if (expected[i] != actual[i]) { + if (UNSAFE_TODO(expected[i]) != actual[i]) { return ::testing::AssertionFailure() << "expected: " << ::testing::PrintToString(expected) << ", actual: " << ::testing::PrintToString(actual);
diff --git a/media/mojo/clients/mojo_audio_encoder_unittest.cc b/media/mojo/clients/mojo_audio_encoder_unittest.cc index 13a85a8b..282c2d8 100644 --- a/media/mojo/clients/mojo_audio_encoder_unittest.cc +++ b/media/mojo/clients/mojo_audio_encoder_unittest.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/clients/mojo_audio_encoder.h" #include <memory> +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" @@ -95,7 +91,7 @@ auto result = AudioBus::Create(channels, frames); for (int channel = 0; channel < channels; channel++) { for (int i = 0; i < frames; i++) - result->channel(channel)[i] = seed; + UNSAFE_TODO(result->channel(channel)[i]) = seed; } return result; } @@ -268,10 +264,10 @@ {CHANNEL_LAYOUT_DISCRETE, audio_bus->channels()}, options.sample_rate, audio_bus->frames()); - const auto channel_data = + const auto channel_data = UNSAFE_TODO( base::span(reinterpret_cast<const uint8_t*>(audio_bus->channel(0)), AudioBus::CalculateMemorySize( - /*channels=*/1, audio_bus->frames())); + /*channels=*/1, audio_bus->frames()))); auto encoded_data = base::HeapArray<uint8_t>::CopiedFrom(channel_data); EncodedAudioBuffer output(params, std::move(encoded_data), @@ -297,7 +293,7 @@ auto* const encoded_data = reinterpret_cast<const float*>(output.encoded_data.data()); for (size_t i = 0; i < kFrameCount; i++) { - EXPECT_EQ(encoded_data[i], seed) + UNSAFE_TODO(EXPECT_EQ(encoded_data[i], seed)) << " output_number: " << output_number << " i: " << i; }
diff --git a/media/mojo/common/audio_data_s16_converter.cc b/media/mojo/common/audio_data_s16_converter.cc index 9aca1d3..7a08b99 100644 --- a/media/mojo/common/audio_data_s16_converter.cc +++ b/media/mojo/common/audio_data_s16_converter.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/common/audio_data_s16_converter.h" #include <memory> +#include "base/compiler_specific.h" #include "media/base/audio_buffer.h" #include "media/base/audio_bus.h" #include "media/base/audio_sample_types.h" @@ -43,8 +39,8 @@ signed_buffer->sample_rate = buffer->sample_rate(); int16_t* audio_data = reinterpret_cast<int16_t*>(buffer->channel_data()[0]); signed_buffer->data.assign( - audio_data, - audio_data + buffer->frame_count() * buffer->channel_count()); + audio_data, UNSAFE_TODO(audio_data + buffer->frame_count() * + buffer->channel_count())); return signed_buffer; }
diff --git a/media/mojo/common/audio_data_s16_converter_unittest.cc b/media/mojo/common/audio_data_s16_converter_unittest.cc index 49d54897..3b9a570 100644 --- a/media/mojo/common/audio_data_s16_converter_unittest.cc +++ b/media/mojo/common/audio_data_s16_converter_unittest.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/common/audio_data_s16_converter.h" #include <array> #include <memory> +#include "base/compiler_specific.h" #include "media/base/audio_buffer.h" #include "media/base/audio_bus.h" #include "media/base/audio_sample_types.h" @@ -60,7 +56,7 @@ // Compare. for (int i = 0; i < result->frame_count; i++) { - ASSERT_EQ(kTestVectorContents[i], result->data[i]); + UNSAFE_TODO(ASSERT_EQ(kTestVectorContents[i], result->data[i])); } }
diff --git a/media/mojo/common/media_type_converters.cc b/media/mojo/common/media_type_converters.cc index 269e5319..d2a48e4 100644 --- a/media/mojo/common/media_type_converters.cc +++ b/media/mojo/common/media_type_converters.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/common/media_type_converters.h" #include <memory> #include <variant> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/numerics/checked_math.h" #include "base/numerics/safe_conversions.h" @@ -263,7 +259,7 @@ const size_t size_per_channel = input->data.size() / input->channel_count; DCHECK_EQ(0u, input->data.size() % input->channel_count); for (int i = 0; i < input->channel_count; ++i) { - channel_ptrs[i] = input->data.data() + i * size_per_channel; + channel_ptrs[i] = UNSAFE_TODO(input->data.data() + i * size_per_channel); } return media::AudioBuffer::CopyFrom(
diff --git a/media/mojo/common/media_type_converters_unittest.cc b/media/mojo/common/media_type_converters_unittest.cc index 20a742d..c5e7523 100644 --- a/media/mojo/common/media_type_converters_unittest.cc +++ b/media/mojo/common/media_type_converters_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/common/media_type_converters.h" #include <stddef.h> @@ -17,6 +12,7 @@ #include <memory> #include <variant> +#include "base/compiler_specific.h" #include "media/base/audio_buffer.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" @@ -33,7 +29,7 @@ void CompareBytes(uint8_t* original_data, uint8_t* result_data, size_t length) { EXPECT_GT(length, 0u); - EXPECT_EQ(memcmp(original_data, result_data, length), 0); + UNSAFE_TODO(EXPECT_EQ(memcmp(original_data, result_data, length), 0)); } void CompareAudioBuffers(SampleFormat sample_format,
diff --git a/media/mojo/common/mojo_data_pipe_read_write_unittest.cc b/media/mojo/common/mojo_data_pipe_read_write_unittest.cc index 2024c084..872c9be 100644 --- a/media/mojo/common/mojo_data_pipe_read_write_unittest.cc +++ b/media/mojo/common/mojo_data_pipe_read_write_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/mojo/common/mojo_data_pipe_read_write.h" #include <stdint.h> #include <memory> +#include "base/compiler_specific.h" #include "base/run_loop.h" #include "base/test/mock_callback.h" #include "base/test/task_environment.h" @@ -59,8 +55,8 @@ read_buffer_.resize(buffer.size()); reader_->Read(read_buffer_.data(), buffer.size(), mock_read_cb.Get()); run_loop.RunUntilIdle(); - EXPECT_EQ(0, - std::memcmp(buffer.data(), read_buffer_.data(), buffer.size())); + UNSAFE_TODO(EXPECT_EQ( + 0, std::memcmp(buffer.data(), read_buffer_.data(), buffer.size()))); read_buffer_.clear(); } }
diff --git a/media/mojo/mojom/audio_decoder_config_mojom_traits_unittest.cc b/media/mojo/mojom/audio_decoder_config_mojom_traits_unittest.cc index 4f4c880..40a9438 100644 --- a/media/mojo/mojom/audio_decoder_config_mojom_traits_unittest.cc +++ b/media/mojo/mojom/audio_decoder_config_mojom_traits_unittest.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/mojom/audio_decoder_config_mojom_traits.h" #include <utility> +#include "base/compiler_specific.h" #include "media/base/audio_decoder_config.h" #include "media/base/media_util.h" #include "mojo/public/cpp/base/time_mojom_traits.h" @@ -21,7 +17,7 @@ TEST(AudioDecoderConfigStructTraitsTest, Normal) { const uint8_t kExtraData[] = "input extra data"; const std::vector<uint8_t> kExtraDataVector( - &kExtraData[0], &kExtraData[0] + std::size(kExtraData)); + &kExtraData[0], UNSAFE_TODO(&kExtraData[0] + std::size(kExtraData))); AudioDecoderConfig input; input.Initialize(AudioCodec::kAAC, kSampleFormatU8, CHANNEL_LAYOUT_SURROUND,
diff --git a/media/mojo/mojom/video_decoder_config_mojom_traits_unittest.cc b/media/mojo/mojom/video_decoder_config_mojom_traits_unittest.cc index 49a6b17..7144881 100644 --- a/media/mojo/mojom/video_decoder_config_mojom_traits_unittest.cc +++ b/media/mojo/mojom/video_decoder_config_mojom_traits_unittest.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/mojom/video_decoder_config_mojom_traits.h" #include <utility> +#include "base/compiler_specific.h" #include "media/base/media_util.h" #include "media/base/video_decoder_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,7 +24,7 @@ TEST(VideoDecoderConfigStructTraitsTest, ConvertVideoDecoderConfig_Normal) { const uint8_t kExtraData[] = "config extra data"; const std::vector<uint8_t> kExtraDataVector( - &kExtraData[0], &kExtraData[0] + std::size(kExtraData)); + &kExtraData[0], UNSAFE_TODO(&kExtraData[0] + std::size(kExtraData))); VideoDecoderConfig input(VideoCodec::kVP8, VP8PROFILE_ANY, VideoDecoderConfig::AlphaMode::kIsOpaque, VideoColorSpace(), kNoTransformation, kCodedSize,
diff --git a/media/mojo/services/deferred_destroy_unique_receiver_set_unittest.cc b/media/mojo/services/deferred_destroy_unique_receiver_set_unittest.cc index ec372cc..54e2d1e5 100644 --- a/media/mojo/services/deferred_destroy_unique_receiver_set_unittest.cc +++ b/media/mojo/services/deferred_destroy_unique_receiver_set_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/services/deferred_destroy_unique_receiver_set.h" #include <array> #include <memory> #include <utility> +#include "base/compiler_specific.h" #include "base/run_loop.h" #include "base/test/task_environment.h" #include "mojo/public/interfaces/bindings/tests/ping_service.test-mojom.h" @@ -74,7 +70,7 @@ std::make_unique<DeferredDestroyUniqueReceiverSet<PingService>>(); for (int i = 0; i < 2; ++i) - AddDeferredDestroyReceiver(receivers.get(), ping + i); + AddDeferredDestroyReceiver(receivers.get(), UNSAFE_TODO(ping + i)); EXPECT_EQ(2, DeferredDestroyPingImpl::instance_count); receivers.reset(); @@ -88,7 +84,8 @@ std::make_unique<DeferredDestroyUniqueReceiverSet<PingService>>(); for (int i = 0; i < 4; ++i) - impl[i] = AddDeferredDestroyReceiver(receivers.get(), ping + i); + impl[i] = + AddDeferredDestroyReceiver(receivers.get(), UNSAFE_TODO(ping + i)); EXPECT_EQ(4, DeferredDestroyPingImpl::instance_count); // Destroy deferred after disconnection until set_can_destroy().. @@ -123,7 +120,7 @@ DeferredDestroyUniqueReceiverSet<PingService> receivers; for (int i = 0; i < 2; ++i) - impl[i] = AddDeferredDestroyReceiver(&receivers, ping + i); + impl[i] = AddDeferredDestroyReceiver(&receivers, UNSAFE_TODO(ping + i)); EXPECT_EQ(2, DeferredDestroyPingImpl::instance_count); EXPECT_FALSE(receivers.empty()); @@ -133,7 +130,7 @@ // After CloseAllReceivers, new added receivers can still be deferred // destroyed. - impl[2] = AddDeferredDestroyReceiver(&receivers, ping + 2); + impl[2] = AddDeferredDestroyReceiver(&receivers, UNSAFE_TODO(ping + 2)); EXPECT_EQ(1, DeferredDestroyPingImpl::instance_count); ping[2].reset();
diff --git a/media/mojo/services/mojo_cdm_allocator_unittest.cc b/media/mojo/services/mojo_cdm_allocator_unittest.cc index a25a84e7..1a50d40 100644 --- a/media/mojo/services/mojo_cdm_allocator_unittest.cc +++ b/media/mojo/services/mojo_cdm_allocator_unittest.cc
@@ -2,22 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif +#include "media/mojo/services/mojo_cdm_allocator.h" #include <stddef.h> #include <stdint.h> #include <cstring> +#include "base/compiler_specific.h" #include "base/memory/shared_memory_mapping.h" #include "base/memory/unsafe_shared_memory_region.h" #include "media/base/video_frame.h" #include "media/cdm/api/content_decryption_module.h" #include "media/cdm/cdm_helpers.h" -#include "media/mojo/services/mojo_cdm_allocator.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/size.h" @@ -72,7 +69,7 @@ // Create a mapping and write some test data. auto& mapping = GetRegion(buffer).mapping; // Note: deliberately using sizeof() to include the null terminator. - memcpy(mapping.memory(), kTestData, sizeof(kTestData)); + UNSAFE_TODO(memcpy(mapping.memory(), kTestData, sizeof(kTestData))); } buffer->Destroy();
diff --git a/media/mojo/services/mojo_cdm_file_io.cc b/media/mojo/services/mojo_cdm_file_io.cc index e0f721a9..409d1db 100644 --- a/media/mojo/services/mojo_cdm_file_io.cc +++ b/media/mojo/services/mojo_cdm_file_io.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/mojo/services/mojo_cdm_file_io.h" #include <utility> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/metrics/histogram_macros.h" @@ -227,7 +223,7 @@ auto callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( base::BindOnce(&MojoCdmFileIO::OnFileWritten, weak_factory_.GetWeakPtr()), FileStatus::kFailure); - cdm_file_->Write(std::vector<uint8_t>(data, data + data_size), + cdm_file_->Write(std::vector<uint8_t>(data, UNSAFE_TODO(data + data_size)), std::move(callback)); }
diff --git a/media/parsers/h264_bit_reader.cc b/media/parsers/h264_bit_reader.cc index 81a5178..9f8b0d3 100644 --- a/media/parsers/h264_bit_reader.cc +++ b/media/parsers/h264_bit_reader.cc
@@ -2,13 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/parsers/h264_bit_reader.h" + #include "base/check.h" +#include "base/compiler_specific.h" namespace media { @@ -46,7 +43,7 @@ // If a sequence of 0x000003 is found, skip (ignore) the last byte (0x03). if (*data_ == 0x03 && (prev_two_bytes_ & 0xffff) == 0) { // Detected 0x000003, skip last byte. - ++data_; + UNSAFE_TODO(++data_); --bytes_left_; ++emulation_prevention_bytes_; // Need another full three bytes before we can detect the sequence again. @@ -57,7 +54,7 @@ } // Load a new byte and advance pointers. - curr_byte_ = *data_++ & 0xff; + curr_byte_ = *UNSAFE_TODO(data_++) & 0xff; --bytes_left_; num_remaining_bits_in_curr_byte_ = 8; @@ -113,8 +110,9 @@ // don't handle emulation prevention sequences because HasMoreRBSPData() is // not used when parsing slices (where cabac_zero_word elements are legal). for (off_t i = 0; i < bytes_left_; i++) { - if (data_[i] != 0) + if (UNSAFE_TODO(data_[i]) != 0) { return true; + } } bytes_left_ = 0;
diff --git a/media/parsers/h264_parser.cc b/media/parsers/h264_parser.cc index c521f321..9d3955e 100644 --- a/media/parsers/h264_parser.cc +++ b/media/parsers/h264_parser.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/parsers/h264_parser.h" #include <array> @@ -14,6 +9,7 @@ #include <limits> #include <memory> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/notreached.h" #include "base/numerics/safe_math.h" @@ -322,12 +318,13 @@ encrypted_ranges_.clear(); const uint8_t* start = stream; - const uint8_t* stream_end = stream_ + base::checked_cast<size_t>(bytes_left_); + const uint8_t* stream_end = + UNSAFE_TODO(stream_ + base::checked_cast<size_t>(bytes_left_)); for (size_t i = 0; i < subsamples.size() && start < stream_end; ++i) { - start += subsamples[i].clear_bytes; + UNSAFE_TODO(start += subsamples[i].clear_bytes); const uint8_t* end = - std::min(start + subsamples[i].cypher_bytes, stream_end); + std::min(UNSAFE_TODO(start + subsamples[i].cypher_bytes), stream_end); encrypted_ranges_.Add(start, end); start = end; } @@ -354,7 +351,8 @@ } static inline bool IsStartCode(const uint8_t* data) { - return data[0] == 0x00 && data[1] == 0x00 && data[2] == 0x01; + return data[0] == 0x00 && UNSAFE_TODO(data[1]) == 0x00 && + UNSAFE_TODO(data[2]) == 0x01; } // static @@ -368,14 +366,14 @@ while (bytes_left >= 3) { // The start code is "\0\0\1", ones are more unusual than zeroes, so let's // search for it first. - const uint8_t* tmp = - reinterpret_cast<const uint8_t*>(memchr(data + 2, 1, bytes_left - 2)); + const uint8_t* tmp = reinterpret_cast<const uint8_t*>( + UNSAFE_TODO(memchr(data + 2, 1, bytes_left - 2))); if (!tmp) { - data += bytes_left - 2; + UNSAFE_TODO(data += bytes_left - 2); bytes_left = 2; break; } - tmp -= 2; + UNSAFE_TODO(tmp -= 2); bytes_left -= tmp - data; data = tmp; @@ -386,7 +384,7 @@ // If there is a zero byte before this start code, // then it's actually a four-byte start code, so backtrack one byte. - if (*offset > 0 && *(data - 1) == 0x00) { + if (*offset > 0 && *(UNSAFE_TODO(data - 1)) == 0x00) { --(*offset); ++(*start_code_size); } @@ -394,7 +392,7 @@ return true; } - ++data; + UNSAFE_TODO(++data); --bytes_left; } @@ -420,11 +418,11 @@ } // Move the stream to the beginning of the NALU (pointing at the start code). - stream_ += base::checked_cast<size_t>(nalu_start_off); + UNSAFE_TODO(stream_ += base::checked_cast<size_t>(nalu_start_off)); bytes_left_ -= nalu_start_off; const uint8_t* nalu_data = - stream_ + base::checked_cast<size_t>(annexb_start_code_size); + UNSAFE_TODO(stream_ + base::checked_cast<size_t>(annexb_start_code_size)); off_t max_nalu_data_size = bytes_left_ - annexb_start_code_size; if (max_nalu_data_size <= 0) { DVLOG(3) << "End of stream"; @@ -469,16 +467,16 @@ // Construct a Ranges object that represents the region occupied // by the start code and the 1 byte needed to read the NAL unit type. - const uint8_t* start_code = start + *offset; - const uint8_t* start_code_end = start_code + *start_code_size; + const uint8_t* start_code = UNSAFE_TODO(start + *offset); + const uint8_t* start_code_end = UNSAFE_TODO(start_code + *start_code_size); Ranges<const uint8_t*> start_code_range; - start_code_range.Add(start_code, start_code_end + 1); + start_code_range.Add(start_code, UNSAFE_TODO(start_code_end + 1)); if (encrypted_ranges.IntersectionWith(start_code_range).size() > 0) { // The start code is inside an encrypted section so we need to scan // for another start code. *start_code_size = 0; - start += std::min(*offset + 1, bytes_left); + UNSAFE_TODO(start += std::min(*offset + 1, bytes_left)); } } while (*start_code_size == 0); @@ -548,7 +546,8 @@ return kEOStream; } - nalu->data = stream_ + base::checked_cast<size_t>(start_code_size); + nalu->data = + UNSAFE_TODO(stream_ + base::checked_cast<size_t>(start_code_size)); nalu->size = nalu_size_with_start_code - start_code_size; DVLOG(4) << "NALU found: size=" << nalu_size_with_start_code; @@ -563,7 +562,7 @@ // is called, we will effectively be skipping it; // other parsing functions will use the position saved // in bit reader for parsing, so we don't have to remember it here. - stream_ += base::checked_cast<size_t>(nalu_size_with_start_code); + UNSAFE_TODO(stream_ += base::checked_cast<size_t>(nalu_size_with_start_code)); bytes_left_ -= nalu_size_with_start_code; // Read NALU header, skip the forbidden_zero_bit, but check for it. @@ -580,8 +579,9 @@ << " ref: " << static_cast<int>(nalu->nal_ref_idc); previous_nalu_range_.clear(); - previous_nalu_range_.Add(nalu->data.get(), - nalu->data + base::checked_cast<size_t>(nalu->size)); + previous_nalu_range_.Add( + nalu->data.get(), + UNSAFE_TODO(nalu->data + base::checked_cast<size_t>(nalu->size))); return kOk; } @@ -1137,8 +1137,8 @@ Ranges<const uint8_t*> pps_range; // Only check that the next byte is unencrypted, not the rest of the NALU. const uint8_t* next_byte = - previous_nalu_range_.end(0) - br_.NumBitsLeft() / 8; - pps_range.Add(next_byte, next_byte + 1); + UNSAFE_TODO(previous_nalu_range_.end(0) - br_.NumBitsLeft() / 8); + pps_range.Add(next_byte, UNSAFE_TODO(next_byte + 1)); pps_remainder_unencrypted = (encrypted_ranges_.IntersectionWith(pps_range).size() == 0); } @@ -1191,7 +1191,7 @@ return kInvalidStream; for (int i = 0; i < 32; ++i) { - pic_num_mod = &ref_list_mods[i]; + pic_num_mod = &UNSAFE_TODO(ref_list_mods[i]); READ_UE_OR_RETURN(&pic_num_mod->modification_of_pic_nums_idc); TRUE_OR_RETURN(pic_num_mod->modification_of_pic_nums_idc < 4);
diff --git a/media/parsers/ivf_parser.cc b/media/parsers/ivf_parser.cc index 22cc1b9..8d0c758 100644 --- a/media/parsers/ivf_parser.cc +++ b/media/parsers/ivf_parser.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/parsers/ivf_parser.h" #include <cstring> #include "base/check.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" @@ -27,7 +23,7 @@ DCHECK(stream); DCHECK(file_header); ptr_ = stream; - end_ = stream + size; + end_ = UNSAFE_TODO(stream + size); CHECK_GE(end_, ptr_); if (size < sizeof(IvfFileHeader)) { @@ -90,7 +86,7 @@ } *payload = ptr_; - ptr_ += frame_header->frame_size; + UNSAFE_TODO(ptr_ += frame_header->frame_size); return true; }
diff --git a/media/parsers/jpeg_parser.cc b/media/parsers/jpeg_parser.cc index 38191cf..51477a64 100644 --- a/media/parsers/jpeg_parser.cc +++ b/media/parsers/jpeg_parser.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/parsers/jpeg_parser.h" #include <cstring> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/containers/span_reader.h" #include "base/logging.h" @@ -228,10 +224,10 @@ return false; } - if (!reader.ReadCopy(q_table[table_id].value)) { + if (!reader.ReadCopy(UNSAFE_TODO(q_table[table_id]).value)) { return false; } - q_table[table_id].valid = true; + UNSAFE_TODO(q_table[table_id]).valid = true; } return true; } @@ -261,16 +257,16 @@ JpegHuffmanTable* table; if (table_class == 1) - table = &ac_table[table_id]; + table = &UNSAFE_TODO(ac_table[table_id]); else - table = &dc_table[table_id]; + table = &UNSAFE_TODO(dc_table[table_id]); size_t count = 0u; if (!reader.ReadCopy(table->code_length)) { return false; } for (size_t i = 0; i < std::size(table->code_length); i++) - count += table->code_length[i]; + count += UNSAFE_TODO(table->code_length[i]); if (!InRange(count, 0u, sizeof(table->code_value))) { DVLOG(1) << "Invalid code count " << count;
diff --git a/media/parsers/vp8_bool_decoder.cc b/media/parsers/vp8_bool_decoder.cc index 1554b83..25c5b4b2 100644 --- a/media/parsers/vp8_bool_decoder.cc +++ b/media/parsers/vp8_bool_decoder.cc
@@ -3,11 +3,6 @@ // found in the LICENSE file. // -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - /* * Copyright (c) 2010, The WebM Project authors. All rights reserved. * @@ -53,6 +48,7 @@ #include <array> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/numerics/safe_conversions.h" namespace media { @@ -94,7 +90,7 @@ return false; user_buffer_start_ = data; user_buffer_ = data; - user_buffer_end_ = data + size; + user_buffer_end_ = UNSAFE_TODO(data + size); value_ = 0; count_ = -8; range_ = 255; @@ -118,7 +114,7 @@ while (shift >= loop_end) { count_ += CHAR_BIT; value_ |= static_cast<size_t>(*user_buffer_) << shift; - ++user_buffer_; + UNSAFE_TODO(++user_buffer_); shift -= CHAR_BIT; } }
diff --git a/media/parsers/vp9_uncompressed_header_parser.cc b/media/parsers/vp9_uncompressed_header_parser.cc index 64cc5de..cb45d668 100644 --- a/media/parsers/vp9_uncompressed_header_parser.cc +++ b/media/parsers/vp9_uncompressed_header_parser.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/parsers/vp9_uncompressed_header_parser.h" #include <array> #include <type_traits> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" @@ -778,8 +774,10 @@ } void Vp9UncompressedHeaderParser::SetupPastIndependence(Vp9FrameHeader* fhdr) { - memset(&context_->segmentation_, 0, sizeof(context_->segmentation_)); - memset(fhdr->ref_frame_sign_bias, 0, sizeof(fhdr->ref_frame_sign_bias)); + UNSAFE_TODO( + memset(&context_->segmentation_, 0, sizeof(context_->segmentation_))); + UNSAFE_TODO( + memset(fhdr->ref_frame_sign_bias, 0, sizeof(fhdr->ref_frame_sign_bias))); ResetLoopfilter(); fhdr->frame_context = kVp9DefaultFrameContext; @@ -799,15 +797,18 @@ loop_filter.delta_update = reader_.ReadBool(); if (loop_filter.delta_update) { for (size_t i = 0; i < Vp9RefType::VP9_FRAME_MAX; i++) { - loop_filter.update_ref_deltas[i] = reader_.ReadBool(); - if (loop_filter.update_ref_deltas[i]) - loop_filter.ref_deltas[i] = reader_.ReadSignedLiteral(6); + UNSAFE_TODO(loop_filter.update_ref_deltas[i]) = reader_.ReadBool(); + if (UNSAFE_TODO(loop_filter.update_ref_deltas[i])) { + UNSAFE_TODO(loop_filter.ref_deltas[i]) = reader_.ReadSignedLiteral(6); + } } for (size_t i = 0; i < Vp9LoopFilterParams::kNumModeDeltas; i++) { - loop_filter.update_mode_deltas[i] = reader_.ReadBool(); - if (loop_filter.update_mode_deltas[i]) - loop_filter.mode_deltas[i] = reader_.ReadSignedLiteral(6); + UNSAFE_TODO(loop_filter.update_mode_deltas[i]) = reader_.ReadBool(); + if (UNSAFE_TODO(loop_filter.update_mode_deltas[i])) { + UNSAFE_TODO(loop_filter.mode_deltas[i]) = + reader_.ReadSignedLiteral(6); + } } } } @@ -863,8 +864,8 @@ for (size_t i = 0; i < Vp9SegmentationParams::kNumSegments; i++) { for (size_t j = 0; j < Vp9SegmentationParams::SEG_LVL_MAX; j++) { int16_t data = 0; - segmentation.feature_enabled[i][j] = reader_.ReadBool(); - if (segmentation.feature_enabled[i][j]) { + UNSAFE_TODO(segmentation.feature_enabled[i][j]) = reader_.ReadBool(); + if (UNSAFE_TODO(segmentation.feature_enabled[i][j])) { data = reader_.ReadLiteral(kFeatureDataBits[j]); if (kFeatureDataSigned[j]) if (reader_.ReadBool()) { @@ -877,7 +878,7 @@ data = -data; } } - segmentation.feature_data[i][j] = data; + UNSAFE_TODO(segmentation.feature_data[i][j]) = data; } } } @@ -925,7 +926,8 @@ loop_filter.ref_deltas[VP9_FRAME_GOLDEN] = -1; loop_filter.ref_deltas[VP9_FRAME_ALTREF] = -1; - memset(loop_filter.mode_deltas, 0, sizeof(loop_filter.mode_deltas)); + UNSAFE_TODO( + memset(loop_filter.mode_deltas, 0, sizeof(loop_filter.mode_deltas))); } // 6.2 Uncompressed header syntax @@ -935,7 +937,8 @@ DVLOG(2) << "Vp9UncompressedHeaderParser::Parse"; reader_.Initialize(stream, frame_size); - fhdr->data = base::span(stream, base::checked_cast<size_t>(frame_size)); + fhdr->data = + UNSAFE_TODO(base::span(stream, base::checked_cast<size_t>(frame_size))); // frame marker if (reader_.ReadLiteral(2) != 0x2) { @@ -1012,17 +1015,18 @@ Vp9RefType::VP9_FRAME_LAST + kVp9NumRefsPerFrame, "ref_frame_sign_bias is not big enough"); for (size_t i = 0; i < kVp9NumRefsPerFrame; i++) { - fhdr->ref_frame_idx[i] = reader_.ReadLiteral(kVp9NumRefFramesLog2); - fhdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_LAST + i] = + UNSAFE_TODO(fhdr->ref_frame_idx[i]) = + reader_.ReadLiteral(kVp9NumRefFramesLog2); + UNSAFE_TODO(fhdr->ref_frame_sign_bias[Vp9RefType::VP9_FRAME_LAST + i]) = reader_.ReadBool(); // 8.2 Frame order constraints // ref_frame_idx[i] refers to an earlier decoded frame. const Vp9Parser::ReferenceSlot& ref = - context_->GetRefSlot(fhdr->ref_frame_idx[i]); + context_->GetRefSlot(UNSAFE_TODO(fhdr->ref_frame_idx[i])); if (!ref.initialized) { - DVLOG(1) << "ref_frame_idx[" << i - << "]=" << static_cast<int>(fhdr->ref_frame_idx[i]) + DVLOG(1) << "ref_frame_idx[" << i << "]=" + << static_cast<int>(UNSAFE_TODO(fhdr->ref_frame_idx[i])) << " refers to unused frame"; return false; }
diff --git a/media/parsers/vp9_uncompressed_header_parser_unittest.cc b/media/parsers/vp9_uncompressed_header_parser_unittest.cc index ea9ce95..802ce15d 100644 --- a/media/parsers/vp9_uncompressed_header_parser_unittest.cc +++ b/media/parsers/vp9_uncompressed_header_parser_unittest.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/parsers/vp9_uncompressed_header_parser.h" +#include "base/compiler_specific.h" #include "media/parsers/vp9_parser.h" #include "testing/gtest/include/gtest/gtest.h" @@ -62,9 +58,10 @@ static_assert(std::is_trivial<Vp9FrameContext>::value, "Vp9FrameContext is not POD, rewrite the next EXPECT_TRUE"); - EXPECT_TRUE(std::memcmp(&frame_header.frame_context, - &GetVp9DefaultFrameContextForTesting(), - sizeof(GetVp9DefaultFrameContextForTesting())) == 0); + UNSAFE_TODO(EXPECT_TRUE( + std::memcmp(&frame_header.frame_context, + &GetVp9DefaultFrameContextForTesting(), + sizeof(GetVp9DefaultFrameContextForTesting())) == 0)); } } // namespace media
diff --git a/media/parsers/webp_parser_unittest.cc b/media/parsers/webp_parser_unittest.cc index a82d13b..c46a868 100644 --- a/media/parsers/webp_parser_unittest.cc +++ b/media/parsers/webp_parser_unittest.cc
@@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif +#include "media/parsers/webp_parser.h" #include <stddef.h> #include <stdint.h> @@ -13,12 +10,12 @@ #include <memory> #include "base/base_paths.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/files/file_path.h" #include "base/files/memory_mapped_file.h" #include "base/path_service.h" #include "media/parsers/vp8_parser.h" -#include "media/parsers/webp_parser.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -203,8 +200,8 @@ ASSERT_TRUE(stream.Initialize(file_path)) << "Couldn't open stream file: " << file_path.MaybeAsASCII(); - std::unique_ptr<Vp8FrameHeader> result = - ParseWebPImage(base::span<const uint8_t>(stream.data(), stream.length())); + std::unique_ptr<Vp8FrameHeader> result = ParseWebPImage( + UNSAFE_TODO(base::span<const uint8_t>(stream.data(), stream.length()))); ASSERT_TRUE(result); ASSERT_TRUE(result->IsKeyframe()); @@ -230,8 +227,8 @@ << "Couldn't open stream file: " << file_path.MaybeAsASCII(); // Should fail because WebP parser does not parse lossless webp images. - std::unique_ptr<Vp8FrameHeader> result = - ParseWebPImage(base::span<const uint8_t>(stream.data(), stream.length())); + std::unique_ptr<Vp8FrameHeader> result = ParseWebPImage( + UNSAFE_TODO(base::span<const uint8_t>(stream.data(), stream.length()))); ASSERT_FALSE(result); } @@ -249,8 +246,8 @@ << "Couldn't open stream file: " << file_path.MaybeAsASCII(); // Should fail because WebP parser does not parse extended webp images. - std::unique_ptr<Vp8FrameHeader> result = - ParseWebPImage(base::span<const uint8_t>(stream.data(), stream.length())); + std::unique_ptr<Vp8FrameHeader> result = ParseWebPImage( + UNSAFE_TODO(base::span<const uint8_t>(stream.data(), stream.length()))); ASSERT_FALSE(result); }
diff --git a/media/renderers/resource_sync_token_client_unittest.cc b/media/renderers/resource_sync_token_client_unittest.cc index 456b53c..87e099b 100644 --- a/media/renderers/resource_sync_token_client_unittest.cc +++ b/media/renderers/resource_sync_token_client_unittest.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "media/renderers/resource_sync_token_client.h" #include <vector> +#include "base/compiler_specific.h" #include "components/viz/test/test_gles2_interface.h" #include "testing/gtest/include/gtest/gtest.h" @@ -26,13 +22,15 @@ void GenSyncTokenCHROMIUM(GLbyte* sync_token) override { viz::TestGLES2Interface::GenSyncTokenCHROMIUM(sync_token); gpu::SyncToken sync_token_data; - memcpy(sync_token_data.GetData(), sync_token, sizeof(sync_token_data)); + UNSAFE_TODO( + memcpy(sync_token_data.GetData(), sync_token, sizeof(sync_token_data))); generated_tokens_.push_back(sync_token_data); } void WaitSyncTokenCHROMIUM(const GLbyte* sync_token) override { gpu::SyncToken sync_token_data; - memcpy(sync_token_data.GetData(), sync_token, sizeof(sync_token_data)); + UNSAFE_TODO( + memcpy(sync_token_data.GetData(), sync_token, sizeof(sync_token_data))); viz::TestGLES2Interface::WaitSyncTokenCHROMIUM(sync_token); waited_tokens_.push_back(sync_token_data); }
diff --git a/media/video/gpu_memory_buffer_video_frame_pool.cc b/media/video/gpu_memory_buffer_video_frame_pool.cc index 60de1e11..2a0b1a11 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool.cc
@@ -68,10 +68,6 @@ namespace media { -namespace { - -} // namespace - // Implementation of a pool of mappable shared images(MappableSI) used to back // VideoFrames. class GpuMemoryBufferVideoFramePool::PoolImpl @@ -357,8 +353,9 @@ TRACE_EVENT2("media", "CopyRowsToI420Buffer", "bytes_per_row", bytes_per_row, "rows", rows); - if (!output) + if (!output) { return; + } DCHECK_NE(dest_stride, 0); DCHECK_LE(bytes_per_row, std::abs(dest_stride)); @@ -388,8 +385,9 @@ int dest_stride_uv) { TRACE_EVENT2("media", "CopyRowsToP010Buffer", "width", width, "rows", rows); - if (!dest_y || !dest_uv) + if (!dest_y || !dest_uv) { return; + } DCHECK_NE(dest_stride_y, 0); DCHECK_NE(dest_stride_uv, 0); @@ -430,8 +428,9 @@ int dest_stride_uv) { TRACE_EVENT2("media", "CopyRowsToNV12Buffer", "width", width, "rows", rows); - if (!dest_y || !dest_uv) + if (!dest_y || !dest_uv) { return; + } DCHECK_NE(dest_stride_y, 0); DCHECK_NE(dest_stride_uv, 0); @@ -520,8 +519,9 @@ int dest_stride) { TRACE_EVENT2("media", "CopyRowsToRGB10Buffer", "bytes_per_row", width * 2, "rows", rows); - if (!output) + if (!output) { return; + } DCHECK_NE(dest_stride, 0); DCHECK_LE(width, std::abs(dest_stride / 2)); @@ -579,10 +579,12 @@ case GpuVideoAcceleratorFactories::OutputFormat::NV12: DCHECK_EQ(video_frame->visible_rect().x() % 2, 0); DCHECK_EQ(video_frame->visible_rect().y() % 2, 0); - if (!gfx::IsOddWidthMultiPlanarBuffersAllowed()) + if (!gfx::IsOddWidthMultiPlanarBuffersAllowed()) { width = base::bits::AlignUp(width, size_t{2}); - if (!gfx::IsOddHeightMultiPlanarBuffersAllowed()) + } + if (!gfx::IsOddHeightMultiPlanarBuffersAllowed()) { height = base::bits::AlignUp(height, size_t{2}); + } output = gfx::Size(width, height); break; case GpuVideoAcceleratorFactories::OutputFormat::XR30: @@ -641,8 +643,9 @@ // Lazily initialize |output_format_| since VideoFrameOutputFormat() has to be // called on the media_thread while this object might be instantiated on any. const VideoPixelFormat pixel_format = video_frame->format(); - if (output_format_ == GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED) + if (output_format_ == GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED) { output_format_ = gpu_factories_->VideoFrameOutputFormat(pixel_format); + } // Bail if we have a change of GpuVideoAcceleratorFactories::OutputFormat; // such changes should not happen in general (see https://crbug.com/875158). if (output_format_ != gpu_factories_->VideoFrameOutputFormat(pixel_format)) { @@ -657,8 +660,9 @@ bool passthrough = false; #if BUILDFLAG(IS_APPLE) - if (!IOSurfaceCanSetColorSpace(video_frame->ColorSpace())) + if (!IOSurfaceCanSetColorSpace(video_frame->ColorSpace())) { passthrough = true; + } #endif if (!video_frame->IsMappable()) { @@ -666,8 +670,9 @@ passthrough = true; } - if (output_format_ == GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED) + if (output_format_ == GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED) { passthrough = true; + } switch (pixel_format) { // Supported cases. @@ -741,8 +746,9 @@ frame_copy_requests_.emplace_back(std::move(video_frame), std::move(frame_ready_cb), passthrough); - if (frame_copy_requests_.size() == 1u) + if (frame_copy_requests_.size() == 1u) { StartCopy(); + } } bool GpuMemoryBufferVideoFramePool::PoolImpl::OnMemoryDump( @@ -779,8 +785,9 @@ DCHECK(media_task_runner_->RunsTasksInCurrentSequence()); // Abort any pending copy requests. If one is already in flight, we can't do // anything about it. - if (frame_copy_requests_.size() <= 1u) + if (frame_copy_requests_.size() <= 1u) { return; + } frame_copy_requests_.erase(frame_copy_requests_.begin() + 1, frame_copy_requests_.end()); } @@ -821,15 +828,17 @@ : GetOrCreateFrameResource( CodedSize(request.video_frame.get(), output_format_), gfx::BufferUsage::SCANOUT_CPU_READ_WRITE, output_color_space); - if (!frame_resource) { + if (!frame_resource || !frame_resource->shared_image || + !(frame_resource->scoped_mapping = + frame_resource->shared_image->Map())) { + if (frame_resource) { + DLOG(ERROR) << "Could not get or map buffer."; + } std::move(request.frame_ready_cb).Run(std::move(request.video_frame)); frame_copy_requests_.pop_front(); continue; } - if (frame_resource->shared_image) { - frame_resource->scoped_mapping = frame_resource->shared_image->Map(); - } worker_task_runner_->PostTask( FROM_HERE, base::BindOnce(&PoolImpl::CopyVideoFrameToGpuMemoryBuffer, this, request.video_frame, frame_resource)); @@ -845,11 +854,8 @@ scoped_refptr<VideoFrame> video_frame, FrameResource* frame_resource) { CHECK(frame_resource); - if (!frame_resource->shared_image || !frame_resource->scoped_mapping) { - DLOG(ERROR) << "Could not get or map buffer."; - OnCopiesDone(/*copy_failed=*/true, std::move(video_frame), frame_resource); - return; - } + CHECK(frame_resource->shared_image); + CHECK(frame_resource->scoped_mapping); auto on_copies_done = base::BindOnce(&PoolImpl::OnCopiesDone, this, /*copy_failed=*/false, @@ -1247,8 +1253,9 @@ std::move(frame_copy_requests_.front().frame_ready_cb) .Run(std::move(video_frame)); frame_copy_requests_.pop_front(); - if (!frame_copy_requests_.empty()) + if (!frame_copy_requests_.empty()) { StartCopy(); + } } // static @@ -1322,8 +1329,9 @@ GpuMemoryBufferVideoFramePool::~GpuMemoryBufferVideoFramePool() { // May be nullptr in tests. - if (!pool_impl_) + if (!pool_impl_) { return; + } pool_impl_->Shutdown(); base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
diff --git a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc index 44e2539..d8376591 100644 --- a/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc +++ b/media/video/gpu_memory_buffer_video_frame_pool_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "media/video/gpu_memory_buffer_video_frame_pool.h" #include <stdint.h> #include <memory> +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/functional/bind.h" #include "base/task/single_thread_task_runner.h" @@ -319,9 +315,12 @@ EXPECT_EQ(1u, sii_->shared_image_count()); // Y plane = 9x9, U and V plan = 5x5. - ASSERT_EQ(kYValue, software_frame->visible_data(VideoFrame::Plane::kY)[80]); - ASSERT_EQ(kUValue, software_frame->visible_data(VideoFrame::Plane::kU)[24]); - ASSERT_EQ(kVValue, software_frame->visible_data(VideoFrame::Plane::kV)[24]); + UNSAFE_TODO(ASSERT_EQ( + kYValue, software_frame->visible_data(VideoFrame::Plane::kY)[80])); + UNSAFE_TODO(ASSERT_EQ( + kUValue, software_frame->visible_data(VideoFrame::Plane::kU)[24])); + UNSAFE_TODO(ASSERT_EQ( + kVValue, software_frame->visible_data(VideoFrame::Plane::kV)[24])); // Compare the last pixel of each plane in |software_frame| and |frame|. auto* client_si = sii_->MostRecentMappableSharedImage(); @@ -337,14 +336,17 @@ reinterpret_cast<uint8_t*>(mapping->GetMemoryForPlane(2).data()); auto y_stride = mapping->Stride(0); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kY)[80], - y_memory[y_stride * 8 + 8]); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kY)[80], + y_memory[y_stride * 8 + 8])); auto v_stride = mapping->Stride(1); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kV)[24], - v_memory[v_stride * 4 + 4]); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kV)[24], + v_memory[v_stride * 4 + 4])); auto u_stride = mapping->Stride(2); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kU)[24], - u_memory[u_stride * 4 + 4]); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kU)[24], + u_memory[u_stride * 4 + 4])); } else { EXPECT_EQ(software_frame.get(), frame.get()); @@ -416,9 +418,9 @@ software_frame->visible_data(VideoFrame::Plane::kV)); // Y plane = 17x17 = 289, U and V plan = 9x9. - ASSERT_EQ(kYValue, y_plane_data[288]); - ASSERT_EQ(kUValue, u_plane_data[80]); - ASSERT_EQ(kVValue, v_plane_data[80]); + UNSAFE_TODO(ASSERT_EQ(kYValue, y_plane_data[288])); + UNSAFE_TODO(ASSERT_EQ(kUValue, u_plane_data[80])); + UNSAFE_TODO(ASSERT_EQ(kVValue, v_plane_data[80])); // Compare the last pixel of each plane in |software_frame| and |frame|. auto* client_si = sii_->MostRecentMappableSharedImage(); @@ -434,11 +436,12 @@ reinterpret_cast<uint8_t*>(mapping->GetMemoryForPlane(2).data()); auto y_stride = mapping->Stride(0); - EXPECT_EQ(y_plane_data[288] >> 2, y_memory[y_stride * 16 + 16]); + UNSAFE_TODO( + EXPECT_EQ(y_plane_data[288] >> 2, y_memory[y_stride * 16 + 16])); auto v_stride = mapping->Stride(1); - EXPECT_EQ(v_plane_data[80] >> 2, v_memory[v_stride * 8 + 8]); + UNSAFE_TODO(EXPECT_EQ(v_plane_data[80] >> 2, v_memory[v_stride * 8 + 8])); auto u_stride = mapping->Stride(2); - EXPECT_EQ(u_plane_data[80] >> 2, u_memory[u_stride * 8 + 8]); + UNSAFE_TODO(EXPECT_EQ(u_plane_data[80] >> 2, u_memory[u_stride * 8 + 8])); } else { EXPECT_EQ(software_frame.get(), frame.get()); @@ -544,9 +547,12 @@ EXPECT_TRUE(frame->metadata().read_lock_fences_enabled); // Y plane = 5x5, U and V plan = 3x3. - ASSERT_EQ(kYValue, software_frame->visible_data(VideoFrame::Plane::kY)[24]); - ASSERT_EQ(kUValue, software_frame->visible_data(VideoFrame::Plane::kU)[8]); - ASSERT_EQ(kVValue, software_frame->visible_data(VideoFrame::Plane::kV)[8]); + UNSAFE_TODO(ASSERT_EQ( + kYValue, software_frame->visible_data(VideoFrame::Plane::kY)[24])); + UNSAFE_TODO(ASSERT_EQ( + kUValue, software_frame->visible_data(VideoFrame::Plane::kU)[8])); + UNSAFE_TODO(ASSERT_EQ( + kVValue, software_frame->visible_data(VideoFrame::Plane::kV)[8])); auto* client_si = sii_->MostRecentMappableSharedImage(); EXPECT_TRUE(!!client_si); @@ -560,13 +566,16 @@ // Compare the last pixel of each plane in |software_frame| and |frame|. // y_memory = 5x5, uv_memory = 6x3. auto y_stride = mapping->Stride(0); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kY)[24], - y_memory[y_stride * 4 + 4]); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kY)[24], + y_memory[y_stride * 4 + 4])); auto uv_stride = mapping->Stride(1); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kU)[8], - uv_memory[uv_stride * 2 + 4]); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kV)[8], - uv_memory[uv_stride * 2 + 5]); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kU)[8], + uv_memory[uv_stride * 2 + 4])); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kV)[8], + uv_memory[uv_stride * 2 + 5])); } else { EXPECT_EQ(software_frame.get(), frame.get()); } @@ -608,12 +617,12 @@ EXPECT_EQ(1u, sii_->shared_image_count()); // Y plane = 135x135 = 18225, UV plan = 136x68 = 9248. - ASSERT_EQ(kYValue, - software_frame->visible_data(VideoFrame::Plane::kY)[18224]); - ASSERT_EQ(kUValue, - software_frame->visible_data(VideoFrame::Plane::kUV)[9246]); - ASSERT_EQ(kVValue, - software_frame->visible_data(VideoFrame::Plane::kUV)[9247]); + UNSAFE_TODO(ASSERT_EQ( + kYValue, software_frame->visible_data(VideoFrame::Plane::kY)[18224])); + UNSAFE_TODO(ASSERT_EQ( + kUValue, software_frame->visible_data(VideoFrame::Plane::kUV)[9246])); + UNSAFE_TODO(ASSERT_EQ( + kVValue, software_frame->visible_data(VideoFrame::Plane::kUV)[9247])); auto* client_si = sii_->MostRecentMappableSharedImage(); EXPECT_TRUE(!!client_si); @@ -627,13 +636,16 @@ // Compare the last pixel of each plane in |software_frame| and |frame|. // y_memory = 135x135, uv_memory = 136x68. auto y_stride = mapping->Stride(0); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kY)[18224], - y_memory[y_stride * 134 + 134]); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kY)[18224], + y_memory[y_stride * 134 + 134])); auto uv_stride = mapping->Stride(1); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kUV)[9246], - uv_memory[uv_stride * 67 + 134]); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kUV)[9247], - uv_memory[uv_stride * 67 + 135]); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kUV)[9246], + uv_memory[uv_stride * 67 + 134])); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kUV)[9247], + uv_memory[uv_stride * 67 + 135])); } else { EXPECT_EQ(software_frame.get(), frame.get()); } @@ -685,8 +697,9 @@ y_memory[0]); EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kU)[0] << 6, uv_memory[0]); - EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kV)[0] << 6, - uv_memory[1]); + UNSAFE_TODO( + EXPECT_EQ(software_frame->visible_data(VideoFrame::Plane::kV)[0] << 6, + uv_memory[1])); } TEST_F(GpuMemoryBufferVideoFramePoolTest, @@ -717,9 +730,9 @@ software_frame->visible_data(VideoFrame::Plane::kV)); // Y plane = 7x7 = 49, U and V plan = 4x4 = 16. - ASSERT_EQ(kYValue, y_plane_data[48]); - ASSERT_EQ(kUValue, u_plane_data[15]); - ASSERT_EQ(kVValue, v_plane_data[15]); + UNSAFE_TODO(ASSERT_EQ(kYValue, y_plane_data[48])); + UNSAFE_TODO(ASSERT_EQ(kUValue, u_plane_data[15])); + UNSAFE_TODO(ASSERT_EQ(kVValue, v_plane_data[15])); auto* client_si = sii_->MostRecentMappableSharedImage(); EXPECT_TRUE(!!client_si); @@ -733,10 +746,13 @@ // Compare the last pixel of each plane in |software_frame| and |frame|. // y_memory = 7x7, uv_memory = 8x4, scale = 16-10 = 6. auto y_stride = mapping->Stride(0); - EXPECT_EQ(y_plane_data[48], y_memory[y_stride / 2 * 6 + 6] >> 6); + UNSAFE_TODO( + EXPECT_EQ(y_plane_data[48], y_memory[y_stride / 2 * 6 + 6] >> 6)); auto uv_stride = mapping->Stride(1); - EXPECT_EQ(u_plane_data[15], uv_memory[uv_stride / 2 * 3 + 6] >> 6); - EXPECT_EQ(v_plane_data[15], uv_memory[uv_stride / 2 * 3 + 7] >> 6); + UNSAFE_TODO( + EXPECT_EQ(u_plane_data[15], uv_memory[uv_stride / 2 * 3 + 6] >> 6)); + UNSAFE_TODO( + EXPECT_EQ(v_plane_data[15], uv_memory[uv_stride / 2 * 3 + 7] >> 6)); } else { EXPECT_EQ(software_frame.get(), frame.get());
diff --git a/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc b/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc index 46c48aa..4de3667 100644 --- a/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc +++ b/media/video/renderable_gpu_memory_buffer_video_frame_pool.cc
@@ -45,8 +45,12 @@ FrameResources& operator=(const FrameResources& other) = delete; // Allocate GpuMemoryBuffer and create SharedImage. Returns false on failure - // to do so. - bool Initialize(VideoPixelFormat format, const gfx::ColorSpace& color_space); + // to do so. The |requires_cpu_access| parameter indicates whether CPU access + // to the video frames is needed. If true, linear buffers that are mappable by + // CPU will be used; otherwise, GPU optimized buffers may be preferred. + bool Initialize(VideoPixelFormat format, + const gfx::ColorSpace& color_space, + bool requires_cpu_access); // Return true if these resources can be reused for a frame with the specified // parameters. @@ -86,7 +90,8 @@ explicit InternalRefCountedPool( std::unique_ptr<RenderableGpuMemoryBufferVideoFramePool::Context> context, - VideoPixelFormat format); + VideoPixelFormat format, + bool requires_cpu_access); // Create a VideoFrame with the specified parameters, reusing the resources // of a previous frame, if possible. @@ -118,6 +123,9 @@ context_; std::list<std::unique_ptr<FrameResources>> available_frame_resources_; bool shutting_down_ = false; + // Indicates whether the capture pipeline requires CPU mapping of captured + // frames. If true, linear CPU mappable buffers will be used. + bool requires_cpu_access_ = true; }; // Implementation of the RenderableGpuMemoryBufferVideoFramePool abstract @@ -127,7 +135,8 @@ public: explicit RenderableGpuMemoryBufferVideoFramePoolImpl( std::unique_ptr<RenderableGpuMemoryBufferVideoFramePool::Context> context, - VideoPixelFormat format); + VideoPixelFormat format, + bool requires_cpu_access); scoped_refptr<VideoFrame> MaybeCreateVideoFrame( const gfx::Size& visible_size, @@ -174,7 +183,8 @@ } bool FrameResources::Initialize(VideoPixelFormat format, - const gfx::ColorSpace& color_space) { + const gfx::ColorSpace& color_space, + bool requires_cpu_access) { // Currently only support ARGB, ABGR and NV12. CHECK(format == PIXEL_FORMAT_ARGB || format == PIXEL_FORMAT_ABGR || format == PIXEL_FORMAT_NV12 || format == PIXEL_FORMAT_RGBAF16) @@ -182,13 +192,19 @@ auto* context = pool_->GetContext(); - constexpr gfx::BufferUsage kBufferUsage = + gfx::BufferUsage buffer_usage = gfx::BufferUsage::SCANOUT_CPU_READ_WRITE; + #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) - gfx::BufferUsage::SCANOUT_VEA_CPU_READ -#else - gfx::BufferUsage::SCANOUT_CPU_READ_WRITE + buffer_usage = gfx::BufferUsage::SCANOUT_VEA_CPU_READ; +#elif BUILDFLAG(IS_LINUX) + // On Linux, GBM_BO_USE_LINEAR (implied by SCANOUT_CPU_READ_WRITE) can + // prevent GPU rendering on some drivers, notably NVIDIA's GBM driver, + // because it disables GBM_BO_USE_RENDERING. Use SCANOUT instead if + // linear buffers are not supported to ensure GPU rendering compatibility. + if (!requires_cpu_access) { + buffer_usage = gfx::BufferUsage::SCANOUT; + } #endif - ; const gfx::Size coded_size = GetCodedSizeForVideoPixelFormat(format, visible_size_); @@ -230,7 +246,7 @@ VideoPixelFormatToSharedImageFormat(format).value(); shared_image_ = context->CreateSharedImage( - coded_size, kBufferUsage, si_format, color_space, usage, sync_token_); + coded_size, buffer_usage, si_format, color_space, usage, sync_token_); if (!shared_image_) { DLOG(ERROR) << "Failed to allocate shared image for frame: visible_size=" << visible_size_.ToString() @@ -280,8 +296,11 @@ InternalRefCountedPool::InternalRefCountedPool( std::unique_ptr<RenderableGpuMemoryBufferVideoFramePool::Context> context, - const VideoPixelFormat format) - : format_(format), context_(std::move(context)) {} + const VideoPixelFormat format, + bool requires_cpu_access) + : format_(format), + context_(std::move(context)), + requires_cpu_access_(requires_cpu_access) {} scoped_refptr<VideoFrame> InternalRefCountedPool::MaybeCreateVideoFrame( const gfx::Size& visible_size, @@ -298,7 +317,8 @@ } if (!frame_resources) { frame_resources = std::make_unique<FrameResources>(this, visible_size); - if (!frame_resources->Initialize(format_, color_space)) { + if (!frame_resources->Initialize(format_, color_space, + requires_cpu_access_)) { DLOG(ERROR) << "Failed to initialize frame resources."; return nullptr; } @@ -361,11 +381,13 @@ RenderableGpuMemoryBufferVideoFramePoolImpl( std::unique_ptr<RenderableGpuMemoryBufferVideoFramePool::Context> context, - const VideoPixelFormat format) + const VideoPixelFormat format, + bool requires_cpu_access) : format_(format), pool_internal_( base::MakeRefCounted<InternalRefCountedPool>(std::move(context), - format)) {} + format, + requires_cpu_access)) {} scoped_refptr<VideoFrame> RenderableGpuMemoryBufferVideoFramePoolImpl::MaybeCreateVideoFrame( @@ -388,9 +410,10 @@ std::unique_ptr<RenderableGpuMemoryBufferVideoFramePool> RenderableGpuMemoryBufferVideoFramePool::Create( std::unique_ptr<Context> context, - VideoPixelFormat format) { + VideoPixelFormat format, + bool requires_cpu_access) { return std::make_unique<RenderableGpuMemoryBufferVideoFramePoolImpl>( - std::move(context), format); + std::move(context), format, requires_cpu_access); } } // namespace media
diff --git a/media/video/renderable_gpu_memory_buffer_video_frame_pool.h b/media/video/renderable_gpu_memory_buffer_video_frame_pool.h index 3676781..3004525e 100644 --- a/media/video/renderable_gpu_memory_buffer_video_frame_pool.h +++ b/media/video/renderable_gpu_memory_buffer_video_frame_pool.h
@@ -70,9 +70,12 @@ // Create a frame pool. The supplied `context` will live until all frames // created by the pool have been destroyed (so it may outlive the returned // pool). Only NV12 and ARGB formats are supported. + // |requires_cpu_access| determines whether linear CPU mappable buffers will + // be used. static std::unique_ptr<RenderableGpuMemoryBufferVideoFramePool> Create( std::unique_ptr<Context> context, - VideoPixelFormat format = PIXEL_FORMAT_NV12); + VideoPixelFormat format = PIXEL_FORMAT_NV12, + bool requires_cpu_access = true); // Returns a GpuMemoryBuffer-backed VideoFrame that can be rendered to. This // may return nullptr on an unsupported parameter, or may return nullptr
diff --git a/media/video/renderable_gpu_memory_buffer_video_frame_pool_unittest.cc b/media/video/renderable_gpu_memory_buffer_video_frame_pool_unittest.cc index 9f889f3..e36f025 100644 --- a/media/video/renderable_gpu_memory_buffer_video_frame_pool_unittest.cc +++ b/media/video/renderable_gpu_memory_buffer_video_frame_pool_unittest.cc
@@ -9,6 +9,7 @@ #include "base/notimplemented.h" #include "base/task/thread_pool.h" #include "base/test/bind.h" +#include "base/test/run_until.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "components/viz/common/resources/shared_image_format.h" @@ -361,6 +362,92 @@ EXPECT_FALSE(!!context); } +// Verifies that the requires_cpu_access flag controls gfx::BufferUsage in +// RenderableGpuMemoryBufferVideoFramePool allocations. On Linux, +// setting the flag to false avoids GBM linear allocations by switching +// from SCANOUT_CPU_READ_WRITE to SCANOUT. Ensures that the expected +// buffer usage value propagates to the shared image creation code path. +TEST_P(RenderableGpuMemoryBufferVideoFramePoolTest, + RequiresCpuAccessAffectsBufferUsage) { + base::test::SingleThreadTaskEnvironment task_environment; + const gfx::Size size(128, 256); + const gfx::ColorSpace color_space = GetColorSpaceForPixelFormat(format_); + + base::WeakPtr<FakeContext> context; + std::unique_ptr<RenderableGpuMemoryBufferVideoFramePool> pool; + + // Case 1 requires_cpu_access = true + { + auto context_strong = std::make_unique<FakeContext>(); + context = context_strong->GetWeakPtr(); + pool = RenderableGpuMemoryBufferVideoFramePool::Create( + std::move(context_strong), format_, /*requires_cpu_access=*/true); + } + + ASSERT_TRUE(pool); + +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) + gfx::BufferUsage expected_usage = gfx::BufferUsage::SCANOUT_VEA_CPU_READ; +#elif BUILDFLAG(IS_LINUX) + gfx::BufferUsage expected_usage = gfx::BufferUsage::SCANOUT_CPU_READ_WRITE; +#else + gfx::BufferUsage expected_usage = gfx::BufferUsage::SCANOUT_CPU_READ_WRITE; +#endif + + EXPECT_CALL(*context, + DoCreateMappableSharedImage(_, expected_usage, _, _, _, _)) + .Times(1); + + auto frame = pool->MaybeCreateVideoFrame(size, color_space); + + // Expect one frame to be destroyed. + int destroy_count = 0; + EXPECT_CALL(*context, DestroySharedImage(_, _)).WillOnce([&]() { + ++destroy_count; + }); + + frame = nullptr; + pool.reset(); + + EXPECT_TRUE(base::test::RunUntil([&]() { return destroy_count == 1; })); + EXPECT_EQ(destroy_count, 1); + + // Case 2 requires_cpu_access = false + { + auto context_strong = std::make_unique<FakeContext>(); + context = context_strong->GetWeakPtr(); + pool = RenderableGpuMemoryBufferVideoFramePool::Create( + std::move(context_strong), format_, /*requires_cpu_access=*/false); + } + + ASSERT_TRUE(pool); + +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) + gfx::BufferUsage expected_usage2 = gfx::BufferUsage::SCANOUT_VEA_CPU_READ; +#elif BUILDFLAG(IS_LINUX) + gfx::BufferUsage expected_usage2 = gfx::BufferUsage::SCANOUT; +#else + gfx::BufferUsage expected_usage2 = gfx::BufferUsage::SCANOUT_CPU_READ_WRITE; +#endif + + EXPECT_CALL(*context, + DoCreateMappableSharedImage(_, expected_usage2, _, _, _, _)) + .Times(1); + + frame = pool->MaybeCreateVideoFrame(size, color_space); + + // Expect the frame to be destroyed. + destroy_count = 0; + EXPECT_CALL(*context, DestroySharedImage(_, _)).WillRepeatedly([&]() { + ++destroy_count; + }); + + frame = nullptr; + pool.reset(); + EXPECT_TRUE(base::test::RunUntil([&]() { return destroy_count == 1; })); + EXPECT_EQ(destroy_count, 1); +} + INSTANTIATE_TEST_SUITE_P( All, RenderableGpuMemoryBufferVideoFramePoolTest,
diff --git a/net/data/ssl/chrome_root_store/OWNERS b/net/data/ssl/chrome_root_store/OWNERS index 3b1c4b6..64b5c80a 100644 --- a/net/data/ssl/chrome_root_store/OWNERS +++ b/net/data/ssl/chrome_root_store/OWNERS
@@ -1,9 +1,5 @@ # For bot updates to Chrome Root Store -# TODO(crbug.com/40852071): Remove mdb.chrome-pki-metadata@google.com once the -# pod batch migration is complete. -per-file root_store.certs=mdb.chrome-pki-metadata@google.com -per-file root_store.textproto=mdb.chrome-pki-metadata@google.com - +per-file additional.certs=mdb.chrome-pki-metadata-release-jobs@google.com per-file root_store.certs=mdb.chrome-pki-metadata-release-jobs@google.com per-file root_store.textproto=mdb.chrome-pki-metadata-release-jobs@google.com per-file root_store.md=mdb.chrome-pki-metadata-release-jobs@google.com
diff --git a/net/proxy_resolution/proxy_list.cc b/net/proxy_resolution/proxy_list.cc index c9b645f..77735a07 100644 --- a/net/proxy_resolution/proxy_list.cc +++ b/net/proxy_resolution/proxy_list.cc
@@ -205,8 +205,8 @@ NOTREACHED(); } // By default, proxy chains are not retried for 5 minutes. - UpdateRetryInfoOnFallback(proxy_retry_info, base::Minutes(5), true, - std::vector<ProxyChain>(), net_error, net_log); + UpdateRetryInfoOnFallback(proxy_retry_info, base::Minutes(5), true, net_error, + net_log); // Remove this proxy from our list. proxy_chains_.erase(proxy_chains_.begin()); @@ -240,7 +240,6 @@ ProxyRetryInfoMap* proxy_retry_info, base::TimeDelta retry_delay, bool reconsider, - const std::vector<ProxyChain>& additional_proxies_to_bypass, int net_error, const NetLogWithSource& net_log) const { DCHECK(!retry_delay.is_zero()); @@ -253,15 +252,6 @@ if (!first_chain.is_direct()) { AddProxyChainToRetryList(proxy_retry_info, retry_delay, reconsider, first_chain, net_error, net_log); - // If any additional proxies to bypass are specified, add to the retry map - // as well. - for (const ProxyChain& additional_proxy_chain : - additional_proxies_to_bypass) { - AddProxyChainToRetryList( - proxy_retry_info, retry_delay, reconsider, - ProxyChain(additional_proxy_chain.proxy_servers()), net_error, - net_log); - } } }
diff --git a/net/proxy_resolution/proxy_list.h b/net/proxy_resolution/proxy_list.h index db427c8..bbd2f5b 100644 --- a/net/proxy_resolution/proxy_list.h +++ b/net/proxy_resolution/proxy_list.h
@@ -117,22 +117,19 @@ int net_error, const NetLogWithSource& net_log); - // Updates |proxy_retry_info| to indicate that the first proxy chain in the + // Updates `proxy_retry_info` to indicate that the first proxy chain in the // list is bad. This is distinct from Fallback(), above, to allow updating // proxy retry information without modifying a given transction's proxy list. - // Will retry after |retry_delay| if positive, and will use the default proxy + // Will retry after `retry_delay` if positive, and will use the default proxy // retry duration otherwise. It may reconsider the proxy beforehand if - // |reconsider| is true. Additionally updates |proxy_retry_info| with - // |additional_proxies_to_bypass|. |net_error| should contain the network - // error countered when this proxy chain was tried, or OK if the proxy retry - // info is being updated for a non-network related reason (e.g. local policy). - void UpdateRetryInfoOnFallback( - ProxyRetryInfoMap* proxy_retry_info, - base::TimeDelta retry_delay, - bool reconsider, - const std::vector<ProxyChain>& additional_proxies_to_bypass, - int net_error, - const NetLogWithSource& net_log) const; + // `reconsider` is true. `net_error` should contain the network error + // encountered when this proxy chain was tried, or OK if the proxy retry info + // is being updated for a non-network related reason (e.g. local policy). + void UpdateRetryInfoOnFallback(ProxyRetryInfoMap* proxy_retry_info, + base::TimeDelta retry_delay, + bool reconsider, + int net_error, + const NetLogWithSource& net_log) const; private: // Updates |proxy_retry_info| to indicate that the |proxy_to_retry| in
diff --git a/net/proxy_resolution/proxy_list_unittest.cc b/net/proxy_resolution/proxy_list_unittest.cc index 97ba8725..5ceb2aa 100644 --- a/net/proxy_resolution/proxy_list_unittest.cc +++ b/net/proxy_resolution/proxy_list_unittest.cc
@@ -237,12 +237,9 @@ NetLogWithSource net_log; ProxyChain proxy_chain( ProxyUriToProxyChain("foopy1:80", ProxyServer::SCHEME_HTTP)); - std::vector<ProxyChain> bad_proxies; - bad_proxies.push_back(proxy_chain); list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80"); list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true, - bad_proxies, ERR_PROXY_CONNECTION_FAILED, - net_log); + ERR_PROXY_CONNECTION_FAILED, net_log); EXPECT_TRUE(retry_info_map.end() != retry_info_map.find(proxy_chain)); EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, retry_info_map[proxy_chain].net_error); @@ -261,11 +258,9 @@ NetLogWithSource net_log; ProxyChain proxy_chain( ProxyUriToProxyChain("foopy1:80", ProxyServer::SCHEME_HTTP)); - std::vector<ProxyChain> bad_proxies; - bad_proxies.push_back(proxy_chain); list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80"); - list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true, - bad_proxies, OK, net_log); + list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true, OK, + net_log); EXPECT_TRUE(retry_info_map.end() != retry_info_map.find(proxy_chain)); EXPECT_THAT(retry_info_map[proxy_chain].net_error, IsOk()); EXPECT_TRUE(retry_info_map.end() == @@ -275,43 +270,16 @@ retry_info_map.find(ProxyUriToProxyChain( "foopy3:80", ProxyServer::SCHEME_HTTP))); } - // Including another bad proxy should put both the first and the specified - // proxy on the retry list. - { - ProxyList list; - ProxyRetryInfoMap retry_info_map; - NetLogWithSource net_log; - ProxyChain proxy_chain( - ProxyUriToProxyChain("foopy3:80", ProxyServer::SCHEME_HTTP)); - std::vector<ProxyChain> bad_proxies; - bad_proxies.push_back(proxy_chain); - list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80"); - list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true, - bad_proxies, ERR_NAME_RESOLUTION_FAILED, - net_log); - EXPECT_TRUE(retry_info_map.end() != - retry_info_map.find(ProxyUriToProxyChain( - "foopy1:80", ProxyServer::SCHEME_HTTP))); - EXPECT_EQ(ERR_NAME_RESOLUTION_FAILED, - retry_info_map[proxy_chain].net_error); - EXPECT_TRUE(retry_info_map.end() == - retry_info_map.find(ProxyUriToProxyChain( - "foopy2:80", ProxyServer::SCHEME_HTTP))); - EXPECT_TRUE(retry_info_map.end() != retry_info_map.find(proxy_chain)); - } - // If the first proxy is DIRECT, nothing is added to the retry list, even - // if another bad proxy is specified. + // If the first proxy is DIRECT, nothing is added to the retry list. { ProxyList list; ProxyRetryInfoMap retry_info_map; NetLogWithSource net_log; ProxyChain proxy_chain( ProxyUriToProxyChain("foopy2:80", ProxyServer::SCHEME_HTTP)); - std::vector<ProxyChain> bad_proxies; - bad_proxies.push_back(proxy_chain); list.SetFromPacString("DIRECT;PROXY foopy2:80;PROXY foopy3:80"); - list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true, - bad_proxies, OK, net_log); + list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true, OK, + net_log); EXPECT_TRUE(retry_info_map.end() == retry_info_map.find(proxy_chain)); EXPECT_TRUE(retry_info_map.end() == retry_info_map.find(ProxyUriToProxyChain( @@ -328,13 +296,12 @@ // First, mark the proxy as bad for 60 seconds. list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true, - std::vector<ProxyChain>(), ERR_PROXY_CONNECTION_FAILED, net_log); // Next, mark the same proxy as bad for 1 second. This call should have no // effect, since this would cause the bad proxy to be retried sooner than // the existing retry info. - list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(1), false, - std::vector<ProxyChain>(), OK, net_log); + list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(1), false, OK, + net_log); ProxyChain proxy_chain( ProxyUriToProxyChain("foopy1:80", ProxyServer::SCHEME_HTTP)); EXPECT_TRUE(retry_info_map.end() != retry_info_map.find(proxy_chain)); @@ -361,12 +328,11 @@ list.SetFromPacString("PROXY foopy1:80;PROXY foopy2:80;PROXY foopy3:80"); // First, mark the proxy as bad for 1 second. - list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(1), false, - std::vector<ProxyChain>(), OK, net_log); + list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(1), false, OK, + net_log); // Next, mark the same proxy as bad for 60 seconds. This call should replace // the existing retry info with the new 60 second retry info. list.UpdateRetryInfoOnFallback(&retry_info_map, base::Seconds(60), true, - std::vector<ProxyChain>(), ERR_PROXY_CONNECTION_FAILED, net_log); ProxyChain proxy_chain( ProxyUriToProxyChain("foopy1:80", ProxyServer::SCHEME_HTTP));
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc index 4bd99da..f5bfb7a 100644 --- a/net/socket/socket_posix.cc +++ b/net/socket/socket_posix.cc
@@ -678,13 +678,6 @@ statistics_auto_lock.Release(); #endif // DEBUG_CRBUG_40064248_STATISTICS - // Signal to chrome_crashpad_handler that this bug has occurred. It may - // want to collect additional information. - // - // TODO(crbug.com/40064248): Remove this once sufficient information is - // collected. - SCOPED_CRASH_KEY_STRING32("net", "crbug_40064248", "1"); - // This duplicates the CHECK_LE below. Keep it here so that the aliased // debug buffers are in scope when the process crashes. CHECK_LE(send_rv, buf_len);
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index b5a8d4e..26340e4 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -729,27 +729,12 @@ SSL_set_early_data_enabled(ssl_.get(), ssl_config_.early_data_enabled); - // OpenSSL defaults some options to on, others to off. To avoid ambiguity, - // set everything we care about to an absolute value. - SslSetClearMask options; - options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true); + // TODO(crbug.com/41393419): Make this option not a no-op in BoringSSL and + // then disable it. + SSL_set_options(ssl_.get(), SSL_OP_LEGACY_SERVER_CONNECT); - // TODO(joth): Set this conditionally, see http://crbug.com/55410 - options.ConfigureFlag(SSL_OP_LEGACY_SERVER_CONNECT, true); - - SSL_set_options(ssl_.get(), options.set_mask); - SSL_clear_options(ssl_.get(), options.clear_mask); - - // Same as above, this time for the SSL mode. - SslSetClearMask mode; - - mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true); - mode.ConfigureFlag(SSL_MODE_CBC_RECORD_SPLITTING, true); - - mode.ConfigureFlag(SSL_MODE_ENABLE_FALSE_START, true); - - SSL_set_mode(ssl_.get(), mode.set_mask); - SSL_clear_mode(ssl_.get(), mode.clear_mask); + SSL_set_mode(ssl_.get(), + SSL_MODE_CBC_RECORD_SPLITTING | SSL_MODE_ENABLE_FALSE_START); // Use BoringSSL defaults, but disable 3DES and HMAC-SHA1 ciphers in ECDSA. // These are the remaining CBC-mode ECDSA ciphers.
diff --git a/net/socket/ssl_server_socket_impl.cc b/net/socket/ssl_server_socket_impl.cc index 0e4ef3e..1442c16 100644 --- a/net/socket/ssl_server_socket_impl.cc +++ b/net/socket/ssl_server_socket_impl.cc
@@ -1031,22 +1031,6 @@ CHECK(SSL_CTX_set_max_proto_version(ssl_ctx_.get(), ssl_server_config_.version_max)); - // OpenSSL defaults some options to on, others to off. To avoid ambiguity, - // set everything we care about to an absolute value. - SslSetClearMask options; - options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true); - - SSL_CTX_set_options(ssl_ctx_.get(), options.set_mask); - SSL_CTX_clear_options(ssl_ctx_.get(), options.clear_mask); - - // Same as above, this time for the SSL mode. - SslSetClearMask mode; - - mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true); - - SSL_CTX_set_mode(ssl_ctx_.get(), mode.set_mask); - SSL_CTX_clear_mode(ssl_ctx_.get(), mode.clear_mask); - if (ssl_server_config_.cipher_suite_for_testing.has_value()) { const SSL_CIPHER* cipher = SSL_get_cipher_by_value(*ssl_server_config_.cipher_suite_for_testing);
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc index 235ba68d..2614d7d8 100644 --- a/net/socket/ssl_server_socket_unittest.cc +++ b/net/socket/ssl_server_socket_unittest.cc
@@ -42,7 +42,7 @@ #include "base/test/bind.h" #include "base/test/task_environment.h" #include "build/build_config.h" -#include "crypto/rsa_private_key.h" +#include "crypto/evp.h" #include "net/base/address_list.h" #include "net/base/completion_once_callback.h" #include "net/base/host_port_pair.h" @@ -375,10 +375,9 @@ server_private_key_ = ReadTestKey("unittest.key.bin"); ASSERT_TRUE(server_private_key_); - std::unique_ptr<crypto::RSAPrivateKey> key = - ReadTestKey("unittest.key.bin"); + bssl::UniquePtr<EVP_PKEY> key = ReadTestKey("unittest.key.bin"); ASSERT_TRUE(key); - server_ssl_private_key_ = WrapOpenSSLPrivateKey(bssl::UpRef(key->key())); + server_ssl_private_key_ = WrapOpenSSLPrivateKey(std::move(key)); // Certificate provided by the host doesn't need authority. client_ssl_config_.allowed_bad_certs.emplace_back( @@ -397,7 +396,7 @@ channel_1_.reset(); channel_2_.reset(); server_context_ = CreateSSLServerContext( - server_cert_.get(), *server_private_key_, server_ssl_config_); + server_cert_.get(), server_private_key_.get(), server_ssl_config_); } void CreateContextSSLPrivateKey() { @@ -439,13 +438,12 @@ ImportCertFromFile(GetTestCertsDirectory(), cert_file_name); ASSERT_TRUE(client_cert); - std::unique_ptr<crypto::RSAPrivateKey> key = - ReadTestKey(private_key_file_name); + bssl::UniquePtr<EVP_PKEY> key = ReadTestKey(private_key_file_name); ASSERT_TRUE(key); client_context_->SetClientCertificate( GetHostAndPort(), std::move(client_cert), - WrapOpenSSLPrivateKey(bssl::UpRef(key->key()))); + WrapOpenSSLPrivateKey(std::move(key))); } void ConfigureClientCertsForServer() { @@ -469,16 +467,14 @@ } #endif // BUILDFLAG(ENABLE_CLIENT_CERTIFICATES) - std::unique_ptr<crypto::RSAPrivateKey> ReadTestKey(std::string_view name) { + bssl::UniquePtr<EVP_PKEY> ReadTestKey(std::string_view name) { base::FilePath certs_dir(GetTestCertsDirectory()); base::FilePath key_path = certs_dir.AppendASCII(name); - std::string key_string; - if (!base::ReadFileToString(key_path, &key_string)) + std::optional<std::vector<uint8_t>> pkcs8 = base::ReadFileToBytes(key_path); + if (!pkcs8.has_value()) { return nullptr; - std::unique_ptr<crypto::RSAPrivateKey> key( - crypto::RSAPrivateKey::CreateFromPrivateKeyInfo( - base::as_byte_span(key_string))); - return key; + } + return crypto::evp::PrivateKeyFromBytes(*pkcs8); } void PumpServerToClient() { @@ -519,7 +515,7 @@ std::unique_ptr<SSLServerContext> server_context_; std::unique_ptr<SSLClientSocket> client_socket_; std::unique_ptr<SSLServerSocket> server_socket_; - std::unique_ptr<crypto::RSAPrivateKey> server_private_key_; + bssl::UniquePtr<EVP_PKEY> server_private_key_; scoped_refptr<SSLPrivateKey> server_ssl_private_key_; scoped_refptr<X509Certificate> server_cert_; };
diff --git a/net/ssl/openssl_ssl_util.cc b/net/ssl/openssl_ssl_util.cc index 214b43d..a270c43 100644 --- a/net/ssl/openssl_ssl_util.cc +++ b/net/ssl/openssl_ssl_util.cc
@@ -24,14 +24,6 @@ namespace net { -SslSetClearMask::SslSetClearMask() = default; - -void SslSetClearMask::ConfigureFlag(long flag, bool state) { - (state ? set_mask : clear_mask) |= flag; - // Make sure we haven't got any intersection in the set & clear options. - DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state; -} - namespace { class OpenSSLNetErrorLibSingleton {
diff --git a/net/ssl/openssl_ssl_util.h b/net/ssl/openssl_ssl_util.h index 20eabaeb..fe02f6ca 100644 --- a/net/ssl/openssl_ssl_util.h +++ b/net/ssl/openssl_ssl_util.h
@@ -33,16 +33,6 @@ // extracted from |posted_from|. The function code of the error is left as 0. void OpenSSLPutNetError(const base::Location& posted_from, int err); -// Utility to construct the appropriate set & clear masks for use the OpenSSL -// options and mode configuration functions. (SSL_set_options etc) -struct SslSetClearMask { - SslSetClearMask(); - void ConfigureFlag(long flag, bool state); - - long set_mask = 0; - long clear_mask = 0; -}; - // Converts an OpenSSL error code into a net error code, walking the OpenSSL // error stack if needed. //
diff --git a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java index 4a23ebde..96d6777 100644 --- a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java +++ b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServerRule.java
@@ -69,25 +69,28 @@ } /** - * Sets the port that the server will be started with. Must be called before the first - * {@link #getServer()} call. + * Sets the port that the server will be started with. Must be called before the first {@link + * #getServer()} call. * * @param port the port to start the server with, or 0 for an automatically selected one. */ - public void setServerPort(int port) { + public EmbeddedTestServerRule setServerPort(int port) { assert mServer == null; mServerPort = port; + return this; } /** Sets whether to create an HTTPS (vs HTTP) server. */ - public void setServerUsesHttps(boolean useHttps) { + public EmbeddedTestServerRule setServerUsesHttps(boolean useHttps) { assert mServer == null; mUseHttps = useHttps; + return this; } /** Sets what type of certificate the server uses when running as an HTTPS server. */ - public void setCertificateType(@ServerCertificate int certificateType) { + public EmbeddedTestServerRule setCertificateType(@ServerCertificate int certificateType) { assert mServer == null; mCertificateType = certificateType; + return this; } }
diff --git a/net/third_party/quiche/src b/net/third_party/quiche/src index e7874f2..3254739 160000 --- a/net/third_party/quiche/src +++ b/net/third_party/quiche/src
@@ -1 +1 @@ -Subproject commit e7874f26f3bf5b88f155190994cbb2cee8fd42c2 +Subproject commit 3254739b95207731898c7eae118d109009a76c10
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn index 38abd11e..d0fb4ae 100644 --- a/pdf/BUILD.gn +++ b/pdf/BUILD.gn
@@ -258,6 +258,8 @@ "pdf_ink_undo_redo_model.h", "pdfium/pdfium_ink_reader.cc", "pdfium/pdfium_ink_reader.h", + "pdfium/pdfium_ink_transform.cc", + "pdfium/pdfium_ink_transform.h", "pdfium/pdfium_ink_writer.cc", "pdfium/pdfium_ink_writer.h", ] @@ -543,6 +545,7 @@ "pdf_ink_transform_unittest.cc", "pdf_ink_undo_redo_model_unittest.cc", "pdfium/pdfium_ink_reader_unittest.cc", + "pdfium/pdfium_ink_transform_unittest.cc", "pdfium/pdfium_ink_writer_unittest.cc", "test/pdf_ink_test_helpers.cc", "test/pdf_ink_test_helpers.h",
diff --git a/pdf/features.gni b/pdf/features.gni index 63cb8a5..0b596e5 100644 --- a/pdf/features.gni +++ b/pdf/features.gni
@@ -2,7 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//ash/webui/media_app_ui/media_app_ui.gni") import("//build/config/cast.gni") # Most build code won't need to include this file. Instead you can @@ -19,7 +18,7 @@ # This argument indicates whether the ink libraries provided by the ChromeOS # media app dependency is enabled. It also determines whether the annotation # feature is enabled for the PDF Viewer on Chrome OS. - enable_ink = enable_cros_media_app + enable_ink = false # Enable the next generation of ink libraries. This can co-exist with # `enable_ink` above.
diff --git a/pdf/pdf_transform.cc b/pdf/pdf_transform.cc index d622292..1100244 100644 --- a/pdf/pdf_transform.cc +++ b/pdf/pdf_transform.cc
@@ -8,25 +8,51 @@ #include <utility> #include "base/notreached.h" -#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size_f.h" +#include "ui/gfx/geometry/vector2d_f.h" namespace chrome_pdf { namespace { -// When a PdfRectangle has top < bottom, or right < left, the values should be -// swapped. -void SwapPdfRectangleValuesIfNeeded(PdfRectangle* rect) { - if (rect->top < rect->bottom) - std::swap(rect->top, rect->bottom); - if (rect->right < rect->left) - std::swap(rect->right, rect->left); +// Return the default size letter size (8.5" X 11") clip box. This just follows +// the PDFium way of handling these corner cases. PDFium always considers +// US-Letter as the default page size. +PdfRect GetDefaultClipBox(bool rotated) { + constexpr int kDpi = 72; + constexpr float kPaperWidth = 8.5 * kDpi; + constexpr float kPaperHeight = 11 * kDpi; + return PdfRect(/*left=*/0, /*bottom=*/0, + /*right=*/rotated ? kPaperHeight : kPaperWidth, + /*top=*/rotated ? kPaperWidth : kPaperHeight); } } // namespace +void PdfRect::Normalize() { + if (top_ < bottom_) { + std::swap(top_, bottom_); + } + if (right_ < left_) { + std::swap(right_, left_); + } +} + +void PdfRect::Scale(float scale_factor) { + left_ *= scale_factor; + bottom_ *= scale_factor; + right_ *= scale_factor; + top_ *= scale_factor; +} + +void PdfRect::Intersect(const PdfRect& rect) { + left_ = std::max(left_, rect.left_); + bottom_ = std::max(bottom_, rect.bottom_); + right_ = std::min(right_, rect.right_); + top_ = std::min(top_, rect.top_); +} + float CalculateScaleFactor(const gfx::Rect& content_rect, const gfx::SizeF& src_size, bool rotated) { @@ -42,29 +68,19 @@ return std::min(ratio_x, ratio_y); } -void SetDefaultClipBox(bool rotated, PdfRectangle* clip_box) { - constexpr int kDpi = 72; - constexpr float kPaperWidth = 8.5 * kDpi; - constexpr float kPaperHeight = 11 * kDpi; - clip_box->left = 0; - clip_box->bottom = 0; - clip_box->right = rotated ? kPaperHeight : kPaperWidth; - clip_box->top = rotated ? kPaperWidth : kPaperHeight; -} - void CalculateMediaBoxAndCropBox(bool rotated, bool has_media_box, bool has_crop_box, - PdfRectangle* media_box, - PdfRectangle* crop_box) { + PdfRect* media_box, + PdfRect* crop_box) { if (has_media_box) - SwapPdfRectangleValuesIfNeeded(media_box); + media_box->Normalize(); if (has_crop_box) - SwapPdfRectangleValuesIfNeeded(crop_box); + crop_box->Normalize(); if (!has_media_box && !has_crop_box) { - SetDefaultClipBox(rotated, crop_box); - SetDefaultClipBox(rotated, media_box); + *crop_box = GetDefaultClipBox(rotated); + *media_box = *crop_box; } else if (has_crop_box && !has_media_box) { *media_box = *crop_box; } else if (has_media_box && !has_crop_box) { @@ -72,55 +88,40 @@ } } -PdfRectangle CalculateClipBoxBoundary(const PdfRectangle& media_box, - const PdfRectangle& crop_box) { - PdfRectangle clip_box; - +PdfRect CalculateClipBoxBoundary(const PdfRect& media_box, + const PdfRect& crop_box) { // Clip `media_box` to the size of `crop_box`, but ignore `crop_box` if it is // bigger than `media_box`. - clip_box.left = std::max(crop_box.left, media_box.left); - clip_box.bottom = std::max(crop_box.bottom, media_box.bottom); - clip_box.right = std::min(crop_box.right, media_box.right); - clip_box.top = std::min(crop_box.top, media_box.top); + PdfRect clip_box = crop_box; + clip_box.Intersect(media_box); return clip_box; } -void ScalePdfRectangle(float scale_factor, PdfRectangle* rect) { - rect->left *= scale_factor; - rect->bottom *= scale_factor; - rect->right *= scale_factor; - rect->top *= scale_factor; -} - -gfx::PointF CalculateScaledClipBoxOffset(const gfx::Rect& content_rect, - const PdfRectangle& source_clip_box) { - const float clip_box_width = source_clip_box.right - source_clip_box.left; - const float clip_box_height = source_clip_box.top - source_clip_box.bottom; - +gfx::Vector2dF CalculateScaledClipBoxOffset(const gfx::Rect& content_rect, + const PdfRect& source_clip_box) { // Center the intended clip region to real clip region. - return gfx::PointF((content_rect.width() - clip_box_width) / 2 + - content_rect.x() - source_clip_box.left, - (content_rect.height() - clip_box_height) / 2 + - content_rect.y() - source_clip_box.bottom); + return gfx::Vector2dF((content_rect.width() - source_clip_box.width()) / 2 + + content_rect.x() - source_clip_box.left(), + (content_rect.height() - source_clip_box.height()) / 2 + + content_rect.y() - source_clip_box.bottom()); } -gfx::PointF CalculateNonScaledClipBoxOffset( - int rotation, - int page_width, - int page_height, - const PdfRectangle& source_clip_box) { +gfx::Vector2dF CalculateNonScaledClipBoxOffset(int rotation, + int page_width, + int page_height, + const PdfRect& source_clip_box) { // Align the intended clip region to left-top corner of real clip region. switch (rotation) { case 0: - return gfx::PointF(-1 * source_clip_box.left, - page_height - source_clip_box.top); + return gfx::Vector2dF(-1 * source_clip_box.left(), + page_height - source_clip_box.top()); case 1: - return gfx::PointF(0, -1 * source_clip_box.bottom); + return gfx::Vector2dF(0, -1 * source_clip_box.bottom()); case 2: - return gfx::PointF(page_width - source_clip_box.right, 0); + return gfx::Vector2dF(page_width - source_clip_box.right(), 0); case 3: - return gfx::PointF(page_height - source_clip_box.right, - page_width - source_clip_box.top); + return gfx::Vector2dF(page_height - source_clip_box.right(), + page_width - source_clip_box.top()); default: NOTREACHED(); }
diff --git a/pdf/pdf_transform.h b/pdf/pdf_transform.h index 676f0e3..3531ec1 100644 --- a/pdf/pdf_transform.h +++ b/pdf/pdf_transform.h
@@ -5,8 +5,9 @@ #ifndef PDF_PDF_TRANSFORM_H_ #define PDF_PDF_TRANSFORM_H_ +#include "ui/gfx/geometry/vector2d_f.h" + namespace gfx { -class PointF; class Rect; class SizeF; } // namespace gfx @@ -16,12 +17,43 @@ // All the code here works in the PDF coordinate space. The origin is at the // bottom-left, and all units are in points. -// A rect struct for use with FPDF bounding box functions. -struct PdfRectangle { - float left; - float bottom; - float right; - float top; +// Represents PDF rectangles with the properties stated above. +// Can be easily used with PDFium's bounding box functions. +class PdfRect { + public: + constexpr PdfRect() : PdfRect(0, 0, 0, 0) {} + constexpr PdfRect(float left, float bottom, float right, float top) + : left_(left), bottom_(bottom), right_(right), top_(top) {} + constexpr ~PdfRect() = default; + + float left() const { return left_; } + float bottom() const { return bottom_; } + float right() const { return right_; } + float top() const { return top_; } + + // These return pointers so they can be directly passed into PDFium's public + // API, which is written in C. + float* writable_left() { return &left_; } + float* writable_bottom() { return &bottom_; } + float* writable_right() { return &right_; } + float* writable_top() { return &top_; } + + float width() const { return right_ - left_; } + float height() const { return top_ - bottom_; } + + // When a PdfRect has top < bottom, or right < left, the values should be + // swapped. + void Normalize(); + + void Scale(float scale_factor); + + void Intersect(const PdfRect& rect); + + private: + float left_; + float bottom_; + float right_; + float top_; }; // Calculate the scale factor between `content_rect` and a page of `src_size`. @@ -33,20 +65,15 @@ const gfx::SizeF& src_size, bool rotated); -// Make the default size to be letter size (8.5" X 11"). We are just following -// the PDFium way of handling these corner cases. PDFium always consider -// US-Letter as the default page size. -void SetDefaultClipBox(bool rotated, PdfRectangle* clip_box); - // Set the media box and/or crop box as needed. If both boxes are there, then // nothing needs to be done. If one box is missing, then fill it with the value // from the other box. If both boxes are missing, then they both get the default -// value from SetDefaultClipBox(), based on `rotated`. +// value from GetDefaultClipBox(), based on `rotated`. void CalculateMediaBoxAndCropBox(bool rotated, bool has_media_box, bool has_crop_box, - PdfRectangle* media_box, - PdfRectangle* crop_box); + PdfRect* media_box, + PdfRect* crop_box); // Compute source clip box boundaries based on the crop box / media box of // source page and scale factor. @@ -54,11 +81,8 @@ // // `media_box` The PDF's media box. // `crop_box` The PDF's crop box. -PdfRectangle CalculateClipBoxBoundary(const PdfRectangle& media_box, - const PdfRectangle& crop_box); - -// Scale `rect` by `scale_factor`. -void ScalePdfRectangle(float scale_factor, PdfRectangle* rect); +PdfRect CalculateClipBoxBoundary(const PdfRect& media_box, + const PdfRect& crop_box); // Calculate the clip box translation offset for a page that does need to be // scaled. @@ -68,8 +92,8 @@ // origin. // Returns the final translation offsets for the source clip box, relative to // the origin. -gfx::PointF CalculateScaledClipBoxOffset(const gfx::Rect& content_rect, - const PdfRectangle& source_clip_box); +gfx::Vector2dF CalculateScaledClipBoxOffset(const gfx::Rect& content_rect, + const PdfRect& source_clip_box); // Calculate the clip box offset for a page that does not need to be scaled. // @@ -81,11 +105,10 @@ // origin. // Returns the final translation offsets for the source clip box, relative to // the origin. -gfx::PointF CalculateNonScaledClipBoxOffset( - int rotation, - int page_width, - int page_height, - const PdfRectangle& source_clip_box); +gfx::Vector2dF CalculateNonScaledClipBoxOffset(int rotation, + int page_width, + int page_height, + const PdfRect& source_clip_box); } // namespace chrome_pdf
diff --git a/pdf/pdf_transform_unittest.cc b/pdf/pdf_transform_unittest.cc index a8cac8bb..b7f5879 100644 --- a/pdf/pdf_transform_unittest.cc +++ b/pdf/pdf_transform_unittest.cc
@@ -6,9 +6,9 @@ #include "printing/units.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size_f.h" +#include "ui/gfx/geometry/vector2d_f.h" namespace chrome_pdf { @@ -19,44 +19,37 @@ constexpr float kDefaultRatio = kDefaultWidth / kDefaultHeight; constexpr float kTolerance = 0.0001f; -void ExpectDefaultPortraitBox(const PdfRectangle& box) { - EXPECT_FLOAT_EQ(0, box.left); - EXPECT_FLOAT_EQ(0, box.bottom); - EXPECT_FLOAT_EQ(kDefaultWidth, box.right); - EXPECT_FLOAT_EQ(kDefaultHeight, box.top); +void ExpectDefaultPortraitBox(const PdfRect& box) { + EXPECT_FLOAT_EQ(0, box.left()); + EXPECT_FLOAT_EQ(0, box.bottom()); + EXPECT_FLOAT_EQ(kDefaultWidth, box.right()); + EXPECT_FLOAT_EQ(kDefaultHeight, box.top()); } -void ExpectDefaultLandscapeBox(const PdfRectangle& box) { - EXPECT_FLOAT_EQ(0, box.left); - EXPECT_FLOAT_EQ(0, box.bottom); - EXPECT_FLOAT_EQ(kDefaultHeight, box.right); - EXPECT_FLOAT_EQ(kDefaultWidth, box.top); +void ExpectDefaultLandscapeBox(const PdfRect& box) { + EXPECT_FLOAT_EQ(0, box.left()); + EXPECT_FLOAT_EQ(0, box.bottom()); + EXPECT_FLOAT_EQ(kDefaultHeight, box.right()); + EXPECT_FLOAT_EQ(kDefaultWidth, box.top()); } -void ExpectBoxesAreEqual(const PdfRectangle& expected, - const PdfRectangle& actual) { - EXPECT_FLOAT_EQ(expected.left, actual.left); - EXPECT_FLOAT_EQ(expected.bottom, actual.bottom); - EXPECT_FLOAT_EQ(expected.right, actual.right); - EXPECT_FLOAT_EQ(expected.top, actual.top); +void ExpectBoxesAreEqual(const PdfRect& expected, const PdfRect& actual) { + EXPECT_FLOAT_EQ(expected.left(), actual.left()); + EXPECT_FLOAT_EQ(expected.bottom(), actual.bottom()); + EXPECT_FLOAT_EQ(expected.right(), actual.right()); + EXPECT_FLOAT_EQ(expected.top(), actual.top()); } -void InitializeBoxToInvalidValues(PdfRectangle* box) { - box->left = box->bottom = box->right = box->top = -1; +void InitializeBoxToInvalidValues(PdfRect* box) { + *box = PdfRect(-1, -1, -1, -1); } -void InitializeBoxToDefaultPortraitValues(PdfRectangle* box) { - box->left = 0; - box->bottom = 0; - box->right = kDefaultWidth; - box->top = kDefaultHeight; +void InitializeBoxToDefaultPortraitValues(PdfRect* box) { + *box = PdfRect(0, 0, kDefaultWidth, kDefaultHeight); } -void InitializeBoxToDefaultLandscapeValue(PdfRectangle* box) { - box->left = 0; - box->bottom = 0; - box->right = kDefaultHeight; - box->top = kDefaultWidth; +void InitializeBoxToDefaultLandscapeValue(PdfRect* box) { + *box = PdfRect(0, 0, kDefaultHeight, kDefaultWidth); } } // namespace @@ -101,19 +94,9 @@ EXPECT_NEAR(0.01263f, scale, kTolerance); } -TEST(PdfTransformTest, SetDefaultClipBox) { - PdfRectangle box; - - SetDefaultClipBox(false, &box); - ExpectDefaultPortraitBox(box); - - SetDefaultClipBox(true, &box); - ExpectDefaultLandscapeBox(box); -} - TEST(PdfTransformTest, CalculateMediaBoxAndCropBox) { - PdfRectangle media_box; - PdfRectangle crop_box; + PdfRect media_box; + PdfRect crop_box; // Assume both boxes are there. InitializeBoxToDefaultPortraitValues(&media_box); @@ -133,24 +116,24 @@ ExpectDefaultLandscapeBox(crop_box); // Assume crop box is missing. - constexpr PdfRectangle expected_box = {0, 0, 42, 420}; - media_box = expected_box; + constexpr PdfRect kExpctedBox(0, 0, 42, 420); + media_box = kExpctedBox; InitializeBoxToInvalidValues(&crop_box); CalculateMediaBoxAndCropBox(false, true, false, &media_box, &crop_box); - ExpectBoxesAreEqual(expected_box, media_box); - ExpectBoxesAreEqual(expected_box, crop_box); + ExpectBoxesAreEqual(kExpctedBox, media_box); + ExpectBoxesAreEqual(kExpctedBox, crop_box); // Assume media box is missing. InitializeBoxToInvalidValues(&media_box); CalculateMediaBoxAndCropBox(false, false, true, &media_box, &crop_box); - ExpectBoxesAreEqual(expected_box, media_box); - ExpectBoxesAreEqual(expected_box, crop_box); + ExpectBoxesAreEqual(kExpctedBox, media_box); + ExpectBoxesAreEqual(kExpctedBox, crop_box); } TEST(PdfTransformTest, CalculateClipBoxBoundary) { - PdfRectangle media_box; - PdfRectangle crop_box; - PdfRectangle result; + PdfRect media_box; + PdfRect crop_box; + PdfRect result; // media box and crop box are the same. InitializeBoxToDefaultPortraitValues(&media_box); @@ -161,49 +144,50 @@ // media box is portrait and crop box is landscape. InitializeBoxToDefaultLandscapeValue(&crop_box); result = CalculateClipBoxBoundary(media_box, crop_box); - EXPECT_FLOAT_EQ(0, result.left); - EXPECT_FLOAT_EQ(0, result.bottom); - EXPECT_FLOAT_EQ(kDefaultWidth, result.right); - EXPECT_FLOAT_EQ(kDefaultWidth, result.top); + EXPECT_FLOAT_EQ(0, result.left()); + EXPECT_FLOAT_EQ(0, result.bottom()); + EXPECT_FLOAT_EQ(kDefaultWidth, result.right()); + EXPECT_FLOAT_EQ(kDefaultWidth, result.top()); // crop box is smaller than media box. - crop_box.left = 0; - crop_box.bottom = 0; - crop_box.right = 100; - crop_box.top = 200; + crop_box = PdfRect( + /*left=*/0, + /*bottom=*/0, + /*right=*/100, + /*top=*/200); result = CalculateClipBoxBoundary(media_box, crop_box); - EXPECT_FLOAT_EQ(0, result.left); - EXPECT_FLOAT_EQ(0, result.bottom); - EXPECT_FLOAT_EQ(100, result.right); - EXPECT_FLOAT_EQ(200, result.top); + EXPECT_FLOAT_EQ(0, result.left()); + EXPECT_FLOAT_EQ(0, result.bottom()); + EXPECT_FLOAT_EQ(100, result.right()); + EXPECT_FLOAT_EQ(200, result.top()); // crop box is smaller than the media box in one dimension and longer in the // other. - crop_box.left = 0; - crop_box.bottom = 0; - crop_box.right = 100; - crop_box.top = 2000; + crop_box = PdfRect( + /*left=*/0, + /*bottom=*/0, + /*right=*/100, + /*top=*/2000); result = CalculateClipBoxBoundary(media_box, crop_box); - EXPECT_FLOAT_EQ(0, result.left); - EXPECT_FLOAT_EQ(0, result.bottom); - EXPECT_FLOAT_EQ(100, result.right); - EXPECT_FLOAT_EQ(kDefaultHeight, result.top); + EXPECT_FLOAT_EQ(0, result.left()); + EXPECT_FLOAT_EQ(0, result.bottom()); + EXPECT_FLOAT_EQ(100, result.right()); + EXPECT_FLOAT_EQ(kDefaultHeight, result.top()); } TEST(PdfTransformTest, CalculateScaledClipBoxOffset) { constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight); - PdfRectangle clip_box; - gfx::PointF offset; // `rect` and `clip_box` are the same size. + PdfRect clip_box; InitializeBoxToDefaultPortraitValues(&clip_box); - offset = CalculateScaledClipBoxOffset(rect, clip_box); + gfx::Vector2dF offset = CalculateScaledClipBoxOffset(rect, clip_box); EXPECT_FLOAT_EQ(0, offset.x()); EXPECT_FLOAT_EQ(0, offset.y()); // `rect` is larger than `clip_box`. - clip_box.top /= 2; - clip_box.right /= 4; + *clip_box.writable_top() /= 2; + *clip_box.writable_right() /= 4; offset = CalculateScaledClipBoxOffset(rect, clip_box); EXPECT_FLOAT_EQ(229.5f, offset.x()); EXPECT_FLOAT_EQ(198, offset.y()); @@ -212,12 +196,11 @@ TEST(PdfTransformTest, CalculateNonScaledClipBoxOffset) { int page_width = kDefaultWidth; int page_height = kDefaultHeight; - PdfRectangle clip_box; - gfx::PointF offset; // `rect`, page size and `clip_box` are the same. + PdfRect clip_box; InitializeBoxToDefaultPortraitValues(&clip_box); - offset = + gfx::Vector2dF offset = CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box); EXPECT_FLOAT_EQ(0, offset.x()); EXPECT_FLOAT_EQ(0, offset.y()); @@ -235,8 +218,8 @@ EXPECT_FLOAT_EQ(-180, offset.y()); // Smaller `clip_box`. - clip_box.top /= 4; - clip_box.right /= 2; + *clip_box.writable_top() /= 4; + *clip_box.writable_right() /= 2; offset = CalculateNonScaledClipBoxOffset(0, page_width, page_height, clip_box); EXPECT_FLOAT_EQ(0, offset.x()); @@ -281,17 +264,16 @@ int page_width = kDefaultWidth; int page_height = kDefaultHeight; constexpr gfx::Rect rect(kDefaultWidth, kDefaultHeight); - PdfRectangle clip_box; - gfx::PointF offset; - constexpr PdfRectangle expected_media_box_b491160 = {0, -792, 612, 0}; - PdfRectangle media_box_b491160 = {0, 0, 612, -792}; + constexpr PdfRect expected_media_box_b491160 = {0, -792, 612, 0}; + PdfRect media_box_b491160 = {0, 0, 612, -792}; + PdfRect clip_box; CalculateMediaBoxAndCropBox(false, true, false, &media_box_b491160, &clip_box); ExpectBoxesAreEqual(expected_media_box_b491160, media_box_b491160); ExpectBoxesAreEqual(expected_media_box_b491160, clip_box); - offset = CalculateScaledClipBoxOffset(rect, media_box_b491160); + gfx::Vector2dF offset = CalculateScaledClipBoxOffset(rect, media_box_b491160); EXPECT_FLOAT_EQ(0, offset.x()); EXPECT_FLOAT_EQ(792, offset.y()); @@ -300,7 +282,7 @@ EXPECT_FLOAT_EQ(0, offset.x()); EXPECT_FLOAT_EQ(792, offset.y()); - PdfRectangle media_box_b588757 = {0, 792, 612, 0}; + PdfRect media_box_b588757 = {0, 792, 612, 0}; CalculateMediaBoxAndCropBox(false, true, false, &media_box_b588757, &clip_box); ExpectDefaultPortraitBox(media_box_b588757); @@ -315,7 +297,7 @@ EXPECT_FLOAT_EQ(0, offset.x()); EXPECT_FLOAT_EQ(0, offset.y()); - PdfRectangle media_box_left_right_flipped = {612, 792, 0, 0}; + PdfRect media_box_left_right_flipped = {612, 792, 0, 0}; CalculateMediaBoxAndCropBox(false, true, false, &media_box_left_right_flipped, &clip_box); ExpectDefaultPortraitBox(media_box_left_right_flipped);
diff --git a/pdf/pdfium/pdfium_ink_reader.cc b/pdf/pdfium/pdfium_ink_reader.cc index 27d56efa..95f39df 100644 --- a/pdf/pdfium/pdfium_ink_reader.cc +++ b/pdf/pdfium/pdfium_ink_reader.cc
@@ -14,10 +14,9 @@ #include "base/strings/utf_string_conversions.h" #include "pdf/pdf_ink_constants.h" #include "pdf/pdf_ink_conversions.h" -#include "pdf/pdf_ink_transform.h" #include "pdf/pdf_transform.h" #include "pdf/pdfium/pdfium_api_wrappers.h" -#include "pdf/pdfium/pdfium_rotation.h" +#include "pdf/pdfium/pdfium_ink_transform.h" #include "printing/units.h" #include "third_party/ink/src/ink/geometry/mesh.h" #include "third_party/ink/src/ink/geometry/partitioned_mesh.h" @@ -173,19 +172,8 @@ return results; } - // Get the intersection between the page's MediaBox and CropBox, to find - // the translation offset for the shapes' transform. - FS_RECTF bounding_box; - auto result = FPDF_GetPageBoundingBox(page, &bounding_box); - CHECK(result); - const gfx::Vector2dF offset(bounding_box.left, bounding_box.bottom); - const gfx::Transform transform = - GetCanonicalToPdfTransform( - {FPDF_GetPageWidthF(page), FPDF_GetPageHeightF(page)}, - GetPageRotation(page).value_or(PageRotation::kRotate0), offset) - .GetCheckedInverse(); - + GetCanonicalToPdfTransformForPage(page).GetCheckedInverse(); const int page_object_count = FPDFPage_CountObjects(page); for (int i = 0; i < page_object_count; ++i) { FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, i);
diff --git a/pdf/pdfium/pdfium_ink_transform.cc b/pdf/pdfium/pdfium_ink_transform.cc new file mode 100644 index 0000000..98b1aff8 --- /dev/null +++ b/pdf/pdfium/pdfium_ink_transform.cc
@@ -0,0 +1,30 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/pdfium/pdfium_ink_transform.h" + +#include "base/check.h" +#include "pdf/pdf_ink_transform.h" +#include "pdf/pdfium/pdfium_rotation.h" +#include "third_party/pdfium/public/fpdfview.h" +#include "ui/gfx/geometry/vector2d_f.h" + +namespace chrome_pdf { + +gfx::Transform GetCanonicalToPdfTransformForPage(FPDF_PAGE page) { + CHECK(page); + + // Get the intersection between the page's MediaBox and CropBox, to find + // the translation offset for the shapes' transform. + FS_RECTF bounding_box; + bool result = FPDF_GetPageBoundingBox(page, &bounding_box); + CHECK(result); + const gfx::Vector2dF offset(bounding_box.left, bounding_box.bottom); + + return GetCanonicalToPdfTransform( + {FPDF_GetPageWidthF(page), FPDF_GetPageHeightF(page)}, + GetPageRotation(page).value_or(PageRotation::kRotate0), offset); +} + +} // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_ink_transform.h b/pdf/pdfium/pdfium_ink_transform.h new file mode 100644 index 0000000..1aebfd1 --- /dev/null +++ b/pdf/pdfium/pdfium_ink_transform.h
@@ -0,0 +1,22 @@ +// 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 PDF_PDFIUM_PDFIUM_INK_TRANSFORM_H_ +#define PDF_PDFIUM_PDFIUM_INK_TRANSFORM_H_ + +#include "pdf/buildflags.h" +#include "third_party/pdfium/public/fpdfview.h" +#include "ui/gfx/geometry/transform.h" + +static_assert(BUILDFLAG(ENABLE_PDF_INK2), "ENABLE_PDF_INK2 not set to true"); + +namespace chrome_pdf { + +// Wrapper function that returns the GetCanonicalToPdfTransform() result for a +// given `page`. Takes the page's MediaBox and CropBox into account. +gfx::Transform GetCanonicalToPdfTransformForPage(FPDF_PAGE page); + +} // namespace chrome_pdf + +#endif // PDF_PDFIUM_PDFIUM_INK_TRANSFORM_H_
diff --git a/pdf/pdfium/pdfium_ink_transform_unittest.cc b/pdf/pdfium/pdfium_ink_transform_unittest.cc new file mode 100644 index 0000000..923234ce --- /dev/null +++ b/pdf/pdfium/pdfium_ink_transform_unittest.cc
@@ -0,0 +1,65 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "pdf/pdfium/pdfium_ink_transform.h" + +#include <memory> + +#include "pdf/pdfium/pdfium_engine.h" +#include "pdf/pdfium/pdfium_page.h" +#include "pdf/pdfium/pdfium_test_base.h" +#include "pdf/pdfium/pdfium_test_helpers.h" +#include "pdf/test/test_client.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chrome_pdf { + +namespace { + +constexpr gfx::PointF kCanonicalTopLeftPoint(0.0f, 0.0f); +constexpr gfx::PointF kCanonicalMiddlePoint(100.0f, 50.0f); + +} // namespace + +using PDFiumInkTransformTest = PDFiumTestBase; + +TEST_P(PDFiumInkTransformTest, GetCanonicalToPdfTransformForHelloWorld) { + TestClient client; + std::unique_ptr<PDFiumEngine> engine = + InitializeEngine(&client, FILE_PATH_LITERAL("hello_world2.pdf")); + ASSERT_TRUE(engine); + + PDFiumPage& pdfium_page = GetPDFiumPageForTest(*engine, 0); + FPDF_PAGE page = pdfium_page.GetPage(); + ASSERT_TRUE(page); + + const gfx::Transform transform = GetCanonicalToPdfTransformForPage(page); + EXPECT_EQ(gfx::PointF(0.0f, 200.0f), + transform.MapPoint(kCanonicalTopLeftPoint)); + EXPECT_EQ(gfx::PointF(75.0f, 162.5f), + transform.MapPoint(kCanonicalMiddlePoint)); +} + +TEST_P(PDFiumInkTransformTest, GetCanonicalToPdfTransformForHelloWorldCropped) { + TestClient client; + std::unique_ptr<PDFiumEngine> engine = + InitializeEngine(&client, FILE_PATH_LITERAL("hello_world_cropped.pdf")); + ASSERT_TRUE(engine); + + PDFiumPage& pdfium_page = GetPDFiumPageForTest(*engine, 0); + FPDF_PAGE page = pdfium_page.GetPage(); + ASSERT_TRUE(page); + + const gfx::Transform transform = GetCanonicalToPdfTransformForPage(page); + EXPECT_EQ(gfx::PointF(55.0f, 97.0f), + transform.MapPoint(kCanonicalTopLeftPoint)); + EXPECT_EQ(gfx::PointF(130.0f, 59.5f), + transform.MapPoint(kCanonicalMiddlePoint)); +} + +// There are no rendering concerns for doing transforms, so only one variation +// needs be run. +INSTANTIATE_TEST_SUITE_P(All, PDFiumInkTransformTest, testing::Values(false)); + +} // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_ink_writer.cc b/pdf/pdfium/pdfium_ink_writer.cc index 68bbd10..c62c5606 100644 --- a/pdf/pdfium/pdfium_ink_writer.cc +++ b/pdf/pdfium/pdfium_ink_writer.cc
@@ -13,9 +13,8 @@ #include "base/memory/raw_ref.h" #include "pdf/pdf_ink_constants.h" #include "pdf/pdf_ink_conversions.h" -#include "pdf/pdf_ink_transform.h" #include "pdf/pdf_transform.h" -#include "pdf/pdfium/pdfium_rotation.h" +#include "pdf/pdfium/pdfium_ink_transform.h" #include "third_party/ink/src/ink/brush/brush_coat.h" #include "third_party/ink/src/ink/brush/brush_tip.h" #include "third_party/ink/src/ink/geometry/mesh.h" @@ -125,17 +124,7 @@ FPDF_PAGE page) { CHECK(page); - // Get the intersection between the page's MediaBox and CropBox, to find - // the translation offset for the shape's transform. - FS_RECTF bounding_box; - auto result = FPDF_GetPageBoundingBox(page, &bounding_box); - CHECK(result); - const gfx::Vector2dF offset(bounding_box.left, bounding_box.bottom); - - const gfx::Transform transform = GetCanonicalToPdfTransform( - {FPDF_GetPageWidthF(page), FPDF_GetPageHeightF(page)}, - GetPageRotation(page).value_or(PageRotation::kRotate0), offset); - + const gfx::Transform transform = GetCanonicalToPdfTransformForPage(page); std::vector<ScopedFPDFPageObject> results; ModeledShapeOutlinesIterator it(shape); for (std::optional<ModeledShapeOutlinesIterator::OutlineData> outline_data =
diff --git a/pdf/pdfium/pdfium_print.cc b/pdf/pdfium/pdfium_print.cc index ae3d808a..528633a5 100644 --- a/pdf/pdfium/pdfium_print.cc +++ b/pdf/pdfium/pdfium_print.cc
@@ -24,12 +24,12 @@ #include "third_party/pdfium/public/fpdf_transformpage.h" #include "third_party/skia/include/core/SkImageInfo.h" #include "ui/gfx/codec/jpeg_codec.h" -#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/geometry/size_f.h" +#include "ui/gfx/geometry/vector2d_f.h" using printing::ConvertUnit; using printing::ConvertUnitFloat; @@ -125,20 +125,21 @@ } // Calculate positions for the clip box. - PdfRectangle media_box; - PdfRectangle crop_box; - bool has_media_box = - !!FPDFPage_GetMediaBox(page, &media_box.left, &media_box.bottom, - &media_box.right, &media_box.top); + PdfRect media_box; + PdfRect crop_box; + bool has_media_box = !!FPDFPage_GetMediaBox( + page, media_box.writable_left(), media_box.writable_bottom(), + media_box.writable_right(), media_box.writable_top()); bool has_crop_box = !!FPDFPage_GetCropBox( - page, &crop_box.left, &crop_box.bottom, &crop_box.right, &crop_box.top); + page, crop_box.writable_left(), crop_box.writable_bottom(), + crop_box.writable_right(), crop_box.writable_top()); CalculateMediaBoxAndCropBox(rotated, has_media_box, has_crop_box, &media_box, &crop_box); - PdfRectangle source_clip_box = CalculateClipBoxBoundary(media_box, crop_box); - ScalePdfRectangle(scale_factor, &source_clip_box); + PdfRect source_clip_box = CalculateClipBoxBoundary(media_box, crop_box); + source_clip_box.Scale(scale_factor); // Calculate the translation offset values. - gfx::PointF offset = + gfx::Vector2dF offset = fitted_scaling ? CalculateScaledClipBoxOffset(gfx_printed_rect, source_clip_box) : CalculateNonScaledClipBoxOffset( @@ -154,18 +155,21 @@ FPDFPage_SetMediaBox(page, 0, 0, page_size.width(), page_size.height()); FPDFPage_SetCropBox(page, 0, 0, page_size.width(), page_size.height()); - // Transformation is not required, return. Do this check only after updating - // the media box and crop box. For more detailed information, please refer to - // the comment block right before FPDF_SetMediaBox and FPDF_GetMediaBox calls. - if (scale_factor == 1.0f && offset.IsOrigin()) + // Transformation is not required, so return early. Do this check only after + // updating the media box and crop box. For more detailed information, please + // refer to the comment block right before the FPDF_SetMediaBox() and + // FPDF_GetMediaBox() calls. + if (scale_factor == 1.0f && offset.IsZero()) { return; + } // All the positions have been calculated, now manipulate the PDF. const FS_MATRIX matrix = {scale_factor, 0.0f, 0.0f, scale_factor, offset.x(), offset.y()}; - const FS_RECTF cliprect = { - source_clip_box.left + offset.x(), source_clip_box.top + offset.y(), - source_clip_box.right + offset.x(), source_clip_box.bottom + offset.y()}; + const FS_RECTF cliprect = {source_clip_box.left() + offset.x(), + source_clip_box.top() + offset.y(), + source_clip_box.right() + offset.x(), + source_clip_box.bottom() + offset.y()}; FPDFPage_TransFormWithClip(page, &matrix, &cliprect); FPDFPage_TransformAnnots(page, scale_factor, 0, 0, scale_factor, offset.x(), offset.y());
diff --git a/services/on_device_model/android/BUILD.gn b/services/on_device_model/android/BUILD.gn index f27640d6..942a05a2 100644 --- a/services/on_device_model/android/BUILD.gn +++ b/services/on_device_model/android/BUILD.gn
@@ -46,6 +46,7 @@ "java/src/org/chromium/on_device_model/AiCoreSession.java", "java/src/org/chromium/on_device_model/AiCoreSessionFactory.java", "java/src/org/chromium/on_device_model/AiCoreSessionUpstreamImpl.java", + "java/src/org/chromium/on_device_model/GenerateOptionsHelper.java", "java/src/org/chromium/on_device_model/InputPieceHelper.java", "java/src/org/chromium/on_device_model/OnDeviceModelBridge.java", ] @@ -82,6 +83,7 @@ generate_jni("jni_headers") { sources = [ "java/src/org/chromium/on_device_model/AiCoreSession.java", + "java/src/org/chromium/on_device_model/GenerateOptionsHelper.java", "java/src/org/chromium/on_device_model/InputPieceHelper.java", "java/src/org/chromium/on_device_model/OnDeviceModelBridge.java", ]
diff --git a/services/on_device_model/android/backend_model_impl_android_unittest.cc b/services/on_device_model/android/backend_model_impl_android_unittest.cc index 39f45f9..ee20114 100644 --- a/services/on_device_model/android/backend_model_impl_android_unittest.cc +++ b/services/on_device_model/android/backend_model_impl_android_unittest.cc
@@ -46,6 +46,12 @@ return params; } + mojom::GenerateOptionsPtr MakeGenerateOptions(int max_output_tokens) { + auto options = mojom::GenerateOptions::New(); + options->max_output_tokens = max_output_tokens; + return options; + } + mojom::AppendOptionsPtr MakeInput(std::vector<ml::InputPiece> input) { auto options = mojom::AppendOptions::New(); options->input = mojom::Input::New(std::move(input)); @@ -66,7 +72,8 @@ MakeSessionParams(/*top_k=*/3, /*temperature=*/1.0f)); TestResponseHolder response_holder; - session->Generate(mojom::GenerateOptions::New(), response_holder.BindRemote(), + session->Generate(MakeGenerateOptions(/*max_output_tokens=*/100), + response_holder.BindRemote(), /*on_complete=*/base::DoNothing()); response_holder.WaitForCompletion(); EXPECT_TRUE(response_holder.responses().empty()); @@ -109,13 +116,16 @@ } TestResponseHolder response_holder; - session->Generate(mojom::GenerateOptions::New(), response_holder.BindRemote(), + session->Generate(MakeGenerateOptions(/*max_output_tokens=*/100), + response_holder.BindRemote(), /*on_complete=*/base::DoNothing()); response_holder.WaitForCompletion(); EXPECT_THAT( response_holder.responses(), ElementsAre( "<system>mock system input<end><user>mock user input<end><model>")); + Java_OnDeviceModelBridgeNativeUnitTestHelper_verifyGenerateOptions( + env_, java_helper_, /*maxOutputTokens=*/100); histogram_tester_.ExpectUniqueSample( "OnDeviceModel.Android.GenerateResult", BackendSessionImplAndroid::GenerateResult::kSuccess, 1); @@ -134,7 +144,8 @@ BackendSessionImplAndroid::GenerateResult::kUnknownError)); TestResponseHolder response_holder; - session->Generate(mojom::GenerateOptions::New(), response_holder.BindRemote(), + session->Generate(MakeGenerateOptions(/*max_output_tokens=*/100), + response_holder.BindRemote(), /*on_complete=*/base::DoNothing()); response_holder.WaitForCompletion(); EXPECT_THAT(response_holder.responses(), ElementsAre("")); @@ -169,7 +180,7 @@ { TestResponseHolder response_holder; - session->Generate(mojom::GenerateOptions::New(), + session->Generate(MakeGenerateOptions(/*max_output_tokens=*/100), response_holder.BindRemote(), /*on_complete=*/base::DoNothing()); response_holder.WaitForCompletion(); @@ -192,7 +203,8 @@ java_helper_); TestResponseHolder response_holder; - session->Generate(mojom::GenerateOptions::New(), response_holder.BindRemote(), + session->Generate(MakeGenerateOptions(/*max_output_tokens=*/100), + response_holder.BindRemote(), /*on_complete=*/base::DoNothing()); // Delete the native session manually and ensure async completion doesn't
diff --git a/services/on_device_model/android/backend_session_impl_android.cc b/services/on_device_model/android/backend_session_impl_android.cc index 653edee..507450a7 100644 --- a/services/on_device_model/android/backend_session_impl_android.cc +++ b/services/on_device_model/android/backend_session_impl_android.cc
@@ -23,6 +23,7 @@ // Must come after all headers that specialize FromJniType() / ToJniType(). #include "services/on_device_model/android/jni_headers/AiCoreSession_jni.h" +#include "services/on_device_model/android/jni_headers/GenerateOptionsHelper_jni.h" #include "services/on_device_model/android/jni_headers/InputPieceHelper_jni.h" namespace on_device_model { @@ -57,6 +58,12 @@ responder_.Bind(std::move(response)); JNIEnv* env = base::android::AttachCurrentThread(); + // There isn't a generic mojo utility for converting c++ mojo struct to java, + // so disassemble the struct here and reassemble it in java. + // Only passing the parameters that are supported on Android. + base::android::ScopedJavaLocalRef<jobject> java_generate_options = + Java_GenerateOptionsHelper_create(env, input->max_output_tokens); + std::vector<base::android::ScopedJavaLocalRef<jobject>> java_inputs; for (const auto& piece : context_input_pieces_) { if (std::holds_alternative<ml::Token>(piece)) { @@ -73,7 +80,7 @@ } Java_AiCoreSession_generate( - env, java_session_, reinterpret_cast<intptr_t>(this), + env, java_session_, reinterpret_cast<intptr_t>(this), java_generate_options, base::android::ToJavaArrayOfObjects(env, java_inputs)); std::move(on_complete).Run(); }
diff --git a/services/on_device_model/android/java/src/org/chromium/on_device_model/AiCoreSession.java b/services/on_device_model/android/java/src/org/chromium/on_device_model/AiCoreSession.java index 900a41cb..411b5bf 100644 --- a/services/on_device_model/android/java/src/org/chromium/on_device_model/AiCoreSession.java +++ b/services/on_device_model/android/java/src/org/chromium/on_device_model/AiCoreSession.java
@@ -20,11 +20,13 @@ * * @param nativeBackendSession The pointer to the native BackendSession. Used to deliver the * result back to the native side. + * @param generateOptions The generate options to generate the response. Should always be an + * instance of mojom::GenerateOptions. * @param inputPieces The input pieces to generate the response. Should always be an instance of * mojom::InputPiece. */ @CalledByNative - void generate(long nativeBackendSession, Object[] inputPieces); + void generate(long nativeBackendSession, Object generateOptions, Object[] inputPieces); /** * Called when the native session is destroyed. The implementation class should not call native
diff --git a/services/on_device_model/android/java/src/org/chromium/on_device_model/AiCoreSessionUpstreamImpl.java b/services/on_device_model/android/java/src/org/chromium/on_device_model/AiCoreSessionUpstreamImpl.java index 2c644f4..28587b1e 100644 --- a/services/on_device_model/android/java/src/org/chromium/on_device_model/AiCoreSessionUpstreamImpl.java +++ b/services/on_device_model/android/java/src/org/chromium/on_device_model/AiCoreSessionUpstreamImpl.java
@@ -10,7 +10,7 @@ @NullMarked class AiCoreSessionUpstreamImpl implements AiCoreSession { @Override - public void generate(long nativeBackendSession, Object[] inputPieces) { + public void generate(long nativeBackendSession, Object generateOptions, Object[] inputPieces) { AiCoreSessionJni.get().onComplete(nativeBackendSession, GenerateResult.API_NOT_AVAILABLE); }
diff --git a/services/on_device_model/android/java/src/org/chromium/on_device_model/GenerateOptionsHelper.java b/services/on_device_model/android/java/src/org/chromium/on_device_model/GenerateOptionsHelper.java new file mode 100644 index 0000000..5b750e3 --- /dev/null +++ b/services/on_device_model/android/java/src/org/chromium/on_device_model/GenerateOptionsHelper.java
@@ -0,0 +1,22 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.on_device_model; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; + +import org.chromium.build.annotations.NullMarked; +import org.chromium.on_device_model.mojom.GenerateOptions; + +@JNINamespace("on_device_model") +@NullMarked +class GenerateOptionsHelper { + @CalledByNative + private static GenerateOptions create(int maxOutputTokens) { + GenerateOptions generateOptions = new GenerateOptions(); + generateOptions.maxOutputTokens = maxOutputTokens; + return generateOptions; + } +}
diff --git a/services/on_device_model/android/native_java_unittests/src/org/chromium/on_device_model/OnDeviceModelBridgeNativeUnitTestHelper.java b/services/on_device_model/android/native_java_unittests/src/org/chromium/on_device_model/OnDeviceModelBridgeNativeUnitTestHelper.java index c2e424d..121c5152 100644 --- a/services/on_device_model/android/native_java_unittests/src/org/chromium/on_device_model/OnDeviceModelBridgeNativeUnitTestHelper.java +++ b/services/on_device_model/android/native_java_unittests/src/org/chromium/on_device_model/OnDeviceModelBridgeNativeUnitTestHelper.java
@@ -9,6 +9,7 @@ import org.chromium.base.ServiceLoaderUtil; import org.chromium.components.optimization_guide.proto.ModelExecutionProto.ModelExecutionFeature; +import org.chromium.on_device_model.mojom.GenerateOptions; import org.chromium.on_device_model.mojom.InputPiece; import org.chromium.on_device_model.mojom.SessionParams; import org.chromium.on_device_model.mojom.Token; @@ -24,11 +25,14 @@ */ public static class MockAiCoreSession implements AiCoreSession { // If true, the onComplete callback will be called asynchronously through - // resumeOnCompleteCallback. + // resumeOnCompleteCallback. This field should be set before generate() is called. private boolean mCompleteAsync; private @GenerateResult int mGenerateResult; private boolean mNativeDestroyed; + // Below are the params received in the generate() call. private long mNativeBackendSession; + private GenerateOptions mGenerateOptions; + // Below are the params received in the constructor. private final ModelExecutionFeature mFeature; private final SessionParams mParams; @@ -39,7 +43,11 @@ } @Override - public void generate(long nativeBackendSession, Object[] inputPieces) { + public void generate( + long nativeBackendSession, Object generateOptions, Object[] inputPieces) { + assert generateOptions instanceof GenerateOptions; + mGenerateOptions = (GenerateOptions) generateOptions; + StringBuilder sb = new StringBuilder(); for (Object piece : inputPieces) { assert piece instanceof InputPiece; @@ -114,6 +122,12 @@ } @CalledByNative + public void verifyGenerateOptions(int maxOutputTokens) { + GenerateOptions generateOptions = mMockAiCoreSessionFactory.mSession.mGenerateOptions; + assertEquals(maxOutputTokens, generateOptions.maxOutputTokens); + } + + @CalledByNative public void setMockAiCoreSessionFactory() { mMockAiCoreSessionFactory = new MockAiCoreSessionFactory(); ServiceLoaderUtil.setInstanceForTesting(
diff --git a/services/tracing/BUILD.gn b/services/tracing/BUILD.gn index faae7e9..7f56cc4 100644 --- a/services/tracing/BUILD.gn +++ b/services/tracing/BUILD.gn
@@ -93,6 +93,7 @@ "public/cpp/perfetto/perfetto_config_unittest.cc", "public/cpp/perfetto/trace_packet_tokenizer_unittest.cc", "public/cpp/perfetto/traced_value_proto_writer_unittest.cc", + "public/cpp/perfetto/track_name_recorder_unittest.cc", "public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc", "public/cpp/trace_startup_shared_memory_unittest.cc", ]
diff --git a/services/tracing/public/cpp/perfetto/track_name_recorder.cc b/services/tracing/public/cpp/perfetto/track_name_recorder.cc index 2026a86..6ab647d 100644 --- a/services/tracing/public/cpp/perfetto/track_name_recorder.cc +++ b/services/tracing/public/cpp/perfetto/track_name_recorder.cc
@@ -86,23 +86,6 @@ void TrackNameRecorder::SetProcessTrackDescriptor( const std::string& process_name, ChromeProcessDescriptor::ProcessType process_type) { - // We record a few (string) fields here that are stripped for background - // tracing. We rely on the post-process privacy filtering to remove them. - auto process_track = perfetto::ProcessTrack::Current(); - auto process_track_desc = process_track.Serialize(); - auto* process = process_track_desc.mutable_process(); - process->set_pid(base::trace_event::TraceLog::GetInstance()->process_id()); - process->set_process_name(process_name); - process->set_start_timestamp_ns(process_start_timestamp_); - for (const auto& label : process_labels()) { - process->add_process_labels(label.second); - } - - auto* chrome_process = process_track_desc.mutable_chrome_process(); - if (process_type != ChromeProcessDescriptor::PROCESS_UNSPECIFIED) { - chrome_process->set_process_type(process_type); - } - // Add the crash trace ID to all the traces uploaded. If there are crashes // during this tracing session, then the crash will contain the process's // trace ID as "chrome-trace-id" crash key. This should be emitted @@ -110,10 +93,8 @@ // crashes. Metadata can go missing if process crashes. So, record this in // process descriptor. static const std::optional<uint64_t> crash_trace_id = GetTraceCrashId(); - if (crash_trace_id) { - chrome_process->set_crash_trace_id(*crash_trace_id); - } + std::string host_package_name; #if BUILDFLAG(IS_ANDROID) // Host app package name is only recorded if the corresponding TraceLog // setting is set to true. @@ -122,14 +103,59 @@ // processes that "belong" to the same WebView app. if (process_type == ChromeProcessDescriptor::PROCESS_RENDERER || process_type == ChromeProcessDescriptor::PROCESS_BROWSER) { - chrome_process->set_host_app_package_name( - base::android::BuildInfo::GetInstance()->host_package_name()); + host_package_name = + base::android::BuildInfo::GetInstance()->host_package_name(); } } #endif // BUILDFLAG(IS_ANDROID) - base::TrackEvent::SetTrackDescriptor(process_track, - std::move(process_track_desc)); + auto process_track = perfetto::ProcessTrack::Current(); + base::TrackEvent::SetTrackDescriptor( + process_track, + GenerateProcessTrackDescriptor( + process_track, process_name, process_type, + base::trace_event::TraceLog::GetInstance()->process_id(), + process_start_timestamp_, process_labels(), crash_trace_id, + host_package_name)); +} + +// static +perfetto::protos::gen::TrackDescriptor +TrackNameRecorder::GenerateProcessTrackDescriptor( + const perfetto::ProcessTrack& process_track, + const std::string& process_name, + ChromeProcessDescriptor::ProcessType process_type, + base::ProcessId process_id, + int64_t process_start_timestamp, + const absl::flat_hash_map<int, std::string>& process_labels, + const std::optional<uint64_t>& crash_trace_id, + const std::string& host_app_package_name) { + auto process_track_desc = process_track.Serialize(); + + // We record a few (string) fields here that are stripped for background + // tracing. We rely on the post-process privacy filtering to remove them. + auto* process = process_track_desc.mutable_process(); + process->set_pid(process_id); + process->set_process_name(process_name); + process->set_start_timestamp_ns(process_start_timestamp); + for (const auto& label : process_labels) { + process->add_process_labels(label.second); + } + + auto* chrome_process = process_track_desc.mutable_chrome_process(); + if (process_type != ChromeProcessDescriptor::PROCESS_UNSPECIFIED) { + chrome_process->set_process_type(process_type); + } + + if (crash_trace_id) { + chrome_process->set_crash_trace_id(*crash_trace_id); + } + + if (!host_app_package_name.empty()) { + chrome_process->set_host_app_package_name(host_app_package_name); + } + + return process_track_desc; } TrackNameRecorder::TrackNameRecorder()
diff --git a/services/tracing/public/cpp/perfetto/track_name_recorder.h b/services/tracing/public/cpp/perfetto/track_name_recorder.h index 447eb55..9db2e414e 100644 --- a/services/tracing/public/cpp/perfetto/track_name_recorder.h +++ b/services/tracing/public/cpp/perfetto/track_name_recorder.h
@@ -5,7 +5,11 @@ #ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACK_NAME_RECORDER_H_ #define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACK_NAME_RECORDER_H_ +#include <optional> +#include <string> + #include "base/component_export.h" +#include "base/gtest_prod_util.h" #include "base/process/current_process.h" #include "base/process/process_handle.h" #include "base/sequence_checker.h" @@ -14,7 +18,9 @@ #include "base/trace_event/typed_macros.h" #include "third_party/abseil-cpp/absl/container/flat_hash_map.h" #include "third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h" +#include "third_party/perfetto/include/perfetto/tracing/track.h" #include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h" +#include "third_party/perfetto/protos/perfetto/trace/track_event/track_descriptor.gen.h" namespace base { template <typename T> @@ -55,6 +61,8 @@ private: friend class base::NoDestructor<TrackNameRecorder>; + FRIEND_TEST_ALL_PREFIXES(TrackNameRecorderTest, + GenerateProcessTrackDescriptor); using ChromeProcessDescriptor = perfetto::protos::gen::ChromeProcessDescriptor; @@ -67,6 +75,17 @@ ChromeProcessDescriptor::ProcessType process_type); void SetProcessTrackDescriptor(); + // Helper function for SetProcessTrackDescriptor. + static perfetto::protos::gen::TrackDescriptor GenerateProcessTrackDescriptor( + const perfetto::ProcessTrack& process_track, + const std::string& process_name, + ChromeProcessDescriptor::ProcessType process_type, + base::ProcessId process_id, + int64_t process_start_timestamp, + const absl::flat_hash_map<int, std::string>& process_labels, + const std::optional<uint64_t>& crash_trace_id, + const std::string& host_app_package_name); + absl::flat_hash_map<int, std::string> process_labels() const { base::AutoLock lock(lock_); return process_labels_;
diff --git a/services/tracing/public/cpp/perfetto/track_name_recorder_unittest.cc b/services/tracing/public/cpp/perfetto/track_name_recorder_unittest.cc new file mode 100644 index 0000000..c5dd7f5 --- /dev/null +++ b/services/tracing/public/cpp/perfetto/track_name_recorder_unittest.cc
@@ -0,0 +1,68 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "services/tracing/public/cpp/perfetto/track_name_recorder.h" + +#include <optional> +#include <string> + +#include "base/process/process_handle.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/container/flat_hash_map.h" +#include "third_party/perfetto/include/perfetto/protozero/proto_decoder.h" +#include "third_party/perfetto/include/perfetto/tracing/track.h" +#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.gen.h" +#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h" +#include "third_party/perfetto/protos/perfetto/trace/track_event/track_descriptor.gen.h" +#include "third_party/perfetto/protos/perfetto/trace/track_event/track_descriptor.pbzero.h" + +namespace tracing { + +using perfetto::protos::gen::ChromeProcessDescriptor; + +TEST(TrackNameRecorderTest, GenerateProcessTrackDescriptor) { + const auto process_track = perfetto::ProcessTrack::Current(); + const std::string process_name = "Test Process"; + const auto process_type = ChromeProcessDescriptor::PROCESS_BROWSER; + const base::ProcessId process_id = base::GetCurrentProcId(); + const int64_t process_start_timestamp = 54321; + const absl::flat_hash_map<int, std::string> process_labels{ + {1, "label1"}, + {2, "label2"}, + }; + const std::optional<uint64_t> crash_trace_id = 12345; + const std::string host_app_package_name = "Test Package"; + + perfetto::protos::gen::TrackDescriptor track_descriptor = + TrackNameRecorder::GenerateProcessTrackDescriptor( + process_track, process_name, process_type, process_id, + process_start_timestamp, process_labels, crash_trace_id, + host_app_package_name); + + EXPECT_EQ(track_descriptor.uuid(), process_track.uuid); + EXPECT_EQ(track_descriptor.parent_uuid(), process_track.parent_uuid); + EXPECT_EQ(static_cast<base::ProcessId>(track_descriptor.process().pid()), + process_id); + EXPECT_EQ(track_descriptor.process().process_name(), process_name); + EXPECT_EQ(track_descriptor.process().start_timestamp_ns(), + process_start_timestamp); + EXPECT_THAT(track_descriptor.process().process_labels(), + ::testing::UnorderedElementsAre("label1", "label2")); + + // Make sure a deserialized pbzero ChromeProcessDescriptor has all the info. + const std::string serialized_track_descriptor = + track_descriptor.SerializeAsString(); + perfetto::protos::pbzero::TrackDescriptor::Decoder chrome_track_descriptor( + serialized_track_descriptor); + ASSERT_TRUE(chrome_track_descriptor.has_chrome_process()); + perfetto::protos::pbzero::ChromeProcessDescriptor::Decoder + chrome_process_descriptor(chrome_track_descriptor.chrome_process()); + EXPECT_EQ(chrome_process_descriptor.process_type(), process_type); + EXPECT_EQ(chrome_process_descriptor.crash_trace_id(), crash_trace_id); + EXPECT_EQ(chrome_process_descriptor.host_app_package_name().ToStdString(), + host_app_package_name); +} + +} // namespace tracing
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom index fbb00294..3e9144c3 100644 --- a/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom +++ b/services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom
@@ -91,6 +91,12 @@ enum BufferFormatPreference { kDefault = 0, kPreferGpuMemoryBuffer, + // Indicates a preference for using SharedImages that have exportable native + // handles (e.g., DMA BUF FDs on Linux). These buffers may not be CPU + // mappable, allowing for more efficient GPU usage. This option is useful + // when the consumer does not need CPU access to the frame but requires + // interop with other GPU pipelines or platforms. + kPreferSharedImageWithNativeHandle }; // Interface to an implementation that captures the frames of a
diff --git a/services/webnn/ort/environment.cc b/services/webnn/ort/environment.cc index a88fee8..54ba19bf 100644 --- a/services/webnn/ort/environment.cc +++ b/services/webnn/ort/environment.cc
@@ -287,8 +287,13 @@ OrtHardwareDeviceType ort_device_type = GetOrtHardwareDeviceType(device_type); for (const auto* ep_device : ep_devices) { CHECK(ep_device); - if (ort_api->HardwareDevice_Type(ort_api->EpDevice_Device(ep_device)) == - ort_device_type) { + OrtHardwareDeviceType ep_device_type = + ort_api->HardwareDevice_Type(ort_api->EpDevice_Device(ep_device)); + // Check if the external data is supported when the EP device type + // matches the selected device type, or is CPU because CPU EPs might be + // selected by ORT as the fallback EP. + if (ep_device_type == ort_device_type || + ep_device_type == OrtHardwareDeviceType_CPU) { const char* ep_name = ort_api->EpDevice_EpName(ep_device); // SAFETY: ORT guarantees that `ep_name` is valid and null-terminated. const auto& iter =
diff --git a/services/webnn/ort/graph_builder_ort.cc b/services/webnn/ort/graph_builder_ort.cc index 392a8cf0..6e91753 100644 --- a/services/webnn/ort/graph_builder_ort.cc +++ b/services/webnn/ort/graph_builder_ort.cc
@@ -91,7 +91,7 @@ constexpr base::cstring_view kOpTypePRelu = "PRelu"; constexpr base::cstring_view kOpTypeQuantizeLinear = "QuantizeLinear"; constexpr base::cstring_view kOpTypeRelu = "Relu"; -constexpr base::cstring_view kOpTypeResample2d = "Resize"; +constexpr base::cstring_view kOpTypeResize = "Resize"; constexpr base::cstring_view kOpTypeReshape = "Reshape"; constexpr base::cstring_view kOpTypeScatterElements = "ScatterElements"; constexpr base::cstring_view kOpTypeScatterND = "ScatterND"; @@ -158,11 +158,6 @@ constexpr base::cstring_view kToEmulate = "ToEmulate"; constexpr base::cstring_view kUnderscore = "_"; -base::unexpected<mojom::ErrorPtr> NewNotSupportedError(std::string message) { - return base::unexpected(mojom::Error::New( - mojom::Error::Code::kNotSupportedError, std::move(message))); -} - std::string GetOperandName(std::string_view name, OperandId id) { return base::JoinString({name, base::NumberToString(id.value())}, kUnderscore); @@ -354,9 +349,7 @@ } // namespace // static -[[nodiscard]] base::expected<std::unique_ptr<ModelEditor::ModelInfo>, - mojom::ErrorPtr> -GraphBuilderOrt::CreateAndBuild( +std::unique_ptr<ModelEditor::ModelInfo> GraphBuilderOrt::CreateAndBuild( const mojom::GraphInfo& graph_info, ContextProperties context_properties, base::flat_map<OperandId, std::unique_ptr<WebNNConstantOperand>> @@ -655,6 +648,38 @@ return output; } +void GraphBuilderOrt::AddResizeNode(base::cstring_view node_name, + base::cstring_view input, + base::cstring_view scales, + base::cstring_view sizes, + base::cstring_view mode, + base::cstring_view output) { + // Skip the input roi, which only takes effect when the coordinate + // transformation mode is set to "tf_crop_and_resize". Currently WebNN only + // supports "half_pixel", which is the default mode. + const std::string roi; + std::array<const char*, 4> inputs = {input.c_str(), roi.c_str(), + scales.c_str(), sizes.c_str()}; + std::array<const char*, 1> outputs = {output.c_str()}; + + std::array<ScopedOrtOpAttr, 1> attributes = { + model_editor_.CreateAttribute(kAttrMode, mode)}; + + model_editor_.AddNode(kOpTypeResize, node_name, inputs, outputs, attributes); +} + +std::string GraphBuilderOrt::BlockwiseExpand(base::cstring_view input, + base::span<const uint32_t> shape) { + const std::string sizes = CreateInt64InitializerForUint32Array(shape); + const std::string node_name = GenerateNodeName( + base::JoinString({kInserted, kOpTypeResize}, kUnderscore)); + const std::string output = GenerateOperandName(); + AddResizeNode(node_name, input, /*scales=*/"", sizes, + /*mode=*/"nearest", output); + + return output; +} + void GraphBuilderOrt::AddReshapeNode(base::cstring_view node_name, base::cstring_view input, base::cstring_view output, @@ -1070,13 +1095,10 @@ attributes); } -// TODO(crbug.com/433055137): Remove the returned error once the emulation path -// is implemented. template <typename T> requires(std::is_same_v<T, mojom::DequantizeLinear> || std::is_same_v<T, mojom::QuantizeLinear>) -[[nodiscard]] base::expected<void, mojom::ErrorPtr> -GraphBuilderOrt::AddDequantizeOrQuantizeLinearOperation( +void GraphBuilderOrt::AddDequantizeOrQuantizeLinearOperation( const T& operation, base::cstring_view op_type) { const std::string node_name = GenerateNodeName(operation.label); @@ -1103,9 +1125,6 @@ } } - // TODO(crbug.com/433096244): Emulate multiple axes case, e.g. input shape is - // [2, 3, 4, 5] and scale shape is [1, 3, 4, 1]. The multiple axes per-axis - // case will be handled by multi-dimensions blockwise emulation below. bool is_per_axis = axis.has_value() && scale_not_size_one_dimension_count == 1; @@ -1141,15 +1160,37 @@ axis = i; blockwise_axis_count++; } + } - // TODO(crbug.com/433096244): Emulate multi-dimensions blockwise - // quantization and dequantization. - if (blockwise_axis_count > 1) { - return NewNotSupportedError( - "For blockwise quantization and dequantization, scale should has " - "the same shape as the input or except for one dimension in which " - "blocking is performed"); + if (blockwise_axis_count > 1) { + // The data type of zero point can be int4/uint4, which is not + // supported by `resize` operator. So cast it to int8/uint8 before + // `resize` and cast back to int4/uint4 after `resize`. + const OperandDataType zero_point_data_type = + GetOperand(operation.zero_point_operand_id).descriptor.data_type(); + if (zero_point_data_type == OperandDataType::kInt4) { + zero_point = + CreateCastNode(zero_point, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8); + } else if (zero_point_data_type == OperandDataType::kUint4) { + zero_point = + CreateCastNode(zero_point, ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8); } + + scale = BlockwiseExpand(scale, input_shape); + zero_point = BlockwiseExpand(zero_point, input_shape); + + if (zero_point_data_type == OperandDataType::kInt4) { + zero_point = + CreateCastNode(zero_point, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT4); + } else if (zero_point_data_type == OperandDataType::kUint4) { + zero_point = + CreateCastNode(zero_point, ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT4); + } + + // Reset the axis and block_size back to default values, because scale and + // zeroPoint now have the same shape as input. + axis = 0; + block_size = 1; } } @@ -1169,7 +1210,6 @@ } model_editor_.AddNode(op_type, node_name, inputs, outputs, attributes); - return base::ok(); } void GraphBuilderOrt::AddEluOperation(const mojom::Elu& elu) { @@ -2614,10 +2654,6 @@ CHECK(context_properties_.data_type_limits.resample2d_input.Supports( input_descriptor)); - // Skip the input roi, which only takes effect when the coordinate - // transformation mode is set to "tf_crop_and_resize". Currently WebNN only - // supports "half_pixel", which is the default mode. - const std::string roi; std::string scales; std::string sizes; if (resample2d.scales) { @@ -2633,9 +2669,6 @@ sizes = CreateInt64InitializerForUint32Array( GetOperand(resample2d.output_operand_id).descriptor.shape()); } - std::array<const char*, 4> inputs = {input.c_str(), roi.c_str(), - scales.c_str(), sizes.c_str()}; - std::array<const char*, 1> outputs = {output.c_str()}; std::string mode; switch (resample2d.mode) { @@ -2646,11 +2679,8 @@ mode = "nearest"; break; } - std::array<ScopedOrtOpAttr, 1> attributes = { - model_editor_.CreateAttribute(kAttrMode, mode)}; - model_editor_.AddNode(kOpTypeResample2d, node_name, inputs, outputs, - attributes); + AddResizeNode(node_name, input, scales, sizes, mode, output); } void GraphBuilderOrt::AddReshapeOperation(const mojom::Reshape& reshape) { @@ -3019,9 +3049,7 @@ model_editor_.AddNode(kOpTypeWhere, node_name, inputs, outputs); } -[[nodiscard]] base::expected<std::unique_ptr<ModelEditor::ModelInfo>, - mojom::ErrorPtr> -GraphBuilderOrt::BuildModel() { +std::unique_ptr<ModelEditor::ModelInfo> GraphBuilderOrt::BuildModel() { for (OperandId input_id : graph_info_->input_operands) { model_editor_.AddInput(GetOperandNameById(input_id), GetOperand(input_id)); } @@ -3070,8 +3098,8 @@ CHECK(data_type_limits.dequantize_linear_scale.Supports( GetOperand(operation->get_dequantize_linear()->scale_operand_id) .descriptor)); - RETURN_IF_ERROR(AddDequantizeOrQuantizeLinearOperation( - *operation->get_dequantize_linear(), kOpTypeDequantizeLinear)); + AddDequantizeOrQuantizeLinearOperation( + *operation->get_dequantize_linear(), kOpTypeDequantizeLinear); break; } case mojom::Operation::Tag::kElu: { @@ -3193,8 +3221,8 @@ CHECK(data_type_limits.quantize_linear_zero_point.Supports( GetOperand(operation->get_quantize_linear()->zero_point_operand_id) .descriptor)); - RETURN_IF_ERROR(AddDequantizeOrQuantizeLinearOperation( - *operation->get_quantize_linear(), kOpTypeQuantizeLinear)); + AddDequantizeOrQuantizeLinearOperation( + *operation->get_quantize_linear(), kOpTypeQuantizeLinear); break; } case mojom::Operation::Tag::kRelu: {
diff --git a/services/webnn/ort/graph_builder_ort.h b/services/webnn/ort/graph_builder_ort.h index 95a0e16..914f84e 100644 --- a/services/webnn/ort/graph_builder_ort.h +++ b/services/webnn/ort/graph_builder_ort.h
@@ -58,11 +58,7 @@ // Factory method that creates a `GraphBuilderOrt`, builds the graph and // returns `ModelEditor::ModelInfo` which contains the model itself and the // external data (weights). - // - // Returns unexpected if it fails. - [[nodiscard]] static base::expected<std::unique_ptr<ModelEditor::ModelInfo>, - mojom::ErrorPtr> - CreateAndBuild( + static std::unique_ptr<ModelEditor::ModelInfo> CreateAndBuild( const mojom::GraphInfo& graph_info, ContextProperties context_properties, base::flat_map<OperandId, std::unique_ptr<WebNNConstantOperand>> @@ -179,6 +175,17 @@ std::string CreateExpandNode(base::cstring_view input, base::span<const uint32_t> shape); + void AddResizeNode(base::cstring_view node_name, + base::cstring_view input, + base::cstring_view scales, + base::cstring_view sizes, + base::cstring_view mode, + base::cstring_view output); + // A helper function used to blockwise expand the dimension of `input` + // according to `shape` by using `resize` operator with `nearest` mode. + std::string BlockwiseExpand(base::cstring_view input, + base::span<const uint32_t> shape); + void AddReshapeNode(base::cstring_view node_name, base::cstring_view input, base::cstring_view output, @@ -235,9 +242,8 @@ template <typename T> requires(std::is_same_v<T, mojom::DequantizeLinear> || std::is_same_v<T, mojom::QuantizeLinear>) - [[nodiscard]] base::expected<void, mojom::ErrorPtr> - AddDequantizeOrQuantizeLinearOperation(const T& operation, - base::cstring_view op_type); + void AddDequantizeOrQuantizeLinearOperation(const T& operation, + base::cstring_view op_type); void AddEluOperation(const mojom::Elu& elu); void AddLogicalBinaryOperation(const mojom::ElementWiseBinary& logical_binary, base::cstring_view op_type); @@ -284,9 +290,7 @@ void AddTriangularOperation(const mojom::Triangular& triangular); void AddWhereOperation(const mojom::Where& where); - [[nodiscard]] base::expected<std::unique_ptr<ModelEditor::ModelInfo>, - mojom::ErrorPtr> - BuildModel(); + std::unique_ptr<ModelEditor::ModelInfo> BuildModel(); // An increasing id starting from 0, used for generating unique names for each // operand.
diff --git a/services/webnn/ort/graph_impl_ort.cc b/services/webnn/ort/graph_impl_ort.cc index c3fd8a3..b3dd98b 100644 --- a/services/webnn/ort/graph_impl_ort.cc +++ b/services/webnn/ort/graph_impl_ort.cc
@@ -160,11 +160,10 @@ bool is_external_data_supported, ScopedTrace scoped_trace) { scoped_trace.AddStep("Create model info"); - ASSIGN_OR_RETURN( - std::unique_ptr<ModelEditor::ModelInfo> model_info, + std::unique_ptr<ModelEditor::ModelInfo> model_info = GraphBuilderOrt::CreateAndBuild( *graph_info, std::move(context_properties), - std::move(constant_operands), is_external_data_supported)); + std::move(constant_operands), is_external_data_supported); scoped_trace.AddStep("Create session from model"); ScopedOrtSession session;
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index faf8bf40..5f281837 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -161,7 +161,6 @@ defines = [ "IS_SKIA_IMPL=1", "SKIA_IMPLEMENTATION=1", - "SK_FONTMGR_ANDROID_IGNORE_FALLBACK_FIX=1", ] # Let Skia know whether to use `libpng`-based or Rust-based PNG decoder and
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.cc b/storage/browser/quota/quota_temporary_storage_evictor.cc index 2edc839..1c66b4e7 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include "base/auto_reset.h" +#include "base/byte_count.h" #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/metrics/histogram_functions.h" @@ -19,15 +20,14 @@ #include "url/gurl.h" namespace { -constexpr int64_t kMBytes = 1024 * 1024; constexpr double kUsageRatioToStartEviction = 0.7; constexpr int kThresholdOfErrorsToStopEviction = 5; constexpr base::TimeDelta kHistogramReportInterval = base::Minutes(60); constexpr double kDiskSpaceShortageAllowanceRatio = 0.5; -void UmaHistogramMbytes(const std::string& name, int sample) { - base::UmaHistogramCustomCounts(name, sample / kMBytes, 1, - 10 * 1024 * 1024 /* 10 TB */, 100); +void UmaHistogramMbytes(const std::string& name, base::ByteCount sample) { + base::UmaHistogramCustomCounts(name, sample.InMiB(), 1, base::TiB(10).InMiB(), + 100); } } // namespace @@ -66,11 +66,13 @@ base::Time now = base::Time::Now(); base::UmaHistogramTimes("Quota.TimeSpentToAEvictionRound", now - round_statistics_.start_time); - UmaHistogramMbytes("Quota.DiskspaceShortage", - round_statistics_.diskspace_shortage_at_round); - UmaHistogramMbytes("Quota.EvictedBytesPerRound", - round_statistics_.usage_on_beginning_of_round - - round_statistics_.usage_on_end_of_round); + UmaHistogramMbytes( + "Quota.DiskspaceShortage", + base::ByteCount(round_statistics_.diskspace_shortage_at_round)); + UmaHistogramMbytes( + "Quota.EvictedBytesPerRound", + base::ByteCount(round_statistics_.usage_on_beginning_of_round - + round_statistics_.usage_on_end_of_round)); base::UmaHistogramCounts1M("Quota.NumberOfEvictedBucketsPerRound", round_statistics_.num_evicted_buckets); }
diff --git a/testing/perf/cbb_ref_info/chrome/dev/Android.json b/testing/perf/cbb_ref_info/chrome/dev/Android.json index 7a84e56..a148e28 100644 --- a/testing/perf/cbb_ref_info/chrome/dev/Android.json +++ b/testing/perf/cbb_ref_info/chrome/dev/Android.json
@@ -2,5 +2,5 @@ "browser": "Chrome", "channel": "Dev", "platform": "Android", - "version": "140.0.7313.0" + "version": "140.0.7327.5" } \ No newline at end of file
diff --git a/testing/perf/cbb_ref_info/chrome/dev/Windows.json b/testing/perf/cbb_ref_info/chrome/dev/Windows.json index e10800dd..fb7f1ce 100644 --- a/testing/perf/cbb_ref_info/chrome/dev/Windows.json +++ b/testing/perf/cbb_ref_info/chrome/dev/Windows.json
@@ -2,5 +2,5 @@ "browser": "Chrome", "channel": "Dev", "platform": "Windows", - "version": "140.0.7312.0" + "version": "140.0.7327.6" } \ No newline at end of file
diff --git a/testing/perf/cbb_ref_info/chrome/dev/macOS.json b/testing/perf/cbb_ref_info/chrome/dev/macOS.json index 37e0993..86b6c656 100644 --- a/testing/perf/cbb_ref_info/chrome/dev/macOS.json +++ b/testing/perf/cbb_ref_info/chrome/dev/macOS.json
@@ -2,5 +2,5 @@ "browser": "Chrome", "channel": "Dev", "platform": "Mac", - "version": "140.0.7312.0" + "version": "140.0.7327.6" } \ No newline at end of file
diff --git a/testing/perf/cbb_ref_info/chrome/stable/Windows.json b/testing/perf/cbb_ref_info/chrome/stable/Windows.json index 4e9b63c..059fc37d 100644 --- a/testing/perf/cbb_ref_info/chrome/stable/Windows.json +++ b/testing/perf/cbb_ref_info/chrome/stable/Windows.json
@@ -2,5 +2,5 @@ "browser": "Chrome", "channel": "Stable", "platform": "Windows", - "version": "139.0.7258.66" + "version": "139.0.7258.67" } \ No newline at end of file
diff --git a/testing/perf/cbb_ref_info/chrome/stable/macOS.json b/testing/perf/cbb_ref_info/chrome/stable/macOS.json index 0c136e61..a5503b8 100644 --- a/testing/perf/cbb_ref_info/chrome/stable/macOS.json +++ b/testing/perf/cbb_ref_info/chrome/stable/macOS.json
@@ -2,5 +2,5 @@ "browser": "Chrome", "channel": "Stable", "platform": "Mac", - "version": "139.0.7258.66" + "version": "139.0.7258.67" } \ No newline at end of file
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 51c2db0..1157525a 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -9279,6 +9279,21 @@ ] } ], + "EnableClipboardDataControlsAndroid": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled_140", + "enable_features": [ + "EnableClipboardDataControlsAndroid" + ] + } + ] + } + ], "EnableConfigurableThreadCacheMultiplier": [ { "platforms": [ @@ -16800,6 +16815,7 @@ "price_insights": "true", "price_tracking": "true", "product_specifications": "true", + "pwa_install": "true", "translate": "true", "zoom": "true" }, @@ -18519,29 +18535,6 @@ ] } ], - "Prerender2NewTabPageTriggerV2": [ - { - "platforms": [ - "linux", - "mac", - "windows", - "chromeos" - ], - "experiments": [ - { - "name": "BothMouseDownAndMouseHover_20241010", - "params": { - "prerender_new_tab_page_on_mouse_hover_trigger": "true", - "prerender_new_tab_page_on_mouse_pressed_trigger": "true", - "prerender_start_delay_on_mouse_hover_ms": "300" - }, - "enable_features": [ - "NewTabPageTriggerForPrerender2" - ] - } - ] - } - ], "Prerender2ReuseSearchResultHostAndroid": [ { "platforms": [ @@ -23473,6 +23466,21 @@ ] } ], + "SkipDefaultBrowserPromoInFirstRun": [ + { + "platforms": [ + "ios" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "SkipDefaultBrowserPromoInFirstRun" + ] + } + ] + } + ], "SkipModerateMemoryPressureLevelMac": [ { "platforms": [ @@ -25088,6 +25096,21 @@ ] } ], + "UiaDisconnectRootProviders": [ + { + "platforms": [ + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "UiaDisconnectRootProviders" + ] + } + ] + } + ], "UiaProviderWin": [ { "platforms": [
diff --git a/third_party/android_deps/autorolled/BUILD.gn b/third_party/android_deps/autorolled/BUILD.gn index 491a489f..4e014310 100644 --- a/third_party/android_deps/autorolled/BUILD.gn +++ b/third_party/android_deps/autorolled/BUILD.gn
@@ -559,7 +559,7 @@ # This is generated, do not edit. Update BuildConfigGenerator.groovy instead. if (!defined(android_proto_runtime)) { java_prebuilt("com_google_protobuf_protobuf_javalite_java") { - jar_path = "autorolled/cipd/libs/com_google_protobuf_protobuf_javalite/protobuf-javalite-4.32.0-RC1.jar" + jar_path = "autorolled/cipd/libs/com_google_protobuf_protobuf_javalite/protobuf-javalite-4.32.0-RC2.jar" output_name = "com_google_protobuf_protobuf_javalite" supports_android = true requires_android = true
diff --git a/third_party/android_deps/autorolled/VERSION.txt b/third_party/android_deps/autorolled/VERSION.txt index d298c5c..4b1c298 100644 --- a/third_party/android_deps/autorolled/VERSION.txt +++ b/third_party/android_deps/autorolled/VERSION.txt
@@ -1 +1 @@ -522446afe8f183d.eb7be870f3171d7 \ No newline at end of file +3224ac70f349f24.e9e87be8badc1b1 \ No newline at end of file
diff --git a/third_party/android_deps/autorolled/bill_of_materials.json b/third_party/android_deps/autorolled/bill_of_materials.json index 3407112..4e95b00b 100644 --- a/third_party/android_deps/autorolled/bill_of_materials.json +++ b/third_party/android_deps/autorolled/bill_of_materials.json
@@ -1457,7 +1457,7 @@ { "name": "protobuf-javalite", "group": "com.google.protobuf", - "version": "4.32.0-RC1" + "version": "4.32.0-RC2" }, { "name": "protobuf-lite",
diff --git a/third_party/android_deps/autorolled/build.gradle b/third_party/android_deps/autorolled/build.gradle index e8e7b4b..b9e20e62 100644 --- a/third_party/android_deps/autorolled/build.gradle +++ b/third_party/android_deps/autorolled/build.gradle
@@ -305,7 +305,7 @@ versionCache['com.google.guava:guava'] = '33.4.8-jre' versionCache['com.google.guava:listenablefuture'] = '9999.0-empty-to-avoid-conflict-with-guava' versionCache['com.google.j2objc:j2objc-annotations'] = '3.0.0' -versionCache['com.google.protobuf:protobuf-javalite'] = '4.32.0-RC1' +versionCache['com.google.protobuf:protobuf-javalite'] = '4.32.0-RC2' versionCache['com.google.protobuf:protobuf-lite'] = '3.0.1' versionCache['com.google.testparameterinjector:test-parameter-injector'] = '1.18' versionCache['com.googlecode.java-diff-utils:diffutils'] = '1.3.0'
diff --git a/third_party/android_deps/autorolled/committed/libs/com_google_protobuf_protobuf_javalite/README.chromium b/third_party/android_deps/autorolled/committed/libs/com_google_protobuf_protobuf_javalite/README.chromium index c08ef4a7..c6500fb 100644 --- a/third_party/android_deps/autorolled/committed/libs/com_google_protobuf_protobuf_javalite/README.chromium +++ b/third_party/android_deps/autorolled/committed/libs/com_google_protobuf_protobuf_javalite/README.chromium
@@ -1,7 +1,7 @@ Name: Protocol Buffers [Lite] Short Name: protobuf-javalite URL: https://github.com/protocolbuffers/protobuf/blob/master/java/lite.md -Version: 4.32.0-RC1 +Version: 4.32.0-RC2 Update Mechanism: Autoroll License: BSD-3-Clause License File: LICENSE
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 8c21bcf43..3c6f8b91 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -429,7 +429,7 @@ // of the renderer eviction reasons for Back/Forward Cache. BASE_FEATURE(kCaptureJSExecutionLocation, "CaptureJSExecutionLocation", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kCheckHTMLParserBudgetLessOften, "CheckHTMLParserBudgetLessOften",
diff --git a/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc b/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc index db9ab4d..e29d1f3b 100644 --- a/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc +++ b/third_party/blink/common/notifications/notification_mojom_traits_unittest.cc
@@ -6,8 +6,10 @@ #include <array> #include <optional> +#include <string_view> #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" @@ -44,10 +46,8 @@ notification_data.badge = GURL("https://example.com/badge.png"); const auto vibration_pattern = std::to_array<int>({500, 100, 30}); - notification_data.vibration_pattern.assign( - vibration_pattern.data(), base::span<const int>(vibration_pattern) - .subspan(std::size(vibration_pattern)) - .data()); + notification_data.vibration_pattern.assign(vibration_pattern.begin(), + vibration_pattern.end()); notification_data.timestamp = base::Time::FromMillisecondsSinceUnixEpoch(1513966159000.); @@ -57,8 +57,8 @@ notification_data.show_trigger_timestamp = base::Time::Now(); notification_data.scenario = mojom::NotificationScenario::INCOMING_CALL; - const char data[] = "mock binary notification data"; - notification_data.data.assign(data, UNSAFE_TODO(data + std::size(data))); + const std::string_view data_view = "mock binary notification data"; + notification_data.data.assign(data_view.begin(), data_view.end()); notification_data.actions.resize(2); notification_data.actions[0] = blink::mojom::NotificationAction::New();
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 05bc92d..b5559d4 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -1096,6 +1096,7 @@ enum BlockedFrameNavigation BlockedSubresource + NoisedCanvasReadback # This issue warns about uses of APIs that may be considered misuse to # re-identify users. @@ -1104,6 +1105,8 @@ UserReidentificationIssueType type # Applies to BlockedFrameNavigation and BlockedSubresource issue types. optional AffectedRequest request + # Applies to NoisedCanvasReadback issue type. + optional SourceCodeLocation sourceCodeLocation # A unique identifier for the type of issue. Each type may use one of the # optional fields in InspectorIssueDetails to convey more specific
diff --git a/third_party/blink/public/mojom/devtools/inspector_issue.mojom b/third_party/blink/public/mojom/devtools/inspector_issue.mojom index b29903d..981c187 100644 --- a/third_party/blink/public/mojom/devtools/inspector_issue.mojom +++ b/third_party/blink/public/mojom/devtools/inspector_issue.mojom
@@ -345,13 +345,17 @@ enum UserReidentificationIssueType { kBlockedFrameNavigation, kBlockedSubresource, + kNoisedCanvasReadback, }; -// Information for an issue notifying on subresources or navigations that may be -// blocked for suspected user reidentification. +// Information for an issue notifying the user about an intervention that took +// place as the result of a suspected user reidentification. This type of issue +// is used for several interventions such as blocking subresources or +// navigations, and canvas noise. struct UserReidentificationIssueDetails { UserReidentificationIssueType type; AffectedRequest? request; + AffectedLocation? sourceCodeLocation; }; // A collection of optional fields that may store additional data depending
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index a707246..d07f1cd 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -4935,6 +4935,8 @@ kHTMLControlledFrameElement = 5624, kSlowDeserialization = 5625, kSharedWorkerStartOnAndroid = 5626, + kLocalNetworkAccessWithinSharedWorker = 5627, + kLocalNetworkAccessWithinDedicatedWorker = 5628, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots. Also don't add extra
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..2a349d8 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,7 +56,7 @@ Event* event) { DCHECK(execution_context_of_event_target); DCHECK(event); - DCHECK(event->target()); + DCHECK(event->RawTarget()); DCHECK(event->currentTarget()); v8::Isolate* isolate = GetIsolate(); @@ -142,7 +142,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); }
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..d3baddfd 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
@@ -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 = {
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index 3fee47b..5f8fe923 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -1342,10 +1342,10 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_page_transition_event.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_part.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_part.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_patch.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_patch.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_patch_event.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_patch_event.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_patch_status.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_patch_status.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_performance.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_performance.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_performance_container_timing.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni index 975a74d..080ad92 100644 --- a/third_party/blink/renderer/bindings/idl_in_core.gni +++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -564,9 +564,9 @@ "//third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.idl", "//third_party/blink/renderer/core/page/color_page_popup_controller.idl", "//third_party/blink/renderer/core/page/page_popup_controller.idl", + "//third_party/blink/renderer/core/patching/patch.idl", "//third_party/blink/renderer/core/patching/patch_event.idl", "//third_party/blink/renderer/core/patching/patch_event_init.idl", - "//third_party/blink/renderer/core/patching/patch_status.idl", "//third_party/blink/renderer/core/permissions_policy/feature_policy.idl", "//third_party/blink/renderer/core/resize_observer/resize_observer.idl", "//third_party/blink/renderer/core/resize_observer/resize_observer_entry.idl",
diff --git a/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.cc b/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.cc index 5ae5df6..ba7f349 100644 --- a/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.cc +++ b/third_party/blink/renderer/controller/crash_memory_metrics_reporter_impl.cc
@@ -67,11 +67,11 @@ } void CrashMemoryMetricsReporterImpl::SampleMemoryState(TimerBase*) { - base::SystemMemoryInfoKB meminfo; + base::SystemMemoryInfo meminfo; base::GetSystemMemoryInfo(&meminfo); OomInterventionMetrics metrics; - metrics.current_available_memory_kb = meminfo.available; - metrics.current_swap_free_kb = meminfo.swap_free; + metrics.current_available_memory_kb = meminfo.available.InKiB(); + metrics.current_swap_free_kb = meminfo.swap_free.InKiB(); last_reported_metrics_ = metrics; WriteIntoSharedMemory(); }
diff --git a/third_party/blink/renderer/core/canvas_interventions/canvas_interventions_helper.cc b/third_party/blink/renderer/core/canvas_interventions/canvas_interventions_helper.cc index ce957ad..03f5b59 100644 --- a/third_party/blink/renderer/core/canvas_interventions/canvas_interventions_helper.cc +++ b/third_party/blink/renderer/core/canvas_interventions/canvas_interventions_helper.cc
@@ -14,6 +14,7 @@ #include "base/time/time.h" #include "third_party/blink/public/common/fingerprinting_protection/canvas_noise_token.h" #include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h" +#include "third_party/blink/renderer/bindings/core/v8/capture_source_location.h" #include "third_party/blink/renderer/core/canvas_interventions/noise_hash.h" #include "third_party/blink/renderer/core/canvas_interventions/noise_helper.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" @@ -21,6 +22,7 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/platform/graphics/canvas_high_entropy_op_type.h" #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h" @@ -165,6 +167,9 @@ static_cast<int>(high_entropy_canvas_op_types), canvas_op_exclusive_max); + AuditsIssue::ReportUserReidentificationCanvasNoisedIssue( + CaptureSourceLocation(execution_context), execution_context); + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::blink::ConsoleMessageSource::kIntervention, mojom::blink::ConsoleMessageLevel::kInfo,
diff --git a/third_party/blink/renderer/core/css/active_style_sheets_test.cc b/third_party/blink/renderer/core/css/active_style_sheets_test.cc index e3c15e3..48156bf 100644 --- a/third_party/blink/renderer/core/css/active_style_sheets_test.cc +++ b/third_party/blink/renderer/core/css/active_style_sheets_test.cc
@@ -30,7 +30,8 @@ MakeGarbageCollected<CSSParserContext>( kHTMLStandardMode, SecureContextMode::kInsecureContext)); contents->ParseString(css_text); - contents->EnsureRuleSet(MediaQueryEvaluator(GetDocument().GetFrame())); + contents->EnsureRuleSet(MediaQueryEvaluator(GetDocument().GetFrame()), + /*mixins=*/{}); return MakeGarbageCollected<CSSStyleSheet>(contents); } }; @@ -124,7 +125,7 @@ sheet2->Contents()->ClearRuleSet(); sheet2->Contents()->EnsureRuleSet( - MediaQueryEvaluator(GetDocument().GetFrame())); + MediaQueryEvaluator(GetDocument().GetFrame()), /*mixins=*/{}); EXPECT_NE(old_sheets[1].second, &sheet2->Contents()->GetRuleSet());
diff --git a/third_party/blink/renderer/core/css/css_default_style_sheets.cc b/third_party/blink/renderer/core/css/css_default_style_sheets.cc index 585ff84..6abd521 100644 --- a/third_party/blink/renderer/core/css/css_default_style_sheets.cc +++ b/third_party/blink/renderer/core/css/css_default_style_sheets.cc
@@ -226,10 +226,12 @@ default_pseudo_element_style_.Clear(); default_forced_colors_media_controls_style_.Clear(); - default_html_style_->AddRulesFromSheet(DefaultStyleSheet(), ScreenEval()); + default_html_style_->AddRulesFromSheet(DefaultStyleSheet(), ScreenEval(), + /*mixins=*/{}); default_html_quirks_style_->AddRulesFromSheet(QuirksStyleSheet(), - ScreenEval()); - default_print_style_->AddRulesFromSheet(DefaultStyleSheet(), PrintEval()); + ScreenEval(), /*mixins=*/{}); + default_print_style_->AddRulesFromSheet(DefaultStyleSheet(), PrintEval(), + /*mixins=*/{}); default_html_style_->CompactRulesIfNeeded(); default_html_quirks_style_->CompactRulesIfNeeded(); @@ -247,7 +249,7 @@ view_source_style_sheet_ = ParseUASheet( UncompressResourceAsASCIIString(IDR_UASTYLE_VIEW_SOURCE_CSS)); default_view_source_style_->AddRulesFromSheet(view_source_style_sheet_, - ScreenEval()); + ScreenEval(), /*mixins=*/{}); default_view_source_style_->CompactRulesIfNeeded(); } return default_view_source_style_.Get(); @@ -258,8 +260,8 @@ json_style_sheet_ = ParseUASheet( UncompressResourceAsASCIIString(IDR_UASTYLE_JSON_DOCUMENT_CSS)); default_json_document_style_ = MakeGarbageCollected<RuleSet>(); - default_json_document_style_->AddRulesFromSheet(json_style_sheet_, - ScreenEval()); + default_json_document_style_->AddRulesFromSheet( + json_style_sheet_, ScreenEval(), /*mixins=*/{}); default_json_document_style_->CompactRulesIfNeeded(); } return default_json_document_style_.Get(); @@ -279,24 +281,27 @@ NamespaceType type) { switch (type) { case NamespaceType::kHTML: - default_html_style_->AddRulesFromSheet(rules, ScreenEval()); + default_html_style_->AddRulesFromSheet(rules, ScreenEval(), + /*mixins=*/{}); default_html_style_->CompactRulesIfNeeded(); break; case NamespaceType::kSVG: - default_svg_style_->AddRulesFromSheet(rules, ScreenEval()); + default_svg_style_->AddRulesFromSheet(rules, ScreenEval(), /*mixins=*/{}); default_svg_style_->CompactRulesIfNeeded(); break; case NamespaceType::kMathML: - default_mathml_style_->AddRulesFromSheet(rules, ScreenEval()); + default_mathml_style_->AddRulesFromSheet(rules, ScreenEval(), + /*mixins=*/{}); default_mathml_style_->CompactRulesIfNeeded(); break; case NamespaceType::kMediaControls: - default_media_controls_style_->AddRulesFromSheet(rules, ScreenEval()); + default_media_controls_style_->AddRulesFromSheet(rules, ScreenEval(), + /*mixins=*/{}); default_media_controls_style_->CompactRulesIfNeeded(); break; } // Add to print and forced color for all namespaces. - default_print_style_->AddRulesFromSheet(rules, PrintEval()); + default_print_style_->AddRulesFromSheet(rules, PrintEval(), /*mixins=*/{}); default_print_style_->CompactRulesIfNeeded(); if (default_forced_color_style_) { switch (type) { @@ -306,12 +311,12 @@ MakeGarbageCollected<RuleSet>(); } default_forced_colors_media_controls_style_->AddRulesFromSheet( - rules, ForcedColorsEval()); + rules, ForcedColorsEval(), /*mixins=*/{}); default_forced_colors_media_controls_style_->CompactRulesIfNeeded(); break; default: - default_forced_color_style_->AddRulesFromSheet(rules, - ForcedColorsEval()); + default_forced_color_style_->AddRulesFromSheet( + rules, ForcedColorsEval(), /*mixins=*/{}); default_forced_color_style_->CompactRulesIfNeeded(); break; } @@ -430,8 +435,8 @@ if (!default_pseudo_element_style_) { default_pseudo_element_style_ = MakeGarbageCollected<RuleSet>(); } - default_pseudo_element_style_->AddRulesFromSheet(ScrollButtonStyleSheet(), - ScreenEval()); + default_pseudo_element_style_->AddRulesFromSheet( + ScrollButtonStyleSheet(), ScreenEval(), /*mixins=*/{}); default_pseudo_element_style_->CompactRulesIfNeeded(); // We just added a new :focus-visible rule to the UA stylesheet, and // RuleSetGroup caches whether we have any such rules or not, so we need @@ -448,8 +453,8 @@ if (!default_pseudo_element_style_) { default_pseudo_element_style_ = MakeGarbageCollected<RuleSet>(); } - default_pseudo_element_style_->AddRulesFromSheet(ScrollMarkerStyleSheet(), - ScreenEval()); + default_pseudo_element_style_->AddRulesFromSheet( + ScrollMarkerStyleSheet(), ScreenEval(), /*mixins=*/{}); default_pseudo_element_style_->CompactRulesIfNeeded(); // We just added a new :focus-visible rule to the UA stylesheet, and // RuleSetGroup caches whether we have any such rules or not, so we need @@ -466,8 +471,8 @@ if (!default_pseudo_element_style_) { default_pseudo_element_style_ = MakeGarbageCollected<RuleSet>(); } - default_pseudo_element_style_->AddRulesFromSheet(MarkerStyleSheet(), - ScreenEval()); + default_pseudo_element_style_->AddRulesFromSheet( + MarkerStyleSheet(), ScreenEval(), /*mixins=*/{}); default_pseudo_element_style_->CompactRulesIfNeeded(); return true; } @@ -496,7 +501,7 @@ default_fullscreen_style_->AddRulesFromSheet( fullscreen_style_sheet_, - MediaQueryEvaluator(element.GetDocument().GetFrame())); + MediaQueryEvaluator(element.GetDocument().GetFrame()), /*mixins=*/{}); default_fullscreen_style_->CompactRulesIfNeeded(); VerifyUniversalRuleCount(); } @@ -515,7 +520,7 @@ default_fullscreen_style_ = MakeGarbageCollected<RuleSet>(); default_fullscreen_style_->AddRulesFromSheet( fullscreen_style_sheet_, - MediaQueryEvaluator(element.GetDocument().GetFrame())); + MediaQueryEvaluator(element.GetDocument().GetFrame()), /*mixins=*/{}); default_fullscreen_style_->CompactRulesIfNeeded(); VerifyUniversalRuleCount(); rule_set_group_cache_.clear(); @@ -537,13 +542,13 @@ if (!default_forced_color_style_) { default_forced_color_style_ = MakeGarbageCollected<RuleSet>(); } - default_forced_color_style_->AddRulesFromSheet(DefaultStyleSheet(), - ForcedColorsEval()); - default_forced_color_style_->AddRulesFromSheet(ForcedColorsStyleSheet(), - ForcedColorsEval()); + default_forced_color_style_->AddRulesFromSheet( + DefaultStyleSheet(), ForcedColorsEval(), /*mixins=*/{}); + default_forced_color_style_->AddRulesFromSheet( + ForcedColorsStyleSheet(), ForcedColorsEval(), /*mixins=*/{}); if (svg_style_sheet_) { - default_forced_color_style_->AddRulesFromSheet(SvgStyleSheet(), - ForcedColorsEval()); + default_forced_color_style_->AddRulesFromSheet( + SvgStyleSheet(), ForcedColorsEval(), /*mixins=*/{}); } default_forced_color_style_->CompactRulesIfNeeded(); @@ -552,7 +557,7 @@ default_forced_colors_media_controls_style_ = MakeGarbageCollected<RuleSet>(); default_forced_colors_media_controls_style_->AddRulesFromSheet( - MediaControlsStyleSheet(), ForcedColorsEval()); + MediaControlsStyleSheet(), ForcedColorsEval(), /*mixins=*/{}); default_forced_colors_media_controls_style_->CompactRulesIfNeeded(); }
diff --git a/third_party/blink/renderer/core/css/css_global_rule_set.cc b/third_party/blink/renderer/core/css/css_global_rule_set.cc index 194d3b8..0edad58 100644 --- a/third_party/blink/renderer/core/css/css_global_rule_set.cc +++ b/third_party/blink/renderer/core/css/css_global_rule_set.cc
@@ -31,7 +31,7 @@ for (unsigned i = 0; i < watched_selectors.size(); ++i) { watched_selectors_rule_set_->AddStyleRule( watched_selectors[i], /*parent_rule=*/nullptr, *medium, - kRuleHasNoSpecialState, /*within_mixin=*/false); + /*mixins=*/{}, kRuleHasNoSpecialState, /*within_mixin=*/nullptr); } } @@ -48,8 +48,9 @@ MakeGarbageCollected<MediaQueryEvaluator>(document.GetFrame()); for (StyleRule* selector : document_rules_selectors) { document_rules_selectors_rule_set_->AddStyleRule( - selector, /*parent_rule=*/nullptr, *medium, kRuleHasNoSpecialState, - /*within_mixin=*/false); + selector, /*parent_rule=*/nullptr, *medium, /*mixins=*/{}, + kRuleHasNoSpecialState, + /*within_mixin=*/nullptr); } document_rules_selectors_rule_set_->CompactRulesIfNeeded(); }
diff --git a/third_party/blink/renderer/core/css/css_test_helpers.cc b/third_party/blink/renderer/core/css/css_test_helpers.cc index 8b82828..5b35985 100644 --- a/third_party/blink/renderer/core/css/css_test_helpers.cc +++ b/third_party/blink/renderer/core/css/css_test_helpers.cc
@@ -54,7 +54,7 @@ RuleSet& TestStyleSheet::GetRuleSet() { RuleSet& rule_set = style_sheet_->Contents()->EnsureRuleSet( - MediaQueryEvaluator(document_->GetFrame())); + MediaQueryEvaluator(document_->GetFrame()), /*mixins=*/{}); rule_set.CompactRulesIfNeeded(); return rule_set; } @@ -81,7 +81,8 @@ MakeGarbageCollected<MediaQueryEvaluator>(document.GetFrame()); auto* sheet = CSSStyleSheet::Create(document, init, exception_state); sheet->replaceSync(text, exception_state); - return &sheet->Contents()->EnsureRuleSet(*media_query_evaluator); + return &sheet->Contents()->EnsureRuleSet(*media_query_evaluator, + /*mixins=*/{}); } PropertyRegistration* CreatePropertyRegistration(const String& name,
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collection.cc b/third_party/blink/renderer/core/css/document_style_sheet_collection.cc index 14e5620f..ab5ca30 100644 --- a/third_party/blink/renderer/core/css/document_style_sheet_collection.cc +++ b/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
@@ -29,6 +29,7 @@ #include "third_party/blink/renderer/core/css/document_style_sheet_collection.h" #include "third_party/blink/renderer/bindings/core/v8/v8_observable_array_css_style_sheet.h" +#include "third_party/blink/renderer/core/css/css_default_style_sheets.h" #include "third_party/blink/renderer/core/css/document_style_sheet_collector.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" @@ -93,6 +94,7 @@ void DocumentStyleSheetCollection::CollectStyleSheets( StyleEngine& engine, + const MediaQueryEvaluator& medium, DocumentStyleSheetCollector& collector) { for (auto& sheet : GetDocument().GetStyleEngine().InjectedAuthorStyleSheets()) { @@ -103,15 +105,16 @@ GetDocument().GetStyleEngine().InspectorStyleSheets()) { collector.AppendActiveStyleSheet(inspector_sheet); } - collector.FinishCollectingStylesheets(engine); + collector.FinishCollectingStylesheets(engine, medium); } void DocumentStyleSheetCollection::UpdateActiveStyleSheets( - StyleEngine& engine) { + StyleEngine& engine, + const MediaQueryEvaluator& medium) { // StyleSheetCollection is GarbageCollected<>, allocate it on the heap. auto* collection = MakeGarbageCollected<StyleSheetCollection>(); ActiveDocumentStyleSheetCollector collector(*collection); - CollectStyleSheets(engine, collector); + CollectStyleSheets(engine, medium, collector); ApplyActiveStyleSheetChanges(*collection); }
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collection.h b/third_party/blink/renderer/core/css/document_style_sheet_collection.h index 279bf39..62dbee4 100644 --- a/third_party/blink/renderer/core/css/document_style_sheet_collection.h +++ b/third_party/blink/renderer/core/css/document_style_sheet_collection.h
@@ -30,6 +30,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_DOCUMENT_STYLE_SHEET_COLLECTION_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_DOCUMENT_STYLE_SHEET_COLLECTION_H_ +#include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.h" namespace blink { @@ -37,6 +38,7 @@ class DocumentStyleSheetCollector; class StyleEngine; class TreeScope; +class MediaQueryEvaluator; class DocumentStyleSheetCollection final : public TreeScopeStyleSheetCollection { @@ -46,8 +48,10 @@ DocumentStyleSheetCollection& operator=(const DocumentStyleSheetCollection&) = delete; - void UpdateActiveStyleSheets(StyleEngine&); - void CollectStyleSheets(StyleEngine&, DocumentStyleSheetCollector&); + void UpdateActiveStyleSheets(StyleEngine&, const MediaQueryEvaluator&); + void CollectStyleSheets(StyleEngine&, + const MediaQueryEvaluator&, + DocumentStyleSheetCollector&); void Trace(Visitor* visitor) const override { TreeScopeStyleSheetCollection::Trace(visitor);
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collector.cc b/third_party/blink/renderer/core/css/document_style_sheet_collector.cc index 0d149c1..aff95683 100644 --- a/third_party/blink/renderer/core/css/document_style_sheet_collector.cc +++ b/third_party/blink/renderer/core/css/document_style_sheet_collector.cc
@@ -47,8 +47,9 @@ } void DocumentStyleSheetCollector::FinishCollectingStylesheets( - StyleEngine& engine) { - collection_->CreateRuleSets(engine); + StyleEngine& engine, + const MediaQueryEvaluator& medium) { + collection_->CreateRuleSets(engine, medium); } void DocumentStyleSheetCollector::AppendSheetForList(StyleSheet* sheet) {
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collector.h b/third_party/blink/renderer/core/css/document_style_sheet_collector.h index 320cff7..593a87e 100644 --- a/third_party/blink/renderer/core/css/document_style_sheet_collector.h +++ b/third_party/blink/renderer/core/css/document_style_sheet_collector.h
@@ -28,7 +28,6 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_DOCUMENT_STYLE_SHEET_COLLECTOR_H_ #include "third_party/blink/renderer/core/css/active_style_sheets.h" -#include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" #include "third_party/blink/renderer/platform/heap/member.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" @@ -61,7 +60,8 @@ void AppendRuleSetDiff(RuleSetDiff*); // Can only be called once. - void FinishCollectingStylesheets(StyleEngine& engine); + void FinishCollectingStylesheets(StyleEngine& engine, + const MediaQueryEvaluator& medium); private: StyleSheetCollection* collection_;
diff --git a/third_party/blink/renderer/core/css/element_rule_collector_test.cc b/third_party/blink/renderer/core/css/element_rule_collector_test.cc index 8977994..4f8664a 100644 --- a/third_party/blink/renderer/core/css/element_rule_collector_test.cc +++ b/third_party/blink/renderer/core/css/element_rule_collector_test.cc
@@ -43,7 +43,8 @@ MediaQueryEvaluator* medium = MakeGarbageCollected<MediaQueryEvaluator>(document.GetFrame()); rule_set->AddStyleRule(style_rule, /*parent_rule=*/nullptr, *medium, - kRuleHasNoSpecialState, /*within_mixin=*/false); + /*mixins=*/{}, kRuleHasNoSpecialState, + /*within_mixin=*/nullptr); rule_set->CompactRulesIfNeeded(); return rule_set; } @@ -354,12 +355,12 @@ } MediaQueryEvaluator* medium = MakeGarbageCollected<MediaQueryEvaluator>(GetDocument().GetFrame()); - RuleSet& rules = sheet->EnsureRuleSet(*medium); + RuleSet& rules = sheet->EnsureRuleSet(*medium, /*mixins=*/{}); auto* rule = To<StyleRule>(CSSParser::ParseRule( sheet->ParserContext(), sheet, CSSNestingType::kNone, /*parent_rule_for_nesting=*/nullptr, selector + " { color: green }")); - rules.AddStyleRule(rule, /*parent_rule=*/nullptr, *medium, - kRuleHasNoSpecialState, /*within_mixin=*/false); + rules.AddStyleRule(rule, /*parent_rule=*/nullptr, *medium, /*mixins=*/{}, + kRuleHasNoSpecialState, /*within_mixin=*/nullptr); MatchResult result; ElementResolveContext context{element};
diff --git a/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc b/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc index bfca175..e84398a 100644 --- a/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc +++ b/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
@@ -310,6 +310,7 @@ case StyleRule::kStartingStyle: case StyleRule::kMixin: case StyleRule::kApplyMixin: + case StyleRule::kContents: case StyleRule::kPositionTry: case StyleRule::kCustomMedia: // TODO(andruud): Handle other descriptor types here.
diff --git a/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc b/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc index a87cef8..9b7694cf 100644 --- a/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc +++ b/third_party/blink/renderer/core/css/parser/css_at_rule_id.cc
@@ -151,6 +151,9 @@ if (EqualIgnoringASCIICase(name, "apply")) { return CSSAtRuleID::kCSSAtRuleApplyMixin; } + if (EqualIgnoringASCIICase(name, "contents")) { + return CSSAtRuleID::kCSSAtRuleContents; + } } if (RuntimeEnabledFeatures::CSSCustomMediaEnabled()) { @@ -252,6 +255,8 @@ return "@mixin"; case CSSAtRuleID::kCSSAtRuleApplyMixin: return "@apply"; + case CSSAtRuleID::kCSSAtRuleContents: + return "@contents"; case CSSAtRuleID::kCSSAtRuleCustomMedia: return "@custom-media"; case CSSAtRuleID::kCSSAtRuleInvalid: @@ -335,6 +340,7 @@ return WebFeature::kCSSFunctions; case CSSAtRuleID::kCSSAtRuleMixin: case CSSAtRuleID::kCSSAtRuleApplyMixin: + case CSSAtRuleID::kCSSAtRuleContents: return WebFeature::kCSSMixins; case CSSAtRuleID::kCSSAtRuleCustomMedia: return WebFeature::kCSSCustomMedia;
diff --git a/third_party/blink/renderer/core/css/parser/css_at_rule_id.h b/third_party/blink/renderer/core/css/parser/css_at_rule_id.h index 63b153a..d630fbe 100644 --- a/third_party/blink/renderer/core/css/parser/css_at_rule_id.h +++ b/third_party/blink/renderer/core/css/parser/css_at_rule_id.h
@@ -60,6 +60,7 @@ kCSSAtRuleFunction, kCSSAtRuleMixin, kCSSAtRuleApplyMixin, + kCSSAtRuleContents, kCSSAtRuleCustomMedia, kCount // Must go last.
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc index 470d1153..c294c38 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc +++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -908,6 +908,8 @@ return ConsumeMixinRule(stream); case CSSAtRuleID::kCSSAtRuleApplyMixin: return ConsumeApplyMixinRule(stream); + case CSSAtRuleID::kCSSAtRuleContents: + return ConsumeContentsRule(stream); case CSSAtRuleID::kCSSAtRulePositionTry: return ConsumePositionTryRule(stream); case CSSAtRuleID::kCSSAtRuleCharset: @@ -2369,6 +2371,16 @@ } // Parse the actual block. + StyleRule* fake_parent_rule; + { + base::AutoReset<bool> reset_in_nested_style_rule(&in_mixin_, true); + fake_parent_rule = ConsumeDeclarationListForMixins(stream); + } + return MakeGarbageCollected<StyleRuleMixin>(name, fake_parent_rule); +} + +StyleRule* CSSParserImpl::ConsumeDeclarationListForMixins( + CSSParserTokenStream& stream) { CSSParserTokenStream::BlockGuard guard(stream); // When we encounter a declaration list, the selector of our fake parent rule @@ -2385,11 +2397,12 @@ for (StyleRuleBase* child_rule : child_rules) { fake_parent_rule->AddChildRule(child_rule); } - return MakeGarbageCollected<StyleRuleMixin>(name, fake_parent_rule); + return fake_parent_rule; } StyleRuleApplyMixin* CSSParserImpl::ConsumeApplyMixinRule( CSSParserTokenStream& stream) { + wtf_size_t header_start = stream.LookAheadOffset(); if (stream.Peek().GetType() != kIdentToken) { ConsumeErroneousAtRule(stream, CSSAtRuleID::kCSSAtRuleApplyMixin); return nullptr; // Parse error. @@ -2400,11 +2413,71 @@ ConsumeErroneousAtRule(stream, CSSAtRuleID::kCSSAtRuleApplyMixin); return nullptr; } - if (!ConsumeEndOfPreludeForAtRuleWithoutBlock( - stream, CSSAtRuleID::kCSSAtRuleApplyMixin)) { - return nullptr; + + if (stream.AtEnd()) { + // Implicit semicolon at end of block. + return MakeGarbageCollected<StyleRuleApplyMixin>(name, nullptr); } - return MakeGarbageCollected<StyleRuleApplyMixin>(name); + if (stream.UncheckedPeek().GetType() == kSemicolonToken) { + // No declarations block, just a semicolon. + stream.UncheckedConsume(); // kSemicolonToken + return MakeGarbageCollected<StyleRuleApplyMixin>(name, nullptr); + } + + if (stream.UncheckedPeek().GetType() != kLeftBraceToken) { + ConsumeErroneousAtRule(stream, CSSAtRuleID::kCSSAtRuleApplyMixin); + return nullptr; // Parse error. + } + wtf_size_t header_end = stream.LookAheadOffset(); + + if (observer_) { + observer_->StartRuleHeader(StyleRule::kApplyMixin, header_start); + observer_->EndRuleHeader(header_end); + observer_->StartRuleBody(stream.Offset()); + } + + // Parse the @contents block. + StyleRule* fake_parent_rule_for_contents = + ConsumeDeclarationListForMixins(stream); + if (observer_) { + observer_->EndRuleBody(stream.Offset()); + } + return MakeGarbageCollected<StyleRuleApplyMixin>( + name, fake_parent_rule_for_contents); +} + +StyleRuleContentsStatement* CSSParserImpl::ConsumeContentsRule( + CSSParserTokenStream& stream) { + wtf_size_t header_start = stream.LookAheadOffset(); + stream.ConsumeWhitespace(); + if (stream.AtEnd()) { + // Implicit semicolon at end of block. + return MakeGarbageCollected<StyleRuleContentsStatement>(nullptr); + } + if (stream.UncheckedPeek().GetType() == kSemicolonToken) { + // No block, just a semicolon. + stream.UncheckedConsume(); // kSemicolonToken + return MakeGarbageCollected<StyleRuleContentsStatement>(nullptr); + } + + if (stream.UncheckedPeek().GetType() != kLeftBraceToken) { + ConsumeErroneousAtRule(stream, CSSAtRuleID::kCSSAtRuleContents); + return nullptr; // Parse error. + } + wtf_size_t header_end = stream.LookAheadOffset(); + + if (observer_) { + observer_->StartRuleHeader(StyleRule::kContents, header_start); + observer_->EndRuleHeader(header_end); + observer_->StartRuleBody(stream.Offset()); + } + + // Parse the actual block. + StyleRule* fake_parent_rule = ConsumeDeclarationListForMixins(stream); + if (observer_) { + observer_->EndRuleBody(stream.Offset()); + } + return MakeGarbageCollected<StyleRuleContentsStatement>(fake_parent_rule); } // Parse the parameters of a CSS function: Zero or more comma-separated @@ -2895,7 +2968,8 @@ namespace { AllowedRules AllowedNestedRules(StyleRule::RuleType parent_rule_type, - bool in_nested_style_rule) { + bool in_nested_style_rule, + bool in_mixin) { switch (parent_rule_type) { case StyleRule::kScope: if (!in_nested_style_rule) { @@ -2903,7 +2977,12 @@ } [[fallthrough]]; case StyleRule::kStyle: { - return CSSParserImpl::kNestedGroupRules; + if (in_mixin) { + return CSSParserImpl::kNestedGroupRules | + AllowedRules{CSSAtRuleID::kCSSAtRuleContents}; + } else { + return CSSParserImpl::kNestedGroupRules; + } } case StyleRule::kPage: return CSSParserImpl::kPageMarginRules; @@ -2938,7 +3017,7 @@ } else { child = ConsumeAtRuleContents( *id, stream, - AllowedNestedRules(parent_rule_type, in_nested_style_rule_), + AllowedNestedRules(parent_rule_type, in_nested_style_rule_, in_mixin_), nesting_type, parent_rule_for_nesting); } parsed_properties_ = std::move(outer_parsed_properties);
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.h b/third_party/blink/renderer/core/css/parser/css_parser_impl.h index 5b046be8..e55dda7 100644 --- a/third_party/blink/renderer/core/css/parser/css_parser_impl.h +++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.h
@@ -331,7 +331,9 @@ ConsumeFunctionParameters(CSSParserTokenStream& stream); StyleRuleMixin* ConsumeMixinRule(CSSParserTokenStream& stream); StyleRuleApplyMixin* ConsumeApplyMixinRule(CSSParserTokenStream& stream); + StyleRuleContentsStatement* ConsumeContentsRule(CSSParserTokenStream& stream); StyleRuleCustomMedia* ConsumeCustomMediaRule(CSSParserTokenStream& stream); + StyleRule* ConsumeDeclarationListForMixins(CSSParserTokenStream& stream); StyleRuleKeyframe* ConsumeKeyframeStyleRule( std::unique_ptr<Vector<KeyframeOffset>> key_list, @@ -483,6 +485,9 @@ // True when parsing a StyleRule via ConsumeNestedRule. bool in_nested_style_rule_ = false; + // True when parsing a @mixin. + bool in_mixin_ = false; + HeapHashMap<String, Member<const MediaQuerySet>> media_query_cache_; };
diff --git a/third_party/blink/renderer/core/css/parser/css_supports_parser.cc b/third_party/blink/renderer/core/css/parser/css_supports_parser.cc index ee21f96..90c7d82 100644 --- a/third_party/blink/renderer/core/css/parser/css_supports_parser.cc +++ b/third_party/blink/renderer/core/css/parser/css_supports_parser.cc
@@ -274,6 +274,9 @@ case CSSAtRuleID::kCSSAtRuleApplyMixin: rule_type = StyleRule::kApplyMixin; break; + case CSSAtRuleID::kCSSAtRuleContents: + rule_type = StyleRule::kContents; + break; case CSSAtRuleID::kCSSAtRulePositionTry: rule_type = StyleRule::kPositionTry; break;
diff --git a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc index 9246042..996a435 100644 --- a/third_party/blink/renderer/core/css/properties/computed_style_utils.cc +++ b/third_party/blink/renderer/core/css/properties/computed_style_utils.cc
@@ -2086,10 +2086,10 @@ computed_grid_track_list.GetAutoRepeatInsertionPoint(); const GridTrackList& track_list = computed_grid_track_list.GetTrackList(); - // Treat repeat(auto-fill, auto) as none in Grid. + // Treat repeat(auto-fill, <intrinsic-track-size>) as none in Grid. // // TODO(almaher): Change this depending on if we allow this syntax in Grid. - if (!is_masonry && track_list.HasAutoSizedRepeater()) { + if (!is_masonry && track_list.HasIntrinsicSizedRepeater()) { return CSSIdentifierValue::Create(CSSValueID::kNone); } @@ -2104,8 +2104,8 @@ // `force_computed_value` is set (which is used for `grid-template`). Non // layout-grids will always report the computed value. // - // TODO(almaher): Consider if we should force repeat(auto-fill, auto) to the - // computed value instead of used value. + // TODO(almaher): Consider if we should force repeat(auto-fill, + // <intrinsic-track-size>) to the computed value instead of used value. if (grid && !force_computed_value) { // The number of auto repeat tracks. For 'repeat(auto-fill, [x][y])' this // will be 2, regardless of what auto-fill computes to. For subgrids, use
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 9be58eb..a406eaa 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -6347,45 +6347,46 @@ return result; } -bool IsGridBreadthFixedSized(const CSSValue& value) { +bool IsGridBreadthFlexSized(const CSSValue& value) { + return value.IsPrimitiveValue() && To<CSSPrimitiveValue>(value).IsFlex(); +} + +bool IsGridBreadthIntrinsicSized(const CSSValue& value) { if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) { CSSValueID value_id = identifier_value->GetValueID(); - return value_id != CSSValueID::kAuto && - value_id != CSSValueID::kMinContent && - value_id != CSSValueID::kMaxContent; + return value_id == CSSValueID::kAuto || + value_id == CSSValueID::kMinContent || + value_id == CSSValueID::kMaxContent; } - if (auto* primitive_value = DynamicTo<CSSPrimitiveValue>(value)) { - return !primitive_value->IsFlex(); + if (auto* function = DynamicTo<CSSFunctionValue>(value)) { + return function->FunctionType() == CSSValueID::kFitContent; } - NOTREACHED(); + return false; +} + +bool IsGridBreadthFixedSized(const CSSValue& value) { + return !IsGridBreadthFlexSized(value) && !IsGridBreadthIntrinsicSized(value); } bool IsGridTrackFixedSized(const CSSValue& value) { - if (value.IsPrimitiveValue() || value.IsIdentifierValue()) { - return IsGridBreadthFixedSized(value); + // TODO(almaher): Do we want to update this defintion for Masonry? + // + // https://github.com/w3c/csswg-drafts/issues/12573 + auto* function = DynamicTo<CSSFunctionValue>(value); + if (function && function->FunctionType() != CSSValueID::kFitContent) { + const CSSValue& min_value = function->Item(0); + const CSSValue& max_value = function->Item(1); + return IsGridBreadthFixedSized(min_value) || + IsGridBreadthFixedSized(max_value); } - auto& function = To<CSSFunctionValue>(value); - if (function.FunctionType() == CSSValueID::kFitContent) { - return false; - } - - const CSSValue& min_value = function.Item(0); - const CSSValue& max_value = function.Item(1); - return IsGridBreadthFixedSized(min_value) || - IsGridBreadthFixedSized(max_value); + return IsGridBreadthFixedSized(value); } -bool IsGridTrackFixedSizedOrAuto(const CSSValue& value) { - if (auto* identifier_value = DynamicTo<CSSIdentifierValue>(value)) { - CSSValueID value_id = identifier_value->GetValueID(); - if (value_id == CSSValueID::kAuto) { - return true; - } - } - return IsGridTrackFixedSized(value); +bool IsGridTrackFixedOrIntrinsicSized(const CSSValue& value) { + return IsGridBreadthIntrinsicSized(value) || IsGridTrackFixedSized(value); } CSSValue* ConsumeGridTrackSize(CSSParserTokenStream& stream, @@ -6489,7 +6490,7 @@ bool is_subgrid_track_list, CSSValueList& list, bool& is_auto_repeat, - bool& all_tracks_are_auto_repeat_or_fixed_sized) { + bool& all_tracks_are_intrinsic_repeat_or_fixed_sized) { DCHECK_EQ(stream.Peek().GetType(), kFunctionToken); CSSParserTokenStream::BlockGuard guard(stream); stream.ConsumeWhitespace(); @@ -6537,21 +6538,20 @@ if (!track_size) { return false; } - // TODO(almaher): We need to adjust this to allow for other - // intrinsically sized repeats besides auto (like min-content). - if (all_tracks_are_auto_repeat_or_fixed_sized) { - // Whether repeat(auto-fill, auto) should be allowed, and if it should - // apply to both grid and masonry is still in discussion in the CSSWG. + if (all_tracks_are_intrinsic_repeat_or_fixed_sized) { + // Whether repeat(auto-fill, <intrinsic-track-size>) should be allowed, + // and if it should apply to both grid and masonry is still in + // discussion in the CSSWG. // // TODO(almaher): Make adjustments once a resolution is made [1]. // // [1] https://github.com/w3c/csswg-drafts/issues/10915 if (is_auto_repeat && RuntimeEnabledFeatures::CSSMasonryLayoutEnabled()) { - all_tracks_are_auto_repeat_or_fixed_sized = - IsGridTrackFixedSizedOrAuto(*track_size); + all_tracks_are_intrinsic_repeat_or_fixed_sized = + IsGridTrackFixedOrIntrinsicSized(*track_size); } else { - all_tracks_are_auto_repeat_or_fixed_sized = + all_tracks_are_intrinsic_repeat_or_fixed_sized = IsGridTrackFixedSized(*track_size); } } @@ -6762,7 +6762,7 @@ bool allow_repeat = is_subgrid_track_list || track_list_type == TrackListType::kGridTemplate; bool seen_auto_repeat = false; - bool all_tracks_are_auto_repeat_or_fixed_sized = true; + bool all_tracks_are_intrinsic_repeat_or_fixed_sized = true; auto IsRangeAtEnd = [](CSSParserTokenStream& stream) -> bool { return stream.AtEnd() || stream.Peek().GetType() == kDelimiterToken; }; @@ -6780,7 +6780,7 @@ } if (!ConsumeGridTrackRepeatFunction( stream, context, is_subgrid_track_list, *values, is_auto_repeat, - all_tracks_are_auto_repeat_or_fixed_sized)) { + all_tracks_are_intrinsic_repeat_or_fixed_sized)) { return nullptr; } stream.ConsumeWhitespace(); @@ -6797,8 +6797,8 @@ } // TODO(almaher): We need to adjust this to allow intrinsic sized // tracks alongside repeat(auto-fill, auto). - if (all_tracks_are_auto_repeat_or_fixed_sized) { - all_tracks_are_auto_repeat_or_fixed_sized = + if (all_tracks_are_intrinsic_repeat_or_fixed_sized) { + all_tracks_are_intrinsic_repeat_or_fixed_sized = IsGridTrackFixedSized(*value); } @@ -6807,7 +6807,7 @@ return nullptr; } - if (seen_auto_repeat && !all_tracks_are_auto_repeat_or_fixed_sized) { + if (seen_auto_repeat && !all_tracks_are_intrinsic_repeat_or_fixed_sized) { return nullptr; } if (!allow_grid_line_names &&
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc index 73bb2062..6295818 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -345,7 +345,7 @@ CSSStyleSheet::Create(GetDocument(), init, exception_state); sheet->replaceSync(css_text, exception_state); sheet->Contents()->EnsureRuleSet( - MediaQueryEvaluator(GetDocument().GetFrame())); + MediaQueryEvaluator(GetDocument().GetFrame()), /*mixins=*/{}); return sheet; } @@ -369,7 +369,8 @@ GetDocument() .GetStyleEngine() .GetDocumentStyleSheetCollection() - .CreateRuleSets(GetDocument().GetStyleEngine()); + .CreateRuleSets(GetDocument().GetStyleEngine(), + MediaQueryEvaluator(GetDocument().GetFrame())); } Element* DocumentElement() const { return GetDocument().documentElement(); }
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index 89146e8..9191de4 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -823,7 +823,7 @@ RuleSetGroup rule_set_group{rule_set_group_index++}; for (CSSStyleSheet* style : styles) { - RuleSet* rule_set = style_engine.RuleSetForSheet(*style); + RuleSet* rule_set = style_engine.RuleSetForSheet(*style, /*mixins=*/{}); if (!rule_set) { continue; } @@ -2487,7 +2487,8 @@ style_request.search_text_request = StyleRequest::kNotCurrent; } - if (IsTransitionPseudoElement(pseudo_id) && pseudo_id != kPseudoIdViewTransition) { + if (IsTransitionPseudoElement(pseudo_id) && + pseudo_id != kPseudoIdViewTransition) { // Check view transition classes in addition to view transition names. auto* view_transition_element = element.GetPseudoElement(kPseudoIdViewTransition);
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc index 6826c1f..1a11a803 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -1476,7 +1476,7 @@ MediaQueryEvaluator* mq_evaluator = MakeGarbageCollected<MediaQueryEvaluator>(&GetFrame()); - RuleSet& rule_set = contents->EnsureRuleSet(*mq_evaluator); + RuleSet& rule_set = contents->EnsureRuleSet(*mq_evaluator, /*mixins=*/{}); ActiveStyleSheetVector active_stylesheets; active_stylesheets.push_back(std::make_pair(sheet, &rule_set));
diff --git a/third_party/blink/renderer/core/css/rule_set.cc b/third_party/blink/renderer/core/css/rule_set.cc index 20e57f2..da69838 100644 --- a/third_party/blink/renderer/core/css/rule_set.cc +++ b/third_party/blink/renderer/core/css/rule_set.cc
@@ -956,23 +956,24 @@ void RuleSet::AddChildRules(StyleRule* parent_rule, base::span<const Member<StyleRuleBase>> rules, const MediaQueryEvaluator& medium, + const MixinMap& mixins, AddRuleFlags add_rule_flags, const ContainerQuery* container_query, CascadeLayer* cascade_layer, const StyleScope* style_scope, - bool within_mixin) { + const StyleRuleApplyMixin* apply_mixin) { for (StyleRuleBase* rule : rules) { if (auto* style_rule = DynamicTo<StyleRule>(rule)) { - AddStyleRule(style_rule, parent_rule, medium, add_rule_flags, - within_mixin, container_query, cascade_layer, style_scope); + AddStyleRule(style_rule, parent_rule, medium, mixins, add_rule_flags, + apply_mixin, container_query, cascade_layer, style_scope); } else if (auto* page_rule = DynamicTo<StyleRulePage>(rule)) { page_rule->SetCascadeLayer(cascade_layer); AddPageRule(page_rule); } else if (auto* media_rule = DynamicTo<StyleRuleMedia>(rule)) { if (MatchMediaForAddRules(medium, media_rule->MediaQueries())) { - AddChildRules(parent_rule, media_rule->ChildRules(), medium, + AddChildRules(parent_rule, media_rule->ChildRules(), medium, mixins, add_rule_flags, container_query, cascade_layer, - style_scope, within_mixin); + style_scope, apply_mixin); } } else if (auto* font_face_rule = DynamicTo<StyleRuleFontFace>(rule)) { font_face_rule->SetCascadeLayer(cascade_layer); @@ -1009,9 +1010,9 @@ AddFunctionRule(function_rule); } else if (auto* supports_rule = DynamicTo<StyleRuleSupports>(rule)) { if (supports_rule->ConditionIsSupported()) { - AddChildRules(parent_rule, supports_rule->ChildRules(), medium, + AddChildRules(parent_rule, supports_rule->ChildRules(), medium, mixins, add_rule_flags, container_query, cascade_layer, - style_scope, within_mixin); + style_scope, apply_mixin); } } else if (auto* container_rule = DynamicTo<StyleRuleContainer>(rule)) { const ContainerQuery* inner_container_query = @@ -1020,15 +1021,15 @@ inner_container_query = inner_container_query->CopyWithParent(container_query); } - AddChildRules(parent_rule, container_rule->ChildRules(), medium, + AddChildRules(parent_rule, container_rule->ChildRules(), medium, mixins, add_rule_flags, inner_container_query, cascade_layer, - style_scope, within_mixin); + style_scope, apply_mixin); } else if (auto* layer_block_rule = DynamicTo<StyleRuleLayerBlock>(rule)) { CascadeLayer* sub_layer = GetOrAddSubLayer(cascade_layer, layer_block_rule->GetName()); - AddChildRules(parent_rule, layer_block_rule->ChildRules(), medium, + AddChildRules(parent_rule, layer_block_rule->ChildRules(), medium, mixins, add_rule_flags, container_query, sub_layer, style_scope, - within_mixin); + apply_mixin); } else if (auto* layer_statement_rule = DynamicTo<StyleRuleLayerStatement>(rule)) { for (const auto& layer_name : layer_statement_rule->GetNames()) { @@ -1039,34 +1040,42 @@ if (style_scope) { inner_style_scope = inner_style_scope->CopyWithParent(style_scope); } - AddChildRules(parent_rule, scope_rule->ChildRules(), medium, + AddChildRules(parent_rule, scope_rule->ChildRules(), medium, mixins, add_rule_flags, container_query, cascade_layer, - inner_style_scope, within_mixin); + inner_style_scope, apply_mixin); } else if (auto* starting_style_rule = DynamicTo<StyleRuleStartingStyle>(rule)) { AddChildRules(parent_rule, starting_style_rule->ChildRules(), medium, - add_rule_flags | kRuleIsStartingStyle, container_query, - cascade_layer, style_scope, within_mixin); - } else if (auto* mixin_rule = DynamicTo<StyleRuleMixin>(rule)) { - mixins_.Set(mixin_rule->GetName(), mixin_rule); + mixins, add_rule_flags | kRuleIsStartingStyle, + container_query, cascade_layer, style_scope, apply_mixin); } else if (auto* apply_mixin_rule = DynamicTo<StyleRuleApplyMixin>(rule)) { - // TODO(sesse): This lookup needs to work completely differently - // if we are to support mixins from different stylesheets. - // In particular, we need to implement tree-scoped lookups - // in a situation where we don't have the normal ScopedStyleResolver - // available, and also take into account that sharing RuleSets - // won't really work if we cross-reference mixins from other sheets. - auto it = mixins_.find(apply_mixin_rule->GetName()); - if (it != mixins_.end() && it->value->FakeParentRule().ChildRules()) { + auto it = mixins.find(apply_mixin_rule->GetName()); + if (it != mixins.end() && it->value->FakeParentRule().ChildRules()) { AddChildRules(parent_rule, *it->value->FakeParentRule().ChildRules(), - medium, add_rule_flags, container_query, cascade_layer, - style_scope, /*within_mixin=*/true); + medium, mixins, add_rule_flags, container_query, + cascade_layer, style_scope, apply_mixin_rule); + } + } else if (auto* contents_rule = + DynamicTo<StyleRuleContentsStatement>(rule)) { + // Try first the parameter from @apply, then the fallback block given in + // @contents, and if neither exists, nothing happens. + if (apply_mixin->FakeParentRuleForDeclarations()) { + AddChildRules( + parent_rule, + *apply_mixin->FakeParentRuleForDeclarations()->ChildRules(), medium, + mixins, add_rule_flags, container_query, cascade_layer, style_scope, + apply_mixin); + } else if (contents_rule->FakeParentRuleForFallback()) { + AddChildRules(parent_rule, + *contents_rule->FakeParentRuleForFallback()->ChildRules(), + medium, mixins, add_rule_flags, container_query, + cascade_layer, style_scope, apply_mixin); } } else if (auto* nested_declarations = DynamicTo<StyleRuleNestedDeclarations>(rule)) { AddStyleRule(nested_declarations->InnerStyleRule(), parent_rule, medium, - add_rule_flags, within_mixin, container_query, cascade_layer, - style_scope); + mixins, add_rule_flags, apply_mixin, container_query, + cascade_layer, style_scope); } } } @@ -1085,6 +1094,7 @@ void RuleSet::AddRulesFromSheet(const StyleSheetContents* sheet, const MediaQueryEvaluator& medium, + const MixinMap& mixins, CascadeLayer* cascade_layer, const StyleScope* style_scope) { TRACE_EVENT0("blink", "RuleSet::addRulesFromSheet"); @@ -1112,15 +1122,15 @@ GetOrAddSubLayer(cascade_layer, import_rule->GetLayerName()); } if (import_rule->GetStyleSheet()) { - AddRulesFromSheet(import_rule->GetStyleSheet(), medium, import_layer, - import_rule->GetScope()); + AddRulesFromSheet(import_rule->GetStyleSheet(), medium, mixins, + import_layer, import_rule->GetScope()); } } InvalidationSetToSelectorMap::StyleSheetContentsScope contents_scope(sheet); - AddChildRules(/*parent_rule=*/nullptr, sheet->ChildRules(), medium, + AddChildRules(/*parent_rule=*/nullptr, sheet->ChildRules(), medium, mixins, kRuleHasNoSpecialState, nullptr /* container_query */, - cascade_layer, style_scope, /*within_mixin=*/false); + cascade_layer, style_scope, /*apply_mixin=*/nullptr); } // If there's a reference to the parent selector (implicit or explicit) @@ -1248,12 +1258,13 @@ void RuleSet::AddStyleRule(StyleRule* style_rule, StyleRule* parent_rule, const MediaQueryEvaluator& medium, + const MixinMap& mixins, AddRuleFlags add_rule_flags, - bool within_mixin, + const StyleRuleApplyMixin* apply_mixin, const ContainerQuery* container_query, CascadeLayer* cascade_layer, const StyleScope* style_scope) { - if (within_mixin) { + if (apply_mixin) { style_rule = To<StyleRule>(style_rule->Renest(parent_rule)); } for (const CSSSelector* selector = style_rule->FirstSelector(); selector; @@ -1265,8 +1276,9 @@ // Nested rules are taken to be added immediately after their parent rule. if (style_rule->ChildRules() != nullptr) { - AddChildRules(style_rule, *style_rule->ChildRules(), medium, add_rule_flags, - container_query, cascade_layer, style_scope, within_mixin); + AddChildRules(style_rule, *style_rule->ChildRules(), medium, mixins, + add_rule_flags, container_query, cascade_layer, style_scope, + apply_mixin); } } @@ -1705,7 +1717,6 @@ visitor->Trace(layer_intervals_); visitor->Trace(container_query_intervals_); visitor->Trace(scope_intervals_); - visitor->Trace(mixins_); #if DCHECK_IS_ON() visitor->Trace(all_rules_); #endif // DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/css/rule_set.h b/third_party/blink/renderer/core/css/rule_set.h index 12a0935..908e3cf6 100644 --- a/third_party/blink/renderer/core/css/rule_set.h +++ b/third_party/blink/renderer/core/css/rule_set.h
@@ -380,20 +380,22 @@ RuleSet(const RuleSet&) = delete; RuleSet& operator=(const RuleSet&) = delete; - void AddRulesFromSheet(const StyleSheetContents*, - const MediaQueryEvaluator&, - CascadeLayer* = nullptr, - const StyleScope* = nullptr); + void AddRulesFromSheet(const StyleSheetContents* contents, + const MediaQueryEvaluator& medium, + const MixinMap& mixins, + CascadeLayer* cascade_layer = nullptr, + const StyleScope* style_scope = nullptr); - // “within_mixin” means that we are currently adding this rule + // non-nullptr “apply_mixin” means that we are currently adding this rule // as part of @apply in a mixin, and all rules we add must be // duplicated and reparented. This is also propagated through // AddChildRules(). void AddStyleRule(StyleRule* style_rule, StyleRule* parent_rule, const MediaQueryEvaluator& medium, + const MixinMap& mixins, AddRuleFlags add_rule_flags, - bool within_mixin, + const StyleRuleApplyMixin* apply_mixin, const ContainerQuery* container_query = nullptr, CascadeLayer* cascade_layer = nullptr, const StyleScope* style_scope = nullptr); @@ -641,11 +643,12 @@ void AddChildRules(StyleRule* parent_rule, base::span<const Member<StyleRuleBase>>, const MediaQueryEvaluator& medium, + const MixinMap& mixins, AddRuleFlags, const ContainerQuery*, CascadeLayer*, const StyleScope*, - bool within_mixin); + const StyleRuleApplyMixin* apply_mixin); // Determines whether or not CSSSelector::is_covered_by_bucketing_ should // be computed during calls to FindBestRuleSetAndAdd. @@ -759,7 +762,6 @@ HeapVector<Member<StyleRulePositionTry>> position_try_rules_; HeapVector<MediaQuerySetResult> media_query_set_results_; HeapVector<Member<StyleRuleFunction>> function_rules_; - HeapHashMap<AtomicString, Member<StyleRuleMixin>> mixins_; // Whether there is a ruleset bucket for rules with a selector on // the style attribute (which is rare, but allowed). If so, the caller
diff --git a/third_party/blink/renderer/core/css/rule_set_test.cc b/third_party/blink/renderer/core/css/rule_set_test.cc index da0af73..d5f282d2 100644 --- a/third_party/blink/renderer/core/css/rule_set_test.cc +++ b/third_party/blink/renderer/core/css/rule_set_test.cc
@@ -930,7 +930,8 @@ To<HTMLStyleElement>(GetDocument().QuerySelector(AtomicString("style"))) ->sheet() ->Contents() - ->EnsureRuleSet(MediaQueryEvaluator(GetDocument().GetFrame())); + ->EnsureRuleSet(MediaQueryEvaluator(GetDocument().GetFrame()), + /*mixins=*/{}); rule_set.CompactRulesIfNeeded(); return rule_set; }
diff --git a/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc b/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc index fdbfcca..bf9275e 100644 --- a/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc +++ b/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.cc
@@ -34,6 +34,7 @@ #include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/css/style_sheet_candidate.h" +#include "third_party/blink/renderer/core/css/style_sheet_contents.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/html/html_style_element.h" @@ -79,10 +80,11 @@ } void ShadowTreeStyleSheetCollection::UpdateActiveStyleSheets( - StyleEngine& engine) { + StyleEngine& engine, + const MediaQueryEvaluator& medium) { auto* collection = MakeGarbageCollected<StyleSheetCollection>(); CollectStyleSheets(engine, *collection); - collection->CreateRuleSets(engine); + collection->CreateRuleSets(engine, medium); ApplyActiveStyleSheetChanges(*collection); }
diff --git a/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.h b/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.h index 2f5e5af..89f4183 100644 --- a/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.h +++ b/third_party/blink/renderer/core/css/shadow_tree_style_sheet_collection.h
@@ -30,6 +30,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_SHADOW_TREE_STYLE_SHEET_COLLECTION_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_SHADOW_TREE_STYLE_SHEET_COLLECTION_H_ +#include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.h" #include "third_party/blink/renderer/platform/wtf/casting.h" @@ -48,7 +49,7 @@ ShadowTreeStyleSheetCollection& operator=( const ShadowTreeStyleSheetCollection&) = delete; - void UpdateActiveStyleSheets(StyleEngine&); + void UpdateActiveStyleSheets(StyleEngine&, const MediaQueryEvaluator&); bool IsShadowTreeStyleSheetCollection() const final { return true; } void Trace(Visitor* visitor) const override {
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index e49174b6..055d94f 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -645,7 +645,7 @@ auto* collection = To<ShadowTreeStyleSheetCollection>(StyleSheetCollectionFor(*tree_scope)); DCHECK(collection); - collection->UpdateActiveStyleSheets(*this); + collection->UpdateActiveStyleSheets(*this, EnsureMediaQueryEvaluator()); if (!collection->HasStyleSheetCandidateNodes() && !tree_scope->HasAdoptedStyleSheets()) { tree_scopes_removed.insert(tree_scope); @@ -660,7 +660,8 @@ ActiveStyleSheetVector new_active_sheets; for (auto& sheet : injected_user_style_sheets_) { - if (RuleSet* rule_set = RuleSetForSheet(*sheet.second)) { + // TODO: Support mixins in user stylesheets. + if (RuleSet* rule_set = RuleSetForSheet(*sheet.second, /*mixins=*/{})) { new_active_sheets.push_back(std::make_pair(sheet.second, rule_set)); } } @@ -684,7 +685,8 @@ } if (ShouldUpdateDocumentStyleSheetCollection()) { - GetDocumentStyleSheetCollection().UpdateActiveStyleSheets(*this); + GetDocumentStyleSheetCollection().UpdateActiveStyleSheets( + *this, EnsureMediaQueryEvaluator()); } if (ShouldUpdateShadowTreeStyleSheetCollection()) { @@ -938,18 +940,21 @@ return GetStyleResolver().ComputeFont(element, font_style, font_properties); } -RuleSet* StyleEngine::RuleSetForSheet(CSSStyleSheet& sheet) { +RuleSet* StyleEngine::RuleSetForSheet(CSSStyleSheet& sheet, + const MixinMap& mixins) { if (!sheet.MatchesMediaQueries(EnsureMediaQueryEvaluator())) { return nullptr; } - return &sheet.Contents()->EnsureRuleSet(*media_query_evaluator_); + return &sheet.Contents()->EnsureRuleSet(*media_query_evaluator_, mixins); } -RuleSet* StyleEngine::CreateUnconnectedRuleSet(CSSStyleSheet& sheet) { +RuleSet* StyleEngine::CreateUnconnectedRuleSet(CSSStyleSheet& sheet, + const MixinMap& mixins) { if (!sheet.MatchesMediaQueries(EnsureMediaQueryEvaluator())) { return nullptr; } - return sheet.Contents()->CreateUnconnectedRuleSet(*media_query_evaluator_); + return sheet.Contents()->CreateUnconnectedRuleSet(*media_query_evaluator_, + mixins); } void StyleEngine::ClearResolvers() { @@ -2649,7 +2654,7 @@ auto* css_style_sheet = transition->UAStyleSheet(); return &css_style_sheet->Contents()->EnsureRuleSet( - CSSDefaultStyleSheets::ScreenEval()); + CSSDefaultStyleSheets::ScreenEval(), /*mixins=*/{}); } void StyleEngine::UpdateViewTransitionOptIn() {
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h index 4fb19070..74e9d2136 100644 --- a/third_party/blink/renderer/core/css/style_engine.h +++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -293,12 +293,13 @@ return global_rule_set_->DocumentRulesSelectorsRuleSet(); } - RuleSet* RuleSetForSheet(CSSStyleSheet&); + RuleSet* RuleSetForSheet(CSSStyleSheet&, const MixinMap& mixins); + // See StyleSheetContents::CreateUnconnectedRuleSet. // // Note that this can return nullptr when the associated media query // does not match. - RuleSet* CreateUnconnectedRuleSet(CSSStyleSheet&); + RuleSet* CreateUnconnectedRuleSet(CSSStyleSheet&, const MixinMap& mixins); // A functional @media query is evaluated as a part of some function // during value resolution. This is different from regular media queries,
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 95fa6386..9d1c85df 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -173,8 +173,8 @@ kHTMLStandardMode, SecureContextMode::kInsecureContext)); sheet->ParseString(css_text); HeapHashSet<Member<RuleSet>> rule_sets; - RuleSet& rule_set = - sheet->EnsureRuleSet(MediaQueryEvaluator(GetDocument().GetFrame())); + RuleSet& rule_set = sheet->EnsureRuleSet( + MediaQueryEvaluator(GetDocument().GetFrame()), /*mixins=*/{}); rule_set.CompactRulesIfNeeded(); rule_sets.insert(&rule_set); SelectorFilter selector_filter; @@ -7292,7 +7292,8 @@ sheet->Contents()->ClearRuleSet(); EXPECT_FALSE(sheet->Contents()->HasRuleSet()); - RuleSet* rule_set = GetStyleEngine().CreateUnconnectedRuleSet(*sheet); + RuleSet* rule_set = + GetStyleEngine().CreateUnconnectedRuleSet(*sheet, /*mixins=*/{}); ASSERT_TRUE(rule_set); rule_set->AssertCompacted(); EXPECT_EQ(2u, rule_set->ClassRules(AtomicString("a")).size()); @@ -7313,7 +7314,8 @@ CSSStyleSheet* sheet = To<HTMLStyleElement>(GetDocument().getElementById(AtomicString("style"))) ->sheet(); - EXPECT_FALSE(GetStyleEngine().CreateUnconnectedRuleSet(*sheet)); + EXPECT_FALSE( + GetStyleEngine().CreateUnconnectedRuleSet(*sheet, /*mixins=*/{})); } TEST_F(StyleEngineTest, HasComplexSafaAreaConstraints) {
diff --git a/third_party/blink/renderer/core/css/style_rule.cc b/third_party/blink/renderer/core/css/style_rule.cc index 9b556e39..a6772bb 100644 --- a/third_party/blink/renderer/core/css/style_rule.cc +++ b/third_party/blink/renderer/core/css/style_rule.cc
@@ -181,6 +181,9 @@ case kApplyMixin: To<StyleRuleApplyMixin>(this)->TraceAfterDispatch(visitor); return; + case kContents: + To<StyleRuleContentsStatement>(this)->TraceAfterDispatch(visitor); + return; case kPositionTry: To<StyleRulePositionTry>(this)->TraceAfterDispatch(visitor); return; @@ -274,6 +277,9 @@ case kApplyMixin: To<StyleRuleApplyMixin>(this)->~StyleRuleApplyMixin(); return; + case kContents: + To<StyleRuleContentsStatement>(this)->~StyleRuleContentsStatement(); + return; case kPositionTry: To<StyleRulePositionTry>(this)->~StyleRulePositionTry(); return; @@ -327,6 +333,7 @@ case kKeyframe: case kMixin: case kApplyMixin: + case kContents: case kCustomMedia: NOTREACHED(); case kContainer: @@ -457,6 +464,7 @@ case kCharset: case kMixin: case kApplyMixin: + case kContents: NOTREACHED(); } if (parent_rule) { @@ -670,6 +678,7 @@ return this; case kMixin: case kApplyMixin: + case kContents: // The parent pointers in mixins don't really matter; // they are always replaced during application anyway. return this; @@ -1062,11 +1071,15 @@ visitor->Trace(fake_parent_rule_); } -StyleRuleApplyMixin::StyleRuleApplyMixin(AtomicString name) - : StyleRuleBase(kApplyMixin), name_(std::move(name)) {} - void StyleRuleApplyMixin::TraceAfterDispatch(blink::Visitor* visitor) const { StyleRuleBase::TraceAfterDispatch(visitor); + visitor->Trace(fake_parent_rule_for_declarations_); +} + +void StyleRuleContentsStatement::TraceAfterDispatch( + blink::Visitor* visitor) const { + StyleRuleBase::TraceAfterDispatch(visitor); + visitor->Trace(fake_parent_rule_for_fallback_); } StyleRuleCustomMedia::StyleRuleCustomMedia(AtomicString name,
diff --git a/third_party/blink/renderer/core/css/style_rule.h b/third_party/blink/renderer/core/css/style_rule.h index 969c4ec..d148512b 100644 --- a/third_party/blink/renderer/core/css/style_rule.h +++ b/third_party/blink/renderer/core/css/style_rule.h
@@ -79,6 +79,7 @@ kFunction, kMixin, kApplyMixin, + kContents, kPositionTry, kCustomMedia, }; @@ -130,6 +131,7 @@ bool IsFunctionRule() const { return GetType() == kFunction; } bool IsMixinRule() const { return GetType() == kMixin; } bool IsApplyMixinRule() const { return GetType() == kApplyMixin; } + bool IsContentsRule() const { return GetType() == kContents; } bool IsPositionTryRule() const { return GetType() == kPositionTry; } bool IsCustomMediaRule() const { return GetType() == kCustomMedia; } @@ -703,18 +705,56 @@ Member<StyleRule> fake_parent_rule_; }; +using MixinMap = HeapHashMap<AtomicString, Member<StyleRuleMixin>>; + // An @apply rule, representing applying a mixin. class CORE_EXPORT StyleRuleApplyMixin : public StyleRuleBase { public: - explicit StyleRuleApplyMixin(AtomicString name); + StyleRuleApplyMixin(AtomicString name, + StyleRule* fake_parent_rule_for_declarations) + : StyleRuleBase(kApplyMixin), + name_(name), + fake_parent_rule_for_declarations_(fake_parent_rule_for_declarations) {} StyleRuleApplyMixin(const StyleRuleMixin&) = delete; const AtomicString& GetName() const { return name_; } + // Declarations argument (for @contents). May be nullptr. + StyleRule* FakeParentRuleForDeclarations() const { + return fake_parent_rule_for_declarations_; + } + void TraceAfterDispatch(blink::Visitor*) const; private: AtomicString name_; + Member<StyleRule> fake_parent_rule_for_declarations_; +}; + +// A @contents rule, representing a placeholder within a mixin +// for rules sent in through a parameter to @apply. The @contents +// rule may have a declaration block, which is used as a fallback +// if no @contents is given. We store that declaration block +// as a dummy rule, similar to how StyleRuleMixin works. +// +// This class is named “…Statement” to avoid confusion with +// the more general concept of contents of a style rule. +class CORE_EXPORT StyleRuleContentsStatement : public StyleRuleBase { + public: + explicit StyleRuleContentsStatement(StyleRule* fake_parent_rule_for_fallback) + : StyleRuleBase(kContents), + fake_parent_rule_for_fallback_(fake_parent_rule_for_fallback) {} + StyleRuleContentsStatement(const StyleRuleMixin&) = delete; + + // May be nullptr. + StyleRule* FakeParentRuleForFallback() const { + return fake_parent_rule_for_fallback_; + } + + void TraceAfterDispatch(blink::Visitor*) const; + + private: + Member<StyleRule> fake_parent_rule_for_fallback_; }; class CORE_EXPORT StyleRuleCustomMedia : public StyleRuleBase { @@ -868,6 +908,13 @@ }; template <> +struct DowncastTraits<StyleRuleContentsStatement> { + static bool AllowFrom(const StyleRuleBase& rule) { + return rule.IsContentsRule(); + } +}; + +template <> struct DowncastTraits<StyleRuleCustomMedia> { static bool AllowFrom(const StyleRuleBase& rule) { return rule.IsCustomMediaRule();
diff --git a/third_party/blink/renderer/core/css/style_sheet_collection.cc b/third_party/blink/renderer/core/css/style_sheet_collection.cc index 45d1463d..29fa3d4 100644 --- a/third_party/blink/renderer/core/css/style_sheet_collection.cc +++ b/third_party/blink/renderer/core/css/style_sheet_collection.cc
@@ -60,7 +60,44 @@ active_style_sheets_.push_back(std::pair(sheet, nullptr)); } -void StyleSheetCollection::CreateRuleSets(StyleEngine& engine) { +// FIXME(sesse): Store this somewhere (including the two-level Eval() form), +// so that we know when we need to invalidate. +static bool MatchMediaForMixins(const MediaQueryEvaluator& evaluator, + const MediaQuerySet* media_queries) { + if (!media_queries) { + return true; + } + return evaluator.Eval(*media_queries); +} + +static void ExtractMixinsFromRules( + base::span<const Member<StyleRuleBase>> rules, + const MediaQueryEvaluator& medium, + MixinMap& mixins) { + for (StyleRuleBase* rule : rules) { + // TODO(sesse): @container, @layer, @scope, @starting-style are waiting for + // a resolution in https://github.com/w3c/csswg-drafts/issues/12417. + if (auto* media_rule = DynamicTo<StyleRuleMedia>(rule)) { + if (MatchMediaForMixins(medium, media_rule->MediaQueries())) { + ExtractMixinsFromRules(media_rule->ChildRules(), medium, mixins); + } + } else if (auto* supports_rule = DynamicTo<StyleRuleSupports>(rule)) { + if (supports_rule->ConditionIsSupported()) { + ExtractMixinsFromRules(supports_rule->ChildRules(), medium, mixins); + } + } else if (auto* mixin_rule = DynamicTo<StyleRuleMixin>(rule)) { + mixins.insert(mixin_rule->GetName(), mixin_rule); + } + } +} + +void StyleSheetCollection::CreateRuleSets(StyleEngine& engine, + const MediaQueryEvaluator& medium) { + MixinMap mixins; + for (auto& [css_sheet, rule_set] : active_style_sheets_) { + ExtractMixinsFromRules(css_sheet->Contents()->ChildRules(), medium, mixins); + } + // Keep track of ensured RuleSets with @layer rules to detect // StyleSheetContents sharing; RuleSets should not be shared // between two equal sheets with @layer rules, since anonymous @@ -69,7 +106,7 @@ for (auto& [css_sheet, rule_set] : active_style_sheets_) { CHECK_EQ(rule_set, nullptr); - rule_set = engine.RuleSetForSheet(*css_sheet); + rule_set = engine.RuleSetForSheet(*css_sheet, mixins); // NOTE: If the user has specified the same CSSStyleSheet object multiple // times (which is only possible for constructible stylesheets, in @@ -94,7 +131,7 @@ // // TODO(sesse): Can we detect this before creating the RuleSet? css_sheet->WillMutateRules(); - rule_set = engine.RuleSetForSheet(*css_sheet); + rule_set = engine.RuleSetForSheet(*css_sheet, mixins); } if (css_sheet->Contents()->GetRuleSetDiff()) {
diff --git a/third_party/blink/renderer/core/css/style_sheet_collection.h b/third_party/blink/renderer/core/css/style_sheet_collection.h index fbaa225..7fcd6fc 100644 --- a/third_party/blink/renderer/core/css/style_sheet_collection.h +++ b/third_party/blink/renderer/core/css/style_sheet_collection.h
@@ -81,7 +81,7 @@ // all stylesheets. // // Can only be called once. - void CreateRuleSets(StyleEngine& engine); + void CreateRuleSets(StyleEngine& engine, const MediaQueryEvaluator& medium); virtual void Trace(Visitor*) const; const char* GetHumanReadableName() const override {
diff --git a/third_party/blink/renderer/core/css/style_sheet_contents.cc b/third_party/blink/renderer/core/css/style_sheet_contents.cc index c847528..05e99dc 100644 --- a/third_party/blink/renderer/core/css/style_sheet_contents.cc +++ b/third_party/blink/renderer/core/css/style_sheet_contents.cc
@@ -701,6 +701,7 @@ case StyleRuleBase::kCustomMedia: break; case StyleRuleBase::kApplyMixin: + case StyleRuleBase::kContents: // TODO(sesse): Should we go down into the rules here? // Do we need to do a new name lookup then? break; @@ -809,16 +810,18 @@ referenced_from_resource_ = nullptr; } -RuleSet& StyleSheetContents::EnsureRuleSet(const MediaQueryEvaluator& medium) { +RuleSet& StyleSheetContents::EnsureRuleSet(const MediaQueryEvaluator& medium, + const MixinMap& mixins) { if (rule_set_ && rule_set_->DidMediaQueryResultsChange(medium)) { rule_set_ = nullptr; } + // TODO(sesse): Check if mixins changed, somehow. if (rule_set_diff_) { rule_set_diff_->NewRuleSetCleared(); } if (!rule_set_) { rule_set_ = MakeGarbageCollected<RuleSet>(); - rule_set_->AddRulesFromSheet(this, medium); + rule_set_->AddRulesFromSheet(this, medium, mixins); if (rule_set_diff_) { rule_set_diff_->NewRuleSetCreated(rule_set_); } @@ -828,9 +831,10 @@ } RuleSet* StyleSheetContents::CreateUnconnectedRuleSet( - const MediaQueryEvaluator& medium) const { + const MediaQueryEvaluator& medium, + const MixinMap& mixins) const { auto* rule_set = MakeGarbageCollected<RuleSet>(); - rule_set->AddRulesFromSheet(this, medium); + rule_set->AddRulesFromSheet(this, medium, mixins); rule_set->CompactRulesIfNeeded(); return rule_set; }
diff --git a/third_party/blink/renderer/core/css/style_sheet_contents.h b/third_party/blink/renderer/core/css/style_sheet_contents.h index ef0d7c7..1855631a 100644 --- a/third_party/blink/renderer/core/css/style_sheet_contents.h +++ b/third_party/blink/renderer/core/css/style_sheet_contents.h
@@ -253,12 +253,14 @@ } bool HasRuleSet() { return rule_set_.Get(); } - RuleSet& EnsureRuleSet(const MediaQueryEvaluator&); + RuleSet& EnsureRuleSet(const MediaQueryEvaluator& medium, + const MixinMap& mixins); void ClearRuleSet(); // Create a RuleSet which is not associated (i.e. not owned) // by this StyleSheetContents. This is useful for matching rules // in an "alternate reality", which is the case for InspectorGhostRules. - RuleSet* CreateUnconnectedRuleSet(const MediaQueryEvaluator&) const; + RuleSet* CreateUnconnectedRuleSet(const MediaQueryEvaluator& medium, + const MixinMap& mixins) const; String SourceMapURL() const { return source_map_url_; }
diff --git a/third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.h b/third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.h index e7d434f7..f8e6f1c47 100644 --- a/third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.h +++ b/third_party/blink/renderer/core/css/tree_scope_style_sheet_collection.h
@@ -31,6 +31,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_TREE_SCOPE_STYLE_SHEET_COLLECTION_H_ #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/style_rule.h" #include "third_party/blink/renderer/core/css/style_sheet_collection.h" #include "third_party/blink/renderer/core/dom/tree_ordered_list.h" #include "third_party/blink/renderer/core/dom/tree_scope.h"
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc index 45604d0..1e39d79 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
@@ -42,7 +42,6 @@ #include "third_party/blink/renderer/core/timing/soft_navigation_context.h" #include "third_party/blink/renderer/core/timing/soft_navigation_heuristics.h" #include "third_party/blink/renderer/core/timing/soft_navigation_paint_attribution_tracker.h" -#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/task_environment.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" @@ -2230,37 +2229,6 @@ UpdateAllLifecyclePhasesForTest(); } -TEST_F(DisplayLockContextRenderingTest, - SelectionOnAnonymousColumnSpannerDoesNotCrash) { - ScopedFlowThreadLessForTest scope(false); - SetHtmlInnerHTML(R"HTML( - <style> - #columns { - column-count: 5; - } - #spanner { - column-span: all; - } - </style> - <div id="columns"> - <div id="spanner"></div> - </div> - )HTML"); - - auto* columns_object = - GetDocument().getElementById(AtomicString("columns"))->GetLayoutObject(); - LayoutObject* spanner_placeholder_object = nullptr; - for (auto* candidate = columns_object->SlowFirstChild(); candidate; - candidate = candidate->NextSibling()) { - if (candidate->IsLayoutMultiColumnSpannerPlaceholder()) { - spanner_placeholder_object = candidate; - break; - } - } - - ASSERT_TRUE(spanner_placeholder_object); - EXPECT_FALSE(spanner_placeholder_object->CanBeSelectionLeaf()); -} TEST_F(DisplayLockContextRenderingTest, ObjectsNeedingLayoutConsidersLocks) { SetHtmlInnerHTML(R"HTML(
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 7303995..01c8f3d 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -3836,7 +3836,7 @@ } // https://github.com/WICG/declarative-partial-updates -DOMPatchStatus* Element::currentPatch() { +Patch* Element::currentPatch() { PatchSupplement* supplement = PatchSupplement::FromIfExists(GetDocument()); if (!supplement) { return nullptr; @@ -4368,6 +4368,10 @@ style = HasCustomStyleCallbacks() ? CustomStyleForLayoutObject(new_style_recalc_context) : OriginalStyleForLayoutObject(new_style_recalc_context); + if (!style) { + DCHECK(IsPseudoElement()); + return nullptr; + } } DisplayLockContext* context = GetDisplayLockContext();
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index f4951ea6..72af388 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -86,7 +86,6 @@ class CSSStyleDeclaration; class CustomElementDefinition; class CustomElementRegistry; -class DOMPatchStatus; class DOMRect; class DOMRectList; class DOMStringMap; @@ -112,6 +111,7 @@ class MutableCSSPropertyValueSet; class NamedNodeMap; class OutOfFlowData; +class Patch; class PointerLockOptions; class PopoverData; class PseudoElement; @@ -1515,7 +1515,7 @@ EditContext* editContext() const; // https://github.com/WICG/declarative-partial-updates - DOMPatchStatus* currentPatch(); + Patch* currentPatch(); // Helpers for V8DOMActivityLogger::logEvent. They call logEvent only if // the element is isConnected() and the context is an isolated world.
diff --git a/third_party/blink/renderer/core/dom/element.idl b/third_party/blink/renderer/core/dom/element.idl index 44fb1a2..3a823173 100644 --- a/third_party/blink/renderer/core/dom/element.idl +++ b/third_party/blink/renderer/core/dom/element.idl
@@ -183,7 +183,7 @@ [RuntimeEnabled=ScopedCustomElementRegistry] readonly attribute CustomElementRegistry? customElementRegistry; // Declarative document updates - [RuntimeEnabled=DocumentPatching] readonly attribute PatchStatus? currentPatch; + [RuntimeEnabled=DocumentPatching] readonly attribute Patch? currentPatch; }; Element includes ParentNode;
diff --git a/third_party/blink/renderer/core/dom/events/event.h b/third_party/blink/renderer/core/dom/events/event.h index f82f90b9..8e207f42 100644 --- a/third_party/blink/renderer/core/dom/events/event.h +++ b/third_party/blink/renderer/core/dom/events/event.h
@@ -143,9 +143,14 @@ const AtomicString& type() const { return type_; } void SetType(const AtomicString& type) { type_ = type; } + // Web exposed target of the event. Can't be a pseudo-element. EventTarget* target() const { return target_.Get(); } void SetTarget(EventTarget*); + // This is the target that the event was dispatched to, without any + // retargeting. Can be a pseudo-element. Shouldn't we web exposed. + EventTarget* RawTarget() const { return target_.Get(); } + EventTarget* currentTarget() 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/mutation_observer.cc b/third_party/blink/renderer/core/dom/mutation_observer.cc index b9424685..09476d67 100644 --- a/third_party/blink/renderer/core/dom/mutation_observer.cc +++ b/third_party/blink/renderer/core/dom/mutation_observer.cc
@@ -43,7 +43,7 @@ #include "third_party/blink/renderer/core/execution_context/agent.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/html/html_slot_element.h" -#include "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "third_party/blink/renderer/core/probe/core_probes.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" @@ -52,7 +52,7 @@ namespace blink { using SlotChangeList = HeapVector<Member<HTMLSlotElement>>; -using PatchList = HeapVector<Member<DOMPatchStatus>>; +using PatchList = HeapVector<Member<Patch>>; static unsigned g_observer_priority = 0; struct MutationObserver::ObserverLessThan { @@ -92,7 +92,7 @@ active_slot_change_list_.push_back(&slot); } - void EnqueuePatch(DOMPatchStatus& patch) { + void EnqueuePatch(Patch& patch) { EnsureEnqueueMicrotask(); pending_patches_.push_back(&patch); } @@ -345,7 +345,7 @@ } // static -void MutationObserver::EnqueuePatch(DOMPatchStatus& patch) { +void MutationObserver::EnqueuePatch(Patch& patch) { DCHECK(IsMainThread()); MutationObserverAgentData::From(patch.GetDocument().GetAgent()) .EnqueuePatch(patch);
diff --git a/third_party/blink/renderer/core/dom/mutation_observer.h b/third_party/blink/renderer/core/dom/mutation_observer.h index c513c46..21229ef 100644 --- a/third_party/blink/renderer/core/dom/mutation_observer.h +++ b/third_party/blink/renderer/core/dom/mutation_observer.h
@@ -37,7 +37,7 @@ #include "third_party/blink/renderer/core/dom/mutation_observer_options.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h" #include "third_party/blink/renderer/core/inspector/dom_patch_support.h" -#include "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "third_party/blink/renderer/core/probe/async_task_context.h" #include "third_party/blink/renderer/platform/bindings/name_client.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" @@ -103,7 +103,7 @@ static void DeliverMutations(); static void EnqueueSlotChange(HTMLSlotElement&); static void CleanSlotChangeList(Document&); - static void EnqueuePatch(DOMPatchStatus&); + static void EnqueuePatch(Patch&); static void CleanPatchList(Document&); MutationObserver(ExecutionContext*, Delegate*);
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index db042647..e595b4f 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -3268,8 +3268,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 e0ab43ae..8a322f9 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/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 f4f2a56..55ca54b7f 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; @@ -573,7 +574,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/editing/text_offset_mapping.cc b/third_party/blink/renderer/core/editing/text_offset_mapping.cc index 940557a..563f471 100644 --- a/third_party/blink/renderer/core/editing/text_offset_mapping.cc +++ b/third_party/blink/renderer/core/editing/text_offset_mapping.cc
@@ -55,8 +55,7 @@ return true; } // Since we can't create |EphemeralRange|, we exclude a |LayoutBlockFlow| if - // its entire subtree is anonymous, e.g. |LayoutMultiColumnSet|, - // and with anonymous layout objects. + // its entire subtree is anonymous. return HasNonPsuedoNode(*block_flow); }
diff --git a/third_party/blink/renderer/core/events/mouse_event.cc b/third_party/blink/renderer/core/events/mouse_event.cc index 1d70c26..8dce53e8 100644 --- a/third_party/blink/renderer/core/events/mouse_event.cc +++ b/third_party/blink/renderer/core/events/mouse_event.cc
@@ -367,7 +367,7 @@ type() == event_type_names::kMouseleave) return relatedTarget() ? relatedTarget()->ToNode() : nullptr; - return target() ? target()->ToNode() : nullptr; + return RawTarget() ? RawTarget()->ToNode() : nullptr; } Node* MouseEvent::fromElement() const { @@ -377,7 +377,7 @@ type() != event_type_names::kMouseleave) return relatedTarget() ? relatedTarget()->ToNode() : nullptr; - return target() ? target()->ToNode() : nullptr; + return RawTarget() ? RawTarget()->ToNode() : nullptr; } void MouseEvent::Trace(Visitor* visitor) const { @@ -418,7 +418,7 @@ } } - DCHECK(!target() || target() != relatedTarget()); + DCHECK(!RawTarget() || RawTarget() != relatedTarget()); EventTarget* related_target = relatedTarget(); @@ -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; @@ -528,7 +528,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/events/pointer_event.cc b/third_party/blink/renderer/core/events/pointer_event.cc index 80e9716..b001893 100644 --- a/third_party/blink/renderer/core/events/pointer_event.cc +++ b/third_party/blink/renderer/core/events/pointer_event.cc
@@ -197,7 +197,7 @@ return MouseEvent::DispatchEvent(dispatcher); } - DCHECK(!target() || target() != relatedTarget()); + DCHECK(!RawTarget() || RawTarget() != relatedTarget()); GetEventPath().AdjustForRelatedTarget(dispatcher.GetNode(), relatedTarget());
diff --git a/third_party/blink/renderer/core/fileapi/file_reader.cc b/third_party/blink/renderer/core/fileapi/file_reader.cc index 48bd2d0..429dd00 100644 --- a/third_party/blink/renderer/core/fileapi/file_reader.cc +++ b/third_party/blink/renderer/core/fileapi/file_reader.cc
@@ -423,7 +423,9 @@ // if we're still loading (therefore we need abort process) or not. loading_state_ = kLoadingStateNone; - FireEvent(event_type_names::kProgress); + if (loader_->BytesLoaded() > 0) { + FireEvent(event_type_names::kProgress); + } DCHECK_NE(kDone, state_); state_ = kDone;
diff --git a/third_party/blink/renderer/core/fileapi/file_reader.idl b/third_party/blink/renderer/core/fileapi/file_reader.idl index 4aa6ee9..5f62105 100644 --- a/third_party/blink/renderer/core/fileapi/file_reader.idl +++ b/third_party/blink/renderer/core/fileapi/file_reader.idl
@@ -37,12 +37,12 @@ ] interface FileReader : EventTarget { [CallWith=ExecutionContext] constructor(); // async read methods - [RaisesException] void readAsArrayBuffer(Blob blob); - [RaisesException] void readAsBinaryString(Blob blob); - [RaisesException] void readAsText(Blob blob, optional DOMString label); - [RaisesException] void readAsDataURL(Blob blob); + [RaisesException] undefined readAsArrayBuffer(Blob blob); + [RaisesException] undefined readAsBinaryString(Blob blob); + [RaisesException] undefined readAsText(Blob blob, optional DOMString encoding); + [RaisesException] undefined readAsDataURL(Blob blob); - void abort(); + undefined abort(); // states const unsigned short EMPTY = 0;
diff --git a/third_party/blink/renderer/core/fileapi/url_file_api.idl b/third_party/blink/renderer/core/fileapi/url_file_api.idl index f66e06c3..71ac0025 100644 --- a/third_party/blink/renderer/core/fileapi/url_file_api.idl +++ b/third_party/blink/renderer/core/fileapi/url_file_api.idl
@@ -7,5 +7,5 @@ ImplementedAs=URLFileAPI ] partial interface URL { [Exposed=(Window,DedicatedWorker,SharedWorker), CallWith=ScriptState, RaisesException] static DOMString createObjectURL(Blob blob); - [Exposed=(Window,DedicatedWorker,SharedWorker), CallWith=ScriptState] static void revokeObjectURL(DOMString url); + [Exposed=(Window,DedicatedWorker,SharedWorker), CallWith=ScriptState] static undefined revokeObjectURL(DOMString url); };
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 9b4d6a47..fb26159c 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -123,7 +123,6 @@ #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/pagination_utils.h" #include "third_party/blink/renderer/core/layout/physical_box_fragment.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 81a4b337..b6e70d0 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -3176,8 +3176,8 @@ std::optional<std::string> devtools_request_id, const WebURL& affected_request_url) { DCHECK(GetFrame()); - AuditsIssue::ReportUserReidentificationIssue(GetFrame(), devtools_request_id, - affected_request_url); + AuditsIssue::ReportUserReidentificationResourceBlockedIssue( + GetFrame(), devtools_request_id, affected_request_url); } void WebLocalFrameImpl::AddGenericIssueImpl(
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 88ec3b4..c8dfe7bfd 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
@@ -437,7 +437,7 @@ auto popover = popoverTargetElement(element); 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 = element.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 033d3b8e..2e64646 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 84423530..7a852da 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 28813cb..6134efad 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 b678e36..caa3bdb 100644 --- a/third_party/blink/renderer/core/html/html_summary_element.cc +++ b/third_party/blink/renderer/core/html/html_summary_element.cc
@@ -188,7 +188,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/html_template_element.cc b/third_party/blink/renderer/core/html/html_template_element.cc index 67a50fac..65bc606a 100644 --- a/third_party/blink/renderer/core/html/html_template_element.cc +++ b/third_party/blink/renderer/core/html/html_template_element.cc
@@ -37,7 +37,7 @@ #include "third_party/blink/renderer/core/dom/template_content_document_fragment.h" #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/html_names.h" -#include "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "third_party/blink/renderer/core/patching/patch_supplement.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -110,8 +110,7 @@ FastGetAttribute(html_names::kPatchsrcAttr)) : KURL(); SetOverrideInsertionTarget(target); - patch_status_ = - DOMPatchStatus::Create(target, this, src, start_after, end_before); + patch_status_ = Patch::Create(target, this, src, start_after, end_before); patch_status_->Start(); return true; }
diff --git a/third_party/blink/renderer/core/html/html_template_element.h b/third_party/blink/renderer/core/html/html_template_element.h index 3fd44a7..bcbaa28 100644 --- a/third_party/blink/renderer/core/html/html_template_element.h +++ b/third_party/blink/renderer/core/html/html_template_element.h
@@ -34,7 +34,7 @@ #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/template_content_document_fragment.h" #include "third_party/blink/renderer/core/html/html_element.h" -#include "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -82,7 +82,7 @@ // This returns true if this template is a valid patch and the patch has been // processed. bool ProcessPatch(ContainerNode& target); - DOMPatchStatus* OutgoingPatch() { return patch_status_; } + Patch* OutgoingPatch() { return patch_status_; } private: void CloneNonAttributePropertiesFrom(const Element&, @@ -92,7 +92,7 @@ mutable Member<TemplateContentDocumentFragment> content_; Member<ContainerNode> override_insertion_target_; - Member<DOMPatchStatus> patch_status_; + Member<Patch> patch_status_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc index e5d81c9..957424a 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element_event_listeners_test.cc
@@ -577,17 +577,17 @@ public: void Invoke(ExecutionContext* ctx, Event* event) override { if (event->type() == event_type_names::kEnter) { - EXPECT_TRUE(event->target()->GetWrapperTypeInfo()->Equals( + EXPECT_TRUE(event->RawTarget()->GetWrapperTypeInfo()->Equals( VTTCue::GetStaticWrapperTypeInfo())); - auto* const cue = static_cast<VTTCue*>(event->target()); + auto* const cue = static_cast<VTTCue*>(event->RawTarget()); auto* const media_element = cue->track()->MediaElement(); OnCueEnter(media_element, cue); return; } else if (event->type() == event_type_names::kExit) { - EXPECT_TRUE(event->target()->GetWrapperTypeInfo()->Equals( + EXPECT_TRUE(event->RawTarget()->GetWrapperTypeInfo()->Equals( VTTCue::GetStaticWrapperTypeInfo())); - auto* const cue = static_cast<VTTCue*>(event->target()); + auto* const cue = static_cast<VTTCue*>(event->RawTarget()); auto* const media_element = cue->track()->MediaElement(); OnCueExit(media_element, cue);
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/parser/html_construction_site.cc b/third_party/blink/renderer/core/html/parser/html_construction_site.cc index c0aec3c..0af3609 100644 --- a/third_party/blink/renderer/core/html/parser/html_construction_site.cc +++ b/third_party/blink/renderer/core/html/parser/html_construction_site.cc
@@ -71,7 +71,7 @@ #include "third_party/blink/renderer/core/html_element_factory.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/loader/frame_loader.h" -#include "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "third_party/blink/renderer/core/script/ignore_destructive_write_count_incrementer.h" #include "third_party/blink/renderer/core/svg/svg_script_element.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" @@ -1072,7 +1072,7 @@ WhitespaceMode whitespace_mode) { if (HTMLTemplateElement* current = DynamicTo<HTMLTemplateElement>(CurrentNode())) { - if (DOMPatchStatus* patch = current->OutgoingPatch()) { + if (Patch* patch = current->OutgoingPatch()) { patch->Append(string.ToString()); return; }
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc index 4beb1f2..6b3ec87 100644 --- a/third_party/blink/renderer/core/input/event_handler.cc +++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -2442,7 +2442,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/inspector/inspector_audits_issue.cc b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc index 5a81eea..e7d4487c 100644 --- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc +++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.cc
@@ -895,7 +895,7 @@ } // static -void AuditsIssue::ReportUserReidentificationIssue( +void AuditsIssue::ReportUserReidentificationResourceBlockedIssue( LocalFrame* frame, std::optional<std::string> devtools_request_id, const KURL& affected_request_url) { @@ -927,6 +927,32 @@ frame->DomWindow()->AddInspectorIssue(AuditsIssue(std::move(issue))); } +// static +void AuditsIssue::ReportUserReidentificationCanvasNoisedIssue( + SourceLocation* source_location, + ExecutionContext* execution_context) { + auto reidentification_issue_details = + protocol::Audits::UserReidentificationIssueDetails::create() + .setType(protocol::Audits::UserReidentificationIssueTypeEnum:: + NoisedCanvasReadback) + .setSourceCodeLocation(CreateProtocolLocation(*source_location)) + .build(); + + auto protocol_issue_details = + protocol::Audits::InspectorIssueDetails::create() + .setUserReidentificationIssueDetails( + std::move(reidentification_issue_details)) + .build(); + + auto issue = protocol::Audits::InspectorIssue::create() + .setCode(protocol::Audits::InspectorIssueCodeEnum:: + UserReidentificationIssue) + .setDetails(std::move(protocol_issue_details)) + .build(); + + execution_context->AddInspectorIssue(AuditsIssue(std::move(issue))); +} + AuditsIssue AuditsIssue::CreateContentSecurityPolicyIssue( const blink::SecurityPolicyViolationEventInit& violation_data, bool is_report_only,
diff --git a/third_party/blink/renderer/core/inspector/inspector_audits_issue.h b/third_party/blink/renderer/core/inspector/inspector_audits_issue.h index 396c53c..9fc43b5 100644 --- a/third_party/blink/renderer/core/inspector/inspector_audits_issue.h +++ b/third_party/blink/renderer/core/inspector/inspector_audits_issue.h
@@ -203,11 +203,15 @@ ElementAccessibilityIssueReason issue_reason, bool has_disallowed_attributes); - static void ReportUserReidentificationIssue( + static void ReportUserReidentificationResourceBlockedIssue( LocalFrame* frame, std::optional<std::string> devtools_request_id, const KURL& affected_request_url); + static void ReportUserReidentificationCanvasNoisedIssue( + SourceLocation* source_location, + ExecutionContext* execution_context); + private: std::unique_ptr<protocol::Audits::InspectorIssue> issue_;
diff --git a/third_party/blink/renderer/core/inspector/inspector_ghost_rules.cc b/third_party/blink/renderer/core/inspector/inspector_ghost_rules.cc index 89a6184..2ea38d72 100644 --- a/third_party/blink/renderer/core/inspector/inspector_ghost_rules.cc +++ b/third_party/blink/renderer/core/inspector/inspector_ghost_rules.cc
@@ -125,8 +125,9 @@ resolver->GetActiveStyleSheets()) { CSSStyleSheet* sheet = active_stylesheet.first.Get(); if (affected_stylesheets_.Contains(sheet)) { + // TODO(sesse): Collect mixins from here. alternative_stylesheets.push_back(ActiveStyleSheet{ - sheet, style_engine.CreateUnconnectedRuleSet(*sheet)}); + sheet, style_engine.CreateUnconnectedRuleSet(*sheet, /*mixins=*/{})}); any_affected = true; } else { alternative_stylesheets.push_back(active_stylesheet);
diff --git a/third_party/blink/renderer/core/layout/block_break_token.cc b/third_party/blink/renderer/core/layout/block_break_token.cc index 76f8167..fcbbba0 100644 --- a/third_party/blink/renderer/core/layout/block_break_token.cc +++ b/third_party/blink/renderer/core/layout/block_break_token.cc
@@ -8,7 +8,6 @@ #include "third_party/blink/renderer/core/layout/inline/inline_break_token.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/member.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/size_assertions.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" @@ -147,13 +146,6 @@ string_builder.Append(ConsumedBlockSize().ToString()); string_builder.Append("px"); - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled() && - ConsumedBlockSizeForLegacy() != ConsumedBlockSize()) { - string_builder.Append(" legacy consumed:"); - string_builder.Append(ConsumedBlockSizeForLegacy().ToString()); - string_builder.Append("px"); - } - if (MonolithicOverflow()) { string_builder.Append(" monolithic overflow:"); string_builder.Append(MonolithicOverflow().ToString());
diff --git a/third_party/blink/renderer/core/layout/block_break_token.h b/third_party/blink/renderer/core/layout/block_break_token.h index 376d6cb..aee60fd8 100644 --- a/third_party/blink/renderer/core/layout/block_break_token.h +++ b/third_party/blink/renderer/core/layout/block_break_token.h
@@ -11,7 +11,6 @@ #include "third_party/blink/renderer/core/layout/block_break_token_data.h" #include "third_party/blink/renderer/core/layout/break_token.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -80,23 +79,6 @@ return data_->consumed_block_size; } - // The consumed block size when writing back to legacy layout. The only time - // this may be different than ConsumedBlockSize() is in the case of a - // fragmentainer. We clamp the fragmentainer block size from 0 to 1 for legacy - // write-back only in the case where there is content that overflows the - // zero-height fragmentainer. This can result in a different consumed block - // size when used for legacy. This difference is represented by - // |consumed_block_size_legacy_adjustment_|. - LayoutUnit ConsumedBlockSizeForLegacy() const { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); -#if DCHECK_IS_ON() - DCHECK(!is_repeated_actual_break_); -#endif - DCHECK(data_); - return data_->consumed_block_size + - data_->consumed_block_size_legacy_adjustment; - } - // A unique identifier for a fragment that generates a break token. This is // unique within the generating layout input node. The break token of the // first fragment gets 0, then second 1, and so on. Note that we don't "count"
diff --git a/third_party/blink/renderer/core/layout/block_break_token_data.h b/third_party/blink/renderer/core/layout/block_break_token_data.h index 686f79b..7227c08 100644 --- a/third_party/blink/renderer/core/layout/block_break_token_data.h +++ b/third_party/blink/renderer/core/layout/block_break_token_data.h
@@ -30,8 +30,6 @@ : type(type) { if (other_data) { consumed_block_size = other_data->consumed_block_size; - consumed_block_size_legacy_adjustment = - other_data->consumed_block_size_legacy_adjustment; sequence_number = other_data->sequence_number; monolithic_overflow = other_data->monolithic_overflow; } @@ -52,7 +50,6 @@ virtual void Trace(Visitor* visitor) const {} LayoutUnit consumed_block_size; - LayoutUnit consumed_block_size_legacy_adjustment; LayoutUnit monolithic_overflow; unsigned sequence_number = 0;
diff --git a/third_party/blink/renderer/core/layout/block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/block_layout_algorithm.cc index de8e300..4a92f06 100644 --- a/third_party/blink/renderer/core/layout/block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/block_layout_algorithm.cc
@@ -24,10 +24,8 @@ #include "third_party/blink/renderer/core/layout/inline/inline_node.h" #include "third_party/blink/renderer/core/layout/inline/physical_line_box_fragment.h" #include "third_party/blink/renderer/core/layout/inline/ruby_utils.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_result.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/length_utils.h" #include "third_party/blink/renderer/core/layout/list/unpositioned_list_marker.h" #include "third_party/blink/renderer/core/layout/logical_box_fragment.h" @@ -56,24 +54,20 @@ // Note: |block_flow->NeedsCollectInline()| is true after removing all // children from block[1]. // [1] editing/inserting/insert_after_delete.html - if (!GetLayoutObjectForFirstChildNode(block_flow)) { + if (!block_flow->FirstChild()) { // Note: |block_flow->ChildrenInline()| can be both true or false: // - true: just after construction, <div></div> // - true: one of child is inline them remove all, <div>abc</div> // - false: all children are block then remove all, <div><p></p></div> return block_flow->HasLineIfEmpty(); } - if (AreNGBlockFlowChildrenInline(block_flow)) { + if (block_flow->ChildrenInline()) { return block_flow->HasLineIfEmpty() && InlineNode(block_flow).IsBlockLevel(); } const LayoutBlockFlow* fragmentation_context_root = nullptr; - if (RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - if (block_flow->IsMulticolContainer()) { - fragmentation_context_root = block_flow; - } - } else { - fragmentation_context_root = block_flow->MultiColumnFlowThread(); + if (block_flow->IsMulticolContainer()) { + fragmentation_context_root = block_flow; } if (fragmentation_context_root) { DCHECK(!fragmentation_context_root->ChildrenInline());
diff --git a/third_party/blink/renderer/core/layout/block_node.cc b/third_party/blink/renderer/core/layout/block_node.cc index 0f0527bd..a4c015fa 100644 --- a/third_party/blink/renderer/core/layout/block_node.cc +++ b/third_party/blink/renderer/core/layout/block_node.cc
@@ -41,15 +41,11 @@ #include "third_party/blink/renderer/core/layout/layout_box_utils.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" #include "third_party/blink/renderer/core/layout/layout_input_node.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_result.h" #include "third_party/blink/renderer/core/layout/layout_utils.h" #include "third_party/blink/renderer/core/layout/layout_video.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/length_utils.h" #include "third_party/blink/renderer/core/layout/list/layout_list_item.h" #include "third_party/blink/renderer/core/layout/logical_box_fragment.h" @@ -99,16 +95,8 @@ namespace { -inline bool HasInlineChildren(LayoutBlockFlow* block_flow) { - auto* child = GetLayoutObjectForFirstChildNode(block_flow); - return child && AreNGBlockFlowChildrenInline(block_flow); -} - -inline LayoutMultiColumnFlowThread* GetFlowThread( - const LayoutBlockFlow* block_flow) { - if (!block_flow) - return nullptr; - return block_flow->MultiColumnFlowThread(); +inline bool HasInlineChildren(const LayoutBlockFlow* block_flow) { + return block_flow->FirstChild() && block_flow->ChildrenInline(); } // The entire purpose of this function is to avoid allocating space on the stack @@ -901,11 +889,7 @@ box_->SetChildNeedsLayout(kMarkOnlyThis); } - if (has_inline_children) { - if (items && !RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - CopyFragmentItemsToLayoutBox(physical_fragment, *items, break_token); - } - } else { + if (!has_inline_children) { // We still need to clear |InlineNodeData| in case it had inline // children. block_flow->ClearInlineNodeData(); @@ -1162,11 +1146,12 @@ if (!block) [[unlikely]] { return BlockNode(box_->FirstChildBox()); } - auto* child = GetLayoutObjectForFirstChildNode(block); + auto* child = block->FirstChild(); if (!child) return nullptr; - if (!AreNGBlockFlowChildrenInline(block)) + if (!block->ChildrenInline()) { return BlockNode(To<LayoutBox>(child)); + } InlineNode inline_node(To<LayoutBlockFlow>(block)); if (!inline_node.IsBlockLevel()) @@ -1234,207 +1219,17 @@ // the following line when all layout modes do this properly. UpdateMarginPaddingInfoIfNeeded(constraint_space, physical_fragment); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - // If this node doesn't participate in block fragmentation (either because - // there's no outer fragmentation context, or because we're in a monolithic - // subtree), update the box offset right away. Otherwise, we need to wait - // until layout of the outer fragmentation context is finished, in order to - // tell where the fragments are placed relatively to each other. - if (!InvolvedInBlockFragmentation(constraint_space, previous_break_token)) { - UpdateChildLayoutBoxLocations(physical_fragment); - } - if (is_last_fragment) { - box_->UpdateAfterLayout(); - } - return; + // If this node doesn't participate in block fragmentation (either because + // there's no outer fragmentation context, or because we're in a monolithic + // subtree), update the box offset right away. Otherwise, we need to wait + // until layout of the outer fragmentation context is finished, in order to + // tell where the fragments are placed relatively to each other. + if (!InvolvedInBlockFragmentation(constraint_space, previous_break_token)) { + UpdateChildLayoutBoxLocations(physical_fragment); } - - auto* block_flow = DynamicTo<LayoutBlockFlow>(box_.Get()); - LayoutMultiColumnFlowThread* flow_thread = GetFlowThread(block_flow); - - // Position the children inside the box. We skip this if display-lock prevents - // child layout. - if (!ChildLayoutBlockedByDisplayLock()) { - if (flow_thread) [[unlikely]] { - // Hold off writing legacy data for the entire multicol container until - // done with the last fragment (we may have multiple if nested within - // another fragmentation context). This way we'll get everything in order. - // We'd otherwise mess up in complex cases of nested column balancing. The - // column layout algorithms may retry layout for a given fragment, which - // would confuse the code that writes back to legacy objects, so that we - // wouldn't always update column sets or establish fragmentainer groups - // correctly. - if (is_last_fragment) { - const BlockBreakToken* incoming_break_token = nullptr; - for (const PhysicalBoxFragment& multicol_fragment : - box_->PhysicalFragments()) { - PlaceChildrenInFlowThread(flow_thread, constraint_space, - multicol_fragment, incoming_break_token); - incoming_break_token = multicol_fragment.GetBreakToken(); - } - } - } else { - PlaceChildrenInLayoutBox(physical_fragment, previous_break_token); - } + if (is_last_fragment) { + box_->UpdateAfterLayout(); } - - if (!is_last_fragment) [[unlikely]] { - return; - } - - box_->UpdateAfterLayout(); -} - -void BlockNode::PlaceChildrenInLayoutBox( - const PhysicalBoxFragment& physical_fragment, - const BlockBreakToken* previous_break_token, - bool needs_invalidation_check) const { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - for (const auto& child_fragment : physical_fragment.Children()) { - // Skip any line-boxes we have as children, this is handled within - // InlineNode at the moment. - if (!child_fragment->IsBox()) - continue; - - const auto& box_fragment = *To<PhysicalBoxFragment>(child_fragment.get()); - if (!box_fragment.IsFirstForNode()) - continue; - - // The offset for an OOF positioned node that is added as a child of a - // fragmentainer box is handled by - // OutOfFlowLayoutPart::AddOOFToFragmentainer(). - if (physical_fragment.IsFragmentainerBox() && - child_fragment->IsOutOfFlowPositioned()) [[unlikely]] { - continue; - } - - CopyChildFragmentPosition(box_fragment, child_fragment.offset, - physical_fragment, previous_break_token, - needs_invalidation_check); - } -} - -void BlockNode::PlaceChildrenInFlowThread( - LayoutMultiColumnFlowThread* flow_thread, - const ConstraintSpace& space, - const PhysicalBoxFragment& physical_fragment, - const BlockBreakToken* previous_container_break_token) const { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - // Stitch the contents of the columns together in the legacy flow thread, and - // update the position and size of column sets, spanners and spanner - // placeholders. Create fragmentainer groups as needed. When in a nested - // fragmentation context, we need one fragmentainer group for each outer - // fragmentainer in which the column contents occur. All this ensures that the - // legacy layout tree is sufficiently set up, so that DOM position/size - // querying APIs (such as offsetTop and offsetLeft) work correctly. We still - // rely on the legacy engine for this. - // - // This rather complex piece of machinery is described to some extent in the - // design document for legacy multicol: - // https://www.chromium.org/developers/design-documents/multi-column-layout - - WritingModeConverter converter(space.GetWritingDirection(), - physical_fragment.Size()); - - const BlockBreakToken* previous_column_break_token = nullptr; - LayoutUnit flow_thread_offset; - - if (IsBreakInside(previous_container_break_token)) { - // This multicol container is nested inside another fragmentation context, - // and this isn't its first fragment. Locate the break token for the - // previous inner column contents, so that we include the correct amount of - // consumed block-size in the child offsets. If there's a break token for - // column contents, we'll find it at the back. - const auto& child_break_tokens = - previous_container_break_token->ChildBreakTokens(); - if (!child_break_tokens.empty()) { - const auto* token = To<BlockBreakToken>(child_break_tokens.back().Get()); - // We also create break tokens for spanners, so we need to check. - if (token->InputNode() == *this) { - previous_column_break_token = token; - } - } - } - - for (const auto& child : physical_fragment.Children()) { - const auto& child_fragment = To<PhysicalBoxFragment>(*child); - const auto* child_box = To<LayoutBox>(child_fragment.GetLayoutObject()); - if (child_box && child_box != box_) { - CopyChildFragmentPosition(child_fragment, child.offset, - physical_fragment); - continue; - } - - DCHECK(!child_box); - - // Each anonymous child of a multicol container constitutes one column. - // Position each child fragment in the first column that they occur, - // relatively to the block-start of the flow thread. - // - // We may fail to detect visual movement of flow thread children if the - // child re-uses a cached result, since the LayoutBox's frame_rect_ is in - // the flow thread coordinate space. If the column block-size or inline-size - // has changed, we might miss paint invalidation, unless we request it to be - // checked explicitly. We only need to do this for direct flow thread - // children, since movement detection works fine for descendants. If it's - // not detected during layout (due to cache hits), it will be detected - // during pre-paint. - // - // TODO(mstensho): Get rid of this in the future if we become able to - // compare visual offsets rather than flow thread offsets. - PlaceChildrenInLayoutBox(child_fragment, previous_column_break_token, - /* needs_invalidation_check */ true); - - previous_column_break_token = child_fragment.GetBreakToken(); - } - - if (!physical_fragment.GetBreakToken()) { - flow_thread->FinishLayoutFromNG(flow_thread_offset); - } -} - -// Copies data back to the legacy layout tree for a given child fragment. -void BlockNode::CopyChildFragmentPosition( - const PhysicalBoxFragment& child_fragment, - PhysicalOffset offset, - const PhysicalBoxFragment& container_fragment, - const BlockBreakToken* previous_container_break_token, - bool needs_invalidation_check) const { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - auto* layout_box = To<LayoutBox>(child_fragment.GetMutableLayoutObject()); - if (!layout_box) - return; - - if (child_fragment.GetBoxType() == PhysicalFragment::kPageContainer || - child_fragment.GetBoxType() == PhysicalFragment::kPageBorderBox) { - // These fragment types don't need to write anything back to their - // LayoutBox. Furthermore, they have no parent, so the check below would - // fail. - return; - } - - DCHECK(layout_box->Parent()) << "Should be called on children only."; - - DeprecatedLayoutPoint point = - ComputeBoxLocation(child_fragment, offset, container_fragment, - previous_container_break_token); - layout_box->SetLocation(point); - - if (needs_invalidation_check) - layout_box->SetShouldCheckForPaintInvalidation(); -} - -void BlockNode::MakeRoomForExtraColumns(LayoutUnit block_size) const { - if (RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - return; - } - auto* block_flow = DynamicTo<LayoutBlockFlow>(GetLayoutBox()); - DCHECK(block_flow && block_flow->MultiColumnFlowThread()); - MultiColumnFragmentainerGroup& last_group = - block_flow->MultiColumnFlowThread() - ->LastMultiColumnSet() - ->LastFragmentainerGroup(); - last_group.ExtendLogicalBottomInFlowThread(block_size); } void BlockNode::FinishPageContainerLayout(const LayoutResult* result) const { @@ -1448,63 +1243,6 @@ StoreResultInLayoutBox(result, /*BlockBreakToken=*/nullptr); } -void BlockNode::CopyFragmentItemsToLayoutBox( - const PhysicalBoxFragment& container, - const FragmentItems& items, - const BlockBreakToken* previous_break_token) const { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - LayoutUnit previously_consumed_block_size; - if (previous_break_token) { - previously_consumed_block_size = - previous_break_token->ConsumedBlockSizeForLegacy(); - } - bool initial_container_is_flipped = Style().IsFlippedBlocksWritingMode(); - for (InlineCursor cursor(container, items); cursor; cursor.MoveToNext()) { - if (const PhysicalBoxFragment* child = cursor.Current().BoxFragment()) { - // Replaced elements and inline blocks need Location() set relative to - // their block container. Similarly for block-in-inline anonymous wrapper - // blocks, but those may actually fragment, so we need to make sure that - // we only do this when at the first fragment. - if (!child->IsFirstForNode()) - continue; - - LayoutObject* layout_object = child->GetMutableLayoutObject(); - if (!layout_object) - continue; - if (auto* layout_box = DynamicTo<LayoutBox>(layout_object)) { - PhysicalOffset maybe_flipped_offset = - cursor.Current().OffsetInContainerFragment(); - if (initial_container_is_flipped) { - maybe_flipped_offset.left = container.Size().width - - child->Size().width - - maybe_flipped_offset.left; - } - if (container.Style().IsHorizontalWritingMode()) - maybe_flipped_offset.top += previously_consumed_block_size; - else - maybe_flipped_offset.left += previously_consumed_block_size; - layout_box->SetLocation( - maybe_flipped_offset.FaultyToDeprecatedLayoutPoint()); - if (layout_box->HasSelfPaintingLayer()) [[unlikely]] { - layout_box->Layer()->SetNeedsVisualOverflowRecalc(); - } -#if DCHECK_IS_ON() - layout_box->InvalidateVisualOverflowForDCheck(); -#endif - continue; - } - - // Legacy compatibility. This flag is used in paint layer for - // invalidation. - if (auto* layout_inline = DynamicTo<LayoutInline>(layout_object)) { - if (layout_inline->HasSelfPaintingLayer()) [[unlikely]] { - layout_inline->Layer()->SetNeedsVisualOverflowRecalc(); - } - } - } - } -} - bool BlockNode::UseParentPercentageResolutionBlockSizeForChildren() const { auto* block = DynamicTo<LayoutBlock>(box_.Get()); if (!block) { @@ -1515,11 +1253,10 @@ const bool in_quirks_mode = GetDocument().InQuirksMode(); // Anonymous blocks should not impede percentage resolution on a child. // Examples of such anonymous blocks are blocks wrapped around inlines that - // have block siblings (from the CSS spec) and multicol flow threads (an - // implementation detail). Another implementation detail, ruby columns, create - // anonymous inline-blocks, so skip those too. All other types of anonymous - // objects, such as table-cells, will be treated just as if they were - // non-anonymous. + // have block siblings (from the CSS spec). An implementation detail, ruby + // columns, create anonymous inline-blocks, so skip those too. All other types + // of anonymous objects, such as table-cells, will be treated just as if they + // were non-anonymous. if (block->IsAnonymous()) { if (!in_quirks_mode && block->Parent() && block->Parent()->IsFieldset()) { return false; @@ -1561,8 +1298,9 @@ bool BlockNode::IsInlineFormattingContextRoot( InlineNode* first_child_out) const { if (const auto* block = DynamicTo<LayoutBlockFlow>(box_.Get())) { - if (!AreNGBlockFlowChildrenInline(block)) + if (!block->ChildrenInline()) { return false; + } LayoutInputNode first_child = FirstChild(); if (first_child.IsInline()) { if (first_child_out) @@ -1822,15 +1560,6 @@ constraint_space.PercentageResolutionInlineSize()); } -void BlockNode::StoreColumnCount(int count) { - if (RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - return; - } - LayoutMultiColumnFlowThread* flow_thread = - To<LayoutBlockFlow>(box_.Get())->MultiColumnFlowThread(); - flow_thread->SetColumnCountFromNG(count); -} - static bool g_devtools_layout = false; bool DevtoolsReadonlyLayoutScope::InDevtoolsLayout() { return g_devtools_layout;
diff --git a/third_party/blink/renderer/core/layout/block_node.h b/third_party/blink/renderer/core/layout/block_node.h index 127e6f1..7457b84 100644 --- a/third_party/blink/renderer/core/layout/block_node.h +++ b/third_party/blink/renderer/core/layout/block_node.h
@@ -19,11 +19,9 @@ class ColumnSpannerPath; class ConstraintSpace; class EarlyBreak; -class FragmentItems; class InlineNode; class LayoutBox; class LayoutResult; -class PhysicalBoxFragment; class PhysicalFragment; enum class BaselineAlgorithmType; enum class MathScriptType; @@ -203,9 +201,6 @@ bool use_first_line_style, BaselineAlgorithmType baseline_algorithm_type); - // Write the number of columns in a multicol container to legacy. - void StoreColumnCount(int count); - bool ShouldApplyLayoutContainment() const { return box_->ShouldApplyLayoutContainment(); } @@ -222,20 +217,6 @@ LayoutUnit EmptyLineBlockSize( const BlockBreakToken* incoming_break_token) const; - // After we run the layout algorithm, this function copies back the fragment - // position to the layout box. - void CopyChildFragmentPosition( - const PhysicalBoxFragment& child_fragment, - PhysicalOffset, - const PhysicalBoxFragment& container_fragment, - const BlockBreakToken* previous_container_break_token = nullptr, - bool needs_invalidation_check = false) const; - - // If extra columns are added after a multicol has been written back to - // legacy, for example for an OOF positioned element, we need to update the - // legacy flow thread to encompass those extra columns. - void MakeRoomForExtraColumns(LayoutUnit block_size) const; - // Page containers and page border boxes are laid out directly by special // algorithms, rather than going via BlockNode::Layout(), so whatever // side-effects Layout() causes needs to be triggered manually from these @@ -274,18 +255,6 @@ const ConstraintSpace&, const LayoutResult&, const BlockBreakToken* previous_break_token) const; - void CopyFragmentItemsToLayoutBox( - const PhysicalBoxFragment& container, - const FragmentItems& items, - const BlockBreakToken* previous_break_token) const; - void PlaceChildrenInLayoutBox(const PhysicalBoxFragment&, - const BlockBreakToken* previous_break_token, - bool needs_invalidation_check = false) const; - void PlaceChildrenInFlowThread( - LayoutMultiColumnFlowThread*, - const ConstraintSpace&, - const PhysicalBoxFragment&, - const BlockBreakToken* previous_container_break_token) const; void UpdateMarginPaddingInfoIfNeeded(const ConstraintSpace&, const PhysicalFragment& fragment) const;
diff --git a/third_party/blink/renderer/core/layout/box_fragment_builder.h b/third_party/blink/renderer/core/layout/box_fragment_builder.h index 43f1bfc..268d2f2 100644 --- a/third_party/blink/renderer/core/layout/box_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/box_fragment_builder.h
@@ -423,13 +423,6 @@ EnsureBreakTokenData()->consumed_block_size = size; } - // Set how much to adjust |consumed_block_size_| for legacy write-back. See - // BlockBreakToken::ConsumedBlockSizeForLegacy() for more details. - void SetConsumedBlockSizeLegacyAdjustment(LayoutUnit adjustment) { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - EnsureBreakTokenData()->consumed_block_size_legacy_adjustment = adjustment; - } - void ReserveSpaceForMonolithicOverflow(LayoutUnit monolithic_overflow) { DCHECK(GetConstraintSpace().IsPaginated()); auto* data = EnsureBreakTokenData();
diff --git a/third_party/blink/renderer/core/layout/build.gni b/third_party/blink/renderer/core/layout/build.gni index 27164e50..61a39d38 100644 --- a/third_party/blink/renderer/core/layout/build.gni +++ b/third_party/blink/renderer/core/layout/build.gni
@@ -143,8 +143,6 @@ "fragment_builder.h", "fragment_repeater.cc", "fragment_repeater.h", - "fragmentainer_iterator.cc", - "fragmentainer_iterator.h", "fragmentation_utils.cc", "fragmentation_utils.h", "frame_set_layout_algorithm.cc", @@ -332,8 +330,6 @@ "layout_embedded_content.h", "layout_embedded_object.cc", "layout_embedded_object.h", - "layout_flow_thread.cc", - "layout_flow_thread.h", "layout_frame.cc", "layout_frame.h", "layout_frame_set.cc", @@ -356,12 +352,6 @@ "layout_input_node.h", "layout_media.cc", "layout_media.h", - "layout_multi_column_flow_thread.cc", - "layout_multi_column_flow_thread.h", - "layout_multi_column_set.cc", - "layout_multi_column_set.h", - "layout_multi_column_spanner_placeholder.cc", - "layout_multi_column_spanner_placeholder.h", "layout_object.cc", "layout_object.h", "layout_object_child_list.cc", @@ -409,7 +399,6 @@ "layout_view_transition_root.h", "layout_word_break.cc", "layout_word_break.h", - "legacy_layout_tree_walking.h", "length_utils.cc", "length_utils.h", "list/layout_inline_list_item.cc", @@ -476,8 +465,6 @@ "min_max_sizes.cc", "min_max_sizes.h", "min_max_sizes_cache.h", - "multi_column_fragmentainer_group.cc", - "multi_column_fragmentainer_group.h", "natural_sizing_info.cc", "natural_sizing_info.h", "non_overflowing_scroll_range.h", @@ -781,8 +768,6 @@ "layout_inline_test.cc", "layout_input_node_test.cc", "layout_media_test.cc", - "layout_multi_column_flow_thread_test.cc", - "layout_multi_column_set_test.cc", "layout_object_test.cc", "layout_progress_test.cc", "layout_quote_test.cc", @@ -806,7 +791,6 @@ "masonry/masonry_layout_algorithm_test.cc", "min_max_size_test.cc", "min_max_sizes_cache_test.cc", - "multi_column_fragmentainer_group_test.cc", "out_of_flow_layout_part_test.cc", "outline_rect_collector_test.cc", "overflow_model_test.cc",
diff --git a/third_party/blink/renderer/core/layout/column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/column_layout_algorithm.cc index d738f95..16c0b09 100644 --- a/third_party/blink/renderer/core/layout/column_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/column_layout_algorithm.cc
@@ -300,12 +300,6 @@ used_column_count_ = ResolveUsedColumnCount(Style(), ChildAvailableSize().inline_size); - // Write the column count back to the legacy flow thread if we're at the first - // fragment. The legacy fragmentainer group machinery needs the count. - if (!IsBreakInside(GetBreakToken())) { - node_.StoreColumnCount(used_column_count_); - } - // If we know the block-size of the fragmentainers in an outer fragmentation // context (if any), our columns may be constrained by that, meaning that we // may have to fragment earlier than what we would have otherwise, and, if
diff --git a/third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.cc b/third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.cc index 0bbfca9..f4df5f1 100644 --- a/third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.cc +++ b/third_party/blink/renderer/core/layout/depth_ordered_layout_object_list.cc
@@ -8,7 +8,6 @@ #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/layout/layout_object.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" namespace blink {
diff --git a/third_party/blink/renderer/core/layout/fragmentainer_iterator.cc b/third_party/blink/renderer/core/layout/fragmentainer_iterator.cc deleted file mode 100644 index a8812d5..0000000 --- a/third_party/blink/renderer/core/layout/fragmentainer_iterator.cc +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/layout/fragmentainer_iterator.h" - -#include "third_party/blink/renderer/core/layout/geometry/logical_rect.h" -#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" - -namespace blink { - -FragmentainerIterator::FragmentainerIterator( - const LayoutFlowThread& flow_thread, - const PhysicalRect& physical_bounding_box_in_flow_thread) - : current_fragmentainer_group_index_(0) { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - LogicalRect bounds_in_flow_thread = - flow_thread.CreateWritingModeConverter().ToLogical( - physical_bounding_box_in_flow_thread); - - logical_top_in_flow_thread_ = bounds_in_flow_thread.offset.block_offset; - logical_bottom_in_flow_thread_ = bounds_in_flow_thread.BlockEndOffset(); - bounding_box_is_empty_ = bounds_in_flow_thread.IsEmpty(); - - // Jump to the first interesting column set. - current_column_set_ = flow_thread.ColumnSetAtBlockOffset( - logical_top_in_flow_thread_, LayoutBox::kAssociateWithLatterPage); - if (!current_column_set_) { - SetAtEnd(); - return; - } - // Then find the first interesting fragmentainer group. - current_fragmentainer_group_index_ = - current_column_set_->FragmentainerGroupIndexAtFlowThreadOffset( - logical_top_in_flow_thread_, LayoutBox::kAssociateWithLatterPage); - - // Now find the first and last fragmentainer we're interested in. - SetFragmentainersOfInterest(); -} - -void FragmentainerIterator::Advance() { - DCHECK(!AtEnd()); - - if (current_fragmentainer_index_ < end_fragmentainer_index_) { - current_fragmentainer_index_++; - } else { - // That was the last fragmentainer to visit in this fragmentainer group. - // Advance to the next group. - MoveToNextFragmentainerGroup(); - if (AtEnd()) - return; - } -} - -PhysicalRect FragmentainerIterator::ClipRectInFlowThread() const { - DCHECK(!AtEnd()); - PhysicalRect clip_rect; - // An empty bounding box rect would typically be 0,0 0x0, so it would be - // placed in the first column always. However, the first column might not have - // a top edge clip (see FlowThreadPortionOverflowRectAt()). This might cause - // artifacts to paint outside of the column container. To avoid this - // situation, and since the logical bounding box is empty anyway, use the - // portion rect instead which is bounded on all sides. Note that we don't - // return an empty clip here, because an empty clip indicates that we have an - // empty column which may be treated differently by the calling code. - if (bounding_box_is_empty_) { - clip_rect = - CurrentGroup().FlowThreadPortionRectAt(current_fragmentainer_index_); - } else { - clip_rect = CurrentGroup().FlowThreadPortionOverflowRectAt( - current_fragmentainer_index_); - } - return clip_rect; -} - -const MultiColumnFragmentainerGroup& FragmentainerIterator::CurrentGroup() - const { - DCHECK(!AtEnd()); - return current_column_set_ - ->FragmentainerGroups()[current_fragmentainer_group_index_]; -} - -void FragmentainerIterator::MoveToNextFragmentainerGroup() { - current_fragmentainer_group_index_++; - if (current_fragmentainer_group_index_ >= - current_column_set_->FragmentainerGroups().size()) { - // That was the last fragmentainer group in this set. Advance to the next. - current_column_set_ = current_column_set_->NextSiblingMultiColumnSet(); - current_fragmentainer_group_index_ = 0; - if (!current_column_set_ || current_column_set_->LogicalTopInFlowThread() >= - logical_bottom_in_flow_thread_) { - SetAtEnd(); - return; // No more sets or next set out of range. We're done. - } - } - if (CurrentGroup().LogicalTopInFlowThread() >= - logical_bottom_in_flow_thread_) { - // This fragmentainer group doesn't intersect with the range we're - // interested in. We're done. - SetAtEnd(); - return; - } - SetFragmentainersOfInterest(); -} - -void FragmentainerIterator::SetFragmentainersOfInterest() { - const MultiColumnFragmentainerGroup& group = CurrentGroup(); - - // Figure out the start and end fragmentainers for the block range we're - // interested in. We might not have to walk the entire fragmentainer group. - group.ColumnIntervalForBlockRangeInFlowThread( - logical_top_in_flow_thread_, logical_bottom_in_flow_thread_, - current_fragmentainer_index_, end_fragmentainer_index_); - DCHECK_GE(end_fragmentainer_index_, current_fragmentainer_index_); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/fragmentainer_iterator.h b/third_party/blink/renderer/core/layout/fragmentainer_iterator.h deleted file mode 100644 index 8a9645eb..0000000 --- a/third_party/blink/renderer/core/layout/fragmentainer_iterator.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FRAGMENTAINER_ITERATOR_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FRAGMENTAINER_ITERATOR_H_ - -#include "third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -class LayoutFlowThread; -class LayoutMultiColumnSet; - -// Used to find the fragmentainers that intersect with a given portion of the -// flow thread. The portion typically corresponds to the bounds of some -// descendant layout object. The iterator walks in block direction order. -class FragmentainerIterator { - STACK_ALLOCATED(); - - public: - // Initialize the iterator, and move to the first fragmentainer of interest. - // Only thing that can limit the set of fragmentainers to visit is - // |physical_bounding_box_in_flow_thread|. - FragmentainerIterator( - const LayoutFlowThread&, - const PhysicalRect& physical_bounding_box_in_flow_thread); - - // Advance to the next fragmentainer. Not allowed to call this if atEnd() is - // true. - void Advance(); - - // Return true if we have walked through all relevant fragmentainers. - bool AtEnd() const { return !current_column_set_; } - - // Return the physical clip rectangle of the current fragmentainer, relative - // to the flow thread. - PhysicalRect ClipRectInFlowThread() const; - - private: - const LayoutMultiColumnSet* current_column_set_; - unsigned current_fragmentainer_group_index_; - unsigned current_fragmentainer_index_; - unsigned end_fragmentainer_index_; - - LayoutUnit logical_top_in_flow_thread_; - LayoutUnit logical_bottom_in_flow_thread_; - - bool bounding_box_is_empty_; - - const MultiColumnFragmentainerGroup& CurrentGroup() const; - void MoveToNextFragmentainerGroup(); - void SetFragmentainersOfInterest(); - void SetAtEnd() { current_column_set_ = nullptr; } -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FRAGMENTAINER_ITERATOR_H_
diff --git a/third_party/blink/renderer/core/layout/fragmentation_utils.cc b/third_party/blink/renderer/core/layout/fragmentation_utils.cc index 59fd5b8c..13d49a8 100644 --- a/third_party/blink/renderer/core/layout/fragmentation_utils.cc +++ b/third_party/blink/renderer/core/layout/fragmentation_utils.cc
@@ -16,7 +16,6 @@ #include "third_party/blink/renderer/core/layout/physical_box_fragment.h" #include "third_party/blink/renderer/core/layout/space_utils.h" #include "third_party/blink/renderer/core/style/computed_style.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -847,26 +846,6 @@ consumed_block_size += fragmentainer_capacity; builder->SetConsumedBlockSize(consumed_block_size); - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - // We clamp the fragmentainer block size from 0 to 1 for legacy write-back - // if there is content that overflows the zero-height fragmentainer. Set - // the consumed block size adjustment for legacy if this results in a - // different consumed block size than is used for NG layout. - LayoutUnit consumed_block_size_for_legacy = - previous_break_token - ? previous_break_token->ConsumedBlockSizeForLegacy() - : LayoutUnit(); - LayoutUnit legacy_fragmentainer_block_size = - (builder->IntrinsicBlockSize() > LayoutUnit()) - ? fragmentainer_capacity - : block_size; - LayoutUnit consumed_block_size_legacy_adjustment = - consumed_block_size_for_legacy + legacy_fragmentainer_block_size - - consumed_block_size; - builder->SetConsumedBlockSizeLegacyAdjustment( - consumed_block_size_legacy_adjustment); - } - if (previous_break_token && previous_break_token->MonolithicOverflow()) { // Add pages as long as there's monolithic overflow that requires it. LayoutUnit remaining_overflow =
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc b/third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc index 1fa9603..897b7dc 100644 --- a/third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc +++ b/third_party/blink/renderer/core/layout/grid/grid_layout_utils.cc
@@ -68,7 +68,7 @@ LayoutUnit available_size, LayoutUnit min_available_size, LayoutUnit max_available_size, - std::optional<LayoutUnit> auto_repeat_track_size) { + std::optional<LayoutUnit> intrinsic_repeat_track_size) { DCHECK(track_list.HasAutoRepeater()); if (available_size == kIndefiniteSize) { @@ -94,8 +94,9 @@ const GridTrackSize& track_size = track_list.RepeatTrackSize(repeater_index, i); - const bool is_track_size_auto = track_size.IsTrackDefinitionAuto(); - if (is_track_size_auto && !auto_repeat_track_size) { + const bool is_track_size_intrinsic = + track_size.IsTrackDefinitionIntrinsic(); + if (is_track_size_intrinsic && !intrinsic_repeat_track_size) { return 0; } @@ -112,8 +113,8 @@ } LayoutUnit track_contribution; - if (is_track_size_auto) { - track_contribution = auto_repeat_track_size.value(); + if (is_track_size_intrinsic) { + track_contribution = intrinsic_repeat_track_size.value(); } else if (fixed_max_track_breadth && fixed_min_track_breadth) { track_contribution = std::max(*fixed_max_track_breadth, *fixed_min_track_breadth);
diff --git a/third_party/blink/renderer/core/layout/grid/grid_layout_utils.h b/third_party/blink/renderer/core/layout/grid/grid_layout_utils.h index bd54993..f95f425 100644 --- a/third_party/blink/renderer/core/layout/grid/grid_layout_utils.h +++ b/third_party/blink/renderer/core/layout/grid/grid_layout_utils.h
@@ -31,15 +31,15 @@ // https://drafts.csswg.org/css-grid-2/#auto-repeat // // This method assumes that the track list provided has an auto repeater. If -// auto_repeat_track_size` is not nullopt, this will indicate what to size an -// auto track definition within an auto repeater. +// `intrinsic_repeat_track_size` is not nullopt, this will indicate what to size +// an intrinsic track definition within an auto repeater. wtf_size_t CalculateAutomaticRepetitions( const GridTrackList& track_list, const LayoutUnit gutter_size, LayoutUnit available_size, LayoutUnit min_available_size, LayoutUnit max_available_size, - std::optional<LayoutUnit> auto_repeat_track_size = std::nullopt); + std::optional<LayoutUnit> intrinsic_repeat_track_size = std::nullopt); } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/grid/grid_track_collection.cc b/third_party/blink/renderer/core/layout/grid/grid_track_collection.cc index b3464f0..5f91334 100644 --- a/third_party/blink/renderer/core/layout/grid/grid_track_collection.cc +++ b/third_party/blink/renderer/core/layout/grid/grid_track_collection.cc
@@ -111,7 +111,7 @@ } GridRangeVector GridRangeBuilder::FinalizeRanges( - bool needs_auto_track_size, + bool needs_intrinsic_track_size, Vector<wtf_size_t>* collapsed_track_indexes) { DCHECK_EQ(start_lines_.size(), end_lines_.size()); @@ -294,9 +294,10 @@ } // Don't collapse tracks if we are in the first track sizing pass used to - // calculate the track size/count for repeat(auto-fit, auto). + // calculate the track size/count for repeat(auto-fit, + // <intrinsic-track-size>). if (is_in_auto_fit_range && open_items_or_repeaters == 1 && - !needs_auto_track_size) { + !needs_intrinsic_track_size) { range.SetIsCollapsed(); range.set_count = 0; if (collapsed_track_indexes) { @@ -360,14 +361,14 @@ explicit_tracks_.RepeatSize(i); // Subgrids can have zero auto repetitions. Grids with repeat(auto-fill, - // auto) also currently can have a track count of 0. + // <intrinsic-track-size>) also currently can have a track count of 0. // // TODO (almaher): Update this check depending on if we allow Grid to have - // repeat(auto-fill, auto) track definitions. + // repeat(auto-fill, <intrinsic-track-size>) track definitions. if (repeater_track_count == 0) { DCHECK(explicit_tracks_.IsSubgriddedAxis() || - explicit_tracks_.HasAutoSizedRepeater() || - implicit_tracks_.HasAutoSizedRepeater()); + explicit_tracks_.HasIntrinsicSizedRepeater() || + implicit_tracks_.HasIntrinsicSizedRepeater()); continue; } @@ -1119,9 +1120,9 @@ TrackSpanProperties::kIsDependentOnAvailableSize); } - if (auto_sized_repeater_track_index_ == kNotFound && - set_track_size.IsTrackDefinitionAuto()) { - auto_sized_repeater_track_index_ = i; + if (intrinsic_sized_repeater_track_index_ == kNotFound && + set_track_size.IsTrackDefinitionIntrinsic()) { + intrinsic_sized_repeater_track_index_ = i; } CacheSetProperties(sets_.emplace_back(set_track_count, set_track_size,
diff --git a/third_party/blink/renderer/core/layout/grid/grid_track_collection.h b/third_party/blink/renderer/core/layout/grid/grid_track_collection.h index cd558ea..24f70c6 100644 --- a/third_party/blink/renderer/core/layout/grid/grid_track_collection.h +++ b/third_party/blink/renderer/core/layout/grid/grid_track_collection.h
@@ -100,13 +100,13 @@ wtf_size_t* grid_item_end_range_index); // Build the collection of ranges based on information provided through the - // specified tracks and `EnsureTrackCoverage`. If `needs_auto_track_size` is - // true, that means we are in a track sizing pass to computed a repeat tack - // defintion of auto sized tracks. If `collapsed_track_indexes` is + // specified tracks and `EnsureTrackCoverage`. If `needs_intrinsic_track_size` + // is true, that means we are in a track sizing pass to computed a repeat tack + // defintion of intrinsic sized tracks. If `collapsed_track_indexes` is // not nullptr, this method with populate it with the track indexes of all // collapsed tracks. GridRangeVector FinalizeRanges( - bool needs_auto_track_size = false, + bool needs_intrinsic_track_size = false, Vector<wtf_size_t>* collapsed_track_indexes = nullptr); private: @@ -447,10 +447,10 @@ void SetMajorBaseline(wtf_size_t set_index, LayoutUnit candidate_baseline); void SetMinorBaseline(wtf_size_t set_index, LayoutUnit candidate_baseline); - // Return the index of the first auto sized track within an auto repeat + // Return the index of the first intrinsic sized track within an auto repeat // definition. - wtf_size_t GetAutoSizedRepeaterTrackIndex() const { - return auto_sized_repeater_track_index_; + wtf_size_t GetIntrinsicSizedRepeaterTrackIndex() const { + return intrinsic_sized_repeater_track_index_; } private: @@ -465,7 +465,7 @@ void InitializeSets(LayoutUnit grid_available_size = kIndefiniteSize); wtf_size_t non_collapsed_track_count_{0}; - wtf_size_t auto_sized_repeater_track_index_{kNotFound}; + wtf_size_t intrinsic_sized_repeater_track_index_{kNotFound}; // A vector of every set element that compose the entire collection's ranges; // track definitions from the same set are stored in consecutive positions,
diff --git a/third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.cc b/third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.cc index eb4029f..c7f36a04 100644 --- a/third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.cc +++ b/third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.cc
@@ -283,7 +283,7 @@ const ContributionSizeFunctionRef& contribution_size, GridSizingTrackCollection* track_collection, GridItems* grid_items, - bool needs_auto_track_size) const { + bool needs_intrinsic_track_size) const { DCHECK(track_collection); DCHECK(grid_items); @@ -296,11 +296,11 @@ ResolveIntrinsicTrackSizes(contribution_size, track_collection, grid_items); } - // If we are currently calculating the size of auto tracks in an + // If we are currently calculating the size of intrinsic tracks in an // auto repeat(), there is no need to perform the remaining track // sizing, since we will need to run another pass with the actual - // size for 'auto'. - if (needs_auto_track_size) { + // size for the track(s). + if (needs_intrinsic_track_size) { return; }
diff --git a/third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.h b/third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.h index 5baa0c6..79f3ef9 100644 --- a/third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.h +++ b/third_party/blink/renderer/core/layout/grid/grid_track_sizing_algorithm.h
@@ -78,15 +78,15 @@ // Calculates the used track size from the min and max track sizing functions // as defined in https://drafts.csswg.org/css-grid-2/#algo-track-sizing. If - // `needs_auto_track_size` is true, that means that we have a repeat() track - // definition with an auto sized track, and we are in the first track sizing - // pass used to determine the size of such tracks per + // `needs_intrinsic_track_size` is true, that means that we have a repeat() + // track definition with an intrinsic sized track, and we are in the first + // track sizing pass used to determine the size of such tracks per // https://www.w3.org/TR/css-grid-3/#masonry-intrinsic-repeat. void ComputeUsedTrackSizes( const ContributionSizeFunctionRef& contribution_size, GridSizingTrackCollection* track_collection, GridItems* grid_items, - bool needs_auto_track_size = false) const; + bool needs_intrinsic_track_size = false) const; private: // These methods implement the steps of the algorithm for intrinsic track size
diff --git a/third_party/blink/renderer/core/layout/inline/inline_cursor.cc b/third_party/blink/renderer/core/layout/inline/inline_cursor.cc index 69fbcd7..0d30faab3 100644 --- a/third_party/blink/renderer/core/layout/inline/inline_cursor.cc +++ b/third_party/blink/renderer/core/layout/inline/inline_cursor.cc
@@ -20,7 +20,6 @@ #include "third_party/blink/renderer/core/layout/layout_text_combine.h" #include "third_party/blink/renderer/core/layout/physical_box_fragment.h" #include "third_party/blink/renderer/core/paint/inline_paint_context.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { class HTMLBRElement; @@ -238,7 +237,6 @@ const LayoutObject* layout_object = root_box_fragment_->GetSelfOrContainerLayoutObject(); DCHECK(layout_object); - DCHECK(!layout_object->IsLayoutFlowThread()); return To<LayoutBlockFlow>(layout_object); } NOTREACHED(); @@ -523,49 +521,7 @@ return physical_rect; } -PhysicalRect InlineCursor::CurrentRectInBlockFlow() const { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - PhysicalRect rect = Current().RectInContainerFragment(); - // We'll now convert the offset from being relative to the containing fragment - // to being relative to the containing LayoutBlockFlow. For writing modes that - // don't flip the block direction, this is easy: just add the block-size - // consumed in previous fragments. - auto writing_direction = ContainerFragment().Style().GetWritingDirection(); - switch (writing_direction.GetWritingMode()) { - case WritingMode::kHorizontalTb: - rect.offset.top += previously_consumed_block_size_; - break; - case WritingMode::kSidewaysLr: - case WritingMode::kVerticalLr: - rect.offset.left += previously_consumed_block_size_; - break; - case WritingMode::kSidewaysRl: - case WritingMode::kVerticalRl: { - // For vertical-rl writing-mode it's a bit more complicated. We need to - // convert to logical coordinates in the containing box fragment, in order - // to add the consumed block-size to make it relative to the - // LayoutBlockFlow ("flow thread coordinate space"), and then we convert - // back to physical coordinates. - const LayoutBlock* containing_block = - Current().GetLayoutObject()->ContainingBlock(); - DCHECK_EQ(containing_block->StyleRef().GetWritingDirection(), - ContainerFragment().Style().GetWritingDirection()); - LogicalOffset logical_offset = - WritingModeConverter(writing_direction, ContainerFragment().Size()) - .ToLogical(rect.offset, rect.size); - LogicalOffset logical_offset_in_flow_thread( - logical_offset.inline_offset, - logical_offset.block_offset + previously_consumed_block_size_); - rect.offset = logical_offset_in_flow_thread.ConvertToPhysical( - writing_direction, PhysicalSize(containing_block->Size()), rect.size); - break; - } - }; - return rect; -} - PhysicalRect InlineCursor::CurrentRectInFirstContainerFragment() const { - DCHECK(RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); PhysicalRect rect = Current().RectInContainerFragment(); if (ContainerFragment().IsFirstForNode()) { return rect;
diff --git a/third_party/blink/renderer/core/layout/inline/inline_cursor.h b/third_party/blink/renderer/core/layout/inline/inline_cursor.h index 92dc1f70..299672a 100644 --- a/third_party/blink/renderer/core/layout/inline/inline_cursor.h +++ b/third_party/blink/renderer/core/layout/inline/inline_cursor.h
@@ -331,38 +331,6 @@ const LayoutSelectionStatus& selection_status) const; PhysicalRect CurrentLocalSelectionRectForReplaced() const; - // Return a rectangle (or just an offset) relatively to containing - // LayoutBlockFlow, as if all the container fragments were stitched together - // in the block direction (aka. "flow thread coordinate space"). - // - // Example: - // <div style="columns:2; orphans:1; widows:1; width:20px; line-height:20px;"> - // <div id="container">line1 line2 line3 line4 line5 line6</div> - // </div> - // - // The text will end up on six lines. The first three lines will end up in the - // first column, and the last three lines will end up in the second column. So - // we get two box fragments generated for #container - one for each column. - // - // The offsets returned from these methods will be - // (OffsetInContainerFragment() values in parentheses): - // - // line1: 0,0 (0,0) - // line2: 0,20 (0,20) - // line3: 0,40 (0,40) - // line4: 0,60 (0,0) - // line5: 0,80 (0,20) - // line6: 0,100 (0,40) - // - // We need this functionality, because we're still using the legacy layout - // engine to calculate offsets relatively to some ancestor. - PhysicalRect CurrentRectInBlockFlow() const; - PhysicalOffset CurrentOffsetInBlockFlow() const { - DCHECK_EQ(Current().OffsetInContainerFragment(), - Current().RectInContainerFragment().offset); - return CurrentRectInBlockFlow().offset; - } - // Return the rectangle of the current item, relatively to the first container // fragment. Used by block fragmentation. PhysicalRect CurrentRectInFirstContainerFragment() const;
diff --git a/third_party/blink/renderer/core/layout/inline/inline_node.cc b/third_party/blink/renderer/core/layout/inline/inline_node.cc index be3d66c..2613613 100644 --- a/third_party/blink/renderer/core/layout/inline/inline_node.cc +++ b/third_party/blink/renderer/core/layout/inline/inline_node.cc
@@ -35,7 +35,6 @@ #include "third_party/blink/renderer/core/layout/layout_result.h" #include "third_party/blink/renderer/core/layout/layout_text.h" #include "third_party/blink/renderer/core/layout/layout_text_combine.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/length_utils.h" #include "third_party/blink/renderer/core/layout/list/layout_inline_list_item.h" #include "third_party/blink/renderer/core/layout/list/layout_list_item.h" @@ -323,7 +322,7 @@ const InlineNodeData* previous_data) { LayoutBlockFlow* const block = builder->GetLayoutBlockFlow(); builder->EnterBlock(block->Style()); - LayoutObject* node = GetLayoutObjectForFirstChildNode(block); + LayoutObject* node = block->FirstChild(); const LayoutObject* symbol = LayoutListItem::FindSymbolMarkerLayoutText(block); @@ -434,7 +433,7 @@ node = next; break; } - node = GetLayoutObjectForParentNode(node); + node = node->Parent(); if (node == block || !node) { // Set |node| to |nullptr| to break out of the outer loop. node = nullptr;
diff --git a/third_party/blink/renderer/core/layout/inline/offset_mapping.cc b/third_party/blink/renderer/core/layout/inline/offset_mapping.cc index 60c6aca..847fb4f 100644 --- a/third_party/blink/renderer/core/layout/inline/offset_mapping.cc +++ b/third_party/blink/renderer/core/layout/inline/offset_mapping.cc
@@ -21,9 +21,8 @@ namespace { -// Note: LayoutFlowThread, used for multicol, can't provide offset mapping. bool CanUseOffsetMapping(const LayoutObject& object) { - return object.IsLayoutBlockFlow() && !object.IsLayoutFlowThread(); + return object.IsLayoutBlockFlow(); } Position CreatePositionForOffsetMapping(const Node& node, unsigned dom_offset) {
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index be86d7dd..9586f2c 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -55,7 +55,6 @@ #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_theme.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/length_utils.h" #include "third_party/blink/renderer/core/layout/masonry/layout_masonry.h" #include "third_party/blink/renderer/core/layout/mathml/layout_mathml_block.h" @@ -339,16 +338,9 @@ // Promote all the leftover anonymous block's children (to become children of // this block instead). We still want to keep the leftover block in the tree - // for a moment, for notification purposes done further below (flow threads - // and grids). + // for a moment, for notification purposes done further below (grids). child->MoveAllChildrenTo(this, child->NextSibling()); - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - // Remove all the information in the flow thread associated with the - // leftover anonymous block. - child->RemoveFromLayoutFlowThread(); - } - // Now remove the leftover anonymous block from the tree, and destroy it. // We'll rip it out manually from the tree before destroying it, because we // don't want to trigger any tree adjustments with regards to anonymous blocks @@ -554,7 +546,7 @@ continue; PhysicalOffset child_accumulated_offset = - scrolled_offset + child->PhysicalLocation(this); + scrolled_offset + child->PhysicalLocation(); bool did_hit; if (child->IsFloating()) { if (phase != HitTestPhase::kFloat || !IsLayoutNGObject())
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index d8cdfc1..7a7e5ec 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -49,14 +49,10 @@ #include "third_party/blink/renderer/core/layout/inline/inline_cursor.h" #include "third_party/blink/renderer/core/layout/inline/offset_mapping.h" #include "third_party/blink/renderer/core/layout/layout_block_flow.h" -#include "third_party/blink/renderer/core/layout/layout_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_result.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/logical_box_fragment.h" #include "third_party/blink/renderer/core/layout/physical_box_fragment.h" #include "third_party/blink/renderer/core/layout/shapes/shape_outside_info.h" @@ -82,14 +78,8 @@ // returned, and there are inline children, an anonymous block wrapper needs to // be created. bool AllowsInlineChildren(const LayoutBlockFlow& block) { - bool is_multicol; - if (RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - is_multicol = block.IsMulticolContainer(); - } else { - is_multicol = IsA<LayoutMultiColumnFlowThread>(block); - } const auto* inner_editor = DynamicTo<LayoutTextControlInnerEditor>(block); - return !is_multicol && !block.IsScrollMarkerGroup() && + return !block.IsMulticolContainer() && !block.IsScrollMarkerGroup() && !(inner_editor && inner_editor->IsMultiline()); } @@ -100,7 +90,6 @@ } // anonymous namespace struct SameSizeAsLayoutBlockFlow : public LayoutBlock { - Member<void*> member; Member<void*> inline_node_data; }; @@ -206,15 +195,6 @@ void LayoutBlockFlow::AddChild(LayoutObject* new_child, LayoutObject* before_child) { NOT_DESTROYED(); - - if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) { - if (before_child == flow_thread) - before_child = flow_thread->FirstChild(); - DCHECK(!before_child || before_child->IsDescendantOf(flow_thread)); - flow_thread->AddChild(new_child, before_child); - return; - } - if (before_child && before_child->Parent() != this) { if (RuntimeEnabledFeatures::LayoutAddChildBeforeDescendantFixEnabled()) { AddChildBeforeDescendant(new_child, before_child); @@ -754,9 +734,10 @@ bool LayoutBlockFlow::AllowsColumns() const { NOT_DESTROYED(); - // Ruby elements manage child insertion in a special way, and would mess up - // insertion of the flow thread. The flow thread needs to be a direct child of - // the multicol block (|this|). + // TODO(crbug.com/40414064): Ruby elements manage child insertion in a special + // way, and this would come in conflict with the legacy multicol + // implementation. However, that implementation is now gone, and it should be + // safe to enable multicol for ruby. if (IsRuby()) return false; @@ -773,26 +754,8 @@ return true; } -// TODO(crbug.com/371802475): Remove the parameter. -void LayoutBlockFlow::UpdateForMulticol(const ComputedStyle* old_style) { +void LayoutBlockFlow::UpdateForMulticol() { NOT_DESTROYED(); - bool specifies_columns = StyleRef().SpecifiesColumns(); - - if (MultiColumnFlowThread()) { - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); - DCHECK(old_style); - if (specifies_columns != old_style->SpecifiesColumns()) { - // If we're no longer to be multicol/paged, destroy the flow thread. Also - // destroy it when switching between multicol and paged, since that - // affects the column set structure (multicol containers may have - // spanners, paged containers may not). - MultiColumnFlowThread()->EvacuateAndDestroy(); - SetIsMulticolContainer(false); - DCHECK(!MultiColumnFlowThread()); - } - return; - } - auto ShouldBeMulticol = [this]() -> bool { if (!StyleRef().SpecifiesColumns() || !AllowsColumns()) { return false; @@ -826,34 +789,6 @@ UseCounter::Count(GetDocument(), WebFeature::kMultiColAndListItem); } - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - if (!should_be_multicol) { - return; - } - - auto* flow_thread = - LayoutMultiColumnFlowThread::CreateAnonymous(GetDocument(), StyleRef()); - AddChild(flow_thread); - if (IsLayoutNGObject()) { - // For simplicity of layout algorithm, we assume flow thread having block - // level children only. - // For example, we can handle them in same way: - // <div style="columns:3">abc<br>def<br>ghi<br></div> - // <div style="columns:3"><div>abc<br>def<br>ghi<br></div></div> - flow_thread->SetChildrenInline(false); - } - - // Check that addChild() put the flow thread as a direct child, and didn't - // do fancy things. - DCHECK_EQ(flow_thread->Parent(), this); - - flow_thread->Populate(); - - DCHECK(!multi_column_flow_thread_); - multi_column_flow_thread_ = flow_thread; - return; - } - // Descendants are inside multicol if this is now a multicol container, or if // this ex-multicol container is inside an outer multicol container. bool is_inside_multicol = should_be_multicol || IsInsideMulticol();
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h index ed4dd81..c261dd1 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.h +++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -43,8 +43,6 @@ namespace blink { -class LayoutMultiColumnFlowThread; - struct InlineNodeData; // LayoutBlockFlow is the class that implements a block container in CSS 2.1. @@ -86,15 +84,6 @@ void ChildBecameFloatingOrOutOfFlow(LayoutBox* child); void CollapseAnonymousBlockChild(LayoutBlockFlow* child); - LayoutMultiColumnFlowThread* MultiColumnFlowThread() const { - NOT_DESTROYED(); - return multi_column_flow_thread_.Get(); - } - void ResetMultiColumnFlowThread() { - NOT_DESTROYED(); - multi_column_flow_thread_ = nullptr; - } - // Return true if this block establishes a fragmentation context root (e.g. a // multicol container). bool IsFragmentationContextRoot() const override { @@ -169,7 +158,7 @@ void DirtyLinesFromChangedChild(LayoutObject* child) final; private: - void UpdateForMulticol(const ComputedStyle* old_style); + void UpdateForMulticol(); void AddChildBeforeDescendant(LayoutObject* new_child, LayoutObject* before_descendant); @@ -195,7 +184,6 @@ bool ShouldTruncateOverflowingText() const; private: - Member<LayoutMultiColumnFlowThread> multi_column_flow_thread_; Member<InlineNodeData> inline_node_data_; protected:
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_hot.cc b/third_party/blink/renderer/core/layout/layout_block_flow_hot.cc index 1f18b81..f2ebe9270 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow_hot.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow_hot.cc
@@ -4,14 +4,12 @@ #include "third_party/blink/renderer/core/layout/layout_block_flow.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_view.h" namespace blink { void LayoutBlockFlow::Trace(Visitor* visitor) const { - visitor->Trace(multi_column_flow_thread_); visitor->Trace(inline_node_data_); LayoutBlock::Trace(visitor); } @@ -67,24 +65,9 @@ LayoutBlock::StyleDidChange(diff, old_style); if (diff.NeedsFullLayout() || !old_style) { - UpdateForMulticol(old_style); + UpdateForMulticol(); } if (old_style) { - // TODO(crbug.com/357648037): Remove this path once GapDecorations is - // enabled by default. - if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) { - // Don't go down this route when gap decorations is enabled. This is - // because this is intended solely for forceful invalidation of column - // rules. However, with the `invalidate: paint` setting in - // css_properties.json and the new approach of painting gap decorations - // using `GapGeometry`, this won't be needed. - if (!RuntimeEnabledFeatures::CSSGapDecorationEnabled() && - !StyleRef().ColumnRuleEquivalent(*old_style)) { - // Column rules are painted by anonymous column set children of the - // multicol container. We need to notify them. - flow_thread->ColumnRuleStyleDidChange(); - } - } // We either gained or lost ::column style, trigger relayout to determine, // if column pseudo-elements are needed. if (old_style->CanGeneratePseudoElement(kPseudoIdColumn) !=
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_test.cc b/third_party/blink/renderer/core/layout/layout_block_flow_test.cc index 8c1359fd..f43a472 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow_test.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow_test.cc
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" +#include "third_party/blink/renderer/core/layout/layout_block_flow.h" + #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" namespace blink { @@ -105,16 +106,6 @@ EXPECT_TRUE(child->IsInsideMulticol()); } -// TODO(crbug.com/371802475): Remove this when no longer need. -const LayoutBlockFlow* MulticolContentContainer( - const LayoutBlockFlow* multicol_container) { - if (LayoutBlockFlow* flow_thread = - multicol_container->MultiColumnFlowThread()) { - return flow_thread; - } - return multicol_container; -} - TEST_F(LayoutBlockFlowTest, AnonymousContainer) { SetBodyInnerHTML(R"HTML( <div id="multicol" style="columns:3;"><span id="child1"></span><span id="child2"></span></div> @@ -131,8 +122,8 @@ ASSERT_TRUE(child2); // The children are inline. Need an anonymous wrapper. - const auto* anonymous_wrapper = DynamicTo<LayoutBlockFlow>( - MulticolContentContainer(multicol)->FirstChild()); + const auto* anonymous_wrapper = + DynamicTo<LayoutBlockFlow>(multicol->FirstChild()); ASSERT_TRUE(anonymous_wrapper); EXPECT_TRUE(anonymous_wrapper->IsAnonymousBlockFlow()); EXPECT_EQ(anonymous_wrapper->NextSibling(), nullptr); @@ -159,8 +150,7 @@ "columns", "3", "", ASSERT_NO_EXCEPTION); UpdateAllLifecyclePhasesForTest(); - anonymous_wrapper = DynamicTo<LayoutBlockFlow>( - MulticolContentContainer(multicol)->FirstChild()); + anonymous_wrapper = DynamicTo<LayoutBlockFlow>(multicol->FirstChild()); ASSERT_TRUE(anonymous_wrapper); EXPECT_TRUE(anonymous_wrapper->IsAnonymousBlockFlow()); EXPECT_EQ(anonymous_wrapper->NextSibling(), nullptr); @@ -183,7 +173,6 @@ const auto* multicol = DynamicTo<LayoutBlockFlow>(GetLayoutObjectByElementId("multicol")); ASSERT_TRUE(multicol); - multicol = MulticolContentContainer(multicol); const LayoutObject* child1 = GetLayoutObjectByElementId("child1"); ASSERT_TRUE(child1); const LayoutObject* child2 = GetLayoutObjectByElementId("child2");
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 155942b..a46ad81 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -84,14 +84,11 @@ #include "third_party/blink/renderer/core/layout/inline/inline_cursor.h" #include "third_party/blink/renderer/core/layout/layout_embedded_content.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_result.h" #include "third_party/blink/renderer/core/layout/layout_utils.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/length_utils.h" #include "third_party/blink/renderer/core/layout/logical_box_fragment.h" #include "third_party/blink/renderer/core/layout/measure_cache.h" @@ -151,10 +148,7 @@ static const unsigned kBackgroundObscurationTestMaxDepth = 4; struct SameSizeAsLayoutBox : public LayoutBoxModelObject { - union { - DeprecatedLayoutPoint a; - PhysicalOffset b; - } frame_location_; + PhysicalOffset frame_location_; PhysicalSize frame_size_; PhysicalSize previous_size; MinMaxSizes intrinsic_logical_widths; @@ -467,13 +461,11 @@ } // namespace LayoutBoxRareData::LayoutBoxRareData() - : spanner_placeholder_(nullptr), - // TODO(rego): We should store these based on physical direction. + : // TODO(rego): We should store these based on physical direction. has_override_containing_block_content_logical_width_(false), has_previous_content_box_rect_(false) {} void LayoutBoxRareData::Trace(Visitor* visitor) const { - visitor->Trace(spanner_placeholder_); visitor->Trace(layout_child_); } @@ -690,20 +682,6 @@ UpdateGridPositionAfterStyleChange(old_style); if (old_style) { - // Regular column content (i.e. non-spanners) have a hook into the flow - // thread machinery before (StyleWillChange()) and after (here in - // StyleDidChange()) the style has changed. Column spanners, on the other - // hand, only have a hook here. The LayoutMultiColumnSpannerPlaceholder code - // will do all the necessary things, including removing it as a spanner, if - // it should no longer be one. Therefore, make sure that we skip - // FlowThreadDescendantStyleDidChange() in such cases, as that might trigger - // a duplicate flow thread insertion notification, if the spanner no longer - // is a spanner. - if (LayoutMultiColumnSpannerPlaceholder* placeholder = - SpannerPlaceholder()) { - placeholder->LayoutObjectInFlowThreadStyleDidChange(old_style); - } - UpdateScrollSnapMappingAfterStyleChange(*old_style); if (ShouldClipOverflowAlongEitherAxis()) { @@ -1074,22 +1052,6 @@ return ClientHeight(); } -LayoutUnit LayoutBox::OffsetWidth() const { - NOT_DESTROYED(); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return LayoutBoxModelObject::OffsetWidth(); - } - return Size().width; -} - -LayoutUnit LayoutBox::OffsetHeight() const { - NOT_DESTROYED(); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return LayoutBoxModelObject::OffsetHeight(); - } - return Size().height; -} - bool LayoutBox::UsesOverlayScrollbars() const { NOT_DESTROYED(); if (StyleRef().HasCustomScrollbarStyle(DynamicTo<Element>(GetNode()))) { @@ -1186,30 +1148,20 @@ const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode) const { NOT_DESTROYED(); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - const PhysicalBoxFragment* first_fragment = nullptr; - for (const PhysicalBoxFragment& fragment : PhysicalFragments()) { - // Calculate the offset relatively to the first fragment, which in turn - // will be mapped correctly to the ancestor. - PhysicalOffset offset; - if (!first_fragment) { - first_fragment = &fragment; - } else { - offset = fragment.OffsetFromRootFragmentationContext() - - first_fragment->OffsetFromRootFragmentationContext(); - } - PhysicalRect rect(offset, fragment.Size()); - quads.push_back(LocalRectToAncestorQuad(rect, ancestor, mode)); + const PhysicalBoxFragment* first_fragment = nullptr; + for (const PhysicalBoxFragment& fragment : PhysicalFragments()) { + // Calculate the offset relatively to the first fragment, which in turn + // will be mapped correctly to the ancestor. + PhysicalOffset offset; + if (!first_fragment) { + first_fragment = &fragment; + } else { + offset = fragment.OffsetFromRootFragmentationContext() - + first_fragment->OffsetFromRootFragmentationContext(); } - return; + PhysicalRect rect(offset, fragment.Size()); + quads.push_back(LocalRectToAncestorQuad(rect, ancestor, mode)); } - - if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock()) { - flow_thread->QuadsInAncestorForDescendant(*this, quads, ancestor, mode); - return; - } - quads.push_back( - LocalRectToAncestorQuad(PhysicalBorderBoxRect(), ancestor, mode)); } gfx::RectF LayoutBox::LocalBoundingBoxRectForAccessibility() const { @@ -1259,20 +1211,6 @@ ClearNeedsLayout(); } - if (auto* block_flow = DynamicTo<LayoutBlockFlow>(this)) { - // TODO(crbug.com/371802475): Get rid of this. The special anonymous objects - // created (but not really used anymore) for multicol layout are not laid - // out, and need to be cleared manually, to avoid DCHECK failures. - if (LayoutMultiColumnFlowThread* flow_thread = - block_flow->MultiColumnFlowThread()) { - for (LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - column_box; column_box = column_box->NextSiblingMultiColumnBox()) { - column_box->ClearNeedsLayout(); - } - flow_thread->ClearNeedsLayout(); - } - } - // We should notify the display lock that we've done layout on self, and if // it's not blocked, on children. if (auto* context = GetDisplayLockContext()) { @@ -2133,7 +2071,7 @@ PhysicalOffset child_accumulated_offset = accumulated_offset; if (auto* box = DynamicTo<LayoutBox>(child)) - child_accumulated_offset += box->PhysicalLocation(this); + child_accumulated_offset += box->PhysicalLocation(); if (child->NodeAtPoint(result, hit_test_location, child_accumulated_offset, phase)) @@ -2914,15 +2852,6 @@ void LayoutBox::InvalidateCachedGeometry() { NOT_DESTROYED(); SetHasValidCachedGeometry(false); - if (auto* block_flow = DynamicTo<LayoutBlockFlow>(this)) { - if (auto* flow_thread = block_flow->MultiColumnFlowThread()) { - flow_thread->SetHasValidCachedGeometry(false); - for (auto* sibling = flow_thread->NextSiblingBox(); sibling; - sibling = sibling->NextSiblingBox()) { - sibling->SetHasValidCachedGeometry(false); - } - } - } } // static @@ -3011,21 +2940,6 @@ return &FragmentList().at(BoxFragmentIndex(physical_fragment)); } -void LayoutBox::SetSpannerPlaceholder( - LayoutMultiColumnSpannerPlaceholder& placeholder) { - NOT_DESTROYED(); - // Not expected to change directly from one spanner to another. - CHECK(!rare_data_ || !rare_data_->spanner_placeholder_); - EnsureRareData().spanner_placeholder_ = &placeholder; -} - -void LayoutBox::ClearSpannerPlaceholder() { - NOT_DESTROYED(); - if (!rare_data_) - return; - rare_data_->spanner_placeholder_ = nullptr; -} - bool LayoutBox::IsValidColumnSpanner(const ComputedStyle& style) const { NOT_DESTROYED(); // Note that this function may be called in many circumstances, such as before @@ -3034,9 +2948,6 @@ if (style.GetColumnSpan() != EColumnSpan::kAll) { return false; } - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - return SpannerPlaceholder(); - } if (!Parent() || !IsInsideMulticol()) { return false; @@ -3125,12 +3036,7 @@ if (!container) return true; - PhysicalOffset container_offset; - if (auto* box = DynamicTo<LayoutBox>(container)) { - container_offset += PhysicalLocation(box); - } else { - container_offset += PhysicalLocation(); - } + PhysicalOffset container_offset = PhysicalLocation(); if (IsStickyPositioned()) { container_offset += StickyPositionOffset(); @@ -3854,7 +3760,6 @@ PhysicalRect LayoutBox::VisualOverflowRect() const { NOT_DESTROYED(); - DCHECK(!IsLayoutMultiColumnSet()); if (!VisualOverflowIsSet()) return PhysicalBorderBoxRect(); @@ -4604,14 +4509,9 @@ Size()); } -PhysicalOffset LayoutBox::PhysicalLocation( - const LayoutBox* location_container) const { +PhysicalOffset LayoutBox::PhysicalLocation() const { NOT_DESTROYED(); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return frame_location_.physical_offset; - } - return DeprecatedPhysicalLocationInternal( - location_container ? location_container : LocationContainer()); + return frame_location_; } PhysicalRect LayoutBox::BoundingBoxRelativeToFirstFragment() const {
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index dd9b99f9..da1dae6e 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -42,7 +42,6 @@ #include "third_party/blink/renderer/core/style/style_overflow_clip_margin.h" #include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -53,7 +52,6 @@ class CustomLayoutChild; class EarlyBreak; class Element; -class LayoutMultiColumnSpannerPlaceholder; class LayoutResult; class MeasureCache; class PhysicalBoxFragment; @@ -85,10 +83,6 @@ void Trace(Visitor* visitor) const; - // For spanners, the spanner placeholder that lays us out within the multicol - // container. - Member<LayoutMultiColumnSpannerPlaceholder> spanner_placeholder_; - bool has_override_containing_block_content_logical_width_ : 1; bool has_previous_content_box_rect_ : 1; @@ -252,21 +246,10 @@ void SetLocation(PhysicalOffset location) { NOT_DESTROYED(); - DCHECK(RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - if (location == frame_location_.physical_offset) { + if (location == frame_location_) { return; } - frame_location_.physical_offset = location; - LocationChanged(); - } - - void SetLocation(const DeprecatedLayoutPoint& location) { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - if (location == frame_location_.layout_point) { - return; - } - frame_location_.layout_point = location; + frame_location_ = location; LocationChanged(); } @@ -332,13 +315,6 @@ LayoutBox* NextSiblingBox() const; LayoutBox* ParentBox() const; - // Return the previous sibling column set or spanner placeholder. Only to be - // used on multicol container children. - LayoutBox* PreviousSiblingMultiColumnBox() const; - // Return the next sibling column set or spanner placeholder. Only to be used - // on multicol container children. - LayoutBox* NextSiblingMultiColumnBox() const; - bool CanResize() const; DISABLE_CFI_PERF PhysicalRect NoOverflowRect() const { @@ -347,7 +323,6 @@ } PhysicalRect ScrollableOverflowRect() const { NOT_DESTROYED(); - DCHECK(!IsLayoutMultiColumnSet()); return ScrollableOverflowIsSet() ? overflow_->scrollable_overflow->ScrollableOverflowRect() : NoOverflowRect(); @@ -459,12 +434,6 @@ LayoutUnit DefaultIntrinsicContentBlockSize( bool children_have_geometry) const; - // IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines - // (LayoutFlow) to return the remaining width on a given line (and the height - // of a single line). - LayoutUnit OffsetWidth() const final; - LayoutUnit OffsetHeight() const final; - bool UsesOverlayScrollbars() const; // Physical client rect (a.k.a. PhysicalPaddingBoxRect(), defined by @@ -746,13 +715,6 @@ return !PhysicalFragmentCount(); } - void SetSpannerPlaceholder(LayoutMultiColumnSpannerPlaceholder&); - void ClearSpannerPlaceholder(); - LayoutMultiColumnSpannerPlaceholder* SpannerPlaceholder() const final { - NOT_DESTROYED(); - return rare_data_ ? rare_data_->spanner_placeholder_.Get() : nullptr; - } - bool IsValidColumnSpanner() const final { NOT_DESTROYED(); return IsValidColumnSpanner(StyleRef()); @@ -923,12 +885,7 @@ // this container. This ignores TextDirection. WritingModeConverter CreateWritingModeConverter() const; - // Passing |location_container| causes flipped-block flipping w.r.t. - // that container, or LocationContainer() otherwise. - // - // TODO(crbug.com/40855022): Get rid of the parameter. - virtual PhysicalOffset PhysicalLocation( - const LayoutBox* location_container = nullptr) const; + virtual PhysicalOffset PhysicalLocation() const; PhysicalRect BoundingBoxRelativeToFirstFragment() const override; @@ -1301,14 +1258,6 @@ LayoutUnit ContainingBlockLogicalHeightForPositioned( const LayoutBoxModelObject* containing_block) const; - virtual DeprecatedLayoutPoint DeprecatedLocationInternal() const { - NOT_DESTROYED(); - return frame_location_.layout_point; - } - // Allow LayoutMultiColumnSpannerPlaceholder to call - // DeprecatedLocationInternal() of other instances. - friend class LayoutMultiColumnSpannerPlaceholder; - PhysicalOffset OffsetFromContainerInternal( const LayoutObject*, MapCoordinatesFlags mode) const override; @@ -1390,22 +1339,6 @@ OverlayScrollbarClipBehavior = kIgnoreOverlayScrollbarSize, ShouldIncludeScrollbarGutter = kIncludeScrollbarGutter) const; - PhysicalOffset DeprecatedPhysicalLocationInternal( - const LayoutBox* container_box) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - DCHECK_EQ(container_box, LocationContainer()); - DeprecatedLayoutPoint location = DeprecatedLocationInternal(); - if (!container_box || !container_box->HasFlippedBlocksWritingMode()) - [[likely]] { - return PhysicalOffset(location); - } - - return PhysicalOffset( - container_box->Size().width - Size().width - location.X(), - location.Y()); - } - bool BackgroundClipBorderBoxIsEquivalentToPaddingBox() const; BackgroundPaintLocation ComputeBackgroundPaintLocation( bool needs_root_element_group) const; @@ -1424,11 +1357,7 @@ // this object, to the border edge of the first fragment of // LocationContainer(). It doesn't include transforms, relative position // offsets etc. - union Location { - Location() : physical_offset(PhysicalOffset()) {} - DeprecatedLayoutPoint layout_point; - PhysicalOffset physical_offset; - } frame_location_; + PhysicalOffset frame_location_; // TODO(crbug.com/1353190): Remove frame_size_. PhysicalSize frame_size_; @@ -1454,8 +1383,6 @@ Member<BoxOverflowModel> overflow_; Member<LayoutBoxRareData> rare_data_; - - FRIEND_TEST_ALL_PREFIXES(LayoutMultiColumnSetTest, ScrollAnchroingCrash); }; template <> @@ -1488,21 +1415,6 @@ return To<LayoutBox>(SlowLastChild()); } -inline LayoutBox* LayoutBox::PreviousSiblingMultiColumnBox() const { - NOT_DESTROYED(); - DCHECK(IsLayoutMultiColumnSpannerPlaceholder() || IsLayoutMultiColumnSet()); - LayoutBox* previous_box = PreviousSiblingBox(); - if (previous_box->IsLayoutFlowThread()) - return nullptr; - return previous_box; -} - -inline LayoutBox* LayoutBox::NextSiblingMultiColumnBox() const { - NOT_DESTROYED(); - DCHECK(IsLayoutMultiColumnSpannerPlaceholder() || IsLayoutMultiColumnSet()); - return NextSiblingBox(); -} - inline wtf_size_t LayoutBox::FirstInlineFragmentItemIndex() const { NOT_DESTROYED(); if (!IsInLayoutNGInlineFormattingContext())
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc index 52c469c..48917dd 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -37,12 +37,10 @@ #include "third_party/blink/renderer/core/layout/geometry/transform_state.h" #include "third_party/blink/renderer/core/layout/inline/inline_cursor.h" #include "third_party/blink/renderer/core/layout/layout_block.h" -#include "third_party/blink/renderer/core/layout/layout_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_result.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/svg/svg_resources.h" #include "third_party/blink/renderer/core/layout/table/layout_table_section.h" #include "third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h" @@ -136,13 +134,6 @@ ObjectPaintInvalidator(*this).SlowSetPaintingLayerNeedsRepaint(); } - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled() && Style()) { - LayoutFlowThread* flow_thread = FlowThreadContainingBlock(); - if (flow_thread && flow_thread != this) { - flow_thread->FlowThreadDescendantStyleWillChange(this, diff, new_style); - } - } - LayoutObject::StyleWillChange(diff, new_style); } @@ -235,15 +226,6 @@ } if (old_style && Parent()) { - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock()) { - if (flow_thread != this) { - flow_thread->FlowThreadDescendantStyleDidChange(this, diff, - *old_style); - } - } - } - LayoutBlock* block = InclusiveContainingBlock(); if ((could_contain_fixed && !can_contain_fixed) || @@ -352,18 +334,6 @@ SetNeedsPaintPropertyUpdate(); } -LayoutUnit LayoutBoxModelObject::OffsetWidth() const { - NOT_DESTROYED(); - DCHECK(RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return BoundingBoxRelativeToFirstFragment().size.width; -} - -LayoutUnit LayoutBoxModelObject::OffsetHeight() const { - NOT_DESTROYED(); - DCHECK(RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return BoundingBoxRelativeToFirstFragment().size.height; -} - bool LayoutBoxModelObject::HasSelfPaintingLayer() const { NOT_DESTROYED(); return Layer() && Layer()->IsSelfPaintingLayer(); @@ -745,9 +715,6 @@ current && current->GetNode() != offset_parent; current = current->Container()) { // FIXME: What are we supposed to do inside SVG content? - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - reference_point += current->ColumnOffset(reference_point); - } if (current->IsBox()) { reference_point += To<LayoutBox>(current)->PhysicalLocation(); }
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.h b/third_party/blink/renderer/core/layout/layout_box_model_object.h index d14620a..5c53866 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.h +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.h
@@ -135,15 +135,17 @@ SetNeedsPaintPropertyUpdate(); } - // IE extensions. Used to calculate offsetWidth/Height. Overridden by inlines - // (LayoutInline) to return the remaining width on a given line (and the - // height of a single line). + // IE extensions. Used to calculate offsetWidth/Height. virtual LayoutUnit OffsetLeft(const Element*) const = 0; virtual LayoutUnit OffsetTop(const Element*) const = 0; - // TODO(crbug.com/40855022): These two don't need to be virtual when the - // legacy code is gone. - virtual LayoutUnit OffsetWidth() const; - virtual LayoutUnit OffsetHeight() const; + LayoutUnit OffsetWidth() const { + NOT_DESTROYED(); + return BoundingBoxRelativeToFirstFragment().size.width; + } + LayoutUnit OffsetHeight() const { + NOT_DESTROYED(); + return BoundingBoxRelativeToFirstFragment().size.height; + } // Return the bounding box of all fragments generated by this box, relatively // to the top/left of the first fragment.
diff --git a/third_party/blink/renderer/core/layout/layout_box_utils.cc b/third_party/blink/renderer/core/layout/layout_box_utils.cc index a589670d..3b457e0 100644 --- a/third_party/blink/renderer/core/layout/layout_box_utils.cc +++ b/third_party/blink/renderer/core/layout/layout_box_utils.cc
@@ -320,37 +320,6 @@ return total_block_size; } -DeprecatedLayoutPoint ComputeBoxLocation( - const PhysicalBoxFragment& child_fragment, - PhysicalOffset offset, - const PhysicalBoxFragment& container_fragment, - const BlockBreakToken* previous_container_break_token) { - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - if (container_fragment.Style().IsFlippedBlocksWritingMode()) [[unlikely]] { - // Move the physical offset to the right side of the child fragment, - // relative to the right edge of the container fragment. This is the - // block-start offset in vertical-rl, and the legacy engine expects always - // expects the block offset to be relative to block-start. - offset.left = container_fragment.Size().width - offset.left - - child_fragment.Size().width; - } - - if (previous_container_break_token) [[unlikely]] { - // Add the amount of block-size previously (in previous fragmentainers) - // consumed by the container fragment. This will map the child's offset - // nicely into the flow thread coordinate system used by the legacy engine. - LayoutUnit consumed = - previous_container_break_token->ConsumedBlockSizeForLegacy(); - if (container_fragment.Style().IsHorizontalWritingMode()) { - offset.top += consumed; - } else { - offset.left += consumed; - } - } - - return offset.FaultyToDeprecatedLayoutPoint(); -} - void UpdateChildLayoutBoxLocations(const PhysicalBoxFragment& fragment) { if (fragment.GetLayoutObject()->ChildLayoutBlockedByDisplayLock()) { return;
diff --git a/third_party/blink/renderer/core/layout/layout_box_utils.h b/third_party/blink/renderer/core/layout/layout_box_utils.h index d56cae3d..ea68bbf 100644 --- a/third_party/blink/renderer/core/layout/layout_box_utils.h +++ b/third_party/blink/renderer/core/layout/layout_box_utils.h
@@ -6,12 +6,9 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BOX_UTILS_H_ #include "third_party/blink/renderer/platform/geometry/layout_unit.h" -#include "third_party/blink/renderer/platform/geometry/physical_offset.h" namespace blink { -class BlockBreakToken; -class DeprecatedLayoutPoint; class LayoutBox; class PhysicalBoxFragment; @@ -21,17 +18,6 @@ // The total block-size of all fragments. LayoutUnit BoxTotalBlockSize(const LayoutBox& box); -// Convert a physical offset for a physical fragment to a physical legacy -// DeprecatedLayoutPoint, to be used in LayoutBox. There are special -// considerations for vertical-rl writing-mode, and also for block -// fragmentation (the block-offset should include consumed space in previous -// fragments). -DeprecatedLayoutPoint ComputeBoxLocation( - const PhysicalBoxFragment& child_fragment, - PhysicalOffset offset, - const PhysicalBoxFragment& container_fragment, - const BlockBreakToken* previous_container_break_token); - // Set the LayoutBox location for direct children of the specified fragment, or, // if the specified fragment establishes a root fragmentation context (i.e. when // it does not participate in any outer fragmentation context), do this for the
diff --git a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc index ef9ee6f..1e38be2 100644 --- a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc +++ b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.cc
@@ -179,12 +179,6 @@ overridden_size_ = size; } -DeprecatedLayoutPoint LayoutCustomScrollbarPart::DeprecatedLocationInternal() - const { - NOT_DESTROYED(); - NOTREACHED(); -} - PhysicalSize LayoutCustomScrollbarPart::Size() const { NOT_DESTROYED(); return overridden_size_;
diff --git a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h index 8ed6c83..c283809c 100644 --- a/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h +++ b/third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h
@@ -72,8 +72,6 @@ // Update the overridden size. void SetOverriddenSize(const PhysicalSize& size); - // This should not be called. - DeprecatedLayoutPoint DeprecatedLocationInternal() const override; // Rerturn the overridden size set by SetOverriddenSize(); PhysicalSize Size() const override;
diff --git a/third_party/blink/renderer/core/layout/layout_flow_thread.cc b/third_party/blink/renderer/core/layout/layout_flow_thread.cc deleted file mode 100644 index 958b334..0000000 --- a/third_party/blink/renderer/core/layout/layout_flow_thread.cc +++ /dev/null
@@ -1,282 +0,0 @@ -/* - * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/core/layout/layout_flow_thread.h" - -#include "third_party/blink/renderer/core/layout/fragmentainer_iterator.h" -#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" - -namespace blink { - -LayoutFlowThread::LayoutFlowThread() - : LayoutBlockFlow(nullptr), column_sets_invalidated_(false) { - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); -} - -void LayoutFlowThread::Trace(Visitor* visitor) const { - visitor->Trace(multi_column_set_list_); - LayoutBlockFlow::Trace(visitor); -} - -bool LayoutFlowThread::IsLayoutNGObject() const { - NOT_DESTROYED(); - return false; -} - -LayoutFlowThread* LayoutFlowThread::LocateFlowThreadContainingBlockOf( - const LayoutObject& descendant, - AncestorSearchConstraint constraint) { - DCHECK(descendant.IsInsideMulticol()); - LayoutObject* curr = const_cast<LayoutObject*>(&descendant); - bool inner_is_ng_object = curr->IsLayoutNGObject(); - while (curr) { - if (curr->IsSVGChild()) - return nullptr; - // Always consider an in-flow legend child to be part of the flow - // thread. The containing block of the rendered legend is actually the - // multicol container itself (not its flow thread child), but since which - // element is the rendered legend might change (if we insert another legend - // in front of it, for instance), and such a change won't be detected by - // this child, we'll just pretend that it's part of the flow thread. This - // shouldn't have any negative impact on LayoutNG, and in the legacy engine, - // a fieldset isn't allowed to be a multicol container anyway. - if (curr->IsHTMLLegendElement() && !curr->IsOutOfFlowPositioned() && - !curr->IsColumnSpanAll() && curr->Parent()->IsLayoutFlowThread()) - return To<LayoutFlowThread>(curr->Parent()); - if (curr->IsLayoutFlowThread()) - return To<LayoutFlowThread>(curr); - LayoutObject* container = curr->Container(); - // If we're inside something strictly unbreakable (due to having scrollbars - // or being writing mode roots, for instance), it's also strictly - // unbreakable in any outer fragmentation context. As such, what goes on - // inside any fragmentation context on the inside of this is completely - // opaque to ancestor fragmentation contexts. - if (constraint == kIsolateUnbreakableContainers && container) { - if (const auto* box = DynamicTo<LayoutBox>(container)) { - // We're walking up the tree without knowing which fragmentation engine - // is being used, so we have to detect any engine mismatch ourselves. - if (box->IsLayoutNGObject() != inner_is_ng_object) - return nullptr; - if (box->IsMonolithic()) { - return nullptr; - } - } - } - curr = curr->Parent(); - while (curr != container) { - if (curr->IsLayoutFlowThread()) { - // The nearest ancestor flow thread isn't in our containing block chain. - // Then we aren't really part of any flow thread, and we should stop - // looking. This happens when there are out-of-flow objects or column - // spanners. - return nullptr; - } - curr = curr->Parent(); - } - } - return nullptr; -} - -void LayoutFlowThread::RemoveColumnSetFromThread( - LayoutMultiColumnSet* column_set) { - NOT_DESTROYED(); - DCHECK(column_set); - multi_column_set_list_.erase(column_set); - InvalidateColumnSets(); - // Clear the interval tree right away, instead of leaving it around with dead - // objects. Not that anyone _should_ try to access the interval tree when the - // column sets are marked as invalid, but this is actually possible if other - // parts of the engine has bugs that cause us to not lay out everything that - // was marked for layout, so that LayoutObject::assertLaidOut() (and a LOT - // of other assertions) fails. - multi_column_set_interval_tree_.Clear(); -} - -void LayoutFlowThread::ValidateColumnSets() { - NOT_DESTROYED(); - column_sets_invalidated_ = false; - GenerateColumnSetIntervalTree(); -} - -bool LayoutFlowThread::MapToVisualRectInAncestorSpaceInternal( - const LayoutBoxModelObject* ancestor, - TransformState& transform_state, - VisualRectFlags visual_rect_flags) const { - NOT_DESTROYED(); - // A flow thread should never be an invalidation container. - DCHECK_NE(ancestor, this); - - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return LayoutBlockFlow::MapToVisualRectInAncestorSpaceInternal( - ancestor, transform_state, visual_rect_flags); - } - - transform_state.Flatten(); - gfx::RectF bounding_box = transform_state.LastPlanarQuad().BoundingBox(); - PhysicalRect rect(LayoutUnit(bounding_box.x()), LayoutUnit(bounding_box.y()), - LayoutUnit(bounding_box.width()), - LayoutUnit(bounding_box.height())); - rect = FragmentsBoundingBox(rect); - transform_state.SetQuad(gfx::QuadF(gfx::RectF(rect))); - return LayoutBlockFlow::MapToVisualRectInAncestorSpaceInternal( - ancestor, transform_state, visual_rect_flags); -} - -PaintLayerType LayoutFlowThread::LayerTypeRequired() const { - NOT_DESTROYED(); - return kNoPaintLayer; -} - -void LayoutFlowThread::QuadsInAncestorForDescendant( - const LayoutBox& descendant, - Vector<gfx::QuadF>& quads, - const LayoutBoxModelObject* ancestor, - MapCoordinatesFlags mode) { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - PhysicalOffset offset_from_flow_thread; - for (const LayoutObject* object = &descendant; object != this;) { - // Based on current intended usage, it should be impossible to end up in a - // situation where the ancestor is inside the same fragmentation context as - // the descendant. If needed, though, it should be fairly trivial to add - // support for it. - DCHECK(object != ancestor); - - const LayoutObject* container = object->Container(); - offset_from_flow_thread += object->OffsetFromContainer(container); - object = container; - } - PhysicalRect bounding_rect_in_flow_thread(offset_from_flow_thread, - descendant.Size()); - // Set up a fragments relative to the descendant, in the flow thread - // coordinate space, and convert each of them, individually, to absolute - // coordinates. - for (FragmentainerIterator iterator(*this, bounding_rect_in_flow_thread); - !iterator.AtEnd(); iterator.Advance()) { - PhysicalRect fragment = bounding_rect_in_flow_thread; - // We use InclusiveIntersect() because Intersect() would reset the - // coordinates for zero-height objects. - PhysicalRect clip_rect = iterator.ClipRectInFlowThread(); - fragment.InclusiveIntersect(clip_rect); - fragment.offset -= offset_from_flow_thread; - quads.push_back( - descendant.LocalRectToAncestorQuad(fragment, ancestor, mode)); - } -} - -void LayoutFlowThread::AddOutlineRects( - OutlineRectCollector& collector, - OutlineInfo* info, - const PhysicalOffset& additional_offset, - OutlineType include_block_overflows) const { - NOT_DESTROYED(); - - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return LayoutBlockFlow::AddOutlineRects(collector, info, additional_offset, - include_block_overflows); - } - - Vector<PhysicalRect> rects_in_flowthread; - UnionOutlineRectCollector flow_collector; - LayoutBlockFlow::AddOutlineRects(flow_collector, info, additional_offset, - include_block_overflows); - // Convert the rectangles from the flow thread coordinate space to the visual - // space. The approach here is very simplistic; just calculate a bounding box - // in flow thread coordinates and convert it to one in visual - // coordinates. While the solution can be made more sophisticated by - // e.g. using FragmentainerIterator, the usefulness isn't obvious: our - // multicol implementation has practically no support for overflow in the - // block direction anyway. As far as the inline direction (the column - // progression direction) is concerned, we'll just include the full height of - // each column involved. Should be good enough. - collector.AddRect(FragmentsBoundingBox(flow_collector.Rect())); -} - -void LayoutFlowThread::Paint(const PaintInfo& paint_info) const { - NOT_DESTROYED(); - // NGBoxFragmentPainter traverses a physical fragment tree, and doesn't call - // Paint() for LayoutFlowThread. - NOTREACHED(); -} - -bool LayoutFlowThread::NodeAtPoint(HitTestResult& result, - const HitTestLocation& hit_test_location, - const PhysicalOffset& accumulated_offset, - HitTestPhase phase) { - NOT_DESTROYED(); - if (phase == HitTestPhase::kSelfBlockBackground) - return false; - return LayoutBlockFlow::NodeAtPoint(result, hit_test_location, - accumulated_offset, phase); -} - -RecalcScrollableOverflowResult LayoutFlowThread::RecalcScrollableOverflow() { - NOT_DESTROYED(); - // RecalcScrollableOverflow() traverses a physical fragment tree. So it's not - // called for LayoutFlowThread, which has no physical fragments. - NOTREACHED(); -} - -void LayoutFlowThread::GenerateColumnSetIntervalTree() { - NOT_DESTROYED(); - // FIXME: Optimize not to clear the interval all the time. This implies - // manually managing the tree nodes lifecycle. - multi_column_set_interval_tree_.Clear(); - multi_column_set_interval_tree_.InitIfNeeded(); - for (const auto& column_set : multi_column_set_list_) - multi_column_set_interval_tree_.Add( - MultiColumnSetIntervalTree::CreateInterval( - column_set->LogicalTopInFlowThread(), - column_set->LogicalBottomInFlowThread(), column_set)); -} - -PhysicalRect LayoutFlowThread::FragmentsBoundingBox( - const PhysicalRect& layer_bounding_box) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - DCHECK(!column_sets_invalidated_); - - PhysicalRect result; - for (const auto& column_set : multi_column_set_list_) - result.Unite(column_set->FragmentsBoundingBox(layer_bounding_box)); - - return result; -} - -void LayoutFlowThread::MultiColumnSetSearchAdapter::CollectIfNeeded( - const MultiColumnSetInterval& interval) { - if (result_) - return; - if (interval.Low() <= offset_ && interval.High() > offset_) - result_ = interval.Data(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_flow_thread.h b/third_party/blink/renderer/core/layout/layout_flow_thread.h deleted file mode 100644 index 643119a..0000000 --- a/third_party/blink/renderer/core/layout/layout_flow_thread.h +++ /dev/null
@@ -1,234 +0,0 @@ -/* - * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above - * copyright notice, this list of conditions and the following - * disclaimer. - * 2. Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FLOW_THREAD_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FLOW_THREAD_H_ - -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/layout/layout_block_flow.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/linked_hash_set.h" -#include "third_party/blink/renderer/platform/wtf/pod_interval_tree.h" - -namespace blink { - -class LayoutMultiColumnSet; - -typedef HeapLinkedHashSet<Member<LayoutMultiColumnSet>> - LayoutMultiColumnSetList; - -// LayoutFlowThread is used to collect all the layout objects that participate -// in a flow thread. It will also help in doing the layout. However, it will not -// layout directly to screen. Instead, LayoutMultiColumnSet objects will -// redirect their paint and nodeAtPoint methods to this object. Each -// LayoutMultiColumnSet will actually be a viewPort of the LayoutFlowThread. -class CORE_EXPORT LayoutFlowThread : public LayoutBlockFlow { - public: - explicit LayoutFlowThread(); - ~LayoutFlowThread() override = default; - void Trace(Visitor*) const override; - - bool IsLayoutNGObject() const final; - bool IsLayoutFlowThread() const final { - NOT_DESTROYED(); - return true; - } - virtual bool IsLayoutMultiColumnFlowThread() const { - NOT_DESTROYED(); - return false; - } - - bool CreatesNewFormattingContext() const final { - NOT_DESTROYED(); - // The spec requires multicol containers to establish new formatting - // contexts. Blink uses an anonymous flow thread child of the multicol - // container to actually perform layout inside. Therefore we need to - // propagate the BFCness down to the flow thread, so that floats are fully - // contained by the flow thread, and thereby the multicol container. - return true; - } - - // Search mode when looking for an enclosing fragmentation context. - enum AncestorSearchConstraint { - // No constraints. When we're not laying out (but rather e.g. painting or - // hit-testing), we just want to find all enclosing fragmentation contexts, - // e.g. to calculate the accumulated visual translation. - kAnyAncestor, - - // Consider fragmentation contexts that are strictly unbreakable (seen from - // the outside) to be isolated from the rest, so that such fragmentation - // contexts don't participate in fragmentation of enclosing fragmentation - // contexts, apart from taking up space and otherwise being completely - // unbreakable. This is typically what we want to do during layout. - kIsolateUnbreakableContainers, - }; - - static LayoutFlowThread* LocateFlowThreadContainingBlockOf( - const LayoutObject&, - AncestorSearchConstraint); - - PaintLayerType LayerTypeRequired() const final; - - virtual void FlowThreadDescendantWasInserted(LayoutObject*) { - NOT_DESTROYED(); - } - virtual void FlowThreadDescendantWillBeRemoved(LayoutObject*) { - NOT_DESTROYED(); - } - virtual void FlowThreadDescendantStyleWillChange( - LayoutBoxModelObject*, - StyleDifference, - const ComputedStyle& new_style) { - NOT_DESTROYED(); - } - virtual void FlowThreadDescendantStyleDidChange( - LayoutBoxModelObject*, - StyleDifference, - const ComputedStyle& old_style) { - NOT_DESTROYED(); - } - - void QuadsInAncestorForDescendant(const LayoutBox& descendant, - Vector<gfx::QuadF>&, - const LayoutBoxModelObject* ancestor, - MapCoordinatesFlags); - - void AddOutlineRects(OutlineRectCollector&, - OutlineInfo*, - const PhysicalOffset& additional_offset, - OutlineType) const override; - - void Paint(const PaintInfo& paint_info) const final; - - bool NodeAtPoint(HitTestResult&, - const HitTestLocation&, - const PhysicalOffset& accumulated_offset, - HitTestPhase) final; - - virtual void AddColumnSetToThread(LayoutMultiColumnSet*) = 0; - virtual void RemoveColumnSetFromThread(LayoutMultiColumnSet*); - - bool HasColumnSets() const { - NOT_DESTROYED(); - return multi_column_set_list_.size(); - } - - void ValidateColumnSets(); - void InvalidateColumnSets() { - NOT_DESTROYED(); - column_sets_invalidated_ = true; - } - bool HasValidColumnSetInfo() const { - NOT_DESTROYED(); - return !column_sets_invalidated_ && !multi_column_set_list_.empty(); - } - - bool MapToVisualRectInAncestorSpaceInternal( - const LayoutBoxModelObject* ancestor, - TransformState&, - VisualRectFlags = kDefaultVisualRectFlags) const override; - - virtual bool IsPageLogicalHeightKnown() const { - NOT_DESTROYED(); - return true; - } - // Return the visual bounding box based on the supplied flow-thread bounding - // box. Both rectangles are completely physical in terms of writing mode. - PhysicalRect FragmentsBoundingBox( - const PhysicalRect& layer_bounding_box) const; - - virtual PhysicalOffset VisualPointToFlowThreadPoint( - const PhysicalOffset& visual_point) const = 0; - - virtual LayoutMultiColumnSet* ColumnSetAtBlockOffset( - LayoutUnit, - PageBoundaryRule) const = 0; - - const char* GetName() const override = 0; - - RecalcScrollableOverflowResult RecalcScrollableOverflow() final; - - protected: - void GenerateColumnSetIntervalTree(); - - LayoutMultiColumnSetList multi_column_set_list_; - - using MultiColumnSetInterval = PodInterval<LayoutUnit, LayoutMultiColumnSet*>; - using MultiColumnSetIntervalTree = - PodIntervalTree<LayoutUnit, LayoutMultiColumnSet*>; - - class MultiColumnSetSearchAdapter { - STACK_ALLOCATED(); - - public: - MultiColumnSetSearchAdapter(LayoutUnit offset) - : offset_(offset), result_(nullptr) {} - - const LayoutUnit& LowValue() const { return offset_; } - const LayoutUnit& HighValue() const { return offset_; } - void CollectIfNeeded(const MultiColumnSetInterval&); - - LayoutMultiColumnSet* Result() const { return result_; } - - private: - LayoutUnit offset_; - LayoutMultiColumnSet* result_; - }; - - MultiColumnSetIntervalTree multi_column_set_interval_tree_; - - bool column_sets_invalidated_ : 1; -}; - -template <> -struct DowncastTraits<LayoutFlowThread> { - static bool AllowFrom(const LayoutObject& object) { - return object.IsLayoutFlowThread(); - } -}; - -// These structures are used by PodIntervalTree for debugging. -#ifndef NDEBUG -template <> -struct ValueToString<LayoutMultiColumnSet*> { - static String ToString(const LayoutMultiColumnSet* value) { - return String::Format("%p", value); - } -}; -template <> -struct ValueToString<LayoutUnit> { - static String ToString(const LayoutUnit value) { - return String::Number(value.ToFloat()); - } -}; -#endif - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_FLOW_THREAD_H_
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc index 5efd02a..d7fc156 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.cc +++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -50,7 +50,6 @@ #include "third_party/blink/renderer/core/paint/object_painter.h" #include "third_party/blink/renderer/core/paint/outline_painter.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/size_assertions.h" #include "ui/gfx/geometry/quad_f.h" @@ -448,31 +447,11 @@ cursor.MoveToIncludingCulledInline(*this); for (; cursor; cursor.MoveToNextForSameLayoutObject()) { if (!IsInChildRubyText(*this, cursor.Current().GetLayoutObject())) { - PhysicalRect rect; - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - rect = cursor.CurrentRectInFirstContainerFragment(); - } else { - rect = cursor.CurrentRectInBlockFlow(); - } - yield(rect); + yield(cursor.CurrentRectInFirstContainerFragment()); } } } -bool LayoutInline::AbsoluteTransformDependsOnPoint( - const LayoutObject& object) const { - NOT_DESTROYED(); - const LayoutObject* current = &object; - const LayoutObject* container = object.Container(); - while (container) { - if (current->OffsetForContainerDependsOnPoint(container)) - return true; - current = container; - container = container->Container(); - } - return false; -} - void LayoutInline::QuadsInAncestorInternal(Vector<gfx::QuadF>& quads, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode) const { @@ -486,29 +465,12 @@ bool map_to_ancestor) const { NOT_DESTROYED(); std::optional<gfx::Transform> mapping_to_ancestor; - // Set to true if the transform to absolute space depends on the point - // being mapped (in which case we can't use LocalToAncestorTransform). - bool transform_depends_on_point = false; - bool transform_depends_on_point_computed = false; - auto PushAncestorQuad = [&transform_depends_on_point, - &transform_depends_on_point_computed, - &mapping_to_ancestor, &quads, ancestor, mode, + auto PushAncestorQuad = [&mapping_to_ancestor, &quads, ancestor, mode, this](const PhysicalRect& rect) { - if (!transform_depends_on_point_computed) { - transform_depends_on_point_computed = true; - transform_depends_on_point = - !RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled() && - AbsoluteTransformDependsOnPoint(*this); - if (!transform_depends_on_point) - mapping_to_ancestor.emplace(LocalToAncestorTransform(ancestor, mode)); + if (!mapping_to_ancestor) { + mapping_to_ancestor.emplace(LocalToAncestorTransform(ancestor, mode)); } - if (transform_depends_on_point) { - quads.push_back( - LocalToAncestorQuad(gfx::QuadF(gfx::RectF(rect)), ancestor, mode)); - } else { - quads.push_back( - mapping_to_ancestor->MapQuad(gfx::QuadF(gfx::RectF(rect)))); - } + quads.push_back(mapping_to_ancestor->MapQuad(gfx::QuadF(gfx::RectF(rect)))); }; CollectLineBoxRects( @@ -536,9 +498,6 @@ cursor.MoveToIncludingCulledInline(*this); if (!cursor) return std::nullopt; - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return cursor.CurrentOffsetInBlockFlow(); - } return cursor.CurrentOffsetInFirstContainerFragment(); } return std::nullopt; @@ -589,25 +548,8 @@ return AdjustedPositionRelativeTo(FirstLineBoxTopLeft(), parent).top; } -LayoutUnit LayoutInline::OffsetWidth() const { - NOT_DESTROYED(); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return LayoutBoxModelObject::OffsetWidth(); - } - return PhysicalLinesBoundingBox().Width(); -} - -LayoutUnit LayoutInline::OffsetHeight() const { - NOT_DESTROYED(); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return LayoutBoxModelObject::OffsetHeight(); - } - return PhysicalLinesBoundingBox().Height(); -} - PhysicalRect LayoutInline::BoundingBoxRelativeToFirstFragment() const { NOT_DESTROYED(); - DCHECK(RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); DCHECK(IsInLayoutNGInlineFormattingContext()); InlineCursor cursor; cursor.MoveToIncludingCulledInline(*this);
diff --git a/third_party/blink/renderer/core/layout/layout_inline.h b/third_party/blink/renderer/core/layout/layout_inline.h index 1819253..027ea61 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.h +++ b/third_party/blink/renderer/core/layout/layout_inline.h
@@ -236,7 +236,6 @@ MapCoordinatesFlags) const override; private: - bool AbsoluteTransformDependsOnPoint(const LayoutObject& object) const; void QuadsForSelfInternal(Vector<gfx::QuadF>& quads, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode, @@ -297,8 +296,6 @@ LayoutUnit OffsetLeft(const Element*) const final; LayoutUnit OffsetTop(const Element*) const final; - LayoutUnit OffsetWidth() const final; - LayoutUnit OffsetHeight() const final; PhysicalRect BoundingBoxRelativeToFirstFragment() const final;
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc deleted file mode 100644 index 0cd1af4c..0000000 --- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc +++ /dev/null
@@ -1,1154 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS IN..0TERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" - -#include "third_party/blink/renderer/core/css/resolver/style_resolver.h" -#include "third_party/blink/renderer/core/layout/fragmentation_utils.h" -#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h" -#include "third_party/blink/renderer/core/layout/layout_box_utils.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" -#include "third_party/blink/renderer/core/layout/layout_object_inlines.h" -#include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h" -#include "third_party/blink/renderer/core/layout/physical_box_fragment.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" - -namespace blink { - -#if DCHECK_IS_ON() -const LayoutBoxModelObject* LayoutMultiColumnFlowThread::style_changed_object_; -#endif -bool LayoutMultiColumnFlowThread::could_contain_spanners_; -bool LayoutMultiColumnFlowThread::toggle_spanners_if_needed_; - -LayoutMultiColumnFlowThread::LayoutMultiColumnFlowThread() - : last_set_worked_on_(nullptr), - column_count_(1), - is_being_evacuated_(false) { - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); - SetIsInsideMulticol(true); -} - -LayoutMultiColumnFlowThread::~LayoutMultiColumnFlowThread() = default; - -void LayoutMultiColumnFlowThread::Trace(Visitor* visitor) const { - visitor->Trace(last_set_worked_on_); - LayoutFlowThread::Trace(visitor); -} - -LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::CreateAnonymous( - Document& document, - const ComputedStyle& parent_style) { - LayoutMultiColumnFlowThread* layout_object = - MakeGarbageCollected<LayoutMultiColumnFlowThread>(); - layout_object->SetDocumentForAnonymous(&document); - layout_object->SetStyle( - document.GetStyleResolver().CreateAnonymousStyleWithDisplay( - parent_style, EDisplay::kBlock)); - return layout_object; -} - -LayoutMultiColumnSet* LayoutMultiColumnFlowThread::FirstMultiColumnSet() const { - NOT_DESTROYED(); - for (LayoutObject* sibling = NextSibling(); sibling; - sibling = sibling->NextSibling()) { - if (sibling->IsLayoutMultiColumnSet()) - return To<LayoutMultiColumnSet>(sibling); - } - return nullptr; -} - -LayoutMultiColumnSet* LayoutMultiColumnFlowThread::LastMultiColumnSet() const { - NOT_DESTROYED(); - for (LayoutObject* sibling = MultiColumnBlockFlow()->LastChild(); sibling; - sibling = sibling->PreviousSibling()) { - if (sibling->IsLayoutMultiColumnSet()) - return To<LayoutMultiColumnSet>(sibling); - } - return nullptr; -} - -static inline bool IsMultiColumnContainer(const LayoutObject& object) { - auto* block_flow = DynamicTo<LayoutBlockFlow>(object); - if (!block_flow) - return false; - return block_flow->MultiColumnFlowThread(); -} - -// Return true if there's nothing that prevents the specified object from being -// in the ancestor chain between some column spanner and its containing multicol -// container. A column spanner needs the multicol container to be its containing -// block, so that the spanner is able to escape the flow thread. (Everything -// contained by the flow thread is split into columns, but this is precisely -// what shouldn't be done to a spanner, since it's supposed to span all -// columns.) -// -// We require that the parent of the spanner participate in the block formatting -// context established by the multicol container (i.e. that there are no BFCs or -// other formatting contexts in-between). We also require that there be no -// transforms, since transforms insist on being in the containing block chain -// for everything inside it, which conflicts with a spanners's need to have the -// multicol container as its direct containing block. A transform is supposed to -// be a containing block for everything inside, including fixed-positioned -// elements. Letting spanners escape this containment seems strange. See -// https://github.com/w3c/csswg-drafts/issues/6805 -// Finally, we may also not put spanners inside objects that don't support -// fragmentation. -bool LayoutMultiColumnFlowThread::CanContainSpannerInParentFragmentationContext( - const LayoutObject& object) const { - NOT_DESTROYED(); - const auto* block_flow = DynamicTo<LayoutBlockFlow>(object); - if (!block_flow) - return false; - return !block_flow->CreatesNewFormattingContext() && - !block_flow->CanContainFixedPositionObjects() && - !block_flow->IsMonolithic() && !IsMultiColumnContainer(*block_flow); -} - -static inline bool HasAnyColumnSpanners( - const LayoutMultiColumnFlowThread& flow_thread) { - LayoutBox* first_box = flow_thread.FirstMultiColumnBox(); - return first_box && (first_box != flow_thread.LastMultiColumnBox() || - first_box->IsLayoutMultiColumnSpannerPlaceholder()); -} - -// Find the next layout object that has the multicol container in its containing -// block chain, skipping nested multicol containers. -static LayoutObject* NextInPreOrderAfterChildrenSkippingOutOfFlow( - LayoutMultiColumnFlowThread* flow_thread, - LayoutObject* descendant) { - DCHECK(descendant->IsDescendantOf(flow_thread)); - LayoutObject* object = descendant->NextInPreOrderAfterChildren(flow_thread); - while (object) { - // Walk through the siblings and find the first one which is either in-flow - // or has this flow thread as its containing block flow thread. - if (!object->IsOutOfFlowPositioned()) - break; - if (object->ContainingBlock()->FlowThreadContainingBlock() == flow_thread) { - // This out-of-flow object is still part of the flow thread, because its - // containing block (probably relatively positioned) is part of the flow - // thread. - break; - } - object = object->NextInPreOrderAfterChildren(flow_thread); - } - if (!object) - return nullptr; -#if DCHECK_IS_ON() - // Make sure that we didn't stumble into an inner multicol container. - for (LayoutObject* walker = object->Parent(); walker && walker != flow_thread; - walker = walker->Parent()) - DCHECK(!IsMultiColumnContainer(*walker)); -#endif - return object; -} - -// Find the previous layout object that has the multicol container in its -// containing block chain, skipping nested multicol containers. -static LayoutObject* PreviousInPreOrderSkippingOutOfFlow( - LayoutMultiColumnFlowThread* flow_thread, - LayoutObject* descendant) { - DCHECK(descendant->IsDescendantOf(flow_thread)); - LayoutObject* object = descendant->PreviousInPreOrder(flow_thread); - while (object && object != flow_thread) { - if (object->IsColumnSpanAll()) { - LayoutMultiColumnFlowThread* placeholder_flow_thread = - To<LayoutBox>(object)->SpannerPlaceholder()->FlowThread(); - if (placeholder_flow_thread == flow_thread) - break; - // We're inside an inner multicol container. We have no business there. - // Continue on the outside. - object = placeholder_flow_thread->Parent(); - DCHECK(object->IsDescendantOf(flow_thread)); - continue; - } - if (object->FlowThreadContainingBlock() == flow_thread) { - LayoutObject* ancestor; - for (ancestor = object->Parent();; ancestor = ancestor->Parent()) { - if (ancestor == flow_thread) - return object; - if (IsMultiColumnContainer(*ancestor)) { - // We're inside an inner multicol container. We have no business - // there. - break; - } - } - object = ancestor; - DCHECK(ancestor->IsDescendantOf(flow_thread)); - continue; // Continue on the outside of the inner flow thread. - } - // We're inside something that's out-of-flow. Keep looking upwards and - // backwards in the tree. - object = object->PreviousInPreOrder(flow_thread); - } - if (!object || object == flow_thread) - return nullptr; -#if DCHECK_IS_ON() - // Make sure that we didn't stumble into an inner multicol container. - for (LayoutObject* walker = object->Parent(); walker && walker != flow_thread; - walker = walker->Parent()) - DCHECK(!IsMultiColumnContainer(*walker)); -#endif - return object; -} - -static LayoutObject* FirstLayoutObjectInSet( - LayoutMultiColumnSet* multicol_set) { - LayoutBox* sibling = multicol_set->PreviousSiblingMultiColumnBox(); - if (!sibling) - return multicol_set->FlowThread()->FirstChild(); - // Adjacent column content sets should not occur. We would have no way of - // figuring out what each of them contains then. - CHECK(sibling->IsLayoutMultiColumnSpannerPlaceholder()); - LayoutBox* spanner = To<LayoutMultiColumnSpannerPlaceholder>(sibling) - ->LayoutObjectInFlowThread(); - return NextInPreOrderAfterChildrenSkippingOutOfFlow( - multicol_set->MultiColumnFlowThread(), spanner); -} - -static LayoutObject* LastLayoutObjectInSet(LayoutMultiColumnSet* multicol_set) { - LayoutBox* sibling = multicol_set->NextSiblingMultiColumnBox(); - // By right we should return lastLeafChild() here, but the caller doesn't - // care, so just return nullptr. - if (!sibling) - return nullptr; - // Adjacent column content sets should not occur. We would have no way of - // figuring out what each of them contains then. - CHECK(sibling->IsLayoutMultiColumnSpannerPlaceholder()); - LayoutBox* spanner = To<LayoutMultiColumnSpannerPlaceholder>(sibling) - ->LayoutObjectInFlowThread(); - return PreviousInPreOrderSkippingOutOfFlow( - multicol_set->MultiColumnFlowThread(), spanner); -} - -LayoutMultiColumnSet* LayoutMultiColumnFlowThread::MapDescendantToColumnSet( - LayoutObject* layout_object) const { - NOT_DESTROYED(); - // Should not be used for spanners or content inside them. - DCHECK(!ContainingColumnSpannerPlaceholder(layout_object)); - DCHECK_NE(layout_object, this); - DCHECK(layout_object->IsDescendantOf(this)); - // Out-of-flow objects don't belong in column sets. DHCECK that the object is - // contained by the flow thread, except for legends ("rendered" or - // not). Although a rendered legend isn't part of the fragmentation context, - // we'll let it contribute to creation of a column set, for the sake of - // simplicity. Style and DOM changes may later on change which LEGEND child is - // the rendered legend, and we don't want to keep track of that. - DCHECK(layout_object->IsRenderedLegend() || - layout_object->ContainingBlock()->IsDescendantOf(this)); - DCHECK_EQ(layout_object->FlowThreadContainingBlock(), this); - DCHECK(!layout_object->IsLayoutMultiColumnSet()); - DCHECK(!layout_object->IsLayoutMultiColumnSpannerPlaceholder()); - LayoutMultiColumnSet* multicol_set = FirstMultiColumnSet(); - if (!multicol_set) - return nullptr; - if (!multicol_set->NextSiblingMultiColumnSet()) - return multicol_set; - - // This is potentially SLOW! But luckily very uncommon. You would have to - // dynamically insert a spanner into the middle of column contents to need - // this. - for (; multicol_set; - multicol_set = multicol_set->NextSiblingMultiColumnSet()) { - LayoutObject* first_layout_object = FirstLayoutObjectInSet(multicol_set); - LayoutObject* last_layout_object = LastLayoutObjectInSet(multicol_set); - DCHECK(first_layout_object); - - for (LayoutObject* walker = first_layout_object; walker; - walker = walker->NextInPreOrder(this)) { - if (walker == layout_object) - return multicol_set; - if (walker == last_layout_object) - break; - } - } - - return nullptr; -} - -LayoutMultiColumnSpannerPlaceholder* -LayoutMultiColumnFlowThread::ContainingColumnSpannerPlaceholder( - const LayoutObject* descendant) const { - NOT_DESTROYED(); - DCHECK(descendant->IsDescendantOf(this)); - - if (!HasAnyColumnSpanners(*this)) - return nullptr; - - // We have spanners. See if the layoutObject in question is one or inside of - // one then. - for (const LayoutObject* ancestor = descendant; ancestor && ancestor != this; - ancestor = ancestor->Parent()) { - if (LayoutMultiColumnSpannerPlaceholder* placeholder = - ancestor->SpannerPlaceholder()) - return placeholder; - } - return nullptr; -} - -void LayoutMultiColumnFlowThread::Populate() { - NOT_DESTROYED(); - LayoutBlockFlow* multicol_container = MultiColumnBlockFlow(); - DCHECK(!NextSibling()); - // Reparent children preceding the flow thread into the flow thread. It's - // multicol content now. At this point there's obviously nothing after the - // flow thread, but layoutObjects (column sets and spanners) will be inserted - // there as we insert elements into the flow thread. - multicol_container->MoveChildrenTo(this, multicol_container->FirstChild(), - this, true); -} - -void LayoutMultiColumnFlowThread::EvacuateAndDestroy() { - NOT_DESTROYED(); - LayoutBlockFlow* multicol_container = MultiColumnBlockFlow(); - is_being_evacuated_ = true; - - // Remove all sets and spanners. - while (LayoutBox* column_box = FirstMultiColumnBox()) { - DCHECK(column_box->IsAnonymous()); - column_box->Destroy(); - } - - DCHECK(!PreviousSibling()); - DCHECK(!NextSibling()); - - // Finally we can promote all flow thread's children. Before we move them to - // the flow thread's container, we need to unregister the flow thread, so that - // they aren't just re-added again to the flow thread that we're trying to - // empty. - multicol_container->ResetMultiColumnFlowThread(); - MoveAllChildrenIncludingFloatsTo(multicol_container, true); - - Destroy(); -} - -PhysicalOffset LayoutMultiColumnFlowThread::ColumnOffset( - const PhysicalOffset& point) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return FlowThreadTranslationAtPoint(point); -} - -bool LayoutMultiColumnFlowThread::IsPageLogicalHeightKnown() const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return all_columns_have_known_height_; -} - -PhysicalOffset LayoutMultiColumnFlowThread::FlowThreadTranslationAtOffset( - LayoutUnit offset_in_flow_thread, - PageBoundaryRule rule) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - if (!HasValidColumnSetInfo()) - return PhysicalOffset(); - LayoutMultiColumnSet* column_set = - ColumnSetAtBlockOffset(offset_in_flow_thread, rule); - if (!column_set) - return PhysicalOffset(); - return column_set->FlowThreadTranslationAtOffset(offset_in_flow_thread, rule); -} - -PhysicalOffset LayoutMultiColumnFlowThread::FlowThreadTranslationAtPoint( - const PhysicalOffset& flow_thread_point) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - LayoutUnit block_offset = CreateWritingModeConverter() - .ToLogical(flow_thread_point, {}) - .block_offset; - - // If block direction is flipped, points at a column boundary belong in the - // former column, not the latter. - PageBoundaryRule rule = HasFlippedBlocksWritingMode() - ? kAssociateWithFormerPage - : kAssociateWithLatterPage; - - return FlowThreadTranslationAtOffset(block_offset, rule); -} - -PhysicalOffset LayoutMultiColumnFlowThread::VisualPointToFlowThreadPoint( - const PhysicalOffset& visual_point) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - WritingModeConverter converter( - {StyleRef().GetWritingMode(), TextDirection::kLtr}, Size()); - LayoutUnit block_offset = converter.ToLogical(visual_point, {}).block_offset; - const LayoutMultiColumnSet* column_set = nullptr; - for (const LayoutMultiColumnSet* candidate = FirstMultiColumnSet(); candidate; - candidate = candidate->NextSiblingMultiColumnSet()) { - column_set = candidate; - if (candidate->LogicalRectInContainer().BlockEndOffset() > block_offset) { - break; - } - } - if (!column_set) { - return visual_point; - } - const PhysicalOffset flow_thread_offset = PhysicalLocation(); - const PhysicalOffset column_set_offset = column_set->PhysicalLocation(); - const PhysicalOffset point_in_set = - visual_point + flow_thread_offset - column_set_offset; - return converter.ToPhysical( - column_set->VisualPointToFlowThreadPoint(point_in_set), {}); -} - -LayoutMultiColumnSet* LayoutMultiColumnFlowThread::ColumnSetAtBlockOffset( - LayoutUnit offset, - PageBoundaryRule page_boundary_rule) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - LayoutMultiColumnSet* column_set = last_set_worked_on_; - if (column_set) { - // Layout in progress. We are calculating the set heights as we speak, so - // the column set range information is not up to date. - while (column_set->LogicalTopInFlowThread() > offset) { - // Sometimes we have to use a previous set. This happens when we're - // working with a block that contains a spanner (so that there's a column - // set both before and after the spanner, and both sets contain said - // block). - LayoutMultiColumnSet* previous_set = - column_set->PreviousSiblingMultiColumnSet(); - if (!previous_set) - break; - column_set = previous_set; - } - } else { - DCHECK(!column_sets_invalidated_); - if (multi_column_set_list_.empty()) - return nullptr; - if (offset < LayoutUnit()) { - column_set = multi_column_set_list_.front(); - } else { - MultiColumnSetSearchAdapter adapter(offset); - multi_column_set_interval_tree_ - .AllOverlapsWithAdapter<MultiColumnSetSearchAdapter>(adapter); - - // If no set was found, the offset is in the flow thread overflow. - if (!adapter.Result() && !multi_column_set_list_.empty()) - column_set = multi_column_set_list_.back(); - else - column_set = adapter.Result(); - } - } - if (page_boundary_rule == kAssociateWithFormerPage && column_set && - offset == column_set->LogicalTopInFlowThread()) { - // The column set that we found starts at the exact same flow thread offset - // as we specified. Since we are to associate offsets at boundaries with the - // former fragmentainer, the fragmentainer we're looking for is in the - // previous column set. - if (LayoutMultiColumnSet* previous_set = - column_set->PreviousSiblingMultiColumnSet()) - column_set = previous_set; - } - // Avoid returning zero-height column sets, if possible. We found a column set - // based on a flow thread coordinate. If multiple column sets share that - // coordinate (because we have zero-height column sets between column - // spanners, for instance), look for one that has a height. Also look ahead to - // find a set that actually contains the coordinate. Note that when we do this - // during layout, it means that we might return a column set that hasn't got - // its flow thread boundaries updated yet (and thus using those from the - // previous layout), but that's the best we can do when our engine doesn't - // actually understand fragmentation. This may happen when there's a float - // that's split into multiple fragments because of column spanners, and we - // still perform all its layout at the position before the first spanner in - // question (i.e. where only the first fragment is supposed to be laid out). - for (LayoutMultiColumnSet* walker = column_set; walker; - walker = walker->NextSiblingMultiColumnSet()) { - if (!walker->IsPageLogicalHeightKnown()) - continue; - if (page_boundary_rule == kAssociateWithFormerPage) { - if (walker->LogicalTopInFlowThread() < offset && - walker->LogicalBottomInFlowThread() >= offset) - return walker; - } else if (walker->LogicalTopInFlowThread() <= offset && - walker->LogicalBottomInFlowThread() > offset) { - return walker; - } - } - return column_set; -} - -void LayoutMultiColumnFlowThread::ColumnRuleStyleDidChange() { - NOT_DESTROYED(); - for (LayoutMultiColumnSet* column_set = FirstMultiColumnSet(); column_set; - column_set = column_set->NextSiblingMultiColumnSet()) { - column_set->SetShouldDoFullPaintInvalidation(); - } -} - -bool LayoutMultiColumnFlowThread::RemoveSpannerPlaceholderIfNoLongerValid( - LayoutBox* spanner_object_in_flow_thread) { - NOT_DESTROYED(); - DCHECK(spanner_object_in_flow_thread->SpannerPlaceholder()); - if (DescendantIsValidColumnSpanner(spanner_object_in_flow_thread)) - return false; // Still a valid spanner. - - // No longer a valid spanner. Get rid of the placeholder. - DestroySpannerPlaceholder( - spanner_object_in_flow_thread->SpannerPlaceholder()); - DCHECK(!spanner_object_in_flow_thread->SpannerPlaceholder()); - - // We may have a new containing block, since we're no longer a spanner. Mark - // it for relayout. - spanner_object_in_flow_thread->ContainingBlock() - ->SetNeedsLayoutAndIntrinsicWidthsRecalc( - layout_invalidation_reason::kColumnsChanged); - - // Now generate a column set for this ex-spanner, if needed and none is there - // for us already. - FlowThreadDescendantWasInserted(spanner_object_in_flow_thread); - - return true; -} - -LayoutMultiColumnFlowThread* LayoutMultiColumnFlowThread::EnclosingFlowThread( - AncestorSearchConstraint constraint) const { - NOT_DESTROYED(); - if (!MultiColumnBlockFlow()->IsInsideMulticol()) { - return nullptr; - } - return To<LayoutMultiColumnFlowThread>( - LocateFlowThreadContainingBlockOf(*MultiColumnBlockFlow(), constraint)); -} - -void LayoutMultiColumnFlowThread::SetColumnCountFromNG(unsigned column_count) { - NOT_DESTROYED(); - column_count_ = column_count; -} - -void LayoutMultiColumnFlowThread::FinishLayoutFromNG( - LayoutUnit flow_thread_offset) { - NOT_DESTROYED(); - all_columns_have_known_height_ = true; - for (LayoutBox* column_box = FirstMultiColumnBox(); column_box; - column_box = column_box->NextSiblingMultiColumnBox()) { - column_box->ClearNeedsLayout(); - } - - ValidateColumnSets(); - ClearNeedsLayout(); - last_set_worked_on_ = nullptr; -} - -void LayoutMultiColumnFlowThread::CreateAndInsertMultiColumnSet( - LayoutBox* insert_before) { - NOT_DESTROYED(); - LayoutBlockFlow* multicol_container = MultiColumnBlockFlow(); - LayoutMultiColumnSet* new_set = LayoutMultiColumnSet::CreateAnonymous( - *this, multicol_container->StyleRef()); - multicol_container->LayoutBlock::AddChild(new_set, insert_before); - InvalidateColumnSets(); - - // We cannot handle immediate column set siblings (and there's no need for it, - // either). There has to be at least one spanner separating them. - DCHECK(!new_set->PreviousSiblingMultiColumnBox() || - !new_set->PreviousSiblingMultiColumnBox()->IsLayoutMultiColumnSet()); - DCHECK(!new_set->NextSiblingMultiColumnBox() || - !new_set->NextSiblingMultiColumnBox()->IsLayoutMultiColumnSet()); -} - -void LayoutMultiColumnFlowThread::CreateAndInsertSpannerPlaceholder( - LayoutBox* spanner_object_in_flow_thread, - LayoutObject* inserted_before_in_flow_thread) { - NOT_DESTROYED(); - LayoutBox* insert_before_column_box = nullptr; - LayoutMultiColumnSet* set_to_split = nullptr; - if (inserted_before_in_flow_thread) { - // The spanner is inserted before something. Figure out what this entails. - // If the next object is a spanner too, it means that we can simply insert a - // new spanner placeholder in front of its placeholder. - insert_before_column_box = - inserted_before_in_flow_thread->SpannerPlaceholder(); - if (!insert_before_column_box) { - // The next object isn't a spanner; it's regular column content. Examine - // what comes right before us in the flow thread, then. - LayoutObject* previous_layout_object = - PreviousInPreOrderSkippingOutOfFlow(this, - spanner_object_in_flow_thread); - if (!previous_layout_object || previous_layout_object == this) { - // The spanner is inserted as the first child of the multicol container, - // which means that we simply insert a new spanner placeholder at the - // beginning. - insert_before_column_box = FirstMultiColumnBox(); - } else if (LayoutMultiColumnSpannerPlaceholder* previous_placeholder = - ContainingColumnSpannerPlaceholder( - previous_layout_object)) { - // Before us is another spanner. We belong right after it then. - insert_before_column_box = - previous_placeholder->NextSiblingMultiColumnBox(); - } else { - // We're inside regular column content with both feet. Find out which - // column set this is. It needs to be split it into two sets, so that we - // can insert a new spanner placeholder between them. - set_to_split = MapDescendantToColumnSet(previous_layout_object); - DCHECK_EQ(set_to_split, - MapDescendantToColumnSet(inserted_before_in_flow_thread)); - insert_before_column_box = set_to_split->NextSiblingMultiColumnBox(); - // We've found out which set that needs to be split. Now proceed to - // inserting the spanner placeholder, and then insert a second column - // set. - } - } - DCHECK(set_to_split || insert_before_column_box); - } - - LayoutBlockFlow* multicol_container = MultiColumnBlockFlow(); - LayoutMultiColumnSpannerPlaceholder* new_placeholder = - LayoutMultiColumnSpannerPlaceholder::CreateAnonymous( - multicol_container->StyleRef(), *spanner_object_in_flow_thread); - DCHECK(!insert_before_column_box || - insert_before_column_box->Parent() == multicol_container); - multicol_container->LayoutBlock::AddChild(new_placeholder, - insert_before_column_box); - spanner_object_in_flow_thread->SetSpannerPlaceholder(*new_placeholder); - - if (set_to_split) - CreateAndInsertMultiColumnSet(insert_before_column_box); -} - -void LayoutMultiColumnFlowThread::DestroySpannerPlaceholder( - LayoutMultiColumnSpannerPlaceholder* placeholder) { - NOT_DESTROYED(); - if (LayoutBox* next_column_box = placeholder->NextSiblingMultiColumnBox()) { - LayoutBox* previous_column_box = - placeholder->PreviousSiblingMultiColumnBox(); - if (next_column_box && next_column_box->IsLayoutMultiColumnSet() && - previous_column_box && previous_column_box->IsLayoutMultiColumnSet()) { - // Need to merge two column sets. - next_column_box->Destroy(); - InvalidateColumnSets(); - } - } - placeholder->Destroy(); -} - -bool LayoutMultiColumnFlowThread::DescendantIsValidColumnSpanner( - LayoutObject* descendant) const { - NOT_DESTROYED(); - // This method needs to behave correctly in the following situations: - // - When the descendant doesn't have a spanner placeholder but should have - // one (return true). - // - When the descendant doesn't have a spanner placeholder and still should - // not have one (return false). - // - When the descendant has a spanner placeholder but should no longer have - // one (return false). - // - When the descendant has a spanner placeholder and should still have one - // (return true). - - // We assume that we're inside the flow thread. This function is not to be - // called otherwise. - DCHECK(descendant->IsDescendantOf(this)); - - // The spec says that column-span only applies to in-flow block-level - // elements. - if (descendant->StyleRef().GetColumnSpan() != EColumnSpan::kAll || - !descendant->IsBox() || descendant->IsInline() || - descendant->IsFloatingOrOutOfFlowPositioned()) - return false; - - if (!descendant->ContainingBlock()->IsLayoutBlockFlow()) { - // Needs to be in a block-flow container, and not e.g. a table. - return false; - } - - // This looks like a spanner, but if we're inside something unbreakable or - // something that establishes a new formatting context, it's not to be treated - // as one. - for (LayoutBox* ancestor = To<LayoutBox>(descendant)->ParentBox(); ancestor; - ancestor = ancestor->ContainingBlock()) { - if (ancestor->IsLayoutFlowThread()) { - DCHECK_EQ(ancestor, this); - return true; - } - if (!CanContainSpannerInParentFragmentationContext(*ancestor)) - return false; - } - NOTREACHED(); -} - -void LayoutMultiColumnFlowThread::AddColumnSetToThread( - LayoutMultiColumnSet* column_set) { - NOT_DESTROYED(); - if (LayoutMultiColumnSet* next_set = - column_set->NextSiblingMultiColumnSet()) { - LayoutMultiColumnSetList::iterator it = - multi_column_set_list_.find(next_set); - CHECK(it != multi_column_set_list_.end()); - multi_column_set_list_.InsertBefore(it, column_set); - } else { - multi_column_set_list_.insert(column_set); - } -} - -void LayoutMultiColumnFlowThread::WillBeRemovedFromTree() { - NOT_DESTROYED(); - // Detach all column sets from the flow thread. Cannot destroy them at this - // point, since they are siblings of this object, and there may be pointers to - // this object's sibling somewhere further up on the call stack. - for (LayoutMultiColumnSet* column_set = FirstMultiColumnSet(); column_set; - column_set = column_set->NextSiblingMultiColumnSet()) - column_set->DetachFromFlowThread(); - MultiColumnBlockFlow()->ResetMultiColumnFlowThread(); - LayoutFlowThread::WillBeRemovedFromTree(); -} - -// When processing layout objects to remove or when processing layout objects -// that have just been inserted, certain types of objects should be skipped. -static bool ShouldSkipInsertedOrRemovedChild( - LayoutMultiColumnFlowThread* flow_thread, - const LayoutObject& child) { - if (child.IsSVGChild()) { - // Don't descend into SVG objects. What's in there is of no interest, and - // there might even be a foreignObject there with column-span:all, which - // doesn't apply to us. - return true; - } - if (child.IsLayoutFlowThread()) { - // Found an inner flow thread. We need to skip it and its descendants. - return true; - } - if (child.IsLayoutMultiColumnSet() || - child.IsLayoutMultiColumnSpannerPlaceholder()) { - // Column sets and spanner placeholders in a child multicol context don't - // affect the parent flow thread. - return true; - } - if (child.IsOutOfFlowPositioned() && - child.ContainingBlock()->FlowThreadContainingBlock() != flow_thread) { - // Out-of-flow with its containing block on the outside of the multicol - // container. - return true; - } - return false; -} - -void LayoutMultiColumnFlowThread::FlowThreadDescendantWasInserted( - LayoutObject* descendant) { - NOT_DESTROYED(); - DCHECK(!is_being_evacuated_); - // This method ensures that the list of column sets and spanner placeholders - // reflects the multicol content after having inserted a descendant (or - // descendant subtree). See the header file for more information. Go through - // the subtree that was just inserted and create column sets (needed by - // regular column content) and spanner placeholders (one needed by each - // spanner) where needed. - if (ShouldSkipInsertedOrRemovedChild(this, *descendant)) - return; - LayoutObject* object_after_subtree = - NextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant); - LayoutObject* next; - for (LayoutObject* layout_object = descendant; layout_object; - layout_object = next) { - if (layout_object != descendant && - ShouldSkipInsertedOrRemovedChild(this, *layout_object)) { - next = layout_object->NextInPreOrderAfterChildren(descendant); - continue; - } - next = layout_object->NextInPreOrder(descendant); - if (ContainingColumnSpannerPlaceholder(layout_object)) - continue; // Inside a column spanner. Nothing to do, then. - if (DescendantIsValidColumnSpanner(layout_object)) { - // This layoutObject is a spanner, so it needs to establish a spanner - // placeholder. - CreateAndInsertSpannerPlaceholder(To<LayoutBox>(layout_object), - object_after_subtree); - continue; - } - // This layoutObject is regular column content (i.e. not a spanner). Create - // a set if necessary. - if (object_after_subtree) { - if (LayoutMultiColumnSpannerPlaceholder* placeholder = - object_after_subtree->SpannerPlaceholder()) { - // If inserted right before a spanner, we need to make sure that there's - // a set for us there. - LayoutBox* previous = placeholder->PreviousSiblingMultiColumnBox(); - if (!previous || !previous->IsLayoutMultiColumnSet()) - CreateAndInsertMultiColumnSet(placeholder); - } else { - // Otherwise, since |objectAfterSubtree| isn't a spanner, it has to mean - // that there's already a set for that content. We can use it for this - // layoutObject too. - DCHECK(MapDescendantToColumnSet(object_after_subtree)); - DCHECK_EQ(MapDescendantToColumnSet(layout_object), - MapDescendantToColumnSet(object_after_subtree)); - } - } else { - // Inserting at the end. Then we just need to make sure that there's a - // column set at the end. - LayoutBox* last_column_box = LastMultiColumnBox(); - if (!last_column_box || !last_column_box->IsLayoutMultiColumnSet()) - CreateAndInsertMultiColumnSet(); - } - } -} - -void LayoutMultiColumnFlowThread::FlowThreadDescendantWillBeRemoved( - LayoutObject* descendant) { - NOT_DESTROYED(); - // This method ensures that the list of column sets and spanner placeholders - // reflects the multicol content that we'll be left with after removal of a - // descendant (or descendant subtree). See the header file for more - // information. Removing content may mean that we need to remove column sets - // and/or spanner placeholders. - if (is_being_evacuated_) - return; - if (ShouldSkipInsertedOrRemovedChild(this, *descendant)) - return; - bool had_containing_placeholder = - ContainingColumnSpannerPlaceholder(descendant); - bool processed_something = false; - LayoutObject* next; - // Remove spanner placeholders that are no longer needed, and merge column - // sets around them. - for (LayoutObject* layout_object = descendant; layout_object; - layout_object = next) { - if (layout_object != descendant && - ShouldSkipInsertedOrRemovedChild(this, *layout_object)) { - next = layout_object->NextInPreOrderAfterChildren(descendant); - continue; - } - processed_something = true; - LayoutMultiColumnSpannerPlaceholder* placeholder = - layout_object->SpannerPlaceholder(); - if (!placeholder) { - next = layout_object->NextInPreOrder(descendant); - continue; - } - next = layout_object->NextInPreOrderAfterChildren( - descendant); // It's a spanner. Its children are of no interest to us. - DestroySpannerPlaceholder(placeholder); - } - if (had_containing_placeholder || !processed_something) - return; // No column content will be removed, so we can stop here. - - // Column content will be removed. Does this mean that we should destroy a - // column set? - LayoutMultiColumnSpannerPlaceholder* adjacent_previous_spanner_placeholder = - nullptr; - LayoutObject* previous_layout_object = - PreviousInPreOrderSkippingOutOfFlow(this, descendant); - if (previous_layout_object && previous_layout_object != this) { - adjacent_previous_spanner_placeholder = - ContainingColumnSpannerPlaceholder(previous_layout_object); - if (!adjacent_previous_spanner_placeholder) - return; // Preceded by column content. Set still needed. - } - LayoutMultiColumnSpannerPlaceholder* adjacent_next_spanner_placeholder = - nullptr; - LayoutObject* next_layout_object = - NextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant); - if (next_layout_object) { - adjacent_next_spanner_placeholder = - ContainingColumnSpannerPlaceholder(next_layout_object); - if (!adjacent_next_spanner_placeholder) - return; // Followed by column content. Set still needed. - } - // We have now determined that, with the removal of |descendant|, we should - // remove a column set. Locate it and remove it. Do it without involving - // mapDescendantToColumnSet(), as that might be very slow. Deduce the right - // set from the spanner placeholders that we've already found. - LayoutMultiColumnSet* column_set_to_remove; - if (adjacent_next_spanner_placeholder) { - LayoutBox* sibling = - adjacent_next_spanner_placeholder->PreviousSiblingMultiColumnBox(); - CHECK(sibling->IsLayoutMultiColumnSet()); - column_set_to_remove = To<LayoutMultiColumnSet>(sibling); - DCHECK( - !adjacent_previous_spanner_placeholder || - column_set_to_remove == - adjacent_previous_spanner_placeholder->NextSiblingMultiColumnBox()); - } else if (adjacent_previous_spanner_placeholder) { - LayoutBox* sibling = - adjacent_previous_spanner_placeholder->NextSiblingMultiColumnBox(); - CHECK(sibling->IsLayoutMultiColumnSet()); - column_set_to_remove = To<LayoutMultiColumnSet>(sibling); - } else { - // If there were no adjacent spanners, it has to mean that there's only one - // column set, since it's only spanners that may cause creation of - // multiple sets. - column_set_to_remove = FirstMultiColumnSet(); - DCHECK(column_set_to_remove); - DCHECK(!column_set_to_remove->NextSiblingMultiColumnSet()); - } - DCHECK(column_set_to_remove); - column_set_to_remove->Destroy(); -} - -static inline bool NeedsToReinsertIntoFlowThread( - const LayoutBoxModelObject& object, - const ComputedStyle& old_style, - const ComputedStyle& new_style) { - // If we've become (or are about to become) a container for absolutely - // positioned descendants, or if we're no longer going to be one, we need to - // re-evaluate the need for column sets. There may be out-of-flow descendants - // further down that become part of the flow thread, or cease to be part of - // the flow thread, because of this change. - if (object.ComputeIsFixedContainer(old_style) != - object.ComputeIsFixedContainer(new_style)) { - return true; - } - return old_style.GetPosition() != new_style.GetPosition(); -} - -static inline bool NeedsToRemoveFromFlowThread( - const LayoutBoxModelObject& object, - const ComputedStyle& old_style, - const ComputedStyle& new_style) { - // This function is called BEFORE computed style update. If an in-flow - // descendant goes out-of-flow, we may have to remove column sets and spanner - // placeholders. Note that we may end up with false positives here, since some - // out-of-flow descendants still need to be associated with a column set. This - // is the case when the containing block of the soon-to-be out-of-flow - // positioned descendant is contained by the same flow thread as the - // descendant currently is inside. It's too early to check for that, though, - // since the descendant at this point is still in-flow positioned. We'll - // detect this and re-insert it into the flow thread when computed style has - // been updated. - return (new_style.HasOutOfFlowPosition() && - !old_style.HasOutOfFlowPosition()) || - NeedsToReinsertIntoFlowThread(object, old_style, new_style); -} - -static inline bool NeedsToInsertIntoFlowThread( - const LayoutMultiColumnFlowThread* flow_thread, - const LayoutBoxModelObject* descendant, - const ComputedStyle& old_style, - const ComputedStyle& new_style) { - // This function is called AFTER computed style update. If an out-of-flow - // descendant goes in-flow, we may have to insert column sets and spanner - // placeholders. - bool toggled_out_of_flow = - new_style.HasOutOfFlowPosition() != old_style.HasOutOfFlowPosition(); - if (toggled_out_of_flow) { - // If we're no longer out-of-flow, we definitely need the descendant to be - // associated with a column set. - if (!new_style.HasOutOfFlowPosition()) - return true; - const auto* containing_flow_thread = - descendant->ContainingBlock()->FlowThreadContainingBlock(); - // If an out-of-flow positioned descendant is still going to be contained by - // this flow thread, the descendant needs to be associated with a column - // set. - if (containing_flow_thread == flow_thread) - return true; - } - return NeedsToReinsertIntoFlowThread(*flow_thread, old_style, new_style); -} - -void LayoutMultiColumnFlowThread::FlowThreadDescendantStyleWillChange( - LayoutBoxModelObject* descendant, - StyleDifference diff, - const ComputedStyle& new_style) { - NOT_DESTROYED(); - toggle_spanners_if_needed_ = false; - if (NeedsToRemoveFromFlowThread(*descendant, descendant->StyleRef(), - new_style)) { - FlowThreadDescendantWillBeRemoved(descendant); -#if DCHECK_IS_ON() - style_changed_object_ = nullptr; -#endif - return; - } -#if DCHECK_IS_ON() - style_changed_object_ = descendant; -#endif - // Keep track of whether this object was of such a type that it could contain - // column-span:all descendants. If the style change in progress changes this - // state, we need to look for spanners to add or remove in the subtree of - // |descendant|. - toggle_spanners_if_needed_ = true; - could_contain_spanners_ = - CanContainSpannerInParentFragmentationContext(*descendant); -} - -void LayoutMultiColumnFlowThread::FlowThreadDescendantStyleDidChange( - LayoutBoxModelObject* descendant, - StyleDifference diff, - const ComputedStyle& old_style) { - NOT_DESTROYED(); - -#if DCHECK_IS_ON() - const auto* style_changed_box = style_changed_object_; - style_changed_object_ = nullptr; -#endif - - bool toggle_spanners_if_needed = toggle_spanners_if_needed_; - toggle_spanners_if_needed_ = false; - - if (NeedsToInsertIntoFlowThread(this, descendant, old_style, - descendant->StyleRef())) { - FlowThreadDescendantWasInserted(descendant); - return; - } - if (DescendantIsValidColumnSpanner(descendant)) { - // We went from being regular column content to becoming a spanner. - DCHECK(!descendant->SpannerPlaceholder()); - - // First remove this as regular column content. Note that this will walk the - // entire subtree of |descendant|. There might be spanners there (which - // won't be spanners anymore, since we're not allowed to nest spanners), - // whose placeholders must die. - FlowThreadDescendantWillBeRemoved(descendant); - - CreateAndInsertSpannerPlaceholder( - To<LayoutBox>(descendant), - NextInPreOrderAfterChildrenSkippingOutOfFlow(this, descendant)); - return; - } - - if (!toggle_spanners_if_needed) - return; - - if (could_contain_spanners_ == - CanContainSpannerInParentFragmentationContext(*descendant)) - return; - -#if DCHECK_IS_ON() - // Make sure that we were preceded by a call to - // flowThreadDescendantStyleWillChange() with the same descendant as we have - // now. - if (style_changed_box) - DCHECK_EQ(style_changed_box, descendant); -#endif - - ToggleSpannersInSubtree(descendant); -} - -void LayoutMultiColumnFlowThread::ToggleSpannersInSubtree( - LayoutBoxModelObject* descendant) { - NOT_DESTROYED(); - DCHECK_NE(could_contain_spanners_, - CanContainSpannerInParentFragmentationContext(*descendant)); - - // If there are no spanners at all in this multicol container, there's no - // need to look for any to remove. - if (could_contain_spanners_ && !HasAnyColumnSpanners(*this)) - return; - - bool walk_children; - for (LayoutObject* object = descendant->NextInPreOrder(descendant); object; - object = walk_children - ? object->NextInPreOrder(descendant) - : object->NextInPreOrderAfterChildren(descendant)) { - walk_children = false; - if (!object->IsBox()) - continue; - auto& box = To<LayoutBox>(*object); - if (could_contain_spanners_) { - // Remove all spanners (turn them into regular column content), as we can - // no longer contain them. - if (box.IsColumnSpanAll()) { - DestroySpannerPlaceholder(box.SpannerPlaceholder()); - continue; - } - } else if (DescendantIsValidColumnSpanner(object)) { - // We can now contain spanners, and we found a candidate. Turn it into a - // spanner, if it's not already one. We have to check if it's already a - // spanner, because in some cases we incorrectly think that we need to - // toggle spanners. One known case is when some ancestor changes - // writing-mode (which is an inherited property). Writing mode roots - // establish block formatting context (which means that there can be no - // column spanners inside). When changing the style on one object in the - // tree at a time, we're going to see writing mode roots that are not - // going to remain writing mode roots when all objects have been updated - // (because then all will have got the same writing mode). - if (!box.IsColumnSpanAll()) { - CreateAndInsertSpannerPlaceholder( - &box, NextInPreOrderAfterChildrenSkippingOutOfFlow(this, &box)); - } - continue; - } - walk_children = CanContainSpannerInParentFragmentationContext(box); - } -} - -DeprecatedLayoutPoint LayoutMultiColumnFlowThread::DeprecatedLocationInternal() - const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - if (!HasValidCachedGeometry() && EverHadLayout()) { - // const_cast in order to update the cached value. - const_cast<LayoutMultiColumnFlowThread*>(this)->UpdateGeometry(); - } - return frame_location_.layout_point; -} - -PhysicalSize LayoutMultiColumnFlowThread::Size() const { - NOT_DESTROYED(); - if (!HasValidCachedGeometry() && EverHadLayout()) { - // const_cast in order to update the cached value. - const_cast<LayoutMultiColumnFlowThread*>(this)->UpdateGeometry(); - } - return frame_size_; -} - -void LayoutMultiColumnFlowThread::UpdateGeometry() { - NOT_DESTROYED(); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - // Nobody cares. - return; - } - SetHasValidCachedGeometry(true); - frame_location_.layout_point = DeprecatedLayoutPoint(); - LogicalSize thread_size; - const LayoutBlockFlow* container = MultiColumnBlockFlow(); - if (container->PhysicalFragmentCount() == 0u) { - frame_size_ = PhysicalSize(); - return; - } - const auto* first_fragment = container->GetPhysicalFragment(0); - WritingModeConverter converter(first_fragment->Style().GetWritingDirection()); - bool has_processed_first_column_in_flow_thread = false; - const BlockBreakToken* break_token = nullptr; - for (const auto& container_fragment : container->PhysicalFragments()) { - for (const auto& link : container_fragment.Children()) { - const auto& child_fragment = To<PhysicalBoxFragment>(*link); - if (!child_fragment.IsFragmentainerBox()) { - continue; - } - LogicalSize logical_size = FragmentainerLogicalCapacity(child_fragment); - thread_size.block_size += logical_size.block_size; - if (!has_processed_first_column_in_flow_thread) { - // The offset of the flow thread is the same as that of the first - // column. - frame_location_.layout_point = ComputeBoxLocation( - child_fragment, link.Offset(), container_fragment, break_token); - - thread_size.inline_size = logical_size.inline_size; - has_processed_first_column_in_flow_thread = true; - } - } - break_token = container_fragment.GetBreakToken(); - if (!break_token || break_token->IsRepeated() || - break_token->IsAtBlockEnd()) { - break; - } - } - frame_size_ = converter.ToPhysical(thread_size); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h deleted file mode 100644 index 46c8435..0000000 --- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h +++ /dev/null
@@ -1,299 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_FLOW_THREAD_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_FLOW_THREAD_H_ - -#include "base/dcheck_is_on.h" -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/layout/layout_flow_thread.h" - -namespace blink { - -class LayoutMultiColumnSet; -class LayoutMultiColumnSpannerPlaceholder; - -// Flow thread implementation for CSS multicol. This will be inserted as an -// anonymous child block of the actual multicol container (i.e. the -// LayoutBlockFlow whose style computes to non-auto column-count and/or -// column-width). LayoutMultiColumnFlowThread is the heart of the multicol -// implementation, and there is only one instance per multicol container. Child -// content of the multicol container is parented into the flow thread at the -// time of layoutObject insertion. -// -// Apart from this flow thread child, the multicol container will also have -// LayoutMultiColumnSet children, which are used to position the columns -// visually. The flow thread is in charge of layout, and, after having -// calculated the column width, it lays out content as if everything were in one -// tall single column, except that there will typically be some amount of blank -// space (also known as pagination struts) at the offsets where the actual -// column boundaries are. This way, content that needs to be preceded by a break -// will appear at the top of the next column. Content needs to be preceded by a -// break when there's a forced break or when the content is unbreakable and -// cannot fully fit in the same column as the preceding piece of content. -// Although a LayoutMultiColumnFlowThread is laid out, it does not take up any -// space in its container. It's the LayoutMultiColumnSet objects that take up -// the necessary amount of space, and make sure that the columns are painted and -// hit-tested correctly. -// -// If there is any column content inside the multicol container, we create a -// LayoutMultiColumnSet. We only need to create multiple sets if there are -// spanners (column-span:all) in the multicol container. When a spanner is -// inserted, content preceding it gets its own set, and content succeeding it -// will get another set. The spanner itself will also get its own placeholder -// between the sets (LayoutMultiColumnSpannerPlaceholder), so that it gets -// positioned and sized correctly. The column-span:all element is inside the -// flow thread, but its containing block is the multicol container. -// -// Some invariants for the layout tree structure for multicol: -// - A multicol container is always a LayoutBlockFlow -// - Every multicol container has one and only one LayoutMultiColumnFlowThread -// - All multicol DOM children and pseudo-elements associated with the multicol -// container are reparented into the flow thread. -// - The LayoutMultiColumnFlowThread is the first child of the multicol -// container. -// - A multicol container may only have LayoutMultiColumnFlowThread, -// LayoutMultiColumnSet and LayoutMultiColumnSpannerPlaceholder children. -// - A LayoutMultiColumnSet may not be adjacent to another LayoutMultiColumnSet; -// there are no use-cases for it, and there are also implementation -// limitations behind this requirement. -// - The flow thread is not in the containing block chain for children that are -// not to be laid out in columns. This means column spanners and absolutely -// positioned children whose containing block is outside column content -// - Each spanner (column-span:all) establishes a -// LayoutMultiColumnSpannerPlaceholder -// -// The width of the flow thread is the same as the column width. The width of a -// column set is the same as the content box width of the multicol container; in -// other words exactly enough to hold the number of columns to be used, stacked -// horizontally, plus column gaps between them. -// -// Since it's the first child of the multicol container, the flow thread is laid -// out first, albeit in a slightly special way, since it's not to take up any -// space in its ancestors. Afterwards, the column sets are laid out. Column sets -// get their height from the columns that they hold. In single column-row -// constrained height non-balancing cases without spanners this will simply be -// the same as the content height of the multicol container itself. In most -// other cases we'll have to calculate optimal column heights ourselves, though. -// This process is referred to as column balancing, and then we infer the column -// set height from the height of the flow thread portion occupied by each set. -// -// More on column balancing: the columns' height is unknown in the first layout -// pass when balancing. This means that we cannot insert any implicit (soft / -// unforced) breaks (and pagination struts) when laying out the contents of the -// flow thread. We'll just lay out everything in tall single strip. After the -// initial flow thread layout pass we can determine a tentative / minimal / -// initial column height. This is calculated by simply dividing the flow -// thread's height by the number of specified columns. In the layout pass that -// follows, we can insert breaks (and pagination struts) at column boundaries, -// since we now have a column height. -// It may very easily turn out that the calculated height wasn't enough, though. -// We'll notice this at end of layout. If we end up with too many columns (i.e. -// columns overflowing the multicol container), it wasn't enough. In this case -// we need to increase the column heights. We'll increase them by the lowest -// amount of space that could possibly affect where the breaks occur. We'll -// relayout (to find new break points and the new lowest amount of space -// increase that could affect where they occur, in case we need another round) -// until we've reached an acceptable height (where everything fits perfectly in -// the number of columns that we have specified). The rule of thumb is that we -// shouldn't have to perform more of such iterations than the number of columns -// that we have. -// -// For each layout iteration done for column balancing, the flow thread will -// need a deep layout if column heights changed in the previous pass, since -// column height changes may affect break points and pagination struts anywhere -// in the tree, and currently no way exists to do this in a more optimized -// manner. -// -// There's also some documentation online: -// https://www.chromium.org/developers/design-documents/multi-column-layout -class CORE_EXPORT LayoutMultiColumnFlowThread final : public LayoutFlowThread { - public: - ~LayoutMultiColumnFlowThread() override; - void Trace(Visitor*) const override; - - static LayoutMultiColumnFlowThread* CreateAnonymous( - Document&, - const ComputedStyle& parent_style); - - bool IsLayoutMultiColumnFlowThread() const final { - NOT_DESTROYED(); - return true; - } - - LayoutBlockFlow* MultiColumnBlockFlow() const { - NOT_DESTROYED(); - return To<LayoutBlockFlow>(Parent()); - } - - LayoutMultiColumnSet* FirstMultiColumnSet() const; - LayoutMultiColumnSet* LastMultiColumnSet() const; - - // Return the first column set or spanner placeholder. - LayoutBox* FirstMultiColumnBox() const { - NOT_DESTROYED(); - return NextSiblingBox(); - } - // Return the last column set or spanner placeholder. - LayoutBox* LastMultiColumnBox() const { - NOT_DESTROYED(); - LayoutBox* last_sibling_box = MultiColumnBlockFlow()->LastChildBox(); - // The flow thread is the first child of the multicol container. If the flow - // thread is also the last child, it means that there are no siblings; i.e. - // we have no column boxes. - return last_sibling_box != this ? last_sibling_box : nullptr; - } - - // Find the first set inside which the specified layoutObject (which is a - // flowthread descendant) would be rendered. - LayoutMultiColumnSet* MapDescendantToColumnSet(LayoutObject*) const; - - // Return the spanner placeholder that belongs to the spanner in the - // containing block chain, if any. This includes the layoutObject for the - // element that actually establishes the spanner too. - LayoutMultiColumnSpannerPlaceholder* ContainingColumnSpannerPlaceholder( - const LayoutObject* descendant) const; - - // Populate the flow thread with what's currently its siblings. Called when a - // regular block becomes a multicol container. - void Populate(); - - // Empty the flow thread by moving everything to the parent. Remove all - // multicol specific layoutObjects. Then destroy the flow thread. Called when - // a multicol container becomes a regular block. - void EvacuateAndDestroy(); - - unsigned ColumnCount() const { - NOT_DESTROYED(); - return column_count_; - } - - PhysicalOffset ColumnOffset(const PhysicalOffset&) const final; - - bool IsPageLogicalHeightKnown() const final; - - PhysicalOffset FlowThreadTranslationAtOffset(LayoutUnit, - PageBoundaryRule) const; - PhysicalOffset FlowThreadTranslationAtPoint( - const PhysicalOffset& flow_thread_point) const; - - PhysicalOffset VisualPointToFlowThreadPoint( - const PhysicalOffset& visual_point) const final; - - LayoutMultiColumnSet* ColumnSetAtBlockOffset(LayoutUnit, - PageBoundaryRule) const final; - - void ColumnRuleStyleDidChange(); - - // Remove the spanner placeholder and return true if the specified object is - // no longer a valid spanner. - bool RemoveSpannerPlaceholderIfNoLongerValid( - LayoutBox* spanner_object_in_flow_thread); - - LayoutMultiColumnFlowThread* EnclosingFlowThread( - AncestorSearchConstraint = kIsolateUnbreakableContainers) const; - - void SetColumnCountFromNG(unsigned column_count); - void FinishLayoutFromNG(LayoutUnit flow_thread_offset); - - const char* GetName() const override { - NOT_DESTROYED(); - return "LayoutMultiColumnFlowThread"; - } - - // Note: We call this constructor only in |CreateAnonymous()|, but mark this - // "public" for |MakeGarbageCollected<T>|. - explicit LayoutMultiColumnFlowThread(); - - DeprecatedLayoutPoint DeprecatedLocationInternal() const override; - PhysicalSize Size() const override; - - private: - void CreateAndInsertMultiColumnSet(LayoutBox* insert_before = nullptr); - void CreateAndInsertSpannerPlaceholder( - LayoutBox* spanner_object_in_flow_thread, - LayoutObject* inserted_before_in_flow_thread); - void DestroySpannerPlaceholder(LayoutMultiColumnSpannerPlaceholder*); - bool DescendantIsValidColumnSpanner(LayoutObject* descendant) const; - bool CanContainSpannerInParentFragmentationContext(const LayoutObject&) const; - - void AddColumnSetToThread(LayoutMultiColumnSet*) override; - void WillBeRemovedFromTree() override; - void FlowThreadDescendantWasInserted(LayoutObject*) final; - void FlowThreadDescendantWillBeRemoved(LayoutObject*) final; - void FlowThreadDescendantStyleWillChange( - LayoutBoxModelObject*, - StyleDifference, - const ComputedStyle& new_style) override; - void FlowThreadDescendantStyleDidChange( - LayoutBoxModelObject*, - StyleDifference, - const ComputedStyle& old_style) override; - void ToggleSpannersInSubtree(LayoutBoxModelObject*); - void UpdateGeometry(); - - // The last set we worked on. It's not to be used as the "current set". The - // concept of a "current set" is difficult, since layout may jump back and - // forth in the tree, due to wrong top location estimates (due to e.g. margin - // collapsing), and possibly for other reasons. - Member<LayoutMultiColumnSet> last_set_worked_on_; - -#if DCHECK_IS_ON() - // Used to check consistency between calls to - // flowThreadDescendantStyleWillChange() and - // flowThreadDescendantStyleDidChange(). - static const LayoutBoxModelObject* style_changed_object_; -#endif - - // The used value of column-count - unsigned column_count_; - - bool all_columns_have_known_height_ = false; - - bool is_being_evacuated_; - - // Specifies whether the the descendant whose style is about to change could - // contain spanners or not. The flag is set in - // flowThreadDescendantStyleWillChange(), and then checked in - // flowThreadDescendantStyleDidChange(). - static bool could_contain_spanners_; - - static bool toggle_spanners_if_needed_; -}; - -template <> -struct DowncastTraits<LayoutMultiColumnFlowThread> { - static bool AllowFrom(const LayoutObject& object) { - return object.IsLayoutFlowThread() && - To<LayoutFlowThread>(object).IsLayoutMultiColumnFlowThread(); - } - static bool AllowFrom(const LayoutFlowThread& flow_thread) { - return flow_thread.IsLayoutMultiColumnFlowThread(); - } -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_FLOW_THREAD_H_
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread_test.cc b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread_test.cc deleted file mode 100644 index 65cdc98..0000000 --- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread_test.cc +++ /dev/null
@@ -1,1209 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/core/dom/text.h" -#include "third_party/blink/renderer/core/html/html_div_element.h" -#include "third_party/blink/renderer/core/html/html_span_element.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" -#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" -#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" -#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" - -namespace blink { - -namespace { - -class MultiColumnRenderingTest : public RenderingTest, - ScopedFlowThreadLessForTest { - public: - MultiColumnRenderingTest() : ScopedFlowThreadLessForTest(false) {} - - protected: - LayoutMultiColumnFlowThread* FindFlowThread(const char* id) const; - - // Generate a signature string based on what kind of column boxes the flow - // thread has established. 'c' is used for regular column content sets, while - // 's' is used for spanners. '?' is used when there's an unknown box type - // (which should be considered a failure). - String ColumnSetSignature(LayoutMultiColumnFlowThread*); - String ColumnSetSignature(const char* multicol_id); - - void SetMulticolHTML(const String&); -}; - -LayoutMultiColumnFlowThread* MultiColumnRenderingTest::FindFlowThread( - const char* id) const { - if (auto* multicol_container = - To<LayoutBlockFlow>(GetLayoutObjectByElementId(id))) - return multicol_container->MultiColumnFlowThread(); - return nullptr; -} - -String MultiColumnRenderingTest::ColumnSetSignature( - LayoutMultiColumnFlowThread* flow_thread) { - StringBuilder signature; - for (LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); column_box; - column_box = column_box->NextSiblingMultiColumnBox()) { - if (column_box->IsLayoutMultiColumnSpannerPlaceholder()) - signature.Append('s'); - else if (column_box->IsLayoutMultiColumnSet()) - signature.Append('c'); - else - signature.Append('?'); - } - return signature.ToString(); -} - -String MultiColumnRenderingTest::ColumnSetSignature(const char* multicol_id) { - return ColumnSetSignature(FindFlowThread(multicol_id)); -} - -void MultiColumnRenderingTest::SetMulticolHTML(const String& html) { - const char* style = - "<style>" - " #mc { columns:2; }" - " .s, #spanner, #spanner1, #spanner2 { column-span:all; }" - "</style>"; - SetBodyInnerHTML(style + html); -} - -TEST_F(MultiColumnRenderingTest, OneBlockWithInDepthTreeStructureCheck) { - // Examine the layout tree established by a simple multicol container with a - // block with some text inside. - SetMulticolHTML("<div id='mc'><div>xxx</div></div>"); - auto* multicol_container = - To<LayoutBlockFlow>(GetLayoutObjectByElementId("mc")); - ASSERT_TRUE(multicol_container); - LayoutMultiColumnFlowThread* flow_thread = - multicol_container->MultiColumnFlowThread(); - ASSERT_TRUE(flow_thread); - EXPECT_EQ(ColumnSetSignature(flow_thread), "c"); - EXPECT_EQ(flow_thread->Parent(), multicol_container); - EXPECT_FALSE(flow_thread->PreviousSibling()); - LayoutMultiColumnSet* column_set = flow_thread->FirstMultiColumnSet(); - ASSERT_TRUE(column_set); - EXPECT_EQ(column_set->PreviousSibling(), flow_thread); - EXPECT_FALSE(column_set->NextSibling()); - auto* block = To<LayoutBlockFlow>(flow_thread->FirstChild()); - ASSERT_TRUE(block); - EXPECT_FALSE(block->NextSibling()); - ASSERT_TRUE(block->FirstChild()); - EXPECT_TRUE(block->FirstChild()->IsText()); - EXPECT_FALSE(block->FirstChild()->NextSibling()); -} - -TEST_F(MultiColumnRenderingTest, Empty) { - // If there's no column content, there should be no column set. - SetMulticolHTML("<div id='mc'></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnRenderingTest, OneBlock) { - // There is some content, so we should create a column set. - SetMulticolHTML("<div id='mc'><div id='block'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "c"); - LayoutMultiColumnSet* column_set = flow_thread->FirstMultiColumnSet(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("block")), - column_set); -} - -TEST_F(MultiColumnRenderingTest, TwoBlocks) { - // No matter how much content, we should only create one column set (unless - // there are spanners). - SetMulticolHTML( - "<div id='mc'><div id='block1'></div><div id='block2'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "c"); - LayoutMultiColumnSet* column_set = flow_thread->FirstMultiColumnSet(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("block1")), - column_set); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("block2")), - column_set); -} - -TEST_F(MultiColumnRenderingTest, Spanner) { - // With one spanner and no column content, we should create a spanner set. - SetMulticolHTML("<div id='mc'><div id='spanner'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "s"); - LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - EXPECT_EQ(flow_thread->FirstMultiColumnSet(), nullptr); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner")), - column_box); - EXPECT_EQ(GetLayoutObjectByElementId("spanner")->SpannerPlaceholder(), - column_box); -} - -TEST_F(MultiColumnRenderingTest, ContentThenSpanner) { - // With some column content followed by a spanner, we need a column set - // followed by a spanner set. - SetMulticolHTML( - "<div id='mc'><div id='columnContent'></div><div " - "id='spanner'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "cs"); - LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("columnContent")), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner")), - column_box); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("columnContent")), - nullptr); -} - -TEST_F(MultiColumnRenderingTest, SpannerThenContent) { - // With a spanner followed by some column content, we need a spanner set - // followed by a column set. - SetMulticolHTML( - "<div id='mc'><div id='spanner'></div><div " - "id='columnContent'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "sc"); - LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner")), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("columnContent")), - column_box); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("columnContent")), - nullptr); -} - -TEST_F(MultiColumnRenderingTest, ContentThenSpannerThenContent) { - // With column content followed by a spanner followed by some column content, - // we need a column - // set followed by a spanner set followed by a column set. - SetMulticolHTML( - "<div id='mc'><div id='columnContentBefore'></div><div " - "id='spanner'></div><div id='columnContentAfter'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "csc"); - LayoutBox* column_box = flow_thread->FirstMultiColumnSet(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("columnContentBefore")), - column_box); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("columnContentBefore")), - nullptr); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner")), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("columnContentAfter")), - column_box); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("columnContentAfter")), - nullptr); -} - -TEST_F(MultiColumnRenderingTest, TwoSpanners) { - // With two spanners and no column content, we need two spanner sets. - SetMulticolHTML( - "<div id='mc'><div id='spanner1'></div><div id='spanner2'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "ss"); - LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - EXPECT_EQ(flow_thread->FirstMultiColumnSet(), nullptr); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner1")), - column_box); - EXPECT_EQ(GetLayoutObjectByElementId("spanner1")->SpannerPlaceholder(), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner2")), - column_box); - EXPECT_EQ(GetLayoutObjectByElementId("spanner2")->SpannerPlaceholder(), - column_box); -} - -TEST_F(MultiColumnRenderingTest, SpannerThenContentThenSpanner) { - // With two spanners and some column content in-between, we need a spanner - // set, a column set and another spanner set. - SetMulticolHTML( - "<div id='mc'><div id='spanner1'></div><div " - "id='columnContent'></div><div id='spanner2'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "scs"); - LayoutMultiColumnSet* column_set = flow_thread->FirstMultiColumnSet(); - EXPECT_EQ(column_set->NextSiblingMultiColumnSet(), nullptr); - LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner1")), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(column_box, column_set); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("columnContent")), - column_set); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("columnContent")), - nullptr); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner2")), - column_box); -} - -TEST_F(MultiColumnRenderingTest, SpannerWithSpanner) { - // column-span:all on something inside column-span:all has no effect. - SetMulticolHTML( - "<div id='mc'><div id='spanner'><div id='invalidSpanner' " - "class='s'></div></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - ASSERT_EQ(ColumnSetSignature(flow_thread), "s"); - LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner")), - column_box); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("invalidSpanner")), - column_box); - EXPECT_EQ(To<LayoutMultiColumnSpannerPlaceholder>(column_box) - ->LayoutObjectInFlowThread(), - GetLayoutObjectByElementId("spanner")); - EXPECT_EQ(GetLayoutObjectByElementId("spanner")->SpannerPlaceholder(), - column_box); - EXPECT_EQ(GetLayoutObjectByElementId("invalidSpanner")->SpannerPlaceholder(), - nullptr); -} - -TEST_F(MultiColumnRenderingTest, SubtreeWithSpanner) { - SetMulticolHTML( - "<div id='mc'><div id='outer'><div id='block1'></div><div " - "id='spanner'></div><div id='block2'></div></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - EXPECT_EQ(ColumnSetSignature(flow_thread), "csc"); - LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("outer")), - column_box); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("block1")), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner")), - column_box); - EXPECT_EQ(GetLayoutObjectByElementId("spanner")->SpannerPlaceholder(), - column_box); - EXPECT_EQ(To<LayoutMultiColumnSpannerPlaceholder>(column_box) - ->LayoutObjectInFlowThread(), - GetLayoutObjectByElementId("spanner")); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("outer")), - nullptr); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("block1")), - nullptr); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("block2")), - nullptr); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("block2")), - column_box); -} - -TEST_F(MultiColumnRenderingTest, SubtreeWithSpannerAfterSpanner) { - SetMulticolHTML( - "<div id='mc'><div id='spanner1'></div><div id='outer'>text<div " - "id='spanner2'></div><div id='after'></div></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - EXPECT_EQ(ColumnSetSignature(flow_thread), "scsc"); - LayoutBox* column_box = flow_thread->FirstMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner1")), - column_box); - EXPECT_EQ(To<LayoutMultiColumnSpannerPlaceholder>(column_box) - ->LayoutObjectInFlowThread(), - GetLayoutObjectByElementId("spanner1")); - EXPECT_EQ(GetLayoutObjectByElementId("spanner1")->SpannerPlaceholder(), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("outer")), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner2")), - column_box); - EXPECT_EQ(To<LayoutMultiColumnSpannerPlaceholder>(column_box) - ->LayoutObjectInFlowThread(), - GetLayoutObjectByElementId("spanner2")); - EXPECT_EQ(GetLayoutObjectByElementId("spanner2")->SpannerPlaceholder(), - column_box); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("outer")), - nullptr); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("after")), - nullptr); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("after")), - column_box); -} - -TEST_F(MultiColumnRenderingTest, SubtreeWithSpannerBeforeSpanner) { - SetMulticolHTML( - "<div id='mc'><div id='outer'>text<div " - "id='spanner1'></div>text</div><div id='spanner2'></div></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - EXPECT_EQ(ColumnSetSignature(flow_thread), "cscs"); - LayoutBox* column_box = flow_thread->FirstMultiColumnSet(); - EXPECT_EQ(flow_thread->MapDescendantToColumnSet( - GetLayoutObjectByElementId("outer")), - column_box); - column_box = column_box->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner1")), - column_box); - EXPECT_EQ(GetLayoutObjectByElementId("spanner1")->SpannerPlaceholder(), - column_box); - EXPECT_EQ(To<LayoutMultiColumnSpannerPlaceholder>(column_box) - ->LayoutObjectInFlowThread(), - GetLayoutObjectByElementId("spanner1")); - column_box = - column_box->NextSiblingMultiColumnBox()->NextSiblingMultiColumnBox(); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("spanner2")), - column_box); - EXPECT_EQ(GetLayoutObjectByElementId("spanner2")->SpannerPlaceholder(), - column_box); - EXPECT_EQ(To<LayoutMultiColumnSpannerPlaceholder>(column_box) - ->LayoutObjectInFlowThread(), - GetLayoutObjectByElementId("spanner2")); - EXPECT_EQ(flow_thread->ContainingColumnSpannerPlaceholder( - GetLayoutObjectByElementId("outer")), - nullptr); -} - -class MultiColumnTreeModifyingTest : public MultiColumnRenderingTest { - public: - void SetMulticolHTML(const char*); - void ReparentLayoutObject(const char* new_parent_id, - const char* child_id, - const char* insert_before_id = nullptr); - void DestroyLayoutObject(LayoutObject* child); - void DestroyLayoutObject(const char* child_id); -}; - -void MultiColumnTreeModifyingTest::SetMulticolHTML(const char* html) { - MultiColumnRenderingTest::SetMulticolHTML(html); - // Allow modifications to the layout tree structure, because that's what we - // want to test. - GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); -} - -void MultiColumnTreeModifyingTest::ReparentLayoutObject( - const char* new_parent_id, - const char* child_id, - const char* insert_before_id) { - LayoutObject* new_parent = GetLayoutObjectByElementId(new_parent_id); - LayoutObject* child = GetLayoutObjectByElementId(child_id); - LayoutObject* insert_before = - insert_before_id ? GetLayoutObjectByElementId(insert_before_id) : nullptr; - child->Remove(); - new_parent->AddChild(child, insert_before); -} - -void MultiColumnTreeModifyingTest::DestroyLayoutObject(LayoutObject* child) { - // Remove and destroy in separate steps, so that we get to test removal of - // subtrees. - child->Remove(); - child->GetNode()->DetachLayoutTree(); -} - -void MultiColumnTreeModifyingTest::DestroyLayoutObject(const char* child_id) { - DestroyLayoutObject(GetLayoutObjectByElementId(child_id)); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertFirstContentAndRemove) { - SetMulticolHTML("<div id='block'></div><div id='mc'></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - auto* block = To<LayoutBlockFlow>(GetLayoutObjectByElementId("block")); - auto* multicol_container = - To<LayoutBlockFlow>(GetLayoutObjectByElementId("mc")); - block->Remove(); - multicol_container->AddChild(block); - EXPECT_EQ(block->Parent(), flow_thread); - // A set should have appeared, now that the multicol container has content. - EXPECT_EQ(ColumnSetSignature(flow_thread), "c"); - - DestroyLayoutObject(block); - // The set should be gone again now, since there's nothing inside the multicol - // container anymore. - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertContentBeforeContentAndRemove) { - SetMulticolHTML( - "<div id='block'></div><div id='mc'><div id='insertBefore'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); - ReparentLayoutObject("mc", "block", "insertBefore"); - // There was already some content prior to our insertion, so no new set should - // be inserted. - EXPECT_EQ(ColumnSetSignature("mc"), "c"); - DestroyLayoutObject("block"); - // There's still some content after the removal, so the set should remain. - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertContentAfterContentAndRemove) { - SetMulticolHTML("<div id='block'></div><div id='mc'><div></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); - ReparentLayoutObject("mc", "block"); - // There was already some content prior to our insertion, so no new set should - // be inserted. - EXPECT_EQ(ColumnSetSignature("mc"), "c"); - DestroyLayoutObject("block"); - // There's still some content after the removal, so the set should remain. - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertSpannerAndRemove) { - SetMulticolHTML("<div id='spanner'></div><div id='mc'></div>"); - LayoutMultiColumnFlowThread* flow_thread = FindFlowThread("mc"); - auto* spanner = To<LayoutBlockFlow>(GetLayoutObjectByElementId("spanner")); - auto* multicol_container = - To<LayoutBlockFlow>(GetLayoutObjectByElementId("mc")); - spanner->Remove(); - multicol_container->AddChild(spanner); - EXPECT_EQ(spanner->Parent(), flow_thread); - // We should now have a spanner placeholder, since we just moved a spanner - // into the multicol container. - EXPECT_EQ(ColumnSetSignature(flow_thread), "s"); - DestroyLayoutObject(spanner); - EXPECT_EQ(ColumnSetSignature(flow_thread), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertTwoSpannersAndRemove) { - SetMulticolHTML( - "<div id='block'>ee<div class='s'></div><div class='s'></div></div><div " - "id='mc'></div>"); - ReparentLayoutObject("mc", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "css"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertSpannerAfterContentAndRemove) { - SetMulticolHTML("<div id='spanner'></div><div id='mc'><div></div></div>"); - ReparentLayoutObject("mc", "spanner"); - // We should now have a spanner placeholder, since we just moved a spanner - // into the multicol container. - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertSpannerBeforeContentAndRemove) { - SetMulticolHTML( - "<div id='spanner'></div><div id='mc'><div " - "id='columnContent'></div></div>"); - ReparentLayoutObject("mc", "spanner", "columnContent"); - // We should now have a spanner placeholder, since we just moved a spanner - // into the multicol container. - EXPECT_EQ(ColumnSetSignature("mc"), "sc"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertSpannerBetweenContentAndRemove) { - SetMulticolHTML( - "<div id='spanner'></div><div id='mc'><div></div><div " - "id='insertBefore'></div></div>"); - ReparentLayoutObject("mc", "spanner", "insertBefore"); - // Since the spanner was inserted in the middle of column content, what used - // to be one column set had to be split in two, in order to get a spot to - // insert the spanner placeholder. - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("spanner"); - // The spanner placeholder should be gone again now, and the two sets be - // merged into one. - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSubtreeWithContentAndSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'>text<div id='spanner'></div>text</div><div " - "id='mc'></div>"); - ReparentLayoutObject("mc", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertInsideSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'>text</div><div id='mc'><div id='spanner'></div></div>"); - ReparentLayoutObject("spanner", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSpannerInContentBeforeSpannerAndRemove) { - SetMulticolHTML( - "<div id='spanner'></div><div id='mc'><div></div><div " - "id='insertBefore'></div><div class='s'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - ReparentLayoutObject("mc", "spanner", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "cscs"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSpannerInContentAfterSpannerAndRemove) { - SetMulticolHTML( - "<div id='spanner'></div><div id='mc'><div " - "class='s'></div><div></div><div id='insertBefore'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "sc"); - ReparentLayoutObject("mc", "spanner", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "scsc"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "sc"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertSpannerAfterSpannerAndRemove) { - SetMulticolHTML( - "<div id='spanner'></div><div id='mc'><div class='s'></div></div>"); - ReparentLayoutObject("mc", "spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "ss"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertSpannerBeforeSpannerAndRemove) { - SetMulticolHTML( - "<div id='spanner'></div><div id='mc'><div id='insertBefore' " - "class='s'></div></div>"); - ReparentLayoutObject("mc", "spanner", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "ss"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertContentBeforeSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'></div><div id='mc'><div id='insertBefore' " - "class='s'></div></div>"); - ReparentLayoutObject("mc", "block", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertContentAfterContentBeforeSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'></div><div id='mc'>text<div id='insertBefore' " - "class='s'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - ReparentLayoutObject("mc", "block", "insertBefore"); - // There was already some content before the spanner prior to our insertion, - // so no new set should be inserted. - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertContentAfterContentAndSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'></div><div id='mc'>content<div class='s'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - ReparentLayoutObject("mc", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertContentBeforeSpannerAndContentAndRemove) { - SetMulticolHTML( - "<div id='block'></div><div id='mc'><div id='insertBefore' " - "class='s'></div>content</div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "sc"); - ReparentLayoutObject("mc", "block", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "sc"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSpannerIntoContentBeforeSpannerAndRemove) { - SetMulticolHTML( - "<div id='spanner'></div><div id='mc'><div></div><div " - "id='insertBefore'></div><div class='s'></div><div " - "class='s'></div><div></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cssc"); - ReparentLayoutObject("mc", "spanner", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "cscssc"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "cssc"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSpannerIntoContentAfterSpannerAndRemove) { - SetMulticolHTML( - "<div id='spanner'></div><div id='mc'><div></div><div " - "class='s'></div><div class='s'></div><div></div><div " - "id='insertBefore'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cssc"); - ReparentLayoutObject("mc", "spanner", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "csscsc"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "cssc"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertInvalidSpannerAndRemove) { - SetMulticolHTML( - "<div class='s' id='invalidSpanner'></div><div id='mc'><div " - "id='spanner'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); - ReparentLayoutObject("spanner", "invalidSpanner"); - // It's not allowed to nest spanners. - EXPECT_EQ(ColumnSetSignature("mc"), "s"); - DestroyLayoutObject("invalidSpanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertSpannerWithInvalidSpannerAndRemove) { - SetMulticolHTML( - "<div id='spanner'><div class='s' id='invalidSpanner'></div></div><div " - "id='mc'></div>"); - ReparentLayoutObject("mc", "spanner"); - // It's not allowed to nest spanners. - EXPECT_EQ(ColumnSetSignature("mc"), "s"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertInvalidSpannerInSpannerBetweenContentAndRemove) { - SetMulticolHTML( - "<div class='s' id='invalidSpanner'></div><div id='mc'>text<div " - "id='spanner'></div>text</div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - ReparentLayoutObject("spanner", "invalidSpanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("invalidSpanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertContentAndSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'>text<div id='spanner'></div></div><div " - "id='mc'>text</div>"); - ReparentLayoutObject("mc", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertContentAndSpannerAndContentAndRemove) { - SetMulticolHTML( - "<div id='block'><div id='spanner'></div>text</div><div id='mc'></div>"); - ReparentLayoutObject("mc", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, InsertSubtreeWithSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'>text<div class='s'></div>text</div><div id='mc'></div>"); - ReparentLayoutObject("mc", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSubtreeWithSpannerAfterContentAndRemove) { - SetMulticolHTML( - "<div id='block'>text<div class='s'></div>text</div><div id='mc'>column " - "content</div>"); - ReparentLayoutObject("mc", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSubtreeWithSpannerBeforeContentAndRemove) { - SetMulticolHTML( - "<div id='block'>text<div class='s'></div>text</div><div id='mc'><div " - "id='insertBefore'>column content</div></div>"); - ReparentLayoutObject("mc", "block", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSubtreeWithSpannerInsideContentAndRemove) { - SetMulticolHTML( - "<div id='block'>text<div class='s'></div>text</div><div id='mc'><div " - "id='newParent'>outside<div id='insertBefore'>outside</div></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); - ReparentLayoutObject("newParent", "block", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSubtreeWithSpannerAfterSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'>text<div class='s'></div>text</div><div id='mc'><div " - "class='s'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); - ReparentLayoutObject("mc", "block"); - EXPECT_EQ(ColumnSetSignature("mc"), "scsc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); -} - -TEST_F(MultiColumnTreeModifyingTest, - InsertSubtreeWithSpannerBeforeSpannerAndRemove) { - SetMulticolHTML( - "<div id='block'>text<div class='s'></div>text</div><div id='mc'><div " - "id='insertBefore' class='s'></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); - ReparentLayoutObject("mc", "block", "insertBefore"); - EXPECT_EQ(ColumnSetSignature("mc"), "cscs"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "s"); -} - -TEST_F(MultiColumnTreeModifyingTest, RemoveSpannerAndContent) { - SetMulticolHTML( - "<div id='mc'><div id='block'>text<div class='s'></div>text</div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, RemoveSpannerAndSomeContentBefore) { - SetMulticolHTML( - "<div id='mc'>text<div id='block'>text<div class='s'></div></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, RemoveSpannerAndAllContentBefore) { - SetMulticolHTML( - "<div id='mc'><div id='block'>text<div class='s'></div></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cs"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, - RemoveSpannerAndAllContentBeforeWithContentAfter) { - SetMulticolHTML( - "<div id='mc'><div id='block'>text<div class='s'></div></div>text</div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, RemoveSpannerAndSomeContentAfter) { - SetMulticolHTML( - "<div id='mc'><div id='block'><div class='s'></div>text</div>text</div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, RemoveSpannerAndAllContentAfter) { - SetMulticolHTML( - "<div id='mc'><div id='block'><div class='s'></div>text</div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, - RemoveSpannerAndAllContentAfterWithContentBefore) { - SetMulticolHTML( - "<div id='mc'>text<div id='block'><div class='s'></div>text</div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, RemoveTwoSpannersBeforeContent) { - SetMulticolHTML( - "<div id='mc'><div id='block'><div class='s'></div><div " - "class='s'></div></div>text</div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cssc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, RemoveSpannerAndContentAndSpanner) { - SetMulticolHTML( - "<div id='mc'><div id='block'><div class='s'></div>text<div " - "class='s'></div>text</div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cscsc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), ""); -} - -TEST_F(MultiColumnTreeModifyingTest, - RemoveSpannerAndContentAndSpannerBeforeContent) { - SetMulticolHTML( - "<div id='mc'><div id='block'><div class='s'></div>text<div " - "class='s'></div></div>text</div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cscsc"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, - RemoveSpannerAndContentAndSpannerAfterContent) { - SetMulticolHTML( - "<div id='mc'>text<div id='block'><div class='s'></div>text<div " - "class='s'></div></div></div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "cscs"); - DestroyLayoutObject("block"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnTreeModifyingTest, - RemoveInvalidSpannerInSpannerBetweenContent) { - SetMulticolHTML( - "<div id='mc'>text<div class='s'><div " - "id='spanner'></div></div>text</div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); -} - -TEST_F(MultiColumnTreeModifyingTest, - RemoveSpannerWithInvalidSpannerBetweenContent) { - SetMulticolHTML( - "<div id='mc'>text<div id='spanner'><div " - "class='s'></div></div>text</div>"); - EXPECT_EQ(ColumnSetSignature("mc"), "csc"); - DestroyLayoutObject("spanner"); - EXPECT_EQ(ColumnSetSignature("mc"), "c"); -} - -TEST_F(MultiColumnRenderingTest, Continuation) { - InsertStyleElement("#mc { column-count: 2}"); - SetBodyInnerHTML("<div id=mc><span>x<div id=inner></div>y</div>"); - auto& multicol = *GetElementById("mc"); - const auto& container = *To<LayoutBlockFlow>(multicol.GetLayoutObject()); - const auto& flow_thread = *container.MultiColumnFlowThread(); - - ASSERT_TRUE(&flow_thread) - << "We have flow thread even if container has no children."; - - // 1. Continuations should be in anonymous block in LayoutNG. - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutInline SPAN - | | | +--LayoutText #text "x" - | | | +--LayoutBlockFlow (anonymous) - | | | | +--LayoutBlockFlow DIV id="inner" - | | | +--LayoutText #text "y" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 2. Remove #inner to avoid continuation. - GetElementById("inner")->remove(); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutInline SPAN - | | | +--LayoutText #text "x" - | | | +--LayoutText #text "y" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 3. Normalize to merge "x" and "y". - // See http://crbug.com/1201508 for redundant |LayoutInline SPAN|. - multicol.normalize(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutInline SPAN - | | | +--LayoutText #text "xy" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); -} - -TEST_F(MultiColumnRenderingTest, InsertBlock) { - InsertStyleElement("#mc { column-count: 3}"); - SetBodyInnerHTML("<div id=mc></div>"); - - auto& multicol = *GetElementById("mc"); - const auto& container = *To<LayoutBlockFlow>(multicol.GetLayoutObject()); - const auto& flow_thread = *container.MultiColumnFlowThread(); - - ASSERT_TRUE(&flow_thread) - << "We have flow thread even if container has no children."; - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 1. Add inline child - multicol.appendChild(Text::Create(GetDocument(), "x")); - RunDocumentLifecycle(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutText #text "x" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 2. Remove inline child - multicol.removeChild(multicol.firstChild()); - RunDocumentLifecycle(); - - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 3. Insert block - multicol.insertBefore(MakeGarbageCollected<HTMLDivElement>(GetDocument()), - multicol.lastChild()); - RunDocumentLifecycle(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - - EXPECT_EQ( - R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow DIV - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); -} - -TEST_F(MultiColumnRenderingTest, InsertInline) { - InsertStyleElement("#mc { column-count: 3}"); - SetBodyInnerHTML("<div id=mc></div>"); - - auto& multicol = *GetElementById("mc"); - const auto& container = *To<LayoutBlockFlow>(multicol.GetLayoutObject()); - const auto& flow_thread = *container.MultiColumnFlowThread(); - - ASSERT_TRUE(&flow_thread) - << "We have flow thread even if container has no children."; - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 1. Add inline child - multicol.appendChild(Text::Create(GetDocument(), "x")); - RunDocumentLifecycle(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutText #text "x" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 2. Remove inline child - multicol.removeChild(multicol.firstChild()); - RunDocumentLifecycle(); - - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 3. Insert inline - multicol.insertBefore(MakeGarbageCollected<HTMLSpanElement>(GetDocument()), - multicol.lastChild()); - RunDocumentLifecycle(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutInline SPAN - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); -} - -TEST_F(MultiColumnRenderingTest, ListItem) { - InsertStyleElement("#mc { column-count: 3; display: list-item; }"); - SetBodyInnerHTML("<div id=mc></div>"); - - auto& multicol = *GetElementById("mc"); - const auto& container = *To<LayoutBlockFlow>(multicol.GetLayoutObject()); - const auto& flow_thread = *container.MultiColumnFlowThread(); - - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutListItem DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutOutsideListMarker ::marker - | | +--LayoutTextFragment (anonymous) ("\u2022 ") - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); -} - -TEST_F(MultiColumnRenderingTest, SplitInline) { - InsertStyleElement("#mc { column-count: 3}"); - SetBodyInnerHTML("<div id=mc></div>"); - - auto& multicol = *GetElementById("mc"); - const auto& container = *To<LayoutBlockFlow>(multicol.GetLayoutObject()); - const auto& flow_thread = *container.MultiColumnFlowThread(); - - ASSERT_TRUE(&flow_thread) - << "We have flow thread even if container has no children."; - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 1. Add inline child - multicol.appendChild(Text::Create(GetDocument(), "x")); - RunDocumentLifecycle(); - - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutText #text "x" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 2. Remove inline child - multicol.removeChild(multicol.firstChild()); - RunDocumentLifecycle(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 3. Add inline child again - multicol.appendChild(Text::Create(GetDocument(), "x")); - RunDocumentLifecycle(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutText #text "x" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 4. Add inline child (one more) - multicol.appendChild(Text::Create(GetDocument(), "y")); - RunDocumentLifecycle(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutText #text "x" - | | +--LayoutText #text "y" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); - - // 5. Add a block child to split inline children. - multicol.insertBefore(MakeGarbageCollected<HTMLDivElement>(GetDocument()), - multicol.lastChild()); - RunDocumentLifecycle(); - EXPECT_FALSE(flow_thread.ChildrenInline()); - EXPECT_EQ(R"DUMP( -LayoutBlockFlow DIV id="mc" - +--LayoutMultiColumnFlowThread (anonymous) - | +--LayoutBlockFlow (anonymous) - | | +--LayoutText #text "x" - | +--LayoutBlockFlow DIV - | +--LayoutBlockFlow (anonymous) - | | +--LayoutText #text "y" - +--LayoutMultiColumnSet (anonymous) -)DUMP", - ToSimpleLayoutTree(container)); -} - -TEST_F(MultiColumnRenderingTest, FlowThreadUpdateGeometryCrash) { - SetBodyInnerHTML(R"HTML( - <video width="64" height="64" controls> - <iframe width=320 height=320></iframe>)HTML"); - UpdateAllLifecyclePhasesForTest(); - InsertStyleElement(R"CSS( - body, html { - column-count: 2; - overflow: clip; - })CSS"); - UpdateAllLifecyclePhasesForTest(); - // Pass if no crash in LayoutMultiColumnFlowThread::UpdateGeometry() call - // from LayoutMedia::ComputePanelWidth(). -} - -} // anonymous namespace - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_set.cc b/third_party/blink/renderer/core/layout/layout_multi_column_set.cc deleted file mode 100644 index b6b810c..0000000 --- a/third_party/blink/renderer/core/layout/layout_multi_column_set.cc +++ /dev/null
@@ -1,545 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h" - -#include "third_party/blink/renderer/core/css/resolver/style_resolver.h" -#include "third_party/blink/renderer/core/editing/position_with_affinity.h" -#include "third_party/blink/renderer/core/layout/fragmentation_utils.h" -#include "third_party/blink/renderer/core/layout/geometry/box_strut.h" -#include "third_party/blink/renderer/core/layout/layout_box_utils.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" -#include "third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h" -#include "third_party/blink/renderer/core/layout/physical_box_fragment.h" -#include "third_party/blink/renderer/core/paint/paint_layer.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" - -namespace blink { - -namespace { - -// A helper class to access all child fragments of all fragments of a single -// multi-column container. This class ignores repeated fragments. -class ChildFragmentIterator { - STACK_ALLOCATED(); - - public: - explicit ChildFragmentIterator(const LayoutBlockFlow& container) - : container_(container) { - DCHECK(container.IsFragmentationContextRoot()); - SkipEmptyFragments(); - } - - bool IsValid() const { - if (fragment_index_ >= container_.PhysicalFragmentCount()) { - return false; - } - const auto* break_token = CurrentFragment()->GetBreakToken(); - return !break_token || !break_token->IsRepeated(); - } - - bool NextChild() { - DCHECK(IsValid()); - if (++child_index_ >= CurrentFragment()->Children().size()) { - child_index_ = 0; - ++fragment_index_; - SkipEmptyFragments(); - } - return IsValid(); - } - - const PhysicalBoxFragment* operator->() const { - DCHECK(IsValid()); - return To<PhysicalBoxFragment>( - CurrentFragment()->Children()[child_index_].get()); - } - const PhysicalBoxFragment& operator*() const { - DCHECK(IsValid()); - return To<PhysicalBoxFragment>( - *CurrentFragment()->Children()[child_index_]); - } - PhysicalOffset Offset() const { - DCHECK(IsValid()); - return CurrentFragment()->Children()[child_index_].Offset(); - } - - wtf_size_t FragmentIndex() const { return fragment_index_; } - - private: - const PhysicalBoxFragment* CurrentFragment() const { - return container_.GetPhysicalFragment(fragment_index_); - } - - void SkipEmptyFragments() { - DCHECK_EQ(child_index_, 0u); - while (IsValid() && CurrentFragment()->Children().size() == 0u) { - ++fragment_index_; - } - } - - const LayoutBlockFlow& container_; - wtf_size_t fragment_index_ = 0; - wtf_size_t child_index_ = 0; -}; - -DeprecatedLayoutPoint ComputeLocation( - const PhysicalBoxFragment& column_box, - PhysicalOffset column_offset, - LayoutUnit set_inline_size, - const LayoutBlockFlow& container, - wtf_size_t fragment_index, - const PhysicalBoxStrut& border_padding_scrollbar) { - const PhysicalBoxFragment* container_fragment = - container.GetPhysicalFragment(fragment_index); - WritingModeConverter converter( - container_fragment->Style().GetWritingDirection(), - container_fragment->Size()); - // The inline-offset will be the content-box edge of the multicol container, - // and the block-offset will be the block-offset of the column itself. It - // doesn't matter which column from the same row we use, since all columns - // have the same block-offset and block-size (so just use the first one). - LogicalOffset logical_offset( - border_padding_scrollbar.ConvertToLogical(converter.GetWritingDirection()) - .inline_start, - converter.ToLogical(column_offset, column_box.Size()).block_offset); - LogicalSize column_set_logical_size( - set_inline_size, converter.ToLogical(column_box.Size()).block_size); - PhysicalOffset physical_offset = converter.ToPhysical( - logical_offset, converter.ToPhysical(column_set_logical_size)); - const BlockBreakToken* previous_container_break_token = nullptr; - if (fragment_index > 0) { - previous_container_break_token = - container.GetPhysicalFragment(fragment_index - 1)->GetBreakToken(); - } - // We have calculated the physical offset relative to the border edge of - // this multicol container fragment. We'll now convert it to a legacy - // engine DeprecatedLayoutPoint, which will also take care of converting it - // into the flow thread coordinate space, if we happen to be nested inside - // another fragmentation context. - return ComputeBoxLocation(column_box, physical_offset, - *container.GetPhysicalFragment(fragment_index), - previous_container_break_token); -} - -} // namespace - -LayoutMultiColumnSet::LayoutMultiColumnSet(LayoutFlowThread* flow_thread) - : LayoutBlockFlow(nullptr), - fragmentainer_groups_(*this), - flow_thread_(flow_thread) { - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); -} - -LayoutMultiColumnSet* LayoutMultiColumnSet::CreateAnonymous( - LayoutFlowThread& flow_thread, - const ComputedStyle& parent_style) { - Document& document = flow_thread.GetDocument(); - LayoutMultiColumnSet* layout_object = - MakeGarbageCollected<LayoutMultiColumnSet>(&flow_thread); - layout_object->SetDocumentForAnonymous(&document); - layout_object->SetStyle( - document.GetStyleResolver().CreateAnonymousStyleWithDisplay( - parent_style, EDisplay::kBlock)); - return layout_object; -} - -void LayoutMultiColumnSet::Trace(Visitor* visitor) const { - visitor->Trace(fragmentainer_groups_); - visitor->Trace(flow_thread_); - LayoutBlockFlow::Trace(visitor); -} - -bool LayoutMultiColumnSet::IsLayoutNGObject() const { - NOT_DESTROYED(); - return false; -} - -unsigned LayoutMultiColumnSet::FragmentainerGroupIndexAtFlowThreadOffset( - LayoutUnit flow_thread_offset, - PageBoundaryRule rule) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - UpdateGeometryIfNeeded(); - DCHECK_GT(fragmentainer_groups_.size(), 0u); - if (flow_thread_offset <= 0) - return 0; - for (unsigned index = 0; index < fragmentainer_groups_.size(); index++) { - const auto& row = fragmentainer_groups_[index]; - if (rule == kAssociateWithLatterPage) { - if (row.LogicalTopInFlowThread() <= flow_thread_offset && - row.LogicalBottomInFlowThread() > flow_thread_offset) - return index; - } else if (row.LogicalTopInFlowThread() < flow_thread_offset && - row.LogicalBottomInFlowThread() >= flow_thread_offset) { - return index; - } - } - return fragmentainer_groups_.size() - 1; -} - -const MultiColumnFragmentainerGroup& -LayoutMultiColumnSet::FragmentainerGroupAtVisualPoint( - const LogicalOffset& visual_point) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - UpdateGeometryIfNeeded(); - DCHECK_GT(fragmentainer_groups_.size(), 0u); - LayoutUnit block_offset = visual_point.block_offset; - for (unsigned index = 0; index < fragmentainer_groups_.size(); index++) { - const auto& row = fragmentainer_groups_[index]; - if (row.LogicalTop() + row.GroupLogicalHeight() > block_offset) - return row; - } - return fragmentainer_groups_.Last(); -} - -bool LayoutMultiColumnSet::IsPageLogicalHeightKnown() const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return FirstFragmentainerGroup().IsLogicalHeightKnown(); -} - -LayoutMultiColumnSet* LayoutMultiColumnSet::NextSiblingMultiColumnSet() const { - NOT_DESTROYED(); - for (LayoutObject* sibling = NextSibling(); sibling; - sibling = sibling->NextSibling()) { - if (sibling->IsLayoutMultiColumnSet()) - return To<LayoutMultiColumnSet>(sibling); - } - return nullptr; -} - -LayoutMultiColumnSet* LayoutMultiColumnSet::PreviousSiblingMultiColumnSet() - const { - NOT_DESTROYED(); - for (LayoutObject* sibling = PreviousSibling(); sibling; - sibling = sibling->PreviousSibling()) { - if (sibling->IsLayoutMultiColumnSet()) - return To<LayoutMultiColumnSet>(sibling); - } - return nullptr; -} - -MultiColumnFragmentainerGroup& -LayoutMultiColumnSet::AppendNewFragmentainerGroup() { - NOT_DESTROYED(); - MultiColumnFragmentainerGroup new_group(*this); - { // Extra scope here for previousGroup; it's potentially invalid once we - // modify the m_fragmentainerGroups Vector. - MultiColumnFragmentainerGroup& previous_group = - fragmentainer_groups_.Last(); - - // This is the flow thread block offset where |previousGroup| ends and - // |newGroup| takes over. - LayoutUnit block_offset_in_flow_thread = - previous_group.LogicalTopInFlowThread() + - FragmentainerGroupCapacity(previous_group); - previous_group.SetLogicalBottomInFlowThread(block_offset_in_flow_thread); - new_group.SetLogicalTopInFlowThread(block_offset_in_flow_thread); - new_group.SetLogicalTop(previous_group.LogicalTop() + - previous_group.GroupLogicalHeight()); - new_group.ResetColumnHeight(); - } - fragmentainer_groups_.Append(new_group); - return fragmentainer_groups_.Last(); -} - -LayoutUnit LayoutMultiColumnSet::LogicalTopInFlowThread() const { - NOT_DESTROYED(); - return FirstFragmentainerGroup().LogicalTopInFlowThread(); -} - -LayoutUnit LayoutMultiColumnSet::LogicalBottomInFlowThread() const { - NOT_DESTROYED(); - return LastFragmentainerGroup().LogicalBottomInFlowThread(); -} - -PhysicalOffset LayoutMultiColumnSet::FlowThreadTranslationAtOffset( - LayoutUnit block_offset, - PageBoundaryRule rule) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return FragmentainerGroupAtFlowThreadOffset(block_offset, rule) - .FlowThreadTranslationAtOffset(block_offset, rule); -} - -LogicalOffset LayoutMultiColumnSet::VisualPointToFlowThreadPoint( - const PhysicalOffset& visual_point) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - LogicalOffset logical_point = - CreateWritingModeConverter().ToLogical(visual_point, {}); - const MultiColumnFragmentainerGroup& row = - FragmentainerGroupAtVisualPoint(logical_point); - return row.VisualPointToFlowThreadPoint(logical_point - - row.OffsetFromColumnSet()); -} - -void LayoutMultiColumnSet::ResetColumnHeight() { - NOT_DESTROYED(); - fragmentainer_groups_.DeleteExtraGroups(); - fragmentainer_groups_.First().ResetColumnHeight(); -} - -void LayoutMultiColumnSet::StyleDidChange(StyleDifference diff, - const ComputedStyle* old_style) { - NOT_DESTROYED(); - LayoutBlockFlow::StyleDidChange(diff, old_style); - - // column-rule is specified on the parent (the multicol container) of this - // object, but it's the column sets that are in charge of painting them. - // A column rule is pretty much like any other box decoration, like borders. - // We need to say that we have box decorations here, so that the columnn set - // is invalidated when it gets laid out. We cannot check here whether the - // multicol container actually has a visible column rule or not, because we - // may not have been inserted into the tree yet. Painting a column set is - // cheap anyway, because the only thing it can paint is the column rule, while - // actual multicol content is handled by the flow thread. - SetHasBoxDecorationBackground(true); -} - -LayoutUnit LayoutMultiColumnSet::ColumnGap() const { - NOT_DESTROYED(); - LayoutBlockFlow* parent_block = MultiColumnBlockFlow(); - - if (const std::optional<Length>& column_gap = - parent_block->StyleRef().ColumnGap()) { - return ValueForLength(*column_gap, AvailableLogicalWidth()); - } - - // "1em" is recommended as the normal gap setting. Matches <p> margins. - return LayoutUnit( - parent_block->StyleRef().GetFontDescription().ComputedPixelSize()); -} - -unsigned LayoutMultiColumnSet::ActualColumnCount() const { - NOT_DESTROYED(); - // FIXME: remove this method. It's a meaningless question to ask the set "how - // many columns do you actually have?", since that may vary for each row. - return FirstFragmentainerGroup().ActualColumnCount(); -} - -PhysicalRect LayoutMultiColumnSet::FragmentsBoundingBox( - const PhysicalRect& bounding_box_in_flow_thread) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - UpdateGeometryIfNeeded(); - PhysicalRect result; - for (const auto& group : fragmentainer_groups_) - result.Unite(group.FragmentsBoundingBox(bounding_box_in_flow_thread)); - return result; -} - -void LayoutMultiColumnSet::InsertedIntoTree() { - NOT_DESTROYED(); - LayoutBlockFlow::InsertedIntoTree(); - AttachToFlowThread(); -} - -void LayoutMultiColumnSet::WillBeRemovedFromTree() { - NOT_DESTROYED(); - LayoutBlockFlow::WillBeRemovedFromTree(); - DetachFromFlowThread(); -} - -DeprecatedLayoutPoint LayoutMultiColumnSet::DeprecatedLocationInternal() const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - UpdateGeometryIfNeeded(); - return frame_location_.layout_point; -} - -PhysicalSize LayoutMultiColumnSet::Size() const { - NOT_DESTROYED(); - UpdateGeometryIfNeeded(); - return frame_size_; -} - -void LayoutMultiColumnSet::UpdateGeometryIfNeeded() const { - if (!HasValidCachedGeometry() && EverHadLayout()) { - // const_cast in order to update the cached value. - const_cast<LayoutMultiColumnSet*>(this)->UpdateGeometry(); - } -} - -void LayoutMultiColumnSet::UpdateGeometry() { - NOT_DESTROYED(); - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - // Nobody cares. - return; - } - DCHECK(!HasValidCachedGeometry()); - SetHasValidCachedGeometry(true); - frame_location_.layout_point = DeprecatedLayoutPoint(); - ResetColumnHeight(); - const LayoutBlockFlow* container = MultiColumnBlockFlow(); - DCHECK_GT(container->PhysicalFragmentCount(), 0u); - - const auto* first_fragment = container->GetPhysicalFragment(0); - WritingMode writing_mode = first_fragment->Style().GetWritingMode(); - PhysicalBoxStrut border_padding_scrollbar = first_fragment->Borders() + - first_fragment->Padding() + - container->ComputeScrollbars(); - - // Set the inline-size to that of the content-box of the multicol container. - PhysicalSize content_size = - first_fragment->Size() - - PhysicalSize(border_padding_scrollbar.HorizontalSum(), - border_padding_scrollbar.VerticalSum()); - LogicalSize logical_size; - logical_size.inline_size = - ToLogicalSize(content_size, writing_mode).inline_size; - - // TODO(layout-dev): Ideally we should not depend on the layout tree structure - // because it may be different from the tree for the physical fragments. - const auto* previous_placeholder = - DynamicTo<LayoutMultiColumnSpannerPlaceholder>(PreviousSibling()); - bool seen_previous_placeholder = !previous_placeholder; - ChildFragmentIterator iter(*container); - LayoutUnit flow_thread_offset; - - // Skip until a column box after previous_placeholder. - for (; iter.IsValid(); iter.NextChild()) { - if (!iter->IsFragmentainerBox()) { - if (iter->IsLayoutObjectDestroyedOrMoved()) { - continue; - } - const auto* child_box = To<LayoutBox>(iter->GetLayoutObject()); - if (child_box->IsColumnSpanAll()) { - if (seen_previous_placeholder) { - // The legacy tree builder (the flow thread code) sometimes - // incorrectly keeps column sets that shouldn't be there anymore. If - // we have two column spanners, that are in fact adjacent, even though - // there's a spurious column set between them, the column set hasn't - // been initialized correctly (since we still have a - // pending_column_set at this point). Say hello to the column set that - // shouldn't exist, so that it gets some initialization. - SetIsIgnoredByNG(); - frame_size_ = ToPhysicalSize(logical_size, writing_mode); - return; - } - if (previous_placeholder && - child_box == previous_placeholder->LayoutObjectInFlowThread()) { - seen_previous_placeholder = true; - } - } - continue; - } - if (seen_previous_placeholder) { - break; - } - flow_thread_offset += FragmentainerLogicalCapacity(*iter).block_size; - } - if (!iter.IsValid()) { - SetIsIgnoredByNG(); - frame_size_ = ToPhysicalSize(logical_size, writing_mode); - return; - } - // Found the first column box after previous_placeholder. - - frame_location_.layout_point = ComputeLocation( - *iter, iter.Offset(), logical_size.inline_size, *container, - iter.FragmentIndex(), border_padding_scrollbar); - - while (true) { - LogicalSize fragmentainer_logical_size = - FragmentainerLogicalCapacity(*iter); - LastFragmentainerGroup().SetLogicalTopInFlowThread(flow_thread_offset); - logical_size.block_size += fragmentainer_logical_size.block_size; - flow_thread_offset += fragmentainer_logical_size.block_size; - LastFragmentainerGroup().SetColumnBlockSizeFromNG( - fragmentainer_logical_size.block_size); - - // Handle following fragmentainer boxes in the current container fragment. - wtf_size_t fragment_index = iter.FragmentIndex(); - bool should_expand_last_set = false; - while (iter.NextChild() && iter.FragmentIndex() == fragment_index) { - if (iter->IsFragmentainerBox()) { - LayoutUnit column_size = FragmentainerLogicalCapacity(*iter).block_size; - flow_thread_offset += column_size; - if (should_expand_last_set) { - LastFragmentainerGroup().ExtendColumnBlockSizeFromNG(column_size); - should_expand_last_set = false; - } - } else { - if (iter->IsColumnSpanAll()) { - const auto* placeholder = - iter->GetLayoutObject()->SpannerPlaceholder(); - // If there is no column set after the spanner, we should expand the - // last column set (if any) to encompass any columns that were created - // after the spanner. Only do this if we're actually past the last - // column set, though. We may have adjacent spanner placeholders, - // because the legacy and NG engines disagree on whether there's - // column content in-between (NG will create column content if the - // parent block of a spanner has trailing margin / border / padding, - // while legacy does not). - if (placeholder && !placeholder->NextSiblingMultiColumnBox()) { - should_expand_last_set = true; - continue; - } - } - break; - } - } - LastFragmentainerGroup().SetLogicalBottomInFlowThread(flow_thread_offset); - - if (!iter.IsValid()) { - break; - } - if (iter.FragmentIndex() == fragment_index || !iter->IsFragmentainerBox()) { - // Found a physical fragment with !IsFragmentainerBox(). - break; - } - AppendNewFragmentainerGroup(); - } - frame_size_ = ToPhysicalSize(logical_size, writing_mode); -} - -void LayoutMultiColumnSet::AttachToFlowThread() { - NOT_DESTROYED(); - if (DocumentBeingDestroyed()) - return; - - if (!flow_thread_) - return; - - flow_thread_->AddColumnSetToThread(this); -} - -void LayoutMultiColumnSet::DetachFromFlowThread() { - NOT_DESTROYED(); - if (flow_thread_) { - flow_thread_->RemoveColumnSetFromThread(this); - flow_thread_ = nullptr; - } -} - -void LayoutMultiColumnSet::SetIsIgnoredByNG() { - NOT_DESTROYED(); - fragmentainer_groups_.First().SetColumnBlockSizeFromNG(LayoutUnit()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_set.h b/third_party/blink/renderer/core/layout/layout_multi_column_set.h deleted file mode 100644 index 6ac4db0..0000000 --- a/third_party/blink/renderer/core/layout/layout_multi_column_set.h +++ /dev/null
@@ -1,225 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_SET_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_SET_H_ - -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" -#include "third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" - -namespace blink { - -// A set of columns in a multicol container. A column set is inserted as an -// anonymous child of the actual multicol container (i.e. the layoutObject whose -// style computes to non-auto column-count and/or column-width), next to the -// flow thread. There'll be one column set for each contiguous run of column -// content. The only thing that can interrupt a contiguous run of column content -// is a column spanner, which means that if there are no spanners, there'll -// only be one column set. -// -// Since a spanner interrupts an otherwise contiguous run of column content, -// inserting one may result in the creation of additional new column sets. A -// placeholder for the spanning layoutObject has to be placed in between the -// column sets that come before and after the spanner, if there's actually -// column content both before and after the spanner. -// -// A column set has no children on its own, but is merely used to slice a -// portion of the tall "single-column" flow thread into actual columns visually, -// to convert from flow thread coordinates to visual ones. It is in charge of -// both positioning columns correctly relatively to the parent multicol -// container, and to calculate the correct translation for each column's -// contents, and to paint any rules between them. LayoutMultiColumnSet objects -// are used for painting, hit testing, and any other type of operation that -// requires mapping from flow thread coordinates to visual coordinates. -// -// Columns are normally laid out in the inline progression direction, but if the -// multicol container is inside another fragmentation context (e.g. paged media, -// or an another multicol container), we may need to group the columns, so -// that we get one MultiColumnFragmentainerGroup for each outer fragmentainer -// (page / column) that the inner multicol container lives in. Each -// fragmentainer group has its own column height, but the column height is -// uniform within a group. -class CORE_EXPORT LayoutMultiColumnSet final : public LayoutBlockFlow { - public: - static LayoutMultiColumnSet* CreateAnonymous( - LayoutFlowThread&, - const ComputedStyle& parent_style); - - void Trace(Visitor*) const override; - - bool IsLayoutNGObject() const final; - - const MultiColumnFragmentainerGroup& FirstFragmentainerGroup() const { - NOT_DESTROYED(); - UpdateGeometryIfNeeded(); - return fragmentainer_groups_.First(); - } - const MultiColumnFragmentainerGroup& LastFragmentainerGroup() const { - NOT_DESTROYED(); - UpdateGeometryIfNeeded(); - return fragmentainer_groups_.Last(); - } - MultiColumnFragmentainerGroup& LastFragmentainerGroup() { - NOT_DESTROYED(); - UpdateGeometryIfNeeded(); - return fragmentainer_groups_.Last(); - } - unsigned FragmentainerGroupIndexAtFlowThreadOffset(LayoutUnit, - PageBoundaryRule) const; - const MultiColumnFragmentainerGroup& FragmentainerGroupAtFlowThreadOffset( - LayoutUnit flow_thread_offset, - PageBoundaryRule rule) const { - NOT_DESTROYED(); - UpdateGeometryIfNeeded(); - return fragmentainer_groups_[FragmentainerGroupIndexAtFlowThreadOffset( - flow_thread_offset, rule)]; - } - const MultiColumnFragmentainerGroup& FragmentainerGroupAtVisualPoint( - const LogicalOffset&) const; - const MultiColumnFragmentainerGroupList& FragmentainerGroups() const { - NOT_DESTROYED(); - UpdateGeometryIfNeeded(); - return fragmentainer_groups_; - } - - bool IsLayoutMultiColumnSet() const final { - NOT_DESTROYED(); - return true; - } - bool CanHaveChildren() const final { - NOT_DESTROYED(); - return false; - } - - // Return the width and height of a single column or page in the set. - LayoutUnit PageLogicalWidth() const { - NOT_DESTROYED(); - return FlowThread()->LogicalWidth(); - } - bool IsPageLogicalHeightKnown() const; - - LayoutFlowThread* FlowThread() const { - NOT_DESTROYED(); - return flow_thread_.Get(); - } - - LayoutBlockFlow* MultiColumnBlockFlow() const { - NOT_DESTROYED(); - return To<LayoutBlockFlow>(Parent()); - } - LayoutMultiColumnFlowThread* MultiColumnFlowThread() const { - NOT_DESTROYED(); - return To<LayoutMultiColumnFlowThread>(FlowThread()); - } - - LayoutMultiColumnSet* NextSiblingMultiColumnSet() const; - LayoutMultiColumnSet* PreviousSiblingMultiColumnSet() const; - - MultiColumnFragmentainerGroup& AppendNewFragmentainerGroup(); - - LayoutUnit LogicalTopInFlowThread() const; - LayoutUnit LogicalBottomInFlowThread() const; - - // Return the amount of flow thread contents that the specified fragmentainer - // group can hold without overflowing. - LayoutUnit FragmentainerGroupCapacity( - const MultiColumnFragmentainerGroup& group) const { - NOT_DESTROYED(); - return group.ColumnLogicalHeight() * UsedColumnCount(); - } - - // The used CSS value of column-count, i.e. how many columns there are room - // for without overflowing. - unsigned UsedColumnCount() const { - NOT_DESTROYED(); - return MultiColumnFlowThread()->ColumnCount(); - } - - // Find the column that contains the given block offset, and return the - // translation needed to get from flow thread coordinates to visual - // coordinates. - PhysicalOffset FlowThreadTranslationAtOffset(LayoutUnit, - PageBoundaryRule) const; - - LogicalOffset VisualPointToFlowThreadPoint( - const PhysicalOffset& visual_point) const; - - // Reset previously calculated column height. Will mark for layout if needed. - void ResetColumnHeight(); - - void StyleDidChange(StyleDifference, const ComputedStyle* old_style) override; - - void AttachToFlowThread(); - void DetachFromFlowThread(); - - PhysicalRect FragmentsBoundingBox( - const PhysicalRect& bounding_box_in_flow_thread) const; - - LayoutUnit ColumnGap() const; - - // The "CSS actual" value of column-count. This includes overflowing columns, - // if any. - unsigned ActualColumnCount() const; - - const char* GetName() const override { - NOT_DESTROYED(); - return "LayoutMultiColumnSet"; - } - DeprecatedLayoutPoint DeprecatedLocationInternal() const override; - - // Tell the column set that it shouldn't really exist. This happens when - // there's a leftover column set after DOM / style changes, that NG doesn't - // care about. - void SetIsIgnoredByNG(); - - LayoutMultiColumnSet(LayoutFlowThread*); - - private: - void InsertedIntoTree() final; - void WillBeRemovedFromTree() final; - PhysicalSize Size() const override; - - // This function updates frame_location_, frame_size_, and build - // fragmentainer_groups_. - void UpdateGeometry(); - // Call UpdateGeometry() if !HasValidCachedGeometry(). - void UpdateGeometryIfNeeded() const; - - MultiColumnFragmentainerGroupList fragmentainer_groups_; - Member<LayoutFlowThread> flow_thread_; -}; - -template <> -struct DowncastTraits<LayoutMultiColumnSet> { - static bool AllowFrom(const LayoutObject& object) { - return object.IsLayoutMultiColumnSet(); - } -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_SET_H_
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_set_test.cc b/third_party/blink/renderer/core/layout/layout_multi_column_set_test.cc deleted file mode 100644 index ad61b7a7..0000000 --- a/third_party/blink/renderer/core/layout/layout_multi_column_set_test.cc +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" - -namespace blink { - -class LayoutMultiColumnSetTest : public RenderingTest {}; - -// crbug.com/1420201 -TEST_F(LayoutMultiColumnSetTest, ScrollAnchroingCrash) { - SetBodyInnerHTML(R"HTML( -<style> -.c3 { - padding-top: 100%; -} -.c4 { - appearance: button; - column-span: all; -} -.c7 { - position: absolute; - padding-left: 65536px; - zoom: 5; - column-width: 10px; -} -.c13 { - zoom: 5; - column-span: all; - height: 10px; -} -</style> -<div class=c7><div class=c13></div><map class=c4></map></div> -<h1 class=c3><button></button></h1>)HTML"); - // Triggers scroll anchoring. - QuerySelector("button")->Focus(); - UpdateAllLifecyclePhasesForTest(); - - // Reattach c13. - Element* target = QuerySelector(".c13"); - auto* parent = target->parentNode(); - parent->removeChild(target); - parent->insertBefore(target, parent->firstChild()); - // Make sure LayoutMultiColumnSet::UpdateGeometry() is called. - parent->GetLayoutBox()->InvalidateCachedGeometry(); - UpdateAllLifecyclePhasesForTest(); - // Pass if no crash in UpdateGeometry() called through ScrollAnchor. -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc deleted file mode 100644 index fe8192cd..0000000 --- a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.cc +++ /dev/null
@@ -1,119 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" - -#include "third_party/blink/renderer/core/css/resolver/style_resolver.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" -#include "third_party/blink/renderer/core/layout/layout_object_inlines.h" - -namespace blink { - -static void CopyMarginProperties( - ComputedStyleBuilder& placeholder_style_builder, - const ComputedStyle& spanner_style) { - // We really only need the block direction margins, but there are no setters - // for that in ComputedStyle. Just copy all margin sides. The inline ones - // don't matter anyway. - placeholder_style_builder.SetMarginLeft(spanner_style.MarginLeft()); - placeholder_style_builder.SetMarginRight(spanner_style.MarginRight()); - placeholder_style_builder.SetMarginTop(spanner_style.MarginTop()); - placeholder_style_builder.SetMarginBottom(spanner_style.MarginBottom()); -} - -LayoutMultiColumnSpannerPlaceholder* -LayoutMultiColumnSpannerPlaceholder::CreateAnonymous( - const ComputedStyle& parent_style, - LayoutBox& layout_object_in_flow_thread) { - LayoutMultiColumnSpannerPlaceholder* new_spanner = - MakeGarbageCollected<LayoutMultiColumnSpannerPlaceholder>( - &layout_object_in_flow_thread); - Document& document = layout_object_in_flow_thread.GetDocument(); - new_spanner->SetDocumentForAnonymous(&document); - new_spanner->UpdateProperties(parent_style); - return new_spanner; -} - -LayoutMultiColumnSpannerPlaceholder::LayoutMultiColumnSpannerPlaceholder( - LayoutBox* layout_object_in_flow_thread) - : LayoutBox(nullptr), - layout_object_in_flow_thread_(layout_object_in_flow_thread) { - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); -} - -void LayoutMultiColumnSpannerPlaceholder::Trace(Visitor* visitor) const { - visitor->Trace(layout_object_in_flow_thread_); - LayoutBox::Trace(visitor); -} - -void LayoutMultiColumnSpannerPlaceholder:: - LayoutObjectInFlowThreadStyleDidChange(const ComputedStyle* old_style) { - NOT_DESTROYED(); - LayoutBox* object_in_flow_thread = layout_object_in_flow_thread_; - if (FlowThread()->RemoveSpannerPlaceholderIfNoLongerValid( - object_in_flow_thread)) { - // No longer a valid spanner, due to style changes. |this| is now dead. - if (object_in_flow_thread->StyleRef().HasOutOfFlowPosition() && - !old_style->HasOutOfFlowPosition()) { - // We went from being a spanner to being out-of-flow positioned. When an - // object becomes out-of-flow positioned, we need to lay out its parent, - // since that's where the now-out-of-flow object gets added to the right - // containing block for out-of-flow positioned objects. Since neither a - // spanner nor an out-of-flow object is guaranteed to have this parent in - // its containing block chain, we need to mark it here, or we risk that - // the object isn't laid out. - object_in_flow_thread->Parent()->SetNeedsLayout( - layout_invalidation_reason::kColumnsChanged); - } - return; - } - UpdateProperties(Parent()->StyleRef()); -} - -void LayoutMultiColumnSpannerPlaceholder::UpdateProperties( - const ComputedStyle& parent_style) { - NOT_DESTROYED(); - ComputedStyleBuilder new_style_builder = - GetDocument().GetStyleResolver().CreateAnonymousStyleBuilderWithDisplay( - parent_style, EDisplay::kBlock); - CopyMarginProperties(new_style_builder, - layout_object_in_flow_thread_->StyleRef()); - SetStyle(new_style_builder.TakeStyle()); -} - -void LayoutMultiColumnSpannerPlaceholder::InsertedIntoTree() { - NOT_DESTROYED(); - LayoutBox::InsertedIntoTree(); - // The object may previously have been laid out as a non-spanner, but since - // it's a spanner now, it needs to be relaid out. - layout_object_in_flow_thread_->SetNeedsLayoutAndIntrinsicWidthsRecalc( - layout_invalidation_reason::kColumnsChanged); -} - -void LayoutMultiColumnSpannerPlaceholder::WillBeRemovedFromTree() { - NOT_DESTROYED(); - if (layout_object_in_flow_thread_) { - LayoutBox* ex_spanner = layout_object_in_flow_thread_; - layout_object_in_flow_thread_->ClearSpannerPlaceholder(); - // Even if the placeholder is going away, the object in the flow thread - // might live on. Since it's not a spanner anymore, it needs to be relaid - // out. - ex_spanner->SetNeedsLayoutAndIntrinsicWidthsRecalc( - layout_invalidation_reason::kColumnsChanged); - } - LayoutBox::WillBeRemovedFromTree(); -} - -DeprecatedLayoutPoint -LayoutMultiColumnSpannerPlaceholder::DeprecatedLocationInternal() const { - NOT_DESTROYED(); - return layout_object_in_flow_thread_->DeprecatedLocationInternal(); -} - -PhysicalSize LayoutMultiColumnSpannerPlaceholder::Size() const { - NOT_DESTROYED(); - return layout_object_in_flow_thread_->Size(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h b/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h deleted file mode 100644 index 552799bc..0000000 --- a/third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h +++ /dev/null
@@ -1,83 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_SPANNER_PLACEHOLDER_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_SPANNER_PLACEHOLDER_H_ - -#include "base/notreached.h" -#include "third_party/blink/renderer/core/layout/layout_block_flow.h" - -namespace blink { - -// Placeholder layoutObject for column-span:all elements. The column-span:all -// layoutObject itself is a descendant of the flow thread, but due to its -// out-of-flow nature, we need something on the outside to take care of its -// positioning and sizing. LayoutMultiColumnSpannerPlaceholder objects are -// siblings of LayoutMultiColumnSet objects, i.e. direct children of the -// multicol container. -class LayoutMultiColumnSpannerPlaceholder final : public LayoutBox { - public: - bool IsLayoutMultiColumnSpannerPlaceholder() const final { - NOT_DESTROYED(); - return true; - } - - static LayoutMultiColumnSpannerPlaceholder* CreateAnonymous( - const ComputedStyle& parent_style, - LayoutBox&); - - void Trace(Visitor*) const override; - - LayoutBlockFlow* MultiColumnBlockFlow() const { - NOT_DESTROYED(); - return To<LayoutBlockFlow>(Parent()); - } - - LayoutMultiColumnFlowThread* FlowThread() const { - NOT_DESTROYED(); - return To<LayoutBlockFlow>(Parent())->MultiColumnFlowThread(); - } - - LayoutBox* LayoutObjectInFlowThread() const { - NOT_DESTROYED(); - return layout_object_in_flow_thread_.Get(); - } - - bool AnonymousHasStylePropagationOverride() final { - NOT_DESTROYED(); - return true; - } - - void LayoutObjectInFlowThreadStyleDidChange(const ComputedStyle* old_style); - void UpdateProperties(const ComputedStyle& parent_style); - - explicit LayoutMultiColumnSpannerPlaceholder(LayoutBox*); - - const char* GetName() const override { - NOT_DESTROYED(); - return "LayoutMultiColumnSpannerPlaceholder"; - } - - protected: - void InsertedIntoTree() override; - void WillBeRemovedFromTree() override; - - private: - DeprecatedLayoutPoint DeprecatedLocationInternal() const override; - PhysicalSize Size() const override; - - // The actual column-span:all layoutObject inside the flow thread. - Member<LayoutBox> layout_object_in_flow_thread_; -}; - -template <> -struct DowncastTraits<LayoutMultiColumnSpannerPlaceholder> { - static bool AllowFrom(const LayoutObject& object) { - return object.IsLayoutMultiColumnSpannerPlaceholder(); - } -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_MULTI_COLUMN_SPANNER_PLACEHOLDER_H_
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index db87e9e0..f84ddba 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -91,11 +91,9 @@ #include "third_party/blink/renderer/core/layout/layout_counter.h" #include "third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h" #include "third_party/blink/renderer/core/layout/layout_embedded_content.h" -#include "third_party/blink/renderer/core/layout/layout_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_image.h" #include "third_party/blink/renderer/core/layout/layout_image_resource_style_image.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" #include "third_party/blink/renderer/core/layout/layout_object_inl.h" #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_result.h" @@ -156,7 +154,6 @@ LayoutObject* FindColumnSpannerContainer( const LayoutObject* spanner, LayoutObject::AncestorSkipInfo* skip_info) { - DCHECK(RuntimeEnabledFeatures::FlowThreadLessEnabled()); DCHECK(spanner->IsColumnSpanAll()); for (LayoutObject* walker = spanner->Parent(); walker; walker = walker->ContainingBlock(skip_info)) { @@ -183,39 +180,15 @@ skip_info->Update(*object); if (object->IsColumnSpanAll()) [[unlikely]] { - if (RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - object = FindColumnSpannerContainer(object, skip_info); - continue; - } - // The containing block chain goes directly from the column spanner to the - // multi-column container. - const auto* multicol_container = - object->SpannerPlaceholder()->MultiColumnBlockFlow(); - if (multicol_container->IsLayoutNGObject()) { - while (object->Parent() != multicol_container) { - object = object->Parent(); - if (skip_info) - skip_info->Update(*object); - } - } + object = FindColumnSpannerContainer(object, skip_info); + continue; } object = object->Parent(); } return nullptr; } -inline bool MightTraversePhysicalFragments(const LayoutObject& obj) { - if (!obj.IsLayoutNGObject()) { - // Non-NG objects should be painted, hit-tested, etc. by legacy. - if (obj.IsBox()) - return false; - // Non-LayoutBox objects (such as LayoutInline) don't necessarily create NG - // LayoutObjects. If they are laid out by an NG container, though, we may be - // allowed to traverse their fragments. We can't check that at this point - // (potentially before initial layout), though. Unless there are other - // reasons that prevent us from allowing fragment traversal, we'll - // optimistically return true now, and check later. - } +inline bool CalculateCanTraversePhysicalFragments(const LayoutObject& obj) { // The NG paint system currently doesn't support replaced content. if (obj.IsLayoutReplaced()) return false; @@ -224,6 +197,13 @@ if (obj.IsTextControl()) { return false; } + // SVG objects do their own things. The exception here is SVG block containers + // (such as foreignObject or text), which are fully handled by the regular + // layout engine. + if (obj.IsSVG() && !obj.IsLayoutBlock()) { + return false; + } + return true; } @@ -1206,9 +1186,6 @@ auto FindContainer = [](const LayoutObject& object) -> const LayoutObject* { if (object.IsColumnSpanAll()) { // Column spanners paint through their multicolumn containers. - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - return object.SpannerPlaceholder(); - } return object.ContainerForColumnSpanner(); } // Physical fragments and fragment items for ruby-text boxes are not @@ -1297,11 +1274,6 @@ LayoutBlock* containing_block = ContainingBlock(); if (!containing_block) return nullptr; - // Flow threads should be invisible to LayoutNG, so skip to the multicol - // container. - if (containing_block->IsLayoutFlowThread()) [[unlikely]] { - containing_block = To<LayoutBlockFlow>(containing_block->Parent()); - } if (!containing_block->IsLayoutNGObject()) return nullptr; return containing_block; @@ -1335,14 +1307,6 @@ return block_flow && !block_flow->NeedsLayout(); } -LayoutFlowThread* LayoutObject::LocateFlowThreadContainingBlock() const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); - DCHECK(IsInsideMulticol()); - return LayoutFlowThread::LocateFlowThreadContainingBlockOf( - *this, LayoutFlowThread::kAnyAncestor); -} - static inline bool ObjectIsRelayoutBoundary(const LayoutObject* object) { // Only LayoutBox (and subclasses) are allowed to be relayout roots. const auto* box = DynamicTo<LayoutBox>(object); @@ -1506,9 +1470,7 @@ return; } - // Don't mark |LayoutFlowThread| because |CollectInlines()| skips them. - if (!IsLayoutFlowThread()) - SetNeedsCollectInlines(true); + SetNeedsCollectInlines(true); if (LayoutObject* parent = Parent()) parent->SetChildNeedsCollectInlines(); @@ -1518,11 +1480,6 @@ NOT_DESTROYED(); LayoutObject* object = this; do { - // Should not stop at |LayoutFlowThread| as |CollectInlines()| skips them. - if (object->IsLayoutFlowThread()) [[unlikely]] { - object = object->Parent(); - continue; - } if (object->NeedsCollectInlines()) break; object->SetNeedsCollectInlines(true); @@ -1727,11 +1684,6 @@ return true; } - // Flow threads also don't have min/max sizes computed. - if (o->IsLayoutFlowThread()) { - return true; - } - // Invalidate past any subgrids. NOTE: we do this in both axes as we don't // know what writing-mode the root grid is in. if (o->IsLayoutGrid()) { @@ -1787,7 +1739,6 @@ LayoutObject* LayoutObject::ContainerForColumnSpanner( AncestorSkipInfo* skip_info) const { NOT_DESTROYED(); - DCHECK(RuntimeEnabledFeatures::FlowThreadLessEnabled()); return FindColumnSpannerContainer(this, skip_info); } @@ -3282,10 +3233,8 @@ } } } else if (IsBox() && - ((!RuntimeEnabledFeatures::FlowThreadLessEnabled() && - old_style->GetColumnSpan() != style_->GetColumnSpan()) || - To<LayoutBox>(this)->IsValidColumnSpanner(*old_style) != - To<LayoutBox>(this)->IsValidColumnSpanner(*style_))) { + To<LayoutBox>(this)->IsValidColumnSpanner(*old_style) != + To<LayoutBox>(this)->IsValidColumnSpanner(*style_)) { MarkParentForSpannerOrOutOfFlowPositionedChange(); } @@ -3533,14 +3482,6 @@ return; PhysicalOffset container_offset = OffsetFromContainer(container, mode); - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled() && - IsLayoutFlowThread()) { - // So far the point has been in flow thread coordinates (i.e. as if - // everything in the fragmentation context lived in one tall single column). - // Convert it to a visual point now, since we're about to escape the flow - // thread. - container_offset += ColumnOffset(transform_state.MappedPoint()); - } // Text objects just copy their parent's computed style, so we need to ignore // them. @@ -3617,16 +3558,6 @@ : TransformState::kFlattenTransform); } - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled() && - IsLayoutFlowThread()) { - // Descending into a flow thread. Convert to the local coordinate space, - // i.e. flow thread coordinates. - PhysicalOffset visual_point = transform_state.MappedPoint(); - transform_state.Move( - visual_point - - To<LayoutFlowThread>(this)->VisualPointToFlowThreadPoint(visual_point)); - } - if (skip_info.AncestorSkipped()) { container_offset = ancestor->OffsetFromAncestor(container); transform_state.Move(-container_offset); @@ -3742,15 +3673,6 @@ return transform_state.AccumulatedTransform(); } -bool LayoutObject::OffsetForContainerDependsOnPoint( - const LayoutObject* container) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return IsLayoutFlowThread() || - (container->StyleRef().IsFlippedBlocksWritingMode() && - container->IsBox()); -} - PhysicalOffset LayoutObject::OffsetFromContainerInternal( const LayoutObject* o, MapCoordinatesFlags mode) const { @@ -3905,8 +3827,8 @@ // FIXME: We should DCHECK(isRooted()) here but generated content makes some // out-of-order insertion. - bitfields_.SetMightTraversePhysicalFragments( - MightTraversePhysicalFragments(*this)); + bitfields_.SetCanTraversePhysicalFragments( + CalculateCanTraversePhysicalFragments(*this)); // Keep our layer hierarchy updated. Optimize for the common case where we // don't have any children and don't have a layer attached to ourselves. @@ -3934,12 +3856,6 @@ if (Parent()->ChildrenInline()) Parent()->DirtyLinesFromChangedChild(this); - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - if (LayoutFlowThread* flow_thread = FlowThreadContainingBlock()) { - flow_thread->FlowThreadDescendantWasInserted(this); - } - } - if (const Element* element = DynamicTo<Element>(GetNode()); element && element->HasImplicitlyAnchoredElement()) { MarkMayHaveAnchorQuery(); @@ -4002,10 +3918,6 @@ if (IsOutOfFlowPositioned() && Parent()->ChildrenInline()) Parent()->DirtyLinesFromChangedChild(this); - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - RemoveFromLayoutFlowThread(); - } - if (bitfields_.IsScrollAnchorObject()) { // Clear the bit first so that anchor.clear() doesn't recurse into // findReferencingScrollAnchors. @@ -4047,52 +3959,6 @@ FindReferencingScrollAnchors(this, kDontClear)); } -void LayoutObject::RemoveFromLayoutFlowThread() { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); - if (!IsInsideMulticol()) { - return; - } - - // Sometimes we remove the element from the flow, but it's not destroyed at - // that time. - // It's only until later when we actually destroy it and remove all the - // children from it. - // Currently, that happens for firstLetter elements and list markers. - // Pass in the flow thread so that we don't have to look it up for all the - // children. - // If we're a column spanner, we need to use our parent to find the flow - // thread, since a spanner doesn't have the flow thread in its containing - // block chain. We still need to notify the flow thread when the layoutObject - // removed happens to be a spanner, so that we get rid of the spanner - // placeholder, and column sets around the placeholder get merged. - LayoutFlowThread* flow_thread = IsColumnSpanAll() - ? Parent()->FlowThreadContainingBlock() - : FlowThreadContainingBlock(); - RemoveFromLayoutFlowThreadRecursive(flow_thread); -} - -void LayoutObject::RemoveFromLayoutFlowThreadRecursive( - LayoutFlowThread* layout_flow_thread) { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); - if (const LayoutObjectChildList* children = VirtualChildren()) { - for (LayoutObject* child = children->FirstChild(); child; - child = child->NextSibling()) { - if (child->IsLayoutFlowThread()) - continue; // Don't descend into inner fragmentation contexts. - child->RemoveFromLayoutFlowThreadRecursive( - child->IsLayoutFlowThread() ? To<LayoutFlowThread>(child) - : layout_flow_thread); - } - } - - if (layout_flow_thread && layout_flow_thread != this) - layout_flow_thread->FlowThreadDescendantWillBeRemoved(this); - SetIsInsideMulticol(false); - CHECK(!SpannerPlaceholder()); -} - void LayoutObject::DestroyAndCleanupAnonymousWrappers( bool performing_reattach) { NOT_DESTROYED(); @@ -4107,10 +3973,6 @@ for (; destroy_root_parent && destroy_root_parent->IsAnonymous(); destroy_root = destroy_root_parent, destroy_root_parent = destroy_root_parent->Parent()) { - // A flow thread is tracked by its containing block. Whether its children - // are removed or not is irrelevant. - if (destroy_root_parent->IsLayoutFlowThread()) - break; // The anonymous fieldset contents wrapper should be kept. if (destroy_root_parent->Parent() && destroy_root_parent->Parent()->IsFieldset()) {
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index 9f77156..18c4a8e 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -67,7 +67,6 @@ #include "third_party/blink/renderer/platform/graphics/paint_invalidation_reason.h" #include "third_party/blink/renderer/platform/graphics/subtree_paint_property_update_reason.h" #include "third_party/blink/renderer/platform/graphics/visual_rect_flags.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "ui/gfx/geometry/quad_f.h" #include "ui/gfx/geometry/transform.h" @@ -84,8 +83,6 @@ class HitTestResult; class LayoutBlock; class LayoutBlockFlow; -class LayoutFlowThread; -class LayoutMultiColumnSpannerPlaceholder; class LayoutView; class LocalFrameView; class PaintLayer; @@ -330,10 +327,6 @@ // Returns false iff this object or one of its ancestors has opacity:0. bool HasNonZeroEffectiveOpacity() const; - // Returns true if the offset ot the containing block depends on the point - // being mapped. - bool OffsetForContainerDependsOnPoint(const LayoutObject* container) const; - protected: void EnsureIdForTesting() { NOT_DESTROYED(); @@ -463,17 +456,6 @@ // Return the nearest fragmentation context root, if any. LayoutBlock* ContainingFragmentationContextRoot() const; - // Function to return our enclosing flow thread if we are contained inside - // one. This function follows the containing block chain. - LayoutFlowThread* FlowThreadContainingBlock() const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); - if (!IsInsideMulticol()) { - return nullptr; - } - return LocateFlowThreadContainingBlock(); - } - #if DCHECK_IS_ON() void SetHasAXObject(bool flag) { NOT_DESTROYED(); @@ -752,18 +734,6 @@ NOT_DESTROYED(); parent_ = parent; - if (!RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - // Only update if our flow thread state is different from our new parent - // and if we're not a LayoutFlowThread. A LayoutFlowThread is always - // considered to be inside itself, so it never has to change its state in - // response to parent changes. - bool inside_multicol = parent && parent->IsInsideMulticol(); - if (inside_multicol != IsInsideMulticol() && !IsLayoutFlowThread()) { - SetIsInsideMulticolIncludingDescendants(inside_multicol); - } - return; - } - bool inside_multicol = parent && (parent->IsInsideMulticol() || parent->IsMulticolContainer()); if (inside_multicol != IsInsideMulticol()) { @@ -950,14 +920,6 @@ NOT_DESTROYED(); return false; } - virtual bool IsLayoutMultiColumnSet() const { - NOT_DESTROYED(); - return false; - } - virtual bool IsLayoutMultiColumnSpannerPlaceholder() const { - NOT_DESTROYED(); - return false; - } virtual bool IsLayoutReplaced() const { NOT_DESTROYED(); return false; @@ -1032,10 +994,6 @@ NOT_DESTROYED(); return false; } - virtual bool IsLayoutFlowThread() const { - NOT_DESTROYED(); - return false; - } virtual bool IsLayoutInline() const { NOT_DESTROYED(); return false; @@ -1170,10 +1128,6 @@ bitfields_.SetIsInsideMulticol(b); } - // Remove this object and all descendants from the containing - // LayoutFlowThread. - void RemoveFromLayoutFlowThread(); - // Return true if this object might be inside a fragmentation context, or // false if it's definitely *not* inside one. bool MightBeInsideFragmentationContext() const { @@ -1343,8 +1297,7 @@ bool IsAnonymousBlockFlow() const { NOT_DESTROYED(); return IsAnonymous() && IsLayoutBlockFlow() && - StyleRef().Display() == EDisplay::kBlock && !IsLayoutFlowThread() && - !IsLayoutMultiColumnSet(); + StyleRef().Display() == EDisplay::kBlock; } bool IsFloating() const { @@ -1731,11 +1684,6 @@ return GetDocument().GetFrame(); } - virtual LayoutMultiColumnSpannerPlaceholder* SpannerPlaceholder() const { - NOT_DESTROYED(); - return nullptr; - } - // Return true if this box is to be treated as a column spanner. In order to // return true, this function requires `column-span` to be `all`, but there // are additional requirements as well, for it to actually become a @@ -1991,16 +1939,7 @@ // tree instead. bool CanTraversePhysicalFragments() const { NOT_DESTROYED(); - - if (!bitfields_.MightTraversePhysicalFragments()) - return false; - - // Non-LayoutBox objects (such as LayoutInline) don't necessarily create NG - // LayoutObjects. We'll allow traversing their fragments if they are laid - // out by an NG container. - if (!IsBox()) - return IsInLayoutNGInlineFormattingContext(); - return true; + return bitfields_.CanTraversePhysicalFragments(); } // Return true if this is a LayoutBox without physical fragments. @@ -2567,15 +2506,6 @@ // Do a rect-based hit test with this object as the stop node. HitTestResult HitTestForOcclusion(const PhysicalRect&) const; - // Return the offset to the column in which the specified point (in - // flow-thread coordinates) lives. This is used to convert a flow-thread point - // to a point in the containing coordinate space. - virtual PhysicalOffset ColumnOffset(const PhysicalOffset&) const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return PhysicalOffset(); - } - bool IsFloatingOrOutOfFlowPositioned() const { NOT_DESTROYED(); return (IsFloating() || IsOutOfFlowPositioned()); @@ -3593,9 +3523,9 @@ bitfields_.SetSVGDescendantMayHaveTransformRelatedOperations(false); } - void SetMightTraversePhysicalFragments(bool b) { + void SetCanTraversePhysicalFragments(bool b) { NOT_DESTROYED(); - bitfields_.SetMightTraversePhysicalFragments(b); + bitfields_.SetCanTraversePhysicalFragments(b); } void SetHasValidCachedGeometry(bool b) { @@ -3655,9 +3585,6 @@ // |SetShouldInvalidateSelection| on all selected children. void InvalidateSelectedChildrenOnStyleChange(); - LayoutFlowThread* LocateFlowThreadContainingBlock() const; - void RemoveFromLayoutFlowThreadRecursive(LayoutFlowThread*); - // Returns `true` if the LayoutObject is for the specified pseudo-element // type. inline bool IsPseudoElementContent(PseudoId pseudo_id) const; @@ -3829,7 +3756,7 @@ should_skip_next_layout_shift_tracking_(true), should_assume_paint_offset_translation_for_layout_shift_tracking_( false), - might_traverse_physical_fragments_(true), + can_traverse_physical_fragments_(true), whitespace_children_may_change_(false), needs_devtools_info_(false), may_have_anchor_query_(false), @@ -4153,10 +4080,11 @@ should_assume_paint_offset_translation_for_layout_shift_tracking_, ShouldAssumePaintOffsetTranslationForLayoutShiftTracking); - // True if there's a possibility that we can walk NG fragment children of - // this object. False if we definitely need to walk the LayoutObject tree. - ADD_BOOLEAN_BITFIELD(might_traverse_physical_fragments_, - MightTraversePhysicalFragments); + // True if we can walk fragment children of this object (for painting, + // hit-testing, and so on). False if we need to walk the LayoutObject tree + // instead. + ADD_BOOLEAN_BITFIELD(can_traverse_physical_fragments_, + CanTraversePhysicalFragments); // True if children that may affect whitespace have been removed. If true // during style recalc, mark ancestors for layout tree rebuild to cause a
diff --git a/third_party/blink/renderer/core/layout/layout_object_hot.cc b/third_party/blink/renderer/core/layout/layout_object_hot.cc index b488da5..9544cc3 100644 --- a/third_party/blink/renderer/core/layout/layout_object_hot.cc +++ b/third_party/blink/renderer/core/layout/layout_object_hot.cc
@@ -7,7 +7,6 @@ #include "third_party/blink/renderer/core/layout/layout_block_flow.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_custom_scrollbar_part.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_spanner_placeholder.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_object_inl.h" #include "third_party/blink/renderer/core/layout/layout_text.h" @@ -46,18 +45,7 @@ } if (IsColumnSpanAll()) { - if (RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - return ContainerForColumnSpanner(skip_info); - } - LayoutObject* multicol_container = SpannerPlaceholder()->Container(); - if (skip_info) { - // We jumped directly from the spanner to the multicol container. Need to - // check if we skipped |ancestor| or filter/reflection on the way. - for (LayoutObject* walker = Parent(); - walker && walker != multicol_container; walker = walker->Parent()) - skip_info->Update(*walker); - } - return multicol_container; + return ContainerForColumnSpanner(skip_info); } return Parent(); @@ -66,15 +54,6 @@ void LayoutObject::SetNeedsOverflowRecalc( OverflowRecalcType overflow_recalc_type) { NOT_DESTROYED(); - if (IsLayoutFlowThread()) [[unlikely]] { - // If we're a flow thread inside an NG multicol container, just redirect to - // the multicol container, since the overflow recalculation walks down the - // NG fragment tree, and the flow thread isn't represented there. - if (auto* multicol_container = DynamicTo<LayoutBlockFlow>(Parent())) { - multicol_container->SetNeedsOverflowRecalc(overflow_recalc_type); - return; - } - } bool mark_container_chain_scrollable_overflow_recalc = !SelfNeedsScrollableOverflowRecalc(); @@ -227,11 +206,7 @@ } LayoutObject* object; if (IsColumnSpanAll()) { - if (RuntimeEnabledFeatures::FlowThreadLessEnabled()) { - object = ContainerForColumnSpanner(skip_info); - } else { - object = SpannerPlaceholder()->ContainingBlock(); - } + object = ContainerForColumnSpanner(skip_info); } else { object = Parent(); if (!object && IsLayoutCustomScrollbarPart()) {
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.cc b/third_party/blink/renderer/core/layout/layout_replaced.cc index 77198ebc..66018c37 100644 --- a/third_party/blink/renderer/core/layout/layout_replaced.cc +++ b/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -48,7 +48,6 @@ #include "third_party/blink/renderer/core/paint/replaced_painter.h" #include "third_party/blink/renderer/core/style/basic_shapes.h" #include "third_party/blink/renderer/core/style/computed_style_base_constants.h" -#include "third_party/blink/renderer/platform/geometry/layout_point.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" #include "third_party/blink/renderer/platform/geometry/length_functions.h" #include "third_party/blink/renderer/platform/geometry/physical_offset.h" @@ -388,15 +387,7 @@ const auto writing_direction = line_style.GetWritingDirection(); const WritingModeConverter converter(writing_direction, line_box.ContainerFragment().Size()); - PhysicalRect physical_rect; - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - physical_rect = line_box.CurrentRectInFirstContainerFragment(); - } else { - physical_rect = line_box.Current().RectInContainerFragment(); - // The caller expects it to be in the "stitched" coordinate space. - physical_rect.offset += - OffsetInStitchedFragments(line_box.ContainerFragment()); - } + PhysicalRect physical_rect = line_box.CurrentRectInFirstContainerFragment(); const LogicalRect logical_rect = converter.ToLogical(physical_rect); return {logical_rect.offset.block_offset, logical_rect.BlockEndOffset()}; }
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index 5385525..60c618e 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -655,11 +655,7 @@ quad.Scale(1 / scaling_factor, 1 / scaling_factor); quad = LocalToAbsoluteQuad(quad); } else { - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - rect.Move(cursor.CurrentOffsetInFirstContainerFragment()); - } else { - rect.Move(cursor.CurrentOffsetInBlockFlow()); - } + rect.Move(cursor.CurrentOffsetInFirstContainerFragment()); quad = LocalRectToAbsoluteQuad(rect); } if (!is_collapsed) {
diff --git a/third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h b/third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h deleted file mode 100644 index fdd9d1a..0000000 --- a/third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h +++ /dev/null
@@ -1,71 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LEGACY_LAYOUT_TREE_WALKING_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LEGACY_LAYOUT_TREE_WALKING_H_ - -#include "third_party/blink/renderer/core/layout/layout_block_flow.h" - -// We still have the legacy layout tree structure, which means that a multicol -// container LayoutBlockFlow will consist of a LayoutFlowThread child, followed -// by zero or more siblings of type LayoutMultiColumnSet and/or -// LayoutMultiColumnSpannerPlaceholder. NG needs to skip these special -// objects. The actual content is inside the flow thread. - -namespace blink { - -// Return the layout object that should be the first child LayoutInputNode of -// |parent|. Normally this will just be the first layout object child, but there -// are certain layout objects that should be skipped for NG. -inline LayoutObject* GetLayoutObjectForFirstChildNode(LayoutBlock* parent) { - LayoutObject* child = parent->FirstChild(); - if (!child) - return nullptr; - if (child->IsLayoutFlowThread()) [[unlikely]] { - child = To<LayoutBlockFlow>(child)->FirstChild(); - } - return child; -} - -// Return the layout object that should be the parent LayoutInputNode of -// |object|. Normally this will just be the parent layout object, but there -// are certain layout objects that should be skipped for NG. -// -// |Type| should be either "LayoutObject*" or "const LayoutObject*", and may be -// deduced automatically at the call site, based on the type of |object| (unless -// it's a subclass of LayoutObject rather than LayoutObject itself). -template <typename Type> -inline Type GetLayoutObjectForParentNode(Type object) { - // First check that we're not walking where we shouldn't be walking. - DCHECK(!object->IsLayoutFlowThread()); - DCHECK(!object->IsLayoutMultiColumnSet()); - DCHECK(!object->IsLayoutMultiColumnSpannerPlaceholder()); - - Type parent = object->Parent(); - if (!parent) [[unlikely]] { - return nullptr; - } - - if (parent->IsLayoutFlowThread()) [[unlikely]] { - return parent->Parent(); - } - return parent; -} - -// Return true if the LayoutInputNode children of the LayoutInputNode -// established by |block| will be inline; see LayoutObject::ChildrenInline(). -inline bool AreNGBlockFlowChildrenInline(const LayoutBlock* block) { - if (block->ChildrenInline()) - return true; - if (const auto* first_child = block->FirstChild()) { - if (first_child->IsLayoutFlowThread()) [[unlikely]] { - return first_child->ChildrenInline(); - } - } - return false; -} - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LEGACY_LAYOUT_TREE_WALKING_H_
diff --git a/third_party/blink/renderer/core/layout/list/layout_list_item.cc b/third_party/blink/renderer/core/layout/list/layout_list_item.cc index 953f1bb..9000e40f 100644 --- a/third_party/blink/renderer/core/layout/list/layout_list_item.cc +++ b/third_party/blink/renderer/core/layout/list/layout_list_item.cc
@@ -5,7 +5,6 @@ #include "third_party/blink/renderer/core/layout/list/layout_list_item.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/list/layout_inline_list_item.h" #include "third_party/blink/renderer/core/layout/list/list_marker.h" @@ -118,7 +117,7 @@ } if (object->IsAnonymousBlockFlow()) { - return FindSymbolMarkerLayoutText(GetLayoutObjectForParentNode(object)); + return FindSymbolMarkerLayoutText(object->Parent()); } if (object->IsLayoutTextCombine()) {
diff --git a/third_party/blink/renderer/core/layout/map_coordinates_test.cc b/third_party/blink/renderer/core/layout/map_coordinates_test.cc index d0ade5b4..a1d932c 100644 --- a/third_party/blink/renderer/core/layout/map_coordinates_test.cc +++ b/third_party/blink/renderer/core/layout/map_coordinates_test.cc
@@ -8,7 +8,6 @@ #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -787,9 +786,6 @@ LayoutObject* target = GetLayoutObjectByElementId("sibling")->NextSibling(); ASSERT_TRUE(target->IsText()); - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return; - } PhysicalOffset mapped_point = MapLocalToAncestor(target, multicol, PhysicalOffset(220, 20)); EXPECT_EQ(PhysicalOffset(225, 25), mapped_point); @@ -809,9 +805,6 @@ To<LayoutBlockFlow>(GetLayoutBoxByElementId("multicol")); LayoutObject* target = GetLayoutObjectByElementId("target"); - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return; - } PhysicalOffset mapped_point = MapLocalToAncestor(target, multicol, PhysicalOffset(220, 20)); EXPECT_EQ(PhysicalOffset(225, 25), mapped_point); @@ -883,9 +876,6 @@ EXPECT_EQ(PhysicalOffset(), mapped_point); // Walk each ancestor in the chain separately, to verify each step on the way. - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return; - } mapped_point = MapLocalToAncestor(target, inner_multicol, PhysicalOffset()); EXPECT_EQ(PhysicalOffset(420, 90), mapped_point); mapped_point = MapAncestorToLocal(target, inner_multicol, mapped_point);
diff --git a/third_party/blink/renderer/core/layout/masonry/masonry_layout_algorithm.cc b/third_party/blink/renderer/core/layout/masonry/masonry_layout_algorithm.cc index 80488cfb..f060fcf 100644 --- a/third_party/blink/renderer/core/layout/masonry/masonry_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/masonry/masonry_layout_algorithm.cc
@@ -38,8 +38,8 @@ MinMaxSizesResult MasonryLayoutAlgorithm::ComputeMinMaxSizes( const MinMaxSizesFloatInput&) { auto ComputeIntrinsicInlineSize = [&](SizingConstraint sizing_constraint) { - bool needs_auto_track_size = false; - std::optional<LayoutUnit> auto_repeat_track_size = std::nullopt; + bool needs_intrinsic_track_size = false; + std::optional<LayoutUnit> intrinsic_repeat_track_size = std::nullopt; wtf_size_t start_offset; GridItems masonry_items; Vector<wtf_size_t> collapsed_track_indexes; @@ -47,31 +47,32 @@ Style().MasonryTrackSizingDirection() == kForColumns; GridSizingTrackCollection track_collection = ComputeGridAxisTracks( - sizing_constraint, auto_repeat_track_size, masonry_items, - collapsed_track_indexes, start_offset, needs_auto_track_size); + sizing_constraint, intrinsic_repeat_track_size, masonry_items, + collapsed_track_indexes, start_offset, needs_intrinsic_track_size); - // We have a repeat() track definition with an auto sized track(s). The + // We have a repeat() track definition with an intrinsic sized track(s). The // previous track sizing pass was used to find the track size to apply - // to the auto sized track(s). Retrieve that value, and re-run track + // to the intrinsic sized track(s). Retrieve that value, and re-run track // sizing to get the correct number of automatic repetitions for the // repeat() definition. // // https://www.w3.org/TR/css-grid-3/#masonry-intrinsic-repeat - if (needs_auto_track_size) { - CHECK_NE(track_collection.GetAutoSizedRepeaterTrackIndex(), kNotFound); + if (needs_intrinsic_track_size) { + CHECK_NE(track_collection.GetIntrinsicSizedRepeaterTrackIndex(), + kNotFound); CHECK(collapsed_track_indexes.empty()); - // Note that when `needs_auto_track_size` is true, we skip the steps to - // distribute free space during track sizing. This means that the base + // Note that when `needs_intrinsic_track_size` is true, we skip the steps + // to distribute free space during track sizing. This means that the base // track size at this point represents the size of the intrinsic track // without free space distribution. - auto_repeat_track_size = + intrinsic_repeat_track_size = track_collection - .GetSetAt(track_collection.GetAutoSizedRepeaterTrackIndex()) + .GetSetAt(track_collection.GetIntrinsicSizedRepeaterTrackIndex()) .BaseSize(); track_collection = ComputeGridAxisTracks( - sizing_constraint, auto_repeat_track_size, masonry_items, - collapsed_track_indexes, start_offset, needs_auto_track_size); + sizing_constraint, intrinsic_repeat_track_size, masonry_items, + collapsed_track_indexes, start_offset, needs_intrinsic_track_size); } if (is_for_columns) { @@ -118,40 +119,40 @@ } const LayoutResult* MasonryLayoutAlgorithm::Layout() { - bool needs_auto_track_size = false; - std::optional<LayoutUnit> auto_repeat_track_size = std::nullopt; + bool needs_intrinsic_track_size = false; + std::optional<LayoutUnit> intrinsic_repeat_track_size = std::nullopt; wtf_size_t start_offset; GridItems masonry_items; HeapVector<Member<LayoutBox>> oof_children; Vector<wtf_size_t> collapsed_track_indexes; - GridSizingTrackCollection track_collection = - ComputeGridAxisTracks(SizingConstraint::kLayout, auto_repeat_track_size, - masonry_items, collapsed_track_indexes, - start_offset, needs_auto_track_size, &oof_children); + GridSizingTrackCollection track_collection = ComputeGridAxisTracks( + SizingConstraint::kLayout, intrinsic_repeat_track_size, masonry_items, + collapsed_track_indexes, start_offset, needs_intrinsic_track_size, + &oof_children); - // We have a repeat() track definition with an auto sized track(s). The + // We have a repeat() track definition with an intrinsic sized track(s). The // previous track sizing pass was used to find the track size to apply - // to the auto sized track(s). Retrieve that value, and re-run track + // to the intrinsic sized track(s). Retrieve that value, and re-run track // sizing to get the correct number of automatic repetitions for the // repeat() definition. // // https://www.w3.org/TR/css-grid-3/#masonry-intrinsic-repeat - if (needs_auto_track_size) { - CHECK_NE(track_collection.GetAutoSizedRepeaterTrackIndex(), kNotFound); + if (needs_intrinsic_track_size) { + CHECK_NE(track_collection.GetIntrinsicSizedRepeaterTrackIndex(), kNotFound); CHECK(collapsed_track_indexes.empty()); - // Note that when `needs_auto_track_size` is true, we skip the steps to + // Note that when `needs_intrinsic_track_size` is true, we skip the steps to // distribute free space during track sizing. This means that the base track // size at this point represents the size of the intrinsic track without // free space distribution. - auto_repeat_track_size = + intrinsic_repeat_track_size = track_collection - .GetSetAt(track_collection.GetAutoSizedRepeaterTrackIndex()) + .GetSetAt(track_collection.GetIntrinsicSizedRepeaterTrackIndex()) .BaseSize(); track_collection = ComputeGridAxisTracks( - SizingConstraint::kLayout, auto_repeat_track_size, masonry_items, - collapsed_track_indexes, start_offset, needs_auto_track_size); + SizingConstraint::kLayout, intrinsic_repeat_track_size, masonry_items, + collapsed_track_indexes, start_offset, needs_intrinsic_track_size); } if (!masonry_items.IsEmpty()) { @@ -287,7 +288,7 @@ is_for_layout ? CreateConstraintSpaceForLayout( masonry_item, track_collection, &containing_rect) : CreateConstraintSpaceForMeasure( - masonry_item, /*needs_auto_track_size=*/false, + masonry_item, /*needs_intrinsic_track_size=*/false, fixed_inline_size, /*is_for_min_max_sizing=*/true); @@ -393,7 +394,7 @@ GridItems MasonryLayoutAlgorithm::BuildVirtualMasonryItems( const GridLineResolver& line_resolver, const GridItems& masonry_items, - const bool needs_auto_track_size, + const bool needs_intrinsic_track_size, SizingConstraint sizing_constraint, const wtf_size_t auto_repetition_count, wtf_size_t& start_offset) const { @@ -414,7 +415,7 @@ is_for_columns ? style.GridTemplateColumns().GetTrackList() : style.GridTemplateRows().GetTrackList(); GridSpan auto_fit_span = GridSpan::IndefiniteGridSpan(); - if (!needs_auto_track_size && track_list.HasAutoRepeater() && + if (!needs_intrinsic_track_size && track_list.HasAutoRepeater() && track_list.RepeatType(track_list.AutoRepeatTrackIndex()) == GridTrackRepeater::RepeatType::kAutoFit) { auto_fit_span = GridSpan::TranslatedDefiniteGridSpan( @@ -436,8 +437,8 @@ for (const Member<GridItemData>& group_item : group_items) { const GridItemData& item_data = *group_item; const BlockNode& item_node = item_data.node; - const auto space = - CreateConstraintSpaceForMeasure(item_data, needs_auto_track_size); + const auto space = CreateConstraintSpaceForMeasure( + item_data, needs_intrinsic_track_size); const ComputedStyle& item_style = item_node.Style(); bool is_parallel = IsParallelWritingMode( @@ -457,14 +458,14 @@ ComputeMinAndMaxContentContributionForSelf(item_node, space).sizes; min_max_sizes += margins_sum; - // We have a repeat() track definition with an auto sized track(s). The - // current track sizing pass is used to find the track size to apply - // to the auto sized track(s). If the current item spans more than + // We have a repeat() track definition with an intrinsic sized track(s). + // The current track sizing pass is used to find the track size to apply + // to the intrinsic sized track(s). If the current item spans more than // one track, treat it as if it spans one track per the intrinsic // tracks and repeat algorithm [1]. // // [1] https://www.w3.org/TR/css-grid-3/#masonry-intrinsic-repeat - if (needs_auto_track_size && span_size > 1) { + if (needs_intrinsic_track_size && span_size > 1) { LayoutUnit total_gap_spanned = grid_axis_gap * (span_size - 1); min_max_sizes -= total_gap_spanned; min_max_sizes /= LayoutUnit(span_size); @@ -475,17 +476,17 @@ LayoutUnit block_contribution = ComputeMasonryItemBlockContribution( grid_axis_direction, sizing_constraint, space, &item_data, - needs_auto_track_size) + + needs_intrinsic_track_size) + margins_sum; - // We have a repeat() track definition with an auto sized track(s). The - // current track sizing pass is used to find the track size to apply - // to the auto sized track(s). If the current item spans more than + // We have a repeat() track definition with an intrinsic sized track(s). + // The current track sizing pass is used to find the track size to apply + // to the intrinsic sized track(s). If the current item spans more than // one track, treat it as if it spans one track per the intrinsic // tracks and repeat algorithm [1]. // // [1] https://www.w3.org/TR/css-grid-3/#masonry-intrinsic-repeat - if (needs_auto_track_size && span_size > 1) { + if (needs_intrinsic_track_size && span_size > 1) { LayoutUnit total_gap_spanned = grid_axis_gap * (span_size - 1); block_contribution -= total_gap_spanned; block_contribution /= span_size; @@ -495,19 +496,19 @@ } } - // If `needs_auto_track_size` is true, that means we have a repeat() track - // definition with an auto sized track(s). The current track sizing pass is - // used to find the track size to apply to the auto sized track(s). Ignore - // item placement as part of this pass, and apply all items in every - // position, regardless of explicit placement [1]. + // If `needs_intrinsic_track_size` is true, that means we have a repeat() + // track definition with an intrinsic sized track(s). The current track + // sizing pass is used to find the track size to apply to the intrinsic + // sized track(s). Ignore item placement as part of this pass, and apply all + // items in every position, regardless of explicit placement [1]. // // [1] https://www.w3.org/TR/css-grid-3/#masonry-intrinsic-repeat - if (span.IsIndefinite() || needs_auto_track_size) { + if (span.IsIndefinite() || needs_intrinsic_track_size) { // For groups of items that are auto-placed, we need to create copies of // the virtual item and place them at each possible start line. At the end // of the loop below, `span` will be located at the last start line, which // should be the position of the last copy appended to `virtual_items`. - if (needs_auto_track_size) { + if (needs_intrinsic_track_size) { span = GridSpan::TranslatedDefiniteGridSpan(0, 1); } else { span = @@ -582,7 +583,7 @@ SizingConstraint sizing_constraint, const ConstraintSpace space_for_measure, const GridItemData* masonry_item, - const bool needs_auto_track_size) const { + const bool needs_intrinsic_track_size) const { DCHECK(masonry_item); // TODO(ikilpatrick): We'll need to record if any child used an indefinite @@ -607,7 +608,7 @@ masonry_item->node, space_for_measure) .sizes; const auto fallback_space = CreateConstraintSpaceForMeasure( - *masonry_item, needs_auto_track_size, + *masonry_item, needs_intrinsic_track_size, /*opt_fixed_inline_size=*/sizing_constraint == SizingConstraint::kMinContent ? sizes.min_size @@ -631,18 +632,18 @@ GridSizingTrackCollection MasonryLayoutAlgorithm::ComputeGridAxisTracks( const SizingConstraint sizing_constraint, - std::optional<LayoutUnit> auto_repeat_track_size, + std::optional<LayoutUnit> intrinsic_repeat_track_size, GridItems& masonry_items, Vector<wtf_size_t>& collapsed_track_indexes, wtf_size_t& start_offset, - bool& needs_auto_track_size, + bool& needs_intrinsic_track_size, HeapVector<Member<LayoutBox>>* opt_oof_children) const { start_offset = 0; - needs_auto_track_size = false; + needs_intrinsic_track_size = false; const GridLineResolver line_resolver( - Style(), ComputeAutomaticRepetitions(auto_repeat_track_size, - needs_auto_track_size)); + Style(), ComputeAutomaticRepetitions(intrinsic_repeat_track_size, + needs_intrinsic_track_size)); const auto& node = Node(); if (masonry_items.IsEmpty()) { masonry_items = node.ConstructMasonryItems(line_resolver, opt_oof_children); @@ -656,22 +657,23 @@ } return BuildGridAxisTracks(line_resolver, masonry_items, sizing_constraint, - needs_auto_track_size, collapsed_track_indexes, - start_offset); + needs_intrinsic_track_size, + collapsed_track_indexes, start_offset); } GridSizingTrackCollection MasonryLayoutAlgorithm::BuildGridAxisTracks( const GridLineResolver& line_resolver, const GridItems& masonry_items, SizingConstraint sizing_constraint, - bool& needs_auto_track_size, + bool& needs_intrinsic_track_size, Vector<wtf_size_t>& collapsed_track_indexes, wtf_size_t& start_offset) const { const auto& style = Style(); const auto grid_axis_direction = style.MasonryTrackSizingDirection(); GridItems virtual_items = BuildVirtualMasonryItems( - line_resolver, masonry_items, needs_auto_track_size, sizing_constraint, - line_resolver.AutoRepetitions(grid_axis_direction), start_offset); + line_resolver, masonry_items, needs_intrinsic_track_size, + sizing_constraint, line_resolver.AutoRepetitions(grid_axis_direction), + start_offset); auto BuildRanges = [&]() { GridRangeBuilder range_builder( @@ -686,7 +688,7 @@ &range_indices.begin, &range_indices.end); } - return range_builder.FinalizeRanges(needs_auto_track_size, + return range_builder.FinalizeRanges(needs_intrinsic_track_size, &collapsed_track_indexes); }; @@ -704,7 +706,7 @@ track_sizing_algorithm.ComputeUsedTrackSizes( ContributionSizeForVirtualItem, &track_collection, &virtual_items, - needs_auto_track_size); + needs_intrinsic_track_size); } auto first_set_geometry = GridTrackSizingAlgorithm::ComputeFirstSetGeometry( @@ -718,8 +720,8 @@ // https://drafts.csswg.org/css-grid-2/#auto-repeat wtf_size_t MasonryLayoutAlgorithm::ComputeAutomaticRepetitions( - std::optional<LayoutUnit> auto_repeat_track_size, - bool& needs_auto_track_size) const { + std::optional<LayoutUnit> intrinsic_repeat_track_size, + bool& needs_intrinsic_track_size) const { const ComputedStyle& style = Style(); GridTrackSizingDirection masonry_track_sizing_direction = style.MasonryTrackSizingDirection(); @@ -733,15 +735,15 @@ return 0; } - // To determine the auto track size within a repeat, we need to expand + // To determine an intrinsic track size within a repeat, we need to expand // them out once, and run track sizing to get the actual size [1]. Then we - // will run this again with the actual auto track size within a final track - // sizing pass based on this size. + // will run this again with the actual intrinsic track size within a final + // track sizing pass based on this size. // // https://www.w3.org/TR/css-grid-3/#masonry-intrinsic-repeat - if (track_list.HasAutoSizedRepeater() && !auto_repeat_track_size) { - CHECK(!needs_auto_track_size); - needs_auto_track_size = true; + if (track_list.HasIntrinsicSizedRepeater() && !intrinsic_repeat_track_size) { + CHECK(!needs_intrinsic_track_size); + needs_intrinsic_track_size = true; return 1; } @@ -761,7 +763,7 @@ : masonry_min_available_size_.block_size, is_for_columns ? masonry_max_available_size_.inline_size : masonry_max_available_size_.block_size, - auto_repeat_track_size); + intrinsic_repeat_track_size); } ConstraintSpace MasonryLayoutAlgorithm::CreateConstraintSpace( @@ -831,7 +833,7 @@ ConstraintSpace MasonryLayoutAlgorithm::CreateConstraintSpaceForMeasure( const GridItemData& masonry_item, - const bool needs_auto_track_size, + const bool needs_intrinsic_track_size, std::optional<LayoutUnit> opt_fixed_inline_size, bool is_for_min_max_sizing) const { LogicalSize containing_size = masonry_available_size_; @@ -867,10 +869,10 @@ } } - // If we are determining the track size of an auto track within an auto + // If we are determining the track size of an intrinsic track within an auto // repeat(), we resolve percentages against the container. std::optional<LogicalSize> percentage_resolution_size = - needs_auto_track_size + needs_intrinsic_track_size ? std::optional<LogicalSize>(masonry_available_size_) : std::nullopt;
diff --git a/third_party/blink/renderer/core/layout/masonry/masonry_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/masonry/masonry_layout_algorithm_test.cc index 6fc63b0..ab8810b 100644 --- a/third_party/blink/renderer/core/layout/masonry/masonry_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/masonry/masonry_layout_algorithm_test.cc
@@ -28,41 +28,43 @@ collapsed_track_indexes_.clear(); auto masonry_items = algorithm.Node().ConstructMasonryItems(line_resolver); - bool needs_auto_track_size = false; - std::optional<LayoutUnit> auto_repeat_track_size = std::nullopt; + bool needs_intrinsic_track_size = false; + std::optional<LayoutUnit> intrinsic_repeat_track_size = std::nullopt; grid_axis_tracks_ = algorithm.ComputeGridAxisTracks( - SizingConstraint::kLayout, auto_repeat_track_size, masonry_items, - collapsed_track_indexes_, start_offset, needs_auto_track_size); + SizingConstraint::kLayout, intrinsic_repeat_track_size, masonry_items, + collapsed_track_indexes_, start_offset, needs_intrinsic_track_size); - // We have a repeat() track definition with an auto sized track(s). The + // We have a repeat() track definition with an intrinsic sized track(s). The // previous track sizing pass was used to find the track size to apply - // to the auto sized track(s). Retrieve that value, and re-run track + // to the intrinsic sized track(s). Retrieve that value, and re-run track // sizing to get the correct number of automatic repetitions for the // repeat() definition. // // https://www.w3.org/TR/css-grid-3/#masonry-intrinsic-repeat - if (needs_auto_track_size) { - CHECK_NE(grid_axis_tracks_->GetAutoSizedRepeaterTrackIndex(), kNotFound); + if (needs_intrinsic_track_size) { + CHECK_NE(grid_axis_tracks_->GetIntrinsicSizedRepeaterTrackIndex(), + kNotFound); CHECK(collapsed_track_indexes_.empty()); - // Note that when `needs_auto_track_size` is true, we skip the steps to - // distribute free space during track sizing. This means that the base + // Note that when `needs_intrinsic_track_size` is true, we skip the steps + // to distribute free space during track sizing. This means that the base // track size at this point represents the size of the intrinsic track // without free space distribution. - auto_repeat_track_size = + intrinsic_repeat_track_size = grid_axis_tracks_ - ->GetSetAt(grid_axis_tracks_->GetAutoSizedRepeaterTrackIndex()) + ->GetSetAt( + grid_axis_tracks_->GetIntrinsicSizedRepeaterTrackIndex()) .BaseSize(); grid_axis_tracks_ = algorithm.ComputeGridAxisTracks( - SizingConstraint::kLayout, auto_repeat_track_size, masonry_items, - collapsed_track_indexes_, start_offset, needs_auto_track_size); + SizingConstraint::kLayout, intrinsic_repeat_track_size, masonry_items, + collapsed_track_indexes_, start_offset, needs_intrinsic_track_size); } const auto grid_axis_direction = grid_axis_tracks_->Direction(); ASSERT_EQ(grid_axis_direction, style.MasonryTrackSizingDirection()); for (const auto& masonry_item : algorithm.BuildVirtualMasonryItems( - line_resolver, masonry_items, needs_auto_track_size, + line_resolver, masonry_items, needs_intrinsic_track_size, SizingConstraint::kLayout, line_resolver.AutoRepetitions(grid_axis_direction), start_offset)) {
diff --git a/third_party/blink/renderer/core/layout/mathml/layout_table_cell_with_anonymous_mrow.h b/third_party/blink/renderer/core/layout/mathml/layout_table_cell_with_anonymous_mrow.h index 254a89b0..ba84f45 100644 --- a/third_party/blink/renderer/core/layout/mathml/layout_table_cell_with_anonymous_mrow.h +++ b/third_party/blink/renderer/core/layout/mathml/layout_table_cell_with_anonymous_mrow.h
@@ -16,8 +16,10 @@ void AddChild(LayoutObject* new_child, LayoutObject* before_child = nullptr) override; - // The multicol flow thread expects to be a direct child of the multicol - // container, but the AddChild() override above prevents that. + // TODO(crbug.com/40060619): This override was added because of the legacy + // multicol implementation, which required its own special anonymous child + // wrapper, which came in conflict with what AddChild() does here. It should + // now be safe to allow multicol again (if that's useful at all). bool AllowsColumns() const override { NOT_DESTROYED(); return false;
diff --git a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc deleted file mode 100644 index acccc21..0000000 --- a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc +++ /dev/null
@@ -1,373 +0,0 @@ -// Copyright 2015 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h" - -#include "third_party/blink/renderer/core/layout/geometry/logical_rect.h" -#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" - -namespace blink { - -// Limit the maximum column count, to prevent potential performance problems. -static const unsigned kColumnCountClampMax = 10000; - -// Clamp "infinite" clips to a number of pixels that can be losslessly -// converted to and from floating point, to avoid loss of precision. -// Note that tables have something similar, see -// TableLayoutAlgorithm::kTableMaxWidth. -static constexpr LayoutUnit kMulticolMaxClipPixels(1000000); - -MultiColumnFragmentainerGroup::MultiColumnFragmentainerGroup( - const LayoutMultiColumnSet& column_set) - : column_set_(&column_set) { - DCHECK(!RuntimeEnabledFeatures::FlowThreadLessEnabled()); -} - -LogicalOffset MultiColumnFragmentainerGroup::OffsetFromColumnSet() const { - return LogicalOffset(LayoutUnit(), LogicalTop()); -} - -LayoutUnit MultiColumnFragmentainerGroup::LogicalHeightInFlowThreadAt( - unsigned column_index) const { - DCHECK(IsLogicalHeightKnown()); - LayoutUnit column_height = ColumnLogicalHeight(); - LayoutUnit logical_top = LogicalTopInFlowThreadAt(column_index); - LayoutUnit logical_bottom = logical_top + column_height; - unsigned actual_count = ActualColumnCount(); - if (column_index + 1 >= actual_count) { - // The last column may contain overflow content, if the actual column count - // was clamped, so using the column height won't do. This is also a way to - // stay within the bounds of the flow thread, if the last column happens to - // contain LESS than the other columns. We also need this clamping if we're - // given a column index *after* the last column. Height should obviously be - // 0 then. We may be called with a column index that's one entry past the - // end if we're dealing with zero-height content at the very end of the flow - // thread, and this location is at a column boundary. - if (column_index + 1 == actual_count) - logical_bottom = LogicalBottomInFlowThread(); - else - logical_bottom = logical_top; - } - return (logical_bottom - logical_top).ClampNegativeToZero(); -} - -void MultiColumnFragmentainerGroup::ResetColumnHeight() { - is_logical_height_known_ = false; - logical_height_ = LayoutUnit(); -} - -PhysicalOffset MultiColumnFragmentainerGroup::FlowThreadTranslationAtOffset( - LayoutUnit offset_in_flow_thread, - LayoutBox::PageBoundaryRule rule) const { - LayoutMultiColumnFlowThread* flow_thread = - column_set_->MultiColumnFlowThread(); - - // A column out of range doesn't have a flow thread portion, so we need to - // clamp to make sure that we stay within the actual columns. This means that - // content in the overflow area will be mapped to the last actual column, - // instead of being mapped to an imaginary column further ahead. - unsigned column_index = - offset_in_flow_thread >= LogicalBottomInFlowThread() - ? ActualColumnCount() - 1 - : ColumnIndexAtOffset(offset_in_flow_thread, rule); - - PhysicalRect portion_rect(FlowThreadPortionRectAt(column_index)); - portion_rect.offset += flow_thread->PhysicalLocation(); - - LogicalRect column_rect(ColumnRectAt(column_index)); - column_rect.offset += OffsetFromColumnSet(); - PhysicalRect physical_column_rect = - column_set_->CreateWritingModeConverter().ToPhysical(column_rect); - physical_column_rect.offset += column_set_->PhysicalLocation(); - - return physical_column_rect.offset - portion_rect.offset; -} - -LogicalOffset MultiColumnFragmentainerGroup::VisualPointToFlowThreadPoint( - const LogicalOffset& visual_point) const { - unsigned column_index = ColumnIndexAtVisualPoint(visual_point); - LogicalRect column_rect = ColumnRectAt(column_index); - LogicalOffset local_point(visual_point); - local_point -= column_rect.offset; - return LogicalOffset( - local_point.inline_offset, - local_point.block_offset + LogicalTopInFlowThreadAt(column_index)); -} - -PhysicalRect MultiColumnFragmentainerGroup::FragmentsBoundingBox( - const PhysicalRect& bounding_box_in_flow_thread) const { - // Find the start and end column intersected by the bounding box. - const LogicalRect logical_bounding_box = - column_set_->FlowThread()->CreateWritingModeConverter().ToLogical( - bounding_box_in_flow_thread); - LayoutUnit bounding_box_logical_top = - logical_bounding_box.offset.block_offset; - LayoutUnit bounding_box_logical_bottom = - logical_bounding_box.BlockEndOffset(); - if (bounding_box_logical_bottom <= LogicalTopInFlowThread() || - bounding_box_logical_top >= LogicalBottomInFlowThread()) { - // The bounding box doesn't intersect this fragmentainer group. - return PhysicalRect(); - } - unsigned start_column; - unsigned end_column; - ColumnIntervalForBlockRangeInFlowThread(bounding_box_logical_top, - bounding_box_logical_bottom, - start_column, end_column); - - PhysicalRect start_column_rect(bounding_box_in_flow_thread); - start_column_rect.Intersect(FlowThreadPortionOverflowRectAt(start_column)); - start_column_rect.offset += PhysicalOffset( - FlowThreadTranslationAtOffset(LogicalTopInFlowThreadAt(start_column), - LayoutBox::kAssociateWithLatterPage)); - if (start_column == end_column) - return start_column_rect; // It all takes place in one column. We're done. - - PhysicalRect end_column_rect(bounding_box_in_flow_thread); - end_column_rect.Intersect(FlowThreadPortionOverflowRectAt(end_column)); - end_column_rect.offset += PhysicalOffset( - FlowThreadTranslationAtOffset(LogicalTopInFlowThreadAt(end_column), - LayoutBox::kAssociateWithLatterPage)); - return UnionRect(start_column_rect, end_column_rect); -} - -unsigned MultiColumnFragmentainerGroup::ActualColumnCount() const { - unsigned count = UnclampedActualColumnCount(); - count = std::min(count, kColumnCountClampMax); - DCHECK_GE(count, 1u); - return count; -} - -void MultiColumnFragmentainerGroup::SetColumnBlockSizeFromNG( - LayoutUnit block_size) { - // We clamp the fragmentainer block size up to 1 for legacy write-back if - // there is content that overflows the less-than-1px-height (or even - // zero-height) fragmentainer. However, if one fragmentainer contains no - // overflow, while others fragmentainers do, the known height may be different - // than the |block_size| passed in. Don't override the stored height if this - // is the case. - DCHECK(!is_logical_height_known_ || logical_height_ == block_size || - block_size <= LayoutUnit(1)); - if (is_logical_height_known_) - return; - logical_height_ = block_size; - is_logical_height_known_ = true; -} - -void MultiColumnFragmentainerGroup::ExtendColumnBlockSizeFromNG( - LayoutUnit block_size) { - DCHECK(is_logical_height_known_); - logical_height_ += block_size; -} - -LogicalRect MultiColumnFragmentainerGroup::ColumnRectAt( - unsigned column_index) const { - LayoutUnit column_logical_width = column_set_->PageLogicalWidth(); - LayoutUnit column_logical_height = LogicalHeightInFlowThreadAt(column_index); - LayoutUnit column_logical_top; - LayoutUnit column_logical_left; - LayoutUnit column_gap = column_set_->ColumnGap(); - - if (column_set_->StyleRef().IsLeftToRightDirection()) { - column_logical_left += column_index * (column_logical_width + column_gap); - } else { - column_logical_left += column_set_->ContentLogicalWidth() - - column_logical_width - - column_index * (column_logical_width + column_gap); - } - - return LogicalRect(column_logical_left, column_logical_top, - column_logical_width, column_logical_height); -} - -LogicalRect MultiColumnFragmentainerGroup::LogicalFlowThreadPortionRectAt( - unsigned column_index) const { - LayoutUnit logical_top = LogicalTopInFlowThreadAt(column_index); - LayoutUnit portion_logical_height = LogicalHeightInFlowThreadAt(column_index); - return LogicalRect(LayoutUnit(), logical_top, column_set_->PageLogicalWidth(), - portion_logical_height); -} - -PhysicalRect MultiColumnFragmentainerGroup::FlowThreadPortionRectAt( - unsigned column_index) const { - return column_set_->FlowThread()->CreateWritingModeConverter().ToPhysical( - LogicalFlowThreadPortionRectAt(column_index)); -} - -PhysicalRect MultiColumnFragmentainerGroup::FlowThreadPortionOverflowRectAt( - unsigned column_index) const { - // This function determines the portion of the flow thread that paints for the - // column. - // - // In the block direction, we will not clip overflow out of the top of the - // first column, or out of the bottom of the last column. This applies only to - // the true first column and last column across all column sets. - // - // FIXME: Eventually we will know overflow on a per-column basis, but we can't - // do this until we have a painting mode that understands not to paint - // contents from a previous column in the overflow area of a following column. - bool is_first_column_in_row = !column_index; - bool is_last_column_in_row = column_index == ActualColumnCount() - 1; - - LogicalRect portion_rect = LogicalFlowThreadPortionRectAt(column_index); - bool is_first_column_in_multicol_container = - is_first_column_in_row && - this == &column_set_->FirstFragmentainerGroup() && - !column_set_->PreviousSiblingMultiColumnSet(); - bool is_last_column_in_multicol_container = - is_last_column_in_row && this == &column_set_->LastFragmentainerGroup() && - !column_set_->NextSiblingMultiColumnSet(); - // Calculate the overflow rectangle. It will be clipped at the logical top - // and bottom of the column box, unless it's the first or last column in the - // multicol container, in which case it should allow overflow. It will also - // be clipped in the middle of adjacent column gaps. Care is taken here to - // avoid rounding errors. - LogicalRect overflow_rect(-kMulticolMaxClipPixels, -kMulticolMaxClipPixels, - 2 * kMulticolMaxClipPixels, - 2 * kMulticolMaxClipPixels); - if (!is_first_column_in_multicol_container) { - overflow_rect.ShiftBlockStartEdgeTo(portion_rect.offset.block_offset); - } - if (!is_last_column_in_multicol_container) { - overflow_rect.ShiftBlockEndEdgeTo(portion_rect.BlockEndOffset()); - } - return column_set_->FlowThread()->CreateWritingModeConverter().ToPhysical( - overflow_rect); -} - -unsigned MultiColumnFragmentainerGroup::ColumnIndexAtOffset( - LayoutUnit offset_in_flow_thread, - LayoutBox::PageBoundaryRule page_boundary_rule) const { - // Handle the offset being out of range. - if (offset_in_flow_thread < logical_top_in_flow_thread_) - return 0; - - if (!IsLogicalHeightKnown()) - return 0; - LayoutUnit column_height = ColumnLogicalHeight(); - unsigned column_index = - ((offset_in_flow_thread - logical_top_in_flow_thread_) / column_height) - .Floor(); - if (page_boundary_rule == LayoutBox::kAssociateWithFormerPage && - column_index > 0 && - LogicalTopInFlowThreadAt(column_index) == offset_in_flow_thread) { - // We are exactly at a column boundary, and we've been told to associate - // offsets at column boundaries with the former column, not the latter. - column_index--; - } - return column_index; -} - -unsigned MultiColumnFragmentainerGroup::ConstrainedColumnIndexAtOffset( - LayoutUnit offset_in_flow_thread, - LayoutBox::PageBoundaryRule page_boundary_rule) const { - unsigned index = - ColumnIndexAtOffset(offset_in_flow_thread, page_boundary_rule); - return std::min(index, ActualColumnCount() - 1); -} - -unsigned MultiColumnFragmentainerGroup::ColumnIndexAtVisualPoint( - const LogicalOffset& visual_point) const { - LayoutUnit column_length = column_set_->PageLogicalWidth(); - LayoutUnit offset_in_column_progression_direction = - visual_point.inline_offset; - if (!column_set_->StyleRef().IsLeftToRightDirection()) { - offset_in_column_progression_direction = - column_set_->LogicalWidth() - offset_in_column_progression_direction; - } - LayoutUnit column_gap = column_set_->ColumnGap(); - if (column_length + column_gap <= 0) - return 0; - // Column boundaries are in the middle of the column gap. - int index = ((offset_in_column_progression_direction + column_gap / 2) / - (column_length + column_gap)) - .ToInt(); - if (index < 0) - return 0; - return std::min(unsigned(index), ActualColumnCount() - 1); -} - -void MultiColumnFragmentainerGroup::ColumnIntervalForBlockRangeInFlowThread( - LayoutUnit logical_top_in_flow_thread, - LayoutUnit logical_bottom_in_flow_thread, - unsigned& first_column, - unsigned& last_column) const { - logical_top_in_flow_thread = - std::max(logical_top_in_flow_thread, LogicalTopInFlowThread()); - logical_bottom_in_flow_thread = - std::min(logical_bottom_in_flow_thread, LogicalBottomInFlowThread()); - first_column = ConstrainedColumnIndexAtOffset( - logical_top_in_flow_thread, LayoutBox::kAssociateWithLatterPage); - if (logical_bottom_in_flow_thread <= logical_top_in_flow_thread) { - // Zero-height block range. There'll be one column in the interval. Set it - // right away. This is important if we're at a column boundary, since - // calling ConstrainedColumnIndexAtOffset() with the end-exclusive bottom - // offset would actually give us the *previous* column. - last_column = first_column; - } else { - last_column = ConstrainedColumnIndexAtOffset( - logical_bottom_in_flow_thread, LayoutBox::kAssociateWithFormerPage); - } -} - -unsigned MultiColumnFragmentainerGroup::UnclampedActualColumnCount() const { - // We must always return a value of 1 or greater. Column count = 0 is a - // meaningless situation, and will confuse and cause problems in other parts - // of the code. - if (!IsLogicalHeightKnown()) - return 1; - // Our flow thread portion determines our column count. We have as many - // columns as needed to fit all the content. - LayoutUnit flow_thread_portion_height = LogicalHeightInFlowThread(); - if (!flow_thread_portion_height) - return 1; - - LayoutUnit column_height = ColumnLogicalHeight(); - unsigned count = (flow_thread_portion_height / column_height).Floor(); - // flowThreadPortionHeight may be saturated, so detect the remainder manually. - if (count * column_height < flow_thread_portion_height) - count++; - - DCHECK_GE(count, 1u); - return count; -} - -void MultiColumnFragmentainerGroup::Trace(Visitor* visitor) const { - visitor->Trace(column_set_); -} - -MultiColumnFragmentainerGroupList::MultiColumnFragmentainerGroupList( - LayoutMultiColumnSet& column_set) - : column_set_(&column_set) { - Append(MultiColumnFragmentainerGroup(*column_set_)); -} - -// An explicit empty destructor of MultiColumnFragmentainerGroupList should be -// in multi_column_fragmentainer_group.cc, because if an implicit destructor is -// used, msvc 2015 tries to generate its destructor (because the class is -// dll-exported class) and causes a compile error because of lack of -// MultiColumnFragmentainerGroup::operator=. Since -// MultiColumnFragmentainerGroup is non-copyable, we cannot define the -// operator=. -MultiColumnFragmentainerGroupList::~MultiColumnFragmentainerGroupList() = - default; - -MultiColumnFragmentainerGroup& -MultiColumnFragmentainerGroupList::AddExtraGroup() { - Append(MultiColumnFragmentainerGroup(*column_set_)); - return Last(); -} - -void MultiColumnFragmentainerGroupList::DeleteExtraGroups() { - Shrink(1); -} - -void MultiColumnFragmentainerGroupList::Trace(Visitor* visitor) const { - visitor->Trace(column_set_); - visitor->Trace(groups_); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h deleted file mode 100644 index 4570cf8d..0000000 --- a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h +++ /dev/null
@@ -1,227 +0,0 @@ -// Copyright 2015 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_MULTI_COLUMN_FRAGMENTAINER_GROUP_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_MULTI_COLUMN_FRAGMENTAINER_GROUP_H_ - -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" - -namespace blink { - -struct LogicalRect; - -// A group of columns, that are laid out in the inline progression direction, -// all with the same column height. -// -// When a multicol container is inside another fragmentation context, and said -// multicol container lives in multiple outer fragmentainers (pages / columns), -// we need to put these inner columns into separate groups, with one group per -// outer fragmentainer. Such a group of columns is what comprises a "row of -// column boxes" in spec lingo. -// -// Column balancing, when enabled, takes place within a column fragmentainer -// group. -// -// Each fragmentainer group may have its own actual column count (if there are -// unused columns because of forced breaks, for example). If there are multiple -// fragmentainer groups, the actual column count must not exceed the used column -// count (the one calculated based on column-count and column-width from CSS), -// or they'd overflow the outer fragmentainer in the inline direction. If we -// need more columns than what a group has room for, we'll create another group -// and put them there (and make them appear in the next outer fragmentainer). -class CORE_EXPORT MultiColumnFragmentainerGroup { - DISALLOW_NEW(); - - public: - explicit MultiColumnFragmentainerGroup(const LayoutMultiColumnSet&); - - // Position within the LayoutMultiColumnSet. - LayoutUnit LogicalTop() const { return logical_top_; } - void SetLogicalTop(LayoutUnit logical_top) { logical_top_ = logical_top; } - - // Return the amount of block space that this fragmentainer group takes up in - // its containing LayoutMultiColumnSet. - LayoutUnit GroupLogicalHeight() const { - DCHECK(IsLogicalHeightKnown()); - return logical_height_; - } - - // Return the block size of a column (or fragmentainer) in this fragmentainer - // group. The spec says that this value must always be >= 1px, to ensure - // progress. - LayoutUnit ColumnLogicalHeight() const { - DCHECK(IsLogicalHeightKnown()); - return std::max(LayoutUnit(1), logical_height_); - } - - // Return whether we have some column height to work with. This doesn't have - // to be the final height. It will only return false in the first layout pass, - // and even then only if column height is auto and there's no way to even make - // a guess (i.e. when there are no usable constraints). - bool IsLogicalHeightKnown() const { return is_logical_height_known_; } - - LogicalOffset OffsetFromColumnSet() const; - - // The top of our flow thread portion - LayoutUnit LogicalTopInFlowThread() const { - return logical_top_in_flow_thread_; - } - void SetLogicalTopInFlowThread(LayoutUnit logical_top_in_flow_thread) { - logical_top_in_flow_thread_ = logical_top_in_flow_thread; - } - - // The bottom of our flow thread portion - LayoutUnit LogicalBottomInFlowThread() const { - return logical_bottom_in_flow_thread_; - } - void SetLogicalBottomInFlowThread(LayoutUnit logical_bottom_in_flow_thread) { - logical_bottom_in_flow_thread_ = logical_bottom_in_flow_thread; - } - void ExtendLogicalBottomInFlowThread(LayoutUnit block_size) { - logical_bottom_in_flow_thread_ += block_size; - } - - // The height of the flow thread portion for the entire fragmentainer group. - LayoutUnit LogicalHeightInFlowThread() const { - // Due to negative margins, logical bottom may actually end up above logical - // top, but we never want to return negative logical heights. - return (logical_bottom_in_flow_thread_ - logical_top_in_flow_thread_) - .ClampNegativeToZero(); - } - // The height of the flow thread portion for the specified fragmentainer. - // The last fragmentainer may not be using all available space. - LayoutUnit LogicalHeightInFlowThreadAt(unsigned column_index) const; - - void ResetColumnHeight(); - - PhysicalOffset FlowThreadTranslationAtOffset( - LayoutUnit, - LayoutBox::PageBoundaryRule) const; - - LogicalOffset VisualPointToFlowThreadPoint( - const LogicalOffset& visual_point) const; - - PhysicalRect FragmentsBoundingBox( - const PhysicalRect& bounding_box_in_flow_thread) const; - - PhysicalRect FlowThreadPortionRectAt(unsigned column_index) const; - - PhysicalRect FlowThreadPortionOverflowRectAt(unsigned column_index) const; - - // Get the first and the last column intersecting the specified block range. - // Note that |logicalBottomInFlowThread| is an exclusive endpoint. - void ColumnIntervalForBlockRangeInFlowThread( - LayoutUnit logical_top_in_flow_thread, - LayoutUnit logical_bottom_in_flow_thread, - unsigned& first_column, - unsigned& last_column) const; - - unsigned ColumnIndexAtOffset(LayoutUnit offset_in_flow_thread, - LayoutBox::PageBoundaryRule) const; - - // Like ColumnIndexAtOffset(), but with the return value clamped to actual - // column count. While there are legitimate reasons for dealing with columns - // out of bounds during layout, this should not happen when performing read - // operations on the tree (like painting and hit-testing). - unsigned ConstrainedColumnIndexAtOffset(LayoutUnit offset_in_flow_thread, - LayoutBox::PageBoundaryRule) const; - - // The "CSS actual" value of column-count. This includes overflowing columns, - // if any. - // Returns 1 or greater, never 0. - unsigned ActualColumnCount() const; - - void SetColumnBlockSizeFromNG(LayoutUnit); - void ExtendColumnBlockSizeFromNG(LayoutUnit); - - void Trace(Visitor*) const; - - private: - LogicalRect ColumnRectAt(unsigned column_index) const; - LayoutUnit LogicalTopInFlowThreadAt(unsigned column_index) const { - return logical_top_in_flow_thread_ + column_index * ColumnLogicalHeight(); - } - LogicalRect LogicalFlowThreadPortionRectAt(unsigned column_index) const; - // Return the column that the specified visual point belongs to. Only the - // coordinate on the column progression axis is relevant. Every point belongs - // to a column, even if said point is not inside any of the columns. - unsigned ColumnIndexAtVisualPoint(const LogicalOffset& visual_point) const; - - unsigned UnclampedActualColumnCount() const; - - const Member<const LayoutMultiColumnSet> column_set_; - - LayoutUnit logical_top_; - LayoutUnit logical_top_in_flow_thread_; - LayoutUnit logical_bottom_in_flow_thread_; - - // Logical height of the group. This will also be the height of each column - // in this group, with the difference that, while the logical height can be - // 0, the height of a column must be >= 1px. - LayoutUnit logical_height_; - - bool is_logical_height_known_ = false; -}; - -// List of all fragmentainer groups within a column set. There will always be at -// least one group. Deleting the one group is not allowed (or possible). There -// will be more than one group if the owning column set lives in multiple outer -// fragmentainers (e.g. multicol inside paged media). -class CORE_EXPORT MultiColumnFragmentainerGroupList { - DISALLOW_NEW(); - - public: - explicit MultiColumnFragmentainerGroupList(LayoutMultiColumnSet&); - ~MultiColumnFragmentainerGroupList(); - - // Add an additional fragmentainer group to the end of the list, and return - // it. - MultiColumnFragmentainerGroup& AddExtraGroup(); - - // Remove all fragmentainer groups but the first one. - void DeleteExtraGroups(); - - MultiColumnFragmentainerGroup& First() { return groups_.front(); } - const MultiColumnFragmentainerGroup& First() const { return groups_.front(); } - MultiColumnFragmentainerGroup& Last() { return groups_.back(); } - const MultiColumnFragmentainerGroup& Last() const { return groups_.back(); } - - typedef HeapVector<MultiColumnFragmentainerGroup, 1>::iterator iterator; - typedef HeapVector<MultiColumnFragmentainerGroup, 1>::const_iterator - const_iterator; - - iterator begin() { return groups_.begin(); } - const_iterator begin() const { return groups_.begin(); } - iterator end() { return groups_.end(); } - const_iterator end() const { return groups_.end(); } - - wtf_size_t size() const { return groups_.size(); } - MultiColumnFragmentainerGroup& operator[](wtf_size_t i) { - return groups_.at(i); - } - const MultiColumnFragmentainerGroup& operator[](wtf_size_t i) const { - return groups_.at(i); - } - - void Append(const MultiColumnFragmentainerGroup& group) { - groups_.push_back(group); - } - void Shrink(wtf_size_t size) { groups_.Shrink(size); } - - void Trace(Visitor*) const; - - private: - Member<LayoutMultiColumnSet> column_set_; - - HeapVector<MultiColumnFragmentainerGroup, 1> groups_; -}; - -} // namespace blink - -WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS( - blink::MultiColumnFragmentainerGroup) - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_MULTI_COLUMN_FRAGMENTAINER_GROUP_H_
diff --git a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc deleted file mode 100644 index 27c14a6..0000000 --- a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group_test.cc +++ /dev/null
@@ -1,107 +0,0 @@ -// Copyright 2015 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/blink/renderer/core/css/resolver/style_resolver.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_set.h" -#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" -#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" - -namespace blink { - -namespace { - -class MultiColumnFragmentainerGroupTest : public RenderingTest, - public ScopedFlowThreadLessForTest { - public: - MultiColumnFragmentainerGroupTest() - : ScopedFlowThreadLessForTest(false), - flow_thread_(nullptr), - column_set_(nullptr) {} - - protected: - void SetUp() override; - void TearDown() override; - - LayoutMultiColumnSet& ColumnSet() { return *column_set_; } - - static int GroupCount(const MultiColumnFragmentainerGroupList&); - - private: - Persistent<LayoutMultiColumnFlowThread> flow_thread_; - Persistent<LayoutMultiColumnSet> column_set_; -}; - -void MultiColumnFragmentainerGroupTest::SetUp() { - RenderingTest::SetUp(); - const ComputedStyle& style = GetDocument().GetStyleResolver().InitialStyle(); - flow_thread_ = - LayoutMultiColumnFlowThread::CreateAnonymous(GetDocument(), style); - column_set_ = LayoutMultiColumnSet::CreateAnonymous(*flow_thread_, - *flow_thread_->Style()); -} - -void MultiColumnFragmentainerGroupTest::TearDown() { - column_set_->Destroy(); - flow_thread_->Destroy(); - RenderingTest::TearDown(); -} - -int MultiColumnFragmentainerGroupTest::GroupCount( - const MultiColumnFragmentainerGroupList& group_list) { - int count = 0; - for (const auto& dummy_group : group_list) { - (void)dummy_group; - count++; - } - return count; -} - -TEST_F(MultiColumnFragmentainerGroupTest, Create) { - MultiColumnFragmentainerGroupList group_list(ColumnSet()); - EXPECT_EQ(GroupCount(group_list), 1); -} - -TEST_F(MultiColumnFragmentainerGroupTest, DeleteExtra) { - MultiColumnFragmentainerGroupList group_list(ColumnSet()); - EXPECT_EQ(GroupCount(group_list), 1); - group_list.DeleteExtraGroups(); - EXPECT_EQ(GroupCount(group_list), 1); -} - -TEST_F(MultiColumnFragmentainerGroupTest, AddThenDeleteExtra) { - MultiColumnFragmentainerGroupList group_list(ColumnSet()); - EXPECT_EQ(GroupCount(group_list), 1); - group_list.AddExtraGroup(); - EXPECT_EQ(GroupCount(group_list), 2); - group_list.DeleteExtraGroups(); - EXPECT_EQ(GroupCount(group_list), 1); -} - -TEST_F(MultiColumnFragmentainerGroupTest, - AddTwoThenDeleteExtraThenAddThreeThenDeleteExtra) { - MultiColumnFragmentainerGroupList group_list(ColumnSet()); - EXPECT_EQ(GroupCount(group_list), 1); - group_list.AddExtraGroup(); - EXPECT_EQ(GroupCount(group_list), 2); - group_list.AddExtraGroup(); - EXPECT_EQ(GroupCount(group_list), 3); - group_list.DeleteExtraGroups(); - EXPECT_EQ(GroupCount(group_list), 1); - group_list.AddExtraGroup(); - EXPECT_EQ(GroupCount(group_list), 2); - group_list.AddExtraGroup(); - EXPECT_EQ(GroupCount(group_list), 3); - group_list.AddExtraGroup(); - EXPECT_EQ(GroupCount(group_list), 4); - group_list.DeleteExtraGroups(); - EXPECT_EQ(GroupCount(group_list), 1); -} - -} // anonymous namespace - -} // namespace blink
diff --git a/third_party/blink/renderer/core/layout/out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/out_of_flow_layout_part.cc index b65ba5bb..54b8347 100644 --- a/third_party/blink/renderer/core/layout/out_of_flow_layout_part.cc +++ b/third_party/blink/renderer/core/layout/out_of_flow_layout_part.cc
@@ -34,7 +34,6 @@ #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_result.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/logical_fragment.h" #include "third_party/blink/renderer/core/layout/oof_positioned_node.h" #include "third_party/blink/renderer/core/layout/paginated_root_layout_algorithm.h" @@ -49,7 +48,6 @@ #include "third_party/blink/renderer/core/view_transition/view_transition.h" #include "third_party/blink/renderer/core/view_transition/view_transition_utils.h" #include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -1427,11 +1425,6 @@ converter.ToLogical(child.fragment->Size()).block_size; } fragment_mutator.UpdateOverflow(); - - // We've already written back to legacy for |multicol|, but if we added - // new columns to hold any OOF descendants, we need to extend the final - // size of the legacy flow thread to encompass those new columns. - multicol.MakeRoomForExtraColumns(additional_column_block_size); } // Any descendants should have been handled in @@ -2925,40 +2918,6 @@ additional_fixedpos_offset); } algorithm->AppendOutOfFlowResult(result); - - if (RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - // Copying back to the LayoutBox will be done later, when fragmented layout - // is complete. Only then can we know the physical offsets. - return; - } - - // Copy the offset of the OOF node back to legacy such that it is relative - // to its containing block rather than the fragmentainer that it is being - // added to. - if (!descendant.break_token) { - const auto* container = - To<PhysicalBoxFragment>(descendant.containing_block_fragment.Get()); - - if (!container) { - // If we're paginated, we don't have a containing block fragment, but we - // need one now, to calcualte the position correctly for the legacy - // engine. Just pick the first page, which actually happens to be defined - // as the initial containing block: - // https://www.w3.org/TR/CSS22/page.html#page-box - DCHECK(container_builder_->Node().IsPaginatedRoot()); - container = &GetChildFragment(0); - } - - LogicalOffset legacy_offset = - descendant.offset_info.original_offset - - descendant.node_info.base_container_info.offset_to_border_box; - descendant.node_info.node.CopyChildFragmentPosition( - physical_fragment, - legacy_offset.ConvertToPhysical( - container->Style().GetWritingDirection(), container->Size(), - physical_fragment.Size()), - *container, /* previous_container_break_token */ nullptr); - } } ConstraintSpace OutOfFlowLayoutPart::GetFragmentainerConstraintSpace( @@ -3060,8 +3019,7 @@ void OutOfFlowLayoutPart::SaveStaticPositionOnPaintLayer( LayoutBox* layout_box, LogicalStaticPosition position) const { - const LayoutObject* parent = - GetLayoutObjectForParentNode<const LayoutObject*>(layout_box); + const LayoutObject* parent = layout_box->Parent(); const LayoutObject* container = container_builder_->GetLayoutObject(); if (parent == container || (parent->IsLayoutInline() && parent->ContainingBlock() == container)) {
diff --git a/third_party/blink/renderer/core/layout/scrollable_overflow_calculator.cc b/third_party/blink/renderer/core/layout/scrollable_overflow_calculator.cc index e377d767..552832a 100644 --- a/third_party/blink/renderer/core/layout/scrollable_overflow_calculator.cc +++ b/third_party/blink/renderer/core/layout/scrollable_overflow_calculator.cc
@@ -10,7 +10,6 @@ #include "third_party/blink/renderer/core/layout/inline/inline_cursor.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/layout/layout_text_combine.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/length_utils.h" #include "third_party/blink/renderer/core/layout/logical_fragment.h" #include "third_party/blink/renderer/core/layout/physical_box_fragment.h"
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc index cc29249..7f521de 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.cc
@@ -14,7 +14,6 @@ #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/svg/svg_foreign_object_element.h" #include "third_party/blink/renderer/core/svg/svg_length_functions.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -74,20 +73,11 @@ return transform; } -PhysicalOffset LayoutSVGForeignObject::PhysicalLocation( - const LayoutBox*) const { +PhysicalOffset LayoutSVGForeignObject::PhysicalLocation() const { NOT_DESTROYED(); return overridden_location_; } -DeprecatedLayoutPoint LayoutSVGForeignObject::DeprecatedLocationInternal() - const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - return DeprecatedLayoutPoint(overridden_location_.left, - overridden_location_.top); -} - PaintLayerType LayoutSVGForeignObject::LayerTypeRequired() const { NOT_DESTROYED(); // Skip LayoutSVGBlock's override.
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h index 9027b642..a3d47900 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_foreign_object.h
@@ -68,9 +68,7 @@ AffineTransform LocalToSVGParentTransform() const override; // LayoutBox override: - PhysicalOffset PhysicalLocation( - const LayoutBox* location_container = nullptr) const override; - DeprecatedLayoutPoint DeprecatedLocationInternal() const override; + PhysicalOffset PhysicalLocation() const override; PaintLayerType LayerTypeRequired() const override; bool CreatesNewFormattingContext() const override;
diff --git a/third_party/blink/renderer/core/layout/table/layout_table_column.cc b/third_party/blink/renderer/core/layout/table/layout_table_column.cc index 68955b04..360ad76 100644 --- a/third_party/blink/renderer/core/layout/table/layout_table_column.cc +++ b/third_party/blink/renderer/core/layout/table/layout_table_column.cc
@@ -13,7 +13,6 @@ #include "third_party/blink/renderer/core/layout/table/table_borders.h" #include "third_party/blink/renderer/core/layout/table/table_break_token_data.h" #include "third_party/blink/renderer/core/layout/table/table_layout_algorithm_types.h" -#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -210,13 +209,8 @@ return ToPhysicalSize(size, table->StyleRef().GetWritingMode()); } -PhysicalOffset LayoutTableColumn::PhysicalLocation( - const LayoutBox* location_container) const { +PhysicalOffset LayoutTableColumn::PhysicalLocation() const { NOT_DESTROYED(); - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return LayoutBox::PhysicalLocation(location_container); - } - auto* table = Table(); DCHECK(table); if (!table->PhysicalFragmentCount()) { @@ -251,7 +245,6 @@ PhysicalRect LayoutTableColumn::BoundingBoxRelativeToFirstFragment() const { NOT_DESTROYED(); - DCHECK(RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); std::optional<PhysicalOffset> first_offset_from_fragmentation_context_root; PhysicalRect bounding_rect; @@ -277,10 +270,6 @@ const LayoutBoxModelObject* ancestor, MapCoordinatesFlags mode) const { NOT_DESTROYED(); - if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()) { - return LayoutBox::QuadsInAncestorInternal(quads, ancestor, mode); - } - // Offset from the root fragmentation context to the first synthesized table // column fragment. When mapping to ancestors, it's all about the offsets from // the *first* fragment to the *first* container fragment, so any subsequent @@ -317,88 +306,9 @@ } } -DeprecatedLayoutPoint LayoutTableColumn::DeprecatedLocationInternal() const { - NOT_DESTROYED(); - DCHECK(!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - auto* table = Table(); - DCHECK(table); - if (table->PhysicalFragmentCount() == 0) { - return DeprecatedLayoutPoint(); - } - - WritingDirectionMode direction = StyleRef().GetWritingDirection(); - LayoutTableColumn* parent_colgroup = nullptr; - if (IsColumn()) { - parent_colgroup = DynamicTo<LayoutTableColumn>(Parent()); - DCHECK(!parent_colgroup || parent_colgroup->IsColumnGroup()); - } - - LogicalOffset offset; - LogicalSize size; - LayoutUnit parent_colgroup_inline_size; - bool found_geometries = false; - - for (auto& fragment : table->PhysicalFragments()) { - BoxStrut decorations = - (fragment.Padding() + fragment.Borders()).ConvertToLogical(direction); - if (!found_geometries && fragment.TableColumnGeometries()) { - // If there was a table relayout, and this column box doesn't have a - // corresponding column in the table anymore, the column_idx_ will not - // have been updated. Therefore if it is greater or equal to the number of - // table column geometries, or if the geometry at that index doesn't point - // to this layout box, we return early. - if (column_idx_ >= fragment.TableColumnGeometries()->size()) { - return DeprecatedLayoutPoint(); - } - const auto& geometry = (*fragment.TableColumnGeometries())[column_idx_]; - if (geometry.node.GetLayoutBox() != this) { - return DeprecatedLayoutPoint(); - } - - found_geometries = true; - offset.inline_offset = geometry.inline_offset; - if (parent_colgroup) { - const auto& parent_geometry = - (*fragment.TableColumnGeometries())[parent_colgroup->column_idx_]; - offset.inline_offset -= parent_geometry.inline_offset; - parent_colgroup_inline_size = parent_geometry.inline_size; - } - size.inline_size = geometry.inline_size; - - LogicalSize table_border_spacing = table->StyleRef().TableBorderSpacing(); - size.block_size -= table_border_spacing.block_size * 2; - if (!parent_colgroup) { - offset.inline_offset += - decorations.inline_start + table_border_spacing.inline_size; - offset.block_offset += decorations.block_start + - table_border_spacing.block_size + - fragment.TableGridRect().offset.block_offset; - } - } - - size.block_size += - fragment.TableGridRect().size.block_size - decorations.BlockSum(); - } - - PhysicalSize outer_size; - if (!parent_colgroup) { - outer_size = PhysicalSize(table->Size()); - } else { - DCHECK_EQ(parent_colgroup->StyleRef().GetWritingDirection(), direction); - outer_size = ToPhysicalSize( - LogicalSize(parent_colgroup_inline_size, size.block_size), - direction.GetWritingMode()); - } - PhysicalSize inner_size = ToPhysicalSize(size, direction.GetWritingMode()); - return offset.ConvertToPhysical(direction, outer_size, inner_size) - .FaultyToDeprecatedLayoutPoint(); -} - void LayoutTableColumn::ForAllSynthesizedFragments( base::FunctionRef<bool(const SynthesizedFragment&)> callback) const { NOT_DESTROYED(); - DCHECK(RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled()); - auto* table = Table(); DCHECK(table); DCHECK_GT(table->PhysicalFragmentCount(), 0u);
diff --git a/third_party/blink/renderer/core/layout/table/layout_table_column.h b/third_party/blink/renderer/core/layout/table/layout_table_column.h index d81eeb4..7020846e 100644 --- a/third_party/blink/renderer/core/layout/table/layout_table_column.h +++ b/third_party/blink/renderer/core/layout/table/layout_table_column.h
@@ -41,15 +41,13 @@ PhysicalSize Size() const override; - PhysicalOffset PhysicalLocation(const LayoutBox*) const override; + PhysicalOffset PhysicalLocation() const override; PhysicalRect BoundingBoxRelativeToFirstFragment() const override; void QuadsInAncestorInternal(Vector<gfx::QuadF>&, const LayoutBoxModelObject* ancestor, MapCoordinatesFlags) const override; - DeprecatedLayoutPoint DeprecatedLocationInternal() const override; - // LayoutObject methods start. const char* GetName() const override {
diff --git a/third_party/blink/renderer/core/layout/text_autosizer.cc b/third_party/blink/renderer/core/layout/text_autosizer.cc index b3f14c7..342ee2f 100644 --- a/third_party/blink/renderer/core/layout/text_autosizer.cc +++ b/third_party/blink/renderer/core/layout/text_autosizer.cc
@@ -48,7 +48,6 @@ #include "third_party/blink/renderer/core/layout/block_node.h" #include "third_party/blink/renderer/core/layout/layout_block.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_text.h" #include "third_party/blink/renderer/core/layout/layout_view.h" @@ -1097,7 +1096,7 @@ // containing block, and wasn't marked as needing layout. #if DCHECK_IS_ON() DCHECK(blocks_that_have_begun_layout_.Contains(block) || - !block->NeedsLayout() || IsA<LayoutMultiColumnFlowThread>(block)); + !block->NeedsLayout()); #endif // Block width, in CSS pixels. float block_width = WidthFromBlock(block);
diff --git a/third_party/blink/renderer/core/layout/text_autosizer.h b/third_party/blink/renderer/core/layout/text_autosizer.h index ee97eaa..b38a23b 100644 --- a/third_party/blink/renderer/core/layout/text_autosizer.h +++ b/third_party/blink/renderer/core/layout/text_autosizer.h
@@ -361,8 +361,8 @@ Member<const Document> document_; Member<const LayoutBlock> first_block_to_begin_layout_; - // WeakMember because we don't call UnregisterInlineSize() for - // LayoutMultiColumnFlowThread. + // TODO(layout-dev): Probably doesn't need to be WeakMember anymore, since the + // legacy multicol implementation is gone. HeapHashMap<WeakMember<const LayoutBlock>, LayoutUnit> inline_size_map_; #if DCHECK_IS_ON()
diff --git a/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource_test.cc b/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource_test.cc index 7cec47f3..da28085 100644 --- a/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource_test.cc +++ b/third_party/blink/renderer/core/loader/resource/css_style_sheet_resource_test.cc
@@ -143,7 +143,8 @@ contents->CheckLoaded(); EXPECT_TRUE(contents->IsCacheableForResource()); - contents->EnsureRuleSet(MediaQueryEvaluator(GetDocument().GetFrame())); + contents->EnsureRuleSet(MediaQueryEvaluator(GetDocument().GetFrame()), + /*mixins=*/{}); EXPECT_TRUE(contents->HasRuleSet()); css_resource->SaveParsedStyleSheet(contents);
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc index 3af7438..c24e57e 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc
@@ -72,6 +72,14 @@ return; } execution_context->CountUse(WebFeature::kPrivateNetworkAccessWithinWorker); + + if (execution_context->IsDedicatedWorkerGlobalScope()) { + execution_context->CountUse( + WebFeature::kLocalNetworkAccessWithinDedicatedWorker); + } else if (execution_context->IsSharedWorkerGlobalScope()) { + execution_context->CountUse( + WebFeature::kLocalNetworkAccessWithinSharedWorker); + } } void ResourceLoadObserverForWorker::DidReceiveResponse(
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 3b87e22..9b24425c 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/print_context_test.cc b/third_party/blink/renderer/core/page/print_context_test.cc index e2f4ee1..807c0846 100644 --- a/third_party/blink/renderer/core/page/print_context_test.cc +++ b/third_party/blink/renderer/core/page/print_context_test.cc
@@ -673,7 +673,6 @@ } TEST_P(PrintContextTest, LinkedTargetRootMargin) { - ScopedLayoutBoxVisualLocationForTest scoped_feature(true); SetBodyInnerHTML(R"HTML( <style> html { margin-top: 50px; }
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/paint/highlight_painter.cc b/third_party/blink/renderer/core/paint/highlight_painter.cc index 57e50de..931f78a 100644 --- a/third_party/blink/renderer/core/paint/highlight_painter.cc +++ b/third_party/blink/renderer/core/paint/highlight_painter.cc
@@ -284,6 +284,7 @@ ->GetDocument() .GetFrame() ->Selection()) {} + HighlightPainter::SelectionPaintState::SelectionPaintState( const InlineCursor& containing_block, const PhysicalOffset& box_offset, @@ -449,21 +450,25 @@ *text_node, fragment_paint_info_.from, fragment_paint_info_.to); DCHECK(fragment_dom_offsets_); markers_ = controller.ComputeMarkersToPaint(*text_node); - if (RuntimeEnabledFeatures::SearchTextHighlightPseudoEnabled() && - !fragment_item_.IsSvgText()) { - search_ = controller.MarkersFor( - *text_node, DocumentMarker::kTextMatch, + if (!paint_info.IsPrivacyPreserving()) { + // When preserving privacy, only paint custom highlights. This check + // only protects markers painted with the highlight overlay system. + if (RuntimeEnabledFeatures::SearchTextHighlightPseudoEnabled() && + !fragment_item_.IsSvgText()) { + search_ = controller.MarkersFor( + *text_node, DocumentMarker::kTextMatch, + fragment_dom_offsets_->start, fragment_dom_offsets_->end); + } + target_ = controller.MarkersFor( + *text_node, DocumentMarker::kTextFragment, fragment_dom_offsets_->start, fragment_dom_offsets_->end); + spelling_ = controller.MarkersFor( + *text_node, DocumentMarker::kSpelling, + fragment_dom_offsets_->start, fragment_dom_offsets_->end); + grammar_ = controller.MarkersFor(*text_node, DocumentMarker::kGrammar, + fragment_dom_offsets_->start, + fragment_dom_offsets_->end); } - target_ = controller.MarkersFor( - *text_node, DocumentMarker::kTextFragment, - fragment_dom_offsets_->start, fragment_dom_offsets_->end); - spelling_ = controller.MarkersFor(*text_node, DocumentMarker::kSpelling, - fragment_dom_offsets_->start, - fragment_dom_offsets_->end); - grammar_ = controller.MarkersFor(*text_node, DocumentMarker::kGrammar, - fragment_dom_offsets_->start, - fragment_dom_offsets_->end); custom_ = controller.MarkersFor( *text_node, DocumentMarker::kCustomHighlight, fragment_dom_offsets_->start, fragment_dom_offsets_->end); @@ -529,6 +534,13 @@ if (markers_.empty()) return; + // Find-in-page markers are PII because they reveal what a user is + // interested in (though we may change this). Editing markers are transient + // and reflect uncommitted content, so do not draw them. + if (paint_info_.IsPrivacyPreserving()) { + return; + } + CHECK(node_); const StringView text = cursor_.CurrentText(); @@ -634,8 +646,9 @@ } HighlightPainter::Case HighlightPainter::ComputePaintCase() const { - if (selection_ && selection_->ShouldPaintSelectedTextOnly()) + if (selection_ && selection_->ShouldPaintSelectedTextOnly()) { return kSelectionOnly; + } // This can yield false positives (weakening the optimisations below) if all // non-spelling/grammar/selection highlights are outside the text fragment.
diff --git a/third_party/blink/renderer/core/paint/paint_invalidator.cc b/third_party/blink/renderer/core/paint/paint_invalidator.cc index 69cc037..da852ec 100644 --- a/third_party/blink/renderer/core/paint/paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/paint_invalidator.cc
@@ -17,7 +17,6 @@ #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/physical_box_fragment.h" #include "third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h" #include "third_party/blink/renderer/core/page/link_highlight.h"
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index b2e60a1..ea563cee 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -66,14 +66,12 @@ #include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/layout/anchor_position_scroll_data.h" -#include "third_party/blink/renderer/core/layout/fragmentainer_iterator.h" #include "third_party/blink/renderer/core/layout/fragmentation_utils.h" #include "third_party/blink/renderer/core/layout/geometry/transform_state.h" #include "third_party/blink/renderer/core/layout/hit_test_location.h" #include "third_party/blink/renderer/core/layout/hit_test_request.h" #include "third_party/blink/renderer/core/layout/hit_test_result.h" #include "third_party/blink/renderer/core/layout/layout_embedded_content.h" -#include "third_party/blink/renderer/core/layout/layout_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_html_canvas.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" #include "third_party/blink/renderer/core/layout/layout_object.h" @@ -1718,15 +1716,6 @@ // We hit something anonymous, and we didn't find a DOM node ancestor in // this layer. - if (GetLayoutObject().IsLayoutFlowThread()) { - // For a flow thread it's safe to just say that we didn't hit anything. - // That means that we'll continue as normally, and eventually hit a column - // set sibling instead. Column sets are also anonymous, but, unlike flow - // threads, they don't establish layers, so we'll fall back and hit the - // multicol container parent (which should have a DOM node). - return false; - } - Node* e = EnclosingNode(); // FIXME: should be a call to result.setNodeAndPosition. What we would // really want to do here is to return and look for the nearest
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index a9d51a8d..e64a3a2 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -95,7 +95,6 @@ #include "third_party/blink/renderer/core/layout/layout_object_inlines.h" #include "third_party/blink/renderer/core/layout/layout_theme.h" #include "third_party/blink/renderer/core/layout/layout_view.h" -#include "third_party/blink/renderer/core/layout/legacy_layout_tree_walking.h" #include "third_party/blink/renderer/core/layout/physical_box_fragment.h" #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index 8ff8125..76aff02 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -27,7 +27,6 @@ #include "third_party/blink/renderer/core/html/forms/text_control_element.h" #include "third_party/blink/renderer/core/layout/anchor_position_scroll_data.h" #include "third_party/blink/renderer/core/layout/block_break_token.h" -#include "third_party/blink/renderer/core/layout/fragmentainer_iterator.h" #include "third_party/blink/renderer/core/layout/fragmentation_utils.h" #include "third_party/blink/renderer/core/layout/geometry/transform_state.h" #include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc index b18e7c71..62b7a81 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder_test.cc
@@ -17,9 +17,7 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/visual_viewport.h" #include "third_party/blink/renderer/core/html/html_iframe_element.h" -#include "third_party/blink/renderer/core/layout/layout_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_image.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_tree_as_text.h" #include "third_party/blink/renderer/core/layout/physical_box_fragment.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h"
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index 9cd09a6..6b6c346 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -22,7 +22,6 @@ #include "third_party/blink/renderer/core/layout/layout_box_model_object.h" #include "third_party/blink/renderer/core/layout/layout_embedded_content.h" #include "third_party/blink/renderer/core/layout/layout_html_canvas.h" -#include "third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.h" #include "third_party/blink/renderer/core/layout/layout_shift_tracker.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/layout/pagination_utils.h" @@ -567,12 +566,6 @@ const LayoutObject& object, PrePaintTreeWalkContext& context, const PhysicalBoxFragment* fragment) { - // Flow threads don't exist, as far as LayoutNG is concerned. Yet, we - // encounter them here when performing an NG fragment accompanied LayoutObject - // subtree walk. Just ignore. - if (object.IsLayoutFlowThread()) - return; - // If we're in a fragmentation context, the parent fragment of OOFs is the // fragmentainer, unless the object is monolithic, in which case nothing // contained by the object participates in the current block fragmentation @@ -692,11 +685,6 @@ RebuildContextForMissedDescendant(ancestor, *object.Parent(), update_tree_builder_context, context); - if (object.IsLayoutFlowThread()) { - // A flow threads doesn't create fragments. Just ignore it. - return search_fragment; - } - const PhysicalBoxFragment* box_fragment = nullptr; if (context.tree_builder_context && update_tree_builder_context) { PhysicalOffset paint_offset; @@ -906,21 +894,6 @@ WalkFragmentainer(object, child, parent_context); } - - if (!To<LayoutBlockFlow>(&object)->MultiColumnFlowThread()) { - return; - } - // Multicol containers only contain special legacy children invisible to - // LayoutNG, so we need to clean them manually. - if (fragment.GetBreakToken()) { - return; // Wait until we've reached the end. - } - for (const LayoutObject* child = object.SlowFirstChild(); child; - child = child->NextSibling()) { - DCHECK(child->IsLayoutFlowThread() || child->IsLayoutMultiColumnSet() || - child->IsLayoutMultiColumnSpannerPlaceholder()); - child->GetMutableForPainting().ClearPaintFlags(); - } } void PrePaintTreeWalk::WalkPageContainer( @@ -1056,12 +1029,7 @@ } } - // If this is a multicol container, the actual children are inside the flow - // thread child of |parent_object|. - const auto* flow_thread = - To<LayoutBlockFlow>(&parent_object)->MultiColumnFlowThread(); - const auto& actual_parent = flow_thread ? *flow_thread : parent_object; - WalkChildren(actual_parent, &fragmentainer, fragmentainer_context); + WalkChildren(parent_object, &fragmentainer, fragmentainer_context); if (containing_block_context) { containing_block_context->paint_offset -= child_link.offset; @@ -1082,12 +1050,6 @@ // fragmentation, and it also works fine if there's no block fragmentation // involved at all (in such cases we can either to do this, or perform the // PhysicalBoxFragment-accompanied walk that we do further down). - - if (child->IsLayoutMultiColumnSpannerPlaceholder()) { - child->GetMutableForPainting().ClearPaintFlags(); - continue; - } - Walk(*child, context, /* pre_paint_info */ nullptr); continue; } @@ -1283,8 +1245,7 @@ const LayoutBox* box = DynamicTo<LayoutBox>(&object); if (box) { if (traversable_fragment) { - if (!box->IsLayoutFlowThread() && - (!box->IsLayoutNGObject() || !box->PhysicalFragmentCount())) { + if (!box->IsLayoutNGObject() || !box->PhysicalFragmentCount()) { // We can traverse PhysicalFragments in LayoutMedia though it's not // a LayoutNGObject. if (!box->IsMedia()) {
diff --git a/third_party/blink/renderer/core/paint/timing/paint_timing_detector.h b/third_party/blink/renderer/core/paint/timing/paint_timing_detector.h index 7581a40..36dac37b 100644 --- a/third_party/blink/renderer/core/paint/timing/paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/timing/paint_timing_detector.h
@@ -194,12 +194,8 @@ private: friend class PaintTimingDetector; inline static void AggregateTextPaint(const gfx::Rect& visual_rect) { - // Ideally we'd assert that |top_| exists, but there may be text nodes that - // do not have an ancestor non-anonymous block layout objects in the layout - // tree. An example of this is a multicol div, since the - // LayoutMultiColumnFlowThread is in a different layer from the DIV. In - // these cases, |top_| will be null. This is a known bug, see the related - // crbug.com/933479. + // TODO(crbug.com/40614549): This check was allegedly needed for legacy + // multicol, but that implementation is now gone. Turn into DCHECK? if (top_ && top_->data_) { top_->data_->aggregated_visual_rect_.Union(visual_rect); }
diff --git a/third_party/blink/renderer/core/patching/build.gni b/third_party/blink/renderer/core/patching/build.gni index 571b720..6bbfd675 100644 --- a/third_party/blink/renderer/core/patching/build.gni +++ b/third_party/blink/renderer/core/patching/build.gni
@@ -3,8 +3,8 @@ # found in the LICENSE file. blink_core_sources_patching = [ - "dom_patch_status.cc", - "dom_patch_status.h", + "patch.cc", + "patch.h", "patch_supplement.cc", "patch_supplement.h", "patch_event.h",
diff --git a/third_party/blink/renderer/core/patching/dom_patch_status.cc b/third_party/blink/renderer/core/patching/patch.cc similarity index 69% rename from third_party/blink/renderer/core/patching/dom_patch_status.cc rename to third_party/blink/renderer/core/patching/patch.cc index 1795fb0..8dd5975 100644 --- a/third_party/blink/renderer/core/patching/dom_patch_status.cc +++ b/third_party/blink/renderer/core/patching/patch.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 "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "net/http/http_status_code.h" #include "services/network/public/cpp/header_util.h" @@ -41,20 +41,20 @@ namespace blink { // static -DOMPatchStatus* DOMPatchStatus::Create(ContainerNode& target, - HTMLTemplateElement* source, - const KURL& source_url, - Node* previous_child, - Node* next_child) { - return MakeGarbageCollected<DOMPatchStatus>(source, target, source_url, - previous_child, next_child); +Patch* Patch::Create(ContainerNode& target, + HTMLTemplateElement* source, + const KURL& source_url, + Node* previous_child, + Node* next_child) { + return MakeGarbageCollected<Patch>(source, target, source_url, previous_child, + next_child); } -DOMPatchStatus::DOMPatchStatus(HTMLTemplateElement* source, - ContainerNode& target, - const KURL& source_url, - Node* previous_child, - Node* next_child) +Patch::Patch(HTMLTemplateElement* source, + ContainerNode& target, + const KURL& source_url, + Node* previous_child, + Node* next_child) : source_(source), target_(target), previous_child_(previous_child), @@ -64,12 +64,11 @@ target.GetDocument().GetExecutionContext())), source_url_(source_url) {} -ScriptPromise<IDLUndefined> DOMPatchStatus::finished( - ScriptState* script_state) { +ScriptPromise<IDLUndefined> Patch::finished(ScriptState* script_state) { return finished_->Promise(script_state->World()); } -void DOMPatchStatus::Start() { +void Patch::Start() { if (state_ != State::kPending) { return; } @@ -79,7 +78,7 @@ Commit(); } -void DOMPatchStatus::Commit() { +void Patch::Commit() { state_ = State::kActive; loader_.Clear(); if (!next_child_ && !previous_child_) { @@ -106,81 +105,14 @@ ParserPrefetchPolicy::kDisallowPrefetching); } -void DOMPatchStatus::DispatchPatchEvent() { +void Patch::DispatchPatchEvent() { Event* event = MakeGarbageCollected<PatchEvent>(event_type_names::kPatch, this); event->SetTarget(target_); target_->DispatchEvent(*event); } -class PatchLoaderClient : public GarbageCollected<PatchLoaderClient>, - public ThreadableLoaderClient { - public: - explicit PatchLoaderClient(DOMPatchStatus* patch) : patch_(patch) {} - - void Trace(Visitor* visitor) const override { - visitor->Trace(patch_); - ThreadableLoaderClient::Trace(visitor); - } - - private: - void DidReceiveResponse(uint64_t, const ResourceResponse& response) override { - if (!network::IsSuccessfulStatus(response.HttpStatusCode())) { - // TODO(nrosenthal): use different DOMExceptions for different statuses? - // Or maybe using "network error" for all of them? - if (response.HttpStatusCode() == net::HTTP_NOT_FOUND) { - OnError(DOMExceptionCode::kNotFoundError, response.HttpStatusText()); - } else { - OnError(DOMExceptionCode::kNetworkError, response.HttpStatusText()); - } - } else { - patch_->Commit(); - } - } - void DidReceiveData(base::span<const char> bytes) override { - patch_->AppendBytes(reinterpret_cast<const base::span<uint8_t>&>(bytes)); - } - void DidFinishLoading(uint64_t /*identifier*/) override { patch_->Finish(); } - void DidFail(uint64_t /*identifier*/, const ResourceError& error) override { - OnError(DOMExceptionCode::kNetworkError, - AtomicString("Failed to fetch resource")); - } - - void OnError(DOMExceptionCode code, const AtomicString& message) { - ScriptState* script_state = - ToScriptStateForMainWorld(patch_->GetDocument().GetExecutionContext()); - ScriptState::Scope scope(script_state); - v8::Local<v8::Value> exception = V8ThrowDOMException::CreateOrEmpty( - script_state->GetIsolate(), code, message); - patch_->Terminate(ScriptValue(script_state->GetIsolate(), exception)); - } - - Member<DOMPatchStatus> patch_; -}; - -void DOMPatchStatus::Fetch() { - ResourceRequest request(source_url_); - source_url_ = KURL(); - // TODO(nrosenthal): add actual patch request destination & context - request.SetRequestDestination(network::mojom::RequestDestination::kScript); - request.SetRequestContext(mojom::blink::RequestContextType::SUBRESOURCE); - - // TODO(nrosenthal): add a crossorigin property - request.SetCredentialsMode(network::mojom::CredentialsMode::kSameOrigin); - request.SetMode(network::mojom::RequestMode::kCors); - // TODO(nrosenthal): change accept header based on target element - request.SetHttpHeaderField(http_names::kAccept, AtomicString("text/html")); - ResourceLoaderOptions resource_loader_options( - GetDocument().GetExecutionContext()->GetCurrentWorld()); - resource_loader_options.data_buffering_policy = kDoNotBufferData; - - loader_ = MakeGarbageCollected<ThreadableLoader>( - *GetDocument().GetExecutionContext(), - MakeGarbageCollected<PatchLoaderClient>(this), resource_loader_options); - loader_->Start(std::move(request)); -} - -void DOMPatchStatus::Finish() { +void Patch::Finish() { if (state_ == State::kTerminated) { return; } @@ -220,13 +152,7 @@ PatchSupplement::From(GetDocument())->DidComplete(*target_); } -void DOMPatchStatus::Append(const String& text) { - if (state_ != State::kTerminated) { - parser_->Append(text); - } -} - -void DOMPatchStatus::Terminate(ScriptValue reason) { +void Patch::Terminate(ScriptValue reason) { if (state_ == State::kFinished || state_ == State::kTerminated) { return; } @@ -242,7 +168,13 @@ finished_->Reject(reason); } -void DOMPatchStatus::AppendBytes(base::span<uint8_t> bytes) { +void Patch::Append(const String& text) { + if (state_ != State::kTerminated) { + parser_->Append(text); + } +} + +void Patch::AppendBytes(base::span<uint8_t> bytes) { if (state_ == State::kTerminated) { return; } @@ -255,11 +187,68 @@ parser_->AppendBytes(bytes); } -Document& DOMPatchStatus::GetDocument() { +Document& Patch::GetDocument() { return target_->GetDocument(); } -void DOMPatchStatus::Trace(Visitor* visitor) const { +void Patch::Fetch() { + ResourceRequest request(source_url_); + source_url_ = KURL(); + // TODO(nrosenthal): add actual patch request destination & context + request.SetRequestDestination(network::mojom::RequestDestination::kScript); + request.SetRequestContext(mojom::blink::RequestContextType::SUBRESOURCE); + + // TODO(nrosenthal): add a crossorigin property + request.SetCredentialsMode(network::mojom::CredentialsMode::kSameOrigin); + request.SetMode(network::mojom::RequestMode::kCors); + // TODO(nrosenthal): change accept header based on target element + request.SetHttpHeaderField(http_names::kAccept, AtomicString("text/html")); + ResourceLoaderOptions resource_loader_options( + GetDocument().GetExecutionContext()->GetCurrentWorld()); + resource_loader_options.data_buffering_policy = kDoNotBufferData; + + loader_ = MakeGarbageCollected<ThreadableLoader>( + *GetDocument().GetExecutionContext(), this, resource_loader_options); + loader_->Start(std::move(request)); +} + +void Patch::DidReceiveResponse(uint64_t, const ResourceResponse& response) { + if (!network::IsSuccessfulStatus(response.HttpStatusCode())) { + // TODO(nrosenthal): use different DOMExceptions for different statuses? + // Or maybe using "network error" for all of them? + if (response.HttpStatusCode() == net::HTTP_NOT_FOUND) { + OnFetchError(DOMExceptionCode::kNotFoundError, response.HttpStatusText()); + } else { + OnFetchError(DOMExceptionCode::kNetworkError, response.HttpStatusText()); + } + } else { + Commit(); + } +} + +void Patch::DidReceiveData(base::span<const char> bytes) { + AppendBytes(reinterpret_cast<const base::span<uint8_t>&>(bytes)); +} + +void Patch::DidFinishLoading(uint64_t /*identifier*/) { + Finish(); +} + +void Patch::DidFail(uint64_t /*identifier*/, const ResourceError& error) { + OnFetchError(DOMExceptionCode::kNetworkError, + AtomicString("Failed to fetch resource")); +} + +void Patch::OnFetchError(DOMExceptionCode code, const AtomicString& message) { + ScriptState* script_state = + ToScriptStateForMainWorld(GetDocument().GetExecutionContext()); + ScriptState::Scope scope(script_state); + v8::Local<v8::Value> exception = V8ThrowDOMException::CreateOrEmpty( + script_state->GetIsolate(), code, message); + Terminate(ScriptValue(script_state->GetIsolate(), exception)); +} + +void Patch::Trace(Visitor* visitor) const { visitor->Trace(source_); visitor->Trace(target_); visitor->Trace(previous_child_);
diff --git a/third_party/blink/renderer/core/patching/dom_patch_status.h b/third_party/blink/renderer/core/patching/patch.h similarity index 68% rename from third_party/blink/renderer/core/patching/dom_patch_status.h rename to third_party/blink/renderer/core/patching/patch.h index 69b6f95..9a1d1ba 100644 --- a/third_party/blink/renderer/core/patching/dom_patch_status.h +++ b/third_party/blink/renderer/core/patching/patch.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PATCHING_DOM_PATCH_STATUS_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_PATCHING_DOM_PATCH_STATUS_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PATCHING_PATCH_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_PATCHING_PATCH_H_ #include "third_party/blink/renderer/bindings/core/v8/idl_types.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" @@ -16,6 +16,7 @@ #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/loader/threadable_loader.h" +#include "third_party/blink/renderer/core/loader/threadable_loader_client.h" #include "third_party/blink/renderer/platform/bindings/exception_code.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h" @@ -28,20 +29,20 @@ class HTMLTemplateElement; class ScriptState; -class DOMPatchStatus : public ScriptWrappable { +class Patch : public ScriptWrappable, public ThreadableLoaderClient { DEFINE_WRAPPERTYPEINFO(); public: - static DOMPatchStatus* Create(ContainerNode& target, - HTMLTemplateElement* source = nullptr, - const KURL& source_url = KURL(), - Node* previous_child = nullptr, - Node* next_child = nullptr); - DOMPatchStatus(HTMLTemplateElement* source, - ContainerNode& target, - const KURL& source_url, - Node* previous_child, - Node* next_child); + static Patch* Create(ContainerNode& target, + HTMLTemplateElement* source = nullptr, + const KURL& source_url = KURL(), + Node* previous_child = nullptr, + Node* next_child = nullptr); + Patch(HTMLTemplateElement* source, + ContainerNode& target, + const KURL& source_url, + Node* previous_child, + Node* next_child); ScriptPromise<IDLUndefined> finished(ScriptState*); HTMLTemplateElement* source() { return source_; } void Trace(Visitor*) const override; @@ -58,6 +59,14 @@ private: void Fetch(); + + // ThreadableLoaderClient implementation + void DidReceiveResponse(uint64_t, const ResourceResponse& response) override; + void DidReceiveData(base::span<const char> bytes) override; + void DidFinishLoading(uint64_t /*identifier*/) override; + void DidFail(uint64_t /*identifier*/, const ResourceError& error) override; + void OnFetchError(DOMExceptionCode code, const AtomicString& message); + enum class State { kPending, kActive, kTerminated, kFinished }; State state_ = State::kPending; Member<HTMLTemplateElement> source_; @@ -74,4 +83,4 @@ }; } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PATCHING_DOM_PATCH_STATUS_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PATCHING_PATCH_H_
diff --git a/third_party/blink/renderer/core/patching/patch.idl b/third_party/blink/renderer/core/patching/patch.idl new file mode 100644 index 0000000..19e8a50 --- /dev/null +++ b/third_party/blink/renderer/core/patching/patch.idl
@@ -0,0 +1,5 @@ +[Exposed=Window, RuntimeEnabled=DocumentPatching] +interface Patch { + [SameObject, CallWith=ScriptState] readonly attribute Promise<undefined> finished; + [SameObject] readonly attribute HTMLTemplateElement source; +}; \ No newline at end of file
diff --git a/third_party/blink/renderer/core/patching/patch_event.h b/third_party/blink/renderer/core/patching/patch_event.h index b434a1f7..3eb682c 100644 --- a/third_party/blink/renderer/core/patching/patch_event.h +++ b/third_party/blink/renderer/core/patching/patch_event.h
@@ -9,7 +9,7 @@ #include "third_party/blink/renderer/core/dom/events/event.h" #include "third_party/blink/renderer/core/event_interface_names.h" #include "third_party/blink/renderer/core/event_type_names.h" -#include "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/member.h" #include "third_party/blink/renderer/platform/wtf/casting.h" @@ -26,7 +26,7 @@ return MakeGarbageCollected<PatchEvent>(type, init->patch()); } - PatchEvent(const AtomicString& type, DOMPatchStatus* patch) + PatchEvent(const AtomicString& type, Patch* patch) : Event(type, Bubbles::kNo, Cancelable::kNo), patch_(patch) {} ~PatchEvent() override = default; @@ -40,12 +40,12 @@ Event::Trace(visitor); } - DOMPatchStatus* patch() const { return patch_; } + Patch* patch() const { return patch_; } bool IsPatchEvent() const override { return true; } private: - Member<DOMPatchStatus> patch_; + Member<Patch> patch_; }; template <>
diff --git a/third_party/blink/renderer/core/patching/patch_event.idl b/third_party/blink/renderer/core/patching/patch_event.idl index e6569e81..e312195 100644 --- a/third_party/blink/renderer/core/patching/patch_event.idl +++ b/third_party/blink/renderer/core/patching/patch_event.idl
@@ -7,5 +7,5 @@ RuntimeEnabled=DocumentPatching ] interface PatchEvent : Event { constructor(DOMString type, PatchEventInit init); - [SameObject] readonly attribute PatchStatus patch; + [SameObject] readonly attribute Patch patch; };
diff --git a/third_party/blink/renderer/core/patching/patch_event_init.idl b/third_party/blink/renderer/core/patching/patch_event_init.idl index 81e71c7..6a6517b 100644 --- a/third_party/blink/renderer/core/patching/patch_event_init.idl +++ b/third_party/blink/renderer/core/patching/patch_event_init.idl
@@ -3,6 +3,6 @@ // found in the LICENSE file. dictionary PatchEventInit : EventInit { - PatchStatus patch; + Patch patch; };
diff --git a/third_party/blink/renderer/core/patching/patch_status.idl b/third_party/blink/renderer/core/patching/patch_status.idl deleted file mode 100644 index 1c3a7aa..0000000 --- a/third_party/blink/renderer/core/patching/patch_status.idl +++ /dev/null
@@ -1,5 +0,0 @@ -[Exposed=Window, RuntimeEnabled=DocumentPatching, ImplementedAs=DOMPatchStatus] -interface PatchStatus { - [SameObject, CallWith=ScriptState] readonly attribute Promise<undefined> finished; - [SameObject] readonly attribute HTMLTemplateElement source; -};
diff --git a/third_party/blink/renderer/core/patching/patch_supplement.cc b/third_party/blink/renderer/core/patching/patch_supplement.cc index d0e5cc7..3d81b15 100644 --- a/third_party/blink/renderer/core/patching/patch_supplement.cc +++ b/third_party/blink/renderer/core/patching/patch_supplement.cc
@@ -19,7 +19,7 @@ #include "third_party/blink/renderer/core/html/html_template_element.h" #include "third_party/blink/renderer/core/html/parser/html_document_parser.h" #include "third_party/blink/renderer/core/html/parser/parser_synchronization_policy.h" -#include "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "third_party/blink/renderer/core/streams/underlying_sink_base.h" #include "third_party/blink/renderer/core/streams/writable_stream.h" #include "third_party/blink/renderer/core/typed_arrays/dom_array_piece.h" @@ -62,7 +62,7 @@ class SinglePatchSink : public UnderlyingSinkBase { public: explicit SinglePatchSink(ContainerNode& target, Node* a, Node* b) - : patch_(DOMPatchStatus::Create(target, nullptr, KURL(), a, b)) {} + : patch_(Patch::Create(target, nullptr, KURL(), a, b)) {} void Trace(Visitor* visitor) const override { visitor->Trace(patch_); UnderlyingSinkBase::Trace(visitor); @@ -113,7 +113,7 @@ return ToResolvedUndefinedPromise(script_state); } - Member<DOMPatchStatus> patch_; + Member<Patch> patch_; }; } // namespace @@ -219,7 +219,7 @@ return supplement; } -DOMPatchStatus* PatchSupplement::CurrentPatchFor(const Node& target) { +Patch* PatchSupplement::CurrentPatchFor(const Node& target) { if (auto index = IndexOfPatch(target)) { return patches_.at(*index); } else { @@ -236,7 +236,7 @@ return std::nullopt; } -void PatchSupplement::DidStart(Node& target, DOMPatchStatus* status) { +void PatchSupplement::DidStart(Node& target, Patch* status) { patches_.push_back(status); if (Element* element = DynamicTo<Element>(target)) { element->PatchStateChanged(); @@ -257,7 +257,7 @@ ContainerNode& target, Node* previous_child, Node* next_child) { - DOMPatchStatus* previous = CurrentPatchFor(target); + Patch* previous = CurrentPatchFor(target); if (previous) { previous->Terminate(ScriptValue::From( script_state, MakeGarbageCollected<DOMException>(
diff --git a/third_party/blink/renderer/core/patching/patch_supplement.h b/third_party/blink/renderer/core/patching/patch_supplement.h index 77f9c16..2ccb6eb 100644 --- a/third_party/blink/renderer/core/patching/patch_supplement.h +++ b/third_party/blink/renderer/core/patching/patch_supplement.h
@@ -7,7 +7,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/patching/dom_patch_status.h" +#include "third_party/blink/renderer/core/patching/patch.h" #include "third_party/blink/renderer/platform/graphics/dom_node_id.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" @@ -30,8 +30,8 @@ static PatchSupplement* FromIfExists(const Document&); void Trace(Visitor*) const override; - DOMPatchStatus* CurrentPatchFor(const Node&); - void DidStart(Node&, DOMPatchStatus*); + Patch* CurrentPatchFor(const Node&); + void DidStart(Node&, Patch*); void DidComplete(Node&); WritableStream* CreateSinglePatchStream(ScriptState*, ContainerNode& target, @@ -42,7 +42,7 @@ private: std::optional<size_t> IndexOfPatch(const Node& target); // TODO(nrosenthal): multiple patches per destination - HeapVector<Member<DOMPatchStatus>> patches_; + HeapVector<Member<Patch>> patches_; }; } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_PATCHING_PATCH_SUPPLEMENT_H_
diff --git a/third_party/blink/renderer/core/style/grid_track_list.cc b/third_party/blink/renderer/core/style/grid_track_list.cc index fb287f03..fe77fde 100644 --- a/third_party/blink/renderer/core/style/grid_track_list.cc +++ b/third_party/blink/renderer/core/style/grid_track_list.cc
@@ -145,9 +145,11 @@ case GridTrackRepeater::RepeatType::kAutoFill: case GridTrackRepeater::RepeatType::kAutoFit: // Intentional Fallthrough. track_count_before_auto_repeat_ = track_count_without_auto_repeat_; - has_auto_sized_repeater_ = - std::find(repeater_track_sizes.begin(), repeater_track_sizes.end(), - Length::Auto()) != repeater_track_sizes.end(); + has_intrinsic_sized_repeater_ = + std::find_if(repeater_track_sizes.begin(), repeater_track_sizes.end(), + [](const GridTrackSize& track_size) { + return track_size.IsTrackDefinitionIntrinsic(); + }) != repeater_track_sizes.end(); if (HasAutoRepeater() || repeat_size > AvailableTrackCount()) { return false; } @@ -202,7 +204,7 @@ track_count_before_auto_repeat_ = other.track_count_before_auto_repeat_; non_auto_repeat_line_count_ = other.non_auto_repeat_line_count_; axis_type_ = other.axis_type_; - has_auto_sized_repeater_ = other.has_auto_sized_repeater_; + has_intrinsic_sized_repeater_ = other.has_intrinsic_sized_repeater_; } bool GridTrackList::operator==(const GridTrackList& other) const { @@ -213,7 +215,7 @@ repeater_track_sizes_ == other.repeater_track_sizes_ && non_auto_repeat_line_count_ == other.non_auto_repeat_line_count_ && axis_type_ == other.axis_type_ && - has_auto_sized_repeater_ == other.has_auto_sized_repeater_; + has_intrinsic_sized_repeater_ == other.has_intrinsic_sized_repeater_; } } // namespace blink
diff --git a/third_party/blink/renderer/core/style/grid_track_list.h b/third_party/blink/renderer/core/style/grid_track_list.h index 72e865a..483aef8d 100644 --- a/third_party/blink/renderer/core/style/grid_track_list.h +++ b/third_party/blink/renderer/core/style/grid_track_list.h
@@ -102,9 +102,11 @@ // Sets the axis type (standalone or subgrid). void SetAxisType(GridAxisType axis_type); - // If true, this track list has a repeat definition with an auto sized track - // with an automatic number of repetitions. - bool HasAutoSizedRepeater() const { return has_auto_sized_repeater_; } + // If true, this track list has a repeat definition with an intrinsic sized + // track with an automatic number of repetitions. + bool HasIntrinsicSizedRepeater() const { + return has_intrinsic_sized_repeater_; + } // Clears all data. void Clear(); @@ -141,9 +143,9 @@ // while this tracks line names (including empty lines). wtf_size_t non_auto_repeat_line_count_{0}; - // If true, this track list has a repeat definition with an auto sized track - // with an automatic number of repetitions. - bool has_auto_sized_repeater_{false}; + // If true, this track list has a repeat definition with an intrinsic sized + // track with an automatic number of repetitions. + bool has_intrinsic_sized_repeater_{false}; // The grid axis type (standalone or subgridded). GridAxisType axis_type_{GridAxisType::kStandaloneAxis};
diff --git a/third_party/blink/renderer/core/style/grid_track_size.h b/third_party/blink/renderer/core/style/grid_track_size.h index 316f8d73..892b64c 100644 --- a/third_party/blink/renderer/core/style/grid_track_size.h +++ b/third_party/blink/renderer/core/style/grid_track_size.h
@@ -42,6 +42,23 @@ kFitContentTrackSizing }; +static bool IsTrackSizeIntrinsic(const Length& length, + GridTrackSizeType track_size_type) { + switch (track_size_type) { + case kLengthTrackSizing: { + const Length::Type type = length.GetType(); + return type == Length::Type::kAuto || type == Length::Type::kMinContent || + type == Length::Type::kMaxContent; + } + case kMinMaxTrackSizing: + return false; + case kFitContentTrackSizing: + return true; + default: + NOTREACHED(); + } +} + // This class represents a <track-size> from the spec. Althought there are 3 // different types of <track-size> there is always an equivalent minmax() // representation that could represent any of them. The only special case is @@ -71,7 +88,8 @@ ? length : Length::Fixed()), type_(track_size_type), - track_size_definition_is_auto_(length == Length::Auto()) { + track_size_definition_is_intrinsic_( + IsTrackSizeIntrinsic(length, track_size_type)) { DCHECK(track_size_type == kLengthTrackSizing || track_size_type == kFitContentTrackSizing); DCHECK(track_size_type == kLengthTrackSizing || !length.IsFlex()); @@ -84,7 +102,7 @@ max_track_breadth_(max_track_breadth), fit_content_track_breadth_(Length::Fixed()), type_(kMinMaxTrackSizing), - track_size_definition_is_auto_(false) { + track_size_definition_is_intrinsic_(false) { CacheMinMaxTrackBreadthTypes(); } @@ -206,7 +224,9 @@ min_track_breadth_ == max_track_breadth_; } - bool IsTrackDefinitionAuto() const { return track_size_definition_is_auto_; } + bool IsTrackDefinitionIntrinsic() const { + return track_size_definition_is_intrinsic_; + } private: Length min_track_breadth_; @@ -226,7 +246,7 @@ bool max_track_breadth_is_max_content_ : 1; bool min_track_breadth_is_min_content_ : 1; bool max_track_breadth_is_min_content_ : 1; - bool track_size_definition_is_auto_ : 1; + bool track_size_definition_is_intrinsic_ : 1; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc index f3d64ab..da71542 100644 --- a/third_party/blink/renderer/core/testing/internals.cc +++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -649,6 +649,9 @@ return DocumentMarker::kActiveSuggestion; if (EqualIgnoringASCIICase(marker_type, "Suggestion")) return DocumentMarker::kSuggestion; + if (EqualIgnoringASCIICase(marker_type, "Glic")) { + return DocumentMarker::kGlic; + } return std::nullopt; } @@ -1334,20 +1337,33 @@ return; } - if (type != DocumentMarker::kSpelling && type != DocumentMarker::kGrammar) { + if (type != DocumentMarker::kSpelling && type != DocumentMarker::kGrammar && + type != DocumentMarker::kGlic) { exception_state.ThrowDOMException(DOMExceptionCode::kSyntaxError, "internals.setMarker() currently only " - "supports spelling and grammar markers; " - "attempted to add marker of type '" + + "supports spelling, grammar and glic " + " markers; attempted to add marker of " + " type '" + marker_type + "'."); return; } document->UpdateStyleAndLayout(DocumentUpdateReason::kTest); - if (type == DocumentMarker::kSpelling) + if (type == DocumentMarker::kSpelling) { document->Markers().AddSpellingMarker(EphemeralRange(range)); - else + } else if (type == DocumentMarker::kGrammar) { document->Markers().AddGrammarMarker(EphemeralRange(range)); + } else { + // GLIC markers animate their color and start off transparent. So + // we need to start the animation and update it to the end in order to + // see the marker appearance. + document->Markers().AddGlicMarker(EphemeralRange(range)); + document->Markers().StartGlicMarkerAnimationIfNeeded(); + base::TimeTicks ticks; + document->Markers().ContinueGlicMarkerAnimation(ticks); + ticks += base::TimeDelta::Max(); + document->Markers().ContinueGlicMarkerAnimation(ticks); + } } void Internals::removeMarker(Document* document,
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 73d17e5..52fa9bd 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc +++ b/third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
@@ -165,7 +165,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) {
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc index 91b342b..b55fd2ab 100644 --- a/third_party/blink/renderer/core/timing/window_performance.cc +++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -695,11 +695,11 @@ #endif // BUILDFLAG(IS_MAC) } - if (event.target()) { + if (event.RawTarget()) { // `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()); + entry->SetTarget(event.RawTarget()->ToNode()); } // Request presentation time first, because this might increment presentation
diff --git a/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc b/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc index f4f3948..230e388 100644 --- a/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc +++ b/third_party/blink/renderer/modules/app_banner/before_install_prompt_event.cc
@@ -105,8 +105,8 @@ void BeforeInstallPromptEvent::preventDefault() { Event::preventDefault(); - if (target()) { - UseCounter::Count(target()->GetExecutionContext(), + if (RawTarget()) { + UseCounter::Count(RawTarget()->GetExecutionContext(), WebFeature::kBeforeInstallPromptEventPreventDefault); } }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc index c0d3401a..f73c7698 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -729,7 +729,7 @@ DCHECK_EQ(ExecutionContext::From(script_state_), execution_context); DCHECK_EQ(event->type(), event_type_names::kSuccess); - EventTarget* target = event->target(); + EventTarget* target = event->RawTarget(); IDBRequest* request = static_cast<IDBRequest*>(target); ScriptState::Scope scope(script_state_);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.cc b/third_party/blink/renderer/modules/indexeddb/idb_request.cc index 5a8eed3..2bd4754 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_request.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
@@ -880,7 +880,7 @@ return DispatchEventResult::kCanceledBeforeDispatch; DCHECK_EQ(ready_state_, PENDING); DCHECK(has_pending_activity_); - DCHECK_EQ(event.target(), this); + DCHECK_EQ(event.RawTarget(), this); if (event.type() != event_type_names::kBlocked) { ready_state_ = DONE;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc b/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc index d1cd0d3..c4bf415 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc
@@ -686,7 +686,7 @@ DCHECK_NE(state_, kFinished); DCHECK(has_pending_activity_); DCHECK(GetExecutionContext()); - DCHECK_EQ(event.target(), this); + DCHECK_EQ(event.RawTarget(), this); state_ = kFinished; DispatchEventResult dispatch_result =
diff --git a/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc b/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc index 3beb236..f06626c 100644 --- a/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc +++ b/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
@@ -341,7 +341,7 @@ } IDBOpenDBRequest* idb_open_db_request = - static_cast<IDBOpenDBRequest*>(event->target()); + static_cast<IDBOpenDBRequest*>(event->RawTarget()); IDBAny* request_result = idb_open_db_request->ResultAsAny(); if (request_result->GetType() != IDBAny::kIDBDatabaseType) { executable_with_database_->GetRequestCallback()->sendFailure( @@ -391,7 +391,7 @@ // had previously been enumerated was deleted. We don't want to // implicitly re-create it here, so abort the transaction. IDBOpenDBRequest* idb_open_db_request = - static_cast<IDBOpenDBRequest*>(event->target()); + static_cast<IDBOpenDBRequest*>(event->RawTarget()); NonThrowableExceptionState exception_state; idb_open_db_request->transaction()->abort(exception_state); executable_with_database_->GetRequestCallback()->sendFailure( @@ -644,7 +644,7 @@ return; } - IDBRequest* idb_request = static_cast<IDBRequest*>(event->target()); + IDBRequest* idb_request = static_cast<IDBRequest*>(event->RawTarget()); IDBAny* request_result = idb_request->ResultAsAny(); if (request_result->GetType() == IDBAny::kIDBValueType) { end(false); @@ -945,7 +945,7 @@ return; } - IDBRequest* idb_request = static_cast<IDBRequest*>(event->target()); + IDBRequest* idb_request = static_cast<IDBRequest*>(event->RawTarget()); IDBAny* request_result = idb_request->ResultAsAny(); if (request_result->GetType() != IDBAny::kIntegerType) { NotifySubtaskDone(owner_, "Unexpected result type.");
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 5cce528..69184f78 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..7dd14f3 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,7 +166,7 @@ WTF::BindOnce(&MediaControlPopupMenuElement::HideIfNotFocused, WrapWeakPersistent(this))); } else if (event.type() == event_type_names::kClick && - event.target() != this) { + event.RawTarget() != this) { // Since event.target() != this, we know that one of our children was // clicked. OnItemSelected(); @@ -173,7 +174,7 @@ 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 9700baab..a4f1237 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/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/webaudio/BUILD.gn b/third_party/blink/renderer/modules/webaudio/BUILD.gn index 98742b7..c069f46 100644 --- a/third_party/blink/renderer/modules/webaudio/BUILD.gn +++ b/third_party/blink/renderer/modules/webaudio/BUILD.gn
@@ -166,8 +166,6 @@ "script_processor_node.h", "semi_realtime_audio_worklet_thread.cc", "semi_realtime_audio_worklet_thread.h", - "setsinkid_resolver.cc", - "setsinkid_resolver.h", "stereo_panner_handler.cc", "stereo_panner_handler.h", "stereo_panner_node.cc",
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.cc b/third_party/blink/renderer/modules/webaudio/audio_context.cc index 8f78623..8e7f8e07 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_context.cc
@@ -7,9 +7,10 @@ #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/strings/to_string.h" +#include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "media/audio/audio_device_description.h" -#include "base/trace_event/trace_event.h" +#include "media/base/output_device_info.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" @@ -19,9 +20,11 @@ #include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h" #include "third_party/blink/public/platform/web_audio_latency_hint.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_context_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_timestamp.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_union_audiocontextlatencycategory_double.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_union_audiosinkinfo_string.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/html/media/html_media_element.h" @@ -149,10 +152,179 @@ return energy > 0; } -using blink::SetSinkIdResolver; - } // namespace +AudioContext::SetSinkIdResolver::SetSinkIdResolver( + ScriptState* script_state, + AudioContext& audio_context, + const V8UnionAudioSinkOptionsOrString& sink_id) + : audio_context_(audio_context), + resolver_(MakeGarbageCollected<ScriptPromiseResolver<IDLUndefined>>( + script_state)) { + DCHECK(IsMainThread()); + + // Currently the only available AudioSinkOptions is a type of a silent sink, + // which can be specified by an empty descriptor constructor. + auto& frame_token = To<LocalDOMWindow>(audio_context_->GetExecutionContext()) + ->GetLocalFrameToken(); + if (sink_id.GetContentType() == + V8UnionAudioSinkOptionsOrString::ContentType::kAudioSinkOptions) { + sink_descriptor_ = WebAudioSinkDescriptor(frame_token); + } else { + sink_descriptor_ = + WebAudioSinkDescriptor(sink_id.GetAsString(), frame_token); + } + + TRACE_EVENT1("webaudio", "SetSinkIdResolver::SetSinkIdResolver", + "sink_id (after setting sink_descriptor_)", + audio_utilities::GetSinkIdForTracing(sink_descriptor_)); +} + +void AudioContext::SetSinkIdResolver::Trace(Visitor* visitor) const { + visitor->Trace(audio_context_); + visitor->Trace(resolver_); +} + +void AudioContext::SetSinkIdResolver::Start() { + TRACE_EVENT1("webaudio", "SetSinkIdResolver::Start", "sink_id", + audio_utilities::GetSinkIdForTracing(sink_descriptor_)); + DCHECK(IsMainThread()); + + if (!resolver_ || !resolver_->GetExecutionContext() || !audio_context_ || + audio_context_->IsContextCleared()) { + // No point in rejecting promise, as it will bail out upon detached + // context anyway. + return; + } + + // Refer to + // https://webaudio.github.io/web-audio-api/#validating-sink-identifier for + // sink_id/sink_descriptor validation steps. + if (sink_descriptor_ == audio_context_->GetSinkDescriptor()) { + OnSetSinkIdComplete(media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK); + } else if (!audio_context_->IsValidSinkDescriptor(sink_descriptor_)) { + OnSetSinkIdComplete( + media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND); + } else { + auto* audio_destination = audio_context_->destination(); + // A sanity check to make sure we have valid audio_destination node from + // `audio_context_`. + if (!audio_destination) { + OnSetSinkIdComplete( + media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); + } else { + audio_context_->NotifySetSinkIdBegins(); + auto set_sink_id_completion_callback = blink::BindOnce( + &SetSinkIdResolver::OnSetSinkIdComplete, WrapPersistent(this)); + auto set_sink_descriptor_callback = blink::BindOnce( + &RealtimeAudioDestinationNode::SetSinkDescriptor, + WrapWeakPersistent( + static_cast<RealtimeAudioDestinationNode*>(audio_destination)), + sink_descriptor_, std::move(set_sink_id_completion_callback)); + audio_context_->GetExecutionContext() + ->GetTaskRunner(TaskType::kInternalMediaRealTime) + ->PostTask(FROM_HERE, std::move(set_sink_descriptor_callback)); + } + } +} + +void AudioContext::SetSinkIdResolver::Resolve() { + DCHECK(IsMainThread()); + DCHECK(resolver_); + resolver_->Resolve(); + resolver_ = nullptr; +} + +void AudioContext::SetSinkIdResolver::Reject(DOMException* exception) { + DCHECK(IsMainThread()); + DCHECK(resolver_); + resolver_->Reject(exception); + resolver_ = nullptr; +} + +void AudioContext::SetSinkIdResolver::Reject(v8::Local<v8::Value> value) { + DCHECK(IsMainThread()); + DCHECK(resolver_); + resolver_->Reject(value); + resolver_ = nullptr; +} + +ScriptPromise<IDLUndefined> AudioContext::SetSinkIdResolver::GetPromise() { + DCHECK(IsMainThread()); + DCHECK(resolver_); + return resolver_->Promise(); +} + +void AudioContext::SetSinkIdResolver::HandleOutputDeviceStatus( + media::OutputDeviceStatus status) { + ScriptState* script_state = resolver_->GetScriptState(); + ScriptState::Scope scope(script_state); + switch (status) { + case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK: + if (audio_context_ && !audio_context_->IsContextCleared()) { + // Update AudioContext's sink ID and fire the 'onsinkchange' event + audio_context_->NotifySetSinkIdIsDone(sink_descriptor_); + } + Resolve(); + return; + case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND: + Reject(V8ThrowDOMException::CreateOrEmpty( + script_state->GetIsolate(), DOMExceptionCode::kNotFoundError, + StrCat({"AudioContext.setSinkId(): failed: the device ", + String(sink_descriptor_.SinkId()), " is not found."}))); + return; + case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED: + Reject(V8ThrowDOMException::CreateOrEmpty( + script_state->GetIsolate(), DOMExceptionCode::kNotAllowedError, + StrCat({"AudioContext.setSinkId() failed: access to the device ", + String(sink_descriptor_.SinkId()), " is not permitted."}))); + return; + case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_TIMED_OUT: + Reject(V8ThrowDOMException::CreateOrEmpty( + script_state->GetIsolate(), DOMExceptionCode::kTimeoutError, + StrCat({"AudioContext.setSinkId() failed: the request for device ", + String(sink_descriptor_.SinkId()), " is timed out."}))); + return; + case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL: + Reject(V8ThrowDOMException::CreateOrEmpty( + script_state->GetIsolate(), DOMExceptionCode::kInvalidStateError, + StrCat({"AudioContext.setSinkId() failed: the device ", + String(sink_descriptor_.SinkId()), " is not available."}))); + return; + } + NOTREACHED(); +} + +void AudioContext::SetSinkIdResolver::OnSetSinkIdComplete( + media::OutputDeviceStatus status) { + TRACE_EVENT1("webaudio", "SetSinkIdResolver::OnSetSinkIdComplete", "sink_id", + audio_utilities::GetSinkIdForTracing(sink_descriptor_)); + DCHECK(IsMainThread()); + + if (!resolver_) { + return; + } + + auto* excecution_context = resolver_->GetExecutionContext(); + if (!excecution_context || excecution_context->IsContextDestroyed()) { + return; + } + + HandleOutputDeviceStatus(status); + + auto& resolvers = audio_context_->GetSetSinkIdResolver(); + resolvers.pop_front(); + if (!resolvers.empty() && (audio_context_->PendingDeviceListUpdates() == 0)) { + // Prevent potential stack overflow under heavy load by scheduling the next + // resolver start asynchronously instead of invoking it directly. + auto next_start_task = blink::BindOnce( + &SetSinkIdResolver::Start, WrapWeakPersistent(resolvers.front().Get())); + audio_context_->GetExecutionContext() + ->GetTaskRunner(TaskType::kInternalMediaRealTime) + ->PostTask(FROM_HERE, std::move(next_start_task)); + } +} + AudioContext* AudioContext::Create(ExecutionContext* context, const AudioContextOptions* context_options, ExceptionState& exception_state) { @@ -325,8 +497,8 @@ autoplay_status_ = AutoplayStatus::kFailed; blocked_by_prerendering_ = true; window.document()->AddPostPrerenderingActivationStep( - WTF::BindOnce(&AudioContext::ResumeOnPrerenderActivation, - WrapWeakPersistent(this))); + blink::BindOnce(&AudioContext::ResumeOnPrerenderActivation, + WrapWeakPersistent(this))); } break; case AutoplayPolicy::Type::kUserGestureRequired: @@ -367,9 +539,9 @@ window.GetTaskRunner(TaskType::kPermission))); permission_service_->HasPermission( CreatePermissionDescriptor(microphone_permission_name), - WTF::BindOnce(&AudioContext::DidInitialPermissionCheck, - WrapPersistent(this), - CreatePermissionDescriptor(microphone_permission_name))); + blink::BindOnce(&AudioContext::DidInitialPermissionCheck, + WrapPersistent(this), + CreatePermissionDescriptor(microphone_permission_name))); // Initializes MediaDeviceService and `output_device_ids_` only for a valid // device identifier that is not the default sink or a silent sink. @@ -1106,9 +1278,9 @@ audio_context_manager_.BindNewPipeAndPassReceiver( GetWindow()->GetTaskRunner(TaskType::kInternalMedia)))); - audio_context_manager_.set_disconnect_handler( - WTF::BindOnce(&AudioContext::OnAudioContextManagerServiceConnectionError, - WrapWeakPersistent(this))); + audio_context_manager_.set_disconnect_handler(blink::BindOnce( + &AudioContext::OnAudioContextManagerServiceConnectionError, + WrapWeakPersistent(this))); } void AudioContext::OnAudioContextManagerServiceConnectionError() { @@ -1144,8 +1316,8 @@ /* audio output */ true, /* request_video_input_capabilities */ false, /* request_audio_input_capabilities */ false, - WTF::BindOnce(&AudioContext::DevicesEnumerated, - WrapWeakPersistent(this))); + blink::BindOnce(&AudioContext::DevicesEnumerated, + WrapWeakPersistent(this))); } } @@ -1243,8 +1415,8 @@ /* audio output */ true, /* request_video_input_capabilities */ false, /* request_audio_input_capabilities */ false, - WTF::BindOnce(&AudioContext::DevicesEnumerated, - WrapWeakPersistent(this))); + blink::BindOnce(&AudioContext::DevicesEnumerated, + WrapWeakPersistent(this))); } void AudioContext::DevicesEnumerated( @@ -1398,8 +1570,8 @@ render_error_occurred_ = true; GetExecutionContext() ->GetTaskRunner(TaskType::kMediaElementEvent) - ->PostTask(FROM_HERE, WTF::BindOnce(&AudioContext::HandleRenderError, - WrapPersistent(this))); + ->PostTask(FROM_HERE, blink::BindOnce(&AudioContext::HandleRenderError, + WrapPersistent(this))); } void AudioContext::ResumeOnPrerenderActivation() { @@ -1543,7 +1715,7 @@ ->GetRemoteNavigationAssociatedInterfaces() ->GetInterface(media_player_host_.BindNewEndpointAndPassReceiver( GetWindow()->GetTaskRunner(TaskType::kInternalMedia))); - media_player_host_.set_disconnect_handler(WTF::BindOnce( + media_player_host_.set_disconnect_handler(blink::BindOnce( &AudioContext::OnMediaPlayerDisconnect, WrapWeakPersistent(this))); media_player_host_->OnMediaPlayerAdded( @@ -1552,7 +1724,7 @@ media_player_observer_.BindNewEndpointAndPassReceiver( GetWindow()->GetTaskRunner(TaskType::kInternalMedia)), player_id_); - media_player_observer_.set_disconnect_handler(WTF::BindOnce( + media_player_observer_.set_disconnect_handler(blink::BindOnce( &AudioContext::OnMediaPlayerDisconnect, WrapWeakPersistent(this))); }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_context.h b/third_party/blink/renderer/modules/webaudio/audio_context.h index a422268..c0bba21 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_context.h +++ b/third_party/blink/renderer/modules/webaudio/audio_context.h
@@ -22,7 +22,6 @@ #include "third_party/blink/renderer/core/frame/frame_visibility_observer.h" #include "third_party/blink/renderer/core/html/media/autoplay_policy.h" #include "third_party/blink/renderer/modules/webaudio/base_audio_context.h" -#include "third_party/blink/renderer/modules/webaudio/setsinkid_resolver.h" #include "third_party/blink/renderer/platform/audio/audio_frame_stats_accumulator.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_deque.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" @@ -48,6 +47,7 @@ class MediaStreamAudioSourceNode; class RealtimeAudioDestinationNode; class ScriptState; +class V8UnionAudioSinkOptionsOrString; class WebAudioLatencyHint; // This is an BaseAudioContext which actually plays sound, unlike an @@ -61,6 +61,50 @@ DEFINE_WRAPPERTYPEINFO(); public: + // SetSinkIdResolver is a helper class that manages the asynchronous operation + // of AudioContext.setSinkId(). It encapsulates a ScriptPromise that is + // resolved or rejected based on the success or failure of changing the audio + // output device. + class SetSinkIdResolver final : public GarbageCollected<SetSinkIdResolver> { + public: + SetSinkIdResolver(ScriptState*, + AudioContext&, + const V8UnionAudioSinkOptionsOrString&); + SetSinkIdResolver(const SetSinkIdResolver&) = delete; + SetSinkIdResolver& operator=(const SetSinkIdResolver&) = delete; + ~SetSinkIdResolver() = default; + + void Trace(Visitor*) const; + + void Start(); + + // Resolves the promise and sets `resolver_` to nullptr. + void Resolve(); + + // Rejects the promise with a DOMException and sets `resolver_` to nullptr. + void Reject(DOMException* exception); + + // Rejects the promise with a v8::Local<v8::Value> and sets `resolver_` to + // nullptr. Used when creating an exception with + // V8ThrowDOMException::CreateOrEmpty. + void Reject(v8::Local<v8::Value>); + + ScriptPromise<IDLUndefined> GetPromise(); + + private: + // Will decide whether to resolve or reject the promise based on `status`. + // After this method returns, `resolver_` is set to nullptr. + void HandleOutputDeviceStatus(media::OutputDeviceStatus status); + + // This callback function is passed to 'AudioDestinationNode::SetSinkId()'. + // When the device status is okay, 'NotifySetSinkIdIsDone()' gets invoked. + void OnSetSinkIdComplete(media::OutputDeviceStatus status); + + WeakMember<AudioContext> audio_context_; + Member<ScriptPromiseResolver<IDLUndefined>> resolver_; + WebAudioSinkDescriptor sink_descriptor_; + }; + static AudioContext* Create(ExecutionContext*, const AudioContextOptions*, ExceptionState&);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc index 9a3e96e6..c908093e 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.cc
@@ -42,7 +42,6 @@ *GetWorkerThread()->GetTaskRunner(TaskType::kMiscPlatformAPI), FROM_HERE, CrossThreadBindOnce( &AudioWorkletMessagingProxy::CreateProcessorOnRenderingThread, - WrapCrossThreadPersistent(this), CrossThreadUnretained(GetWorkerThread()), handler, handler->Name(), std::move(message_port_channel), std::move(node_options))); }
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h index e74a8fb..400e61d 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_messaging_proxy.h
@@ -39,7 +39,7 @@ // Invokes AudioWorkletGlobalScope to create an instance of // AudioWorkletProcessor. - void CreateProcessorOnRenderingThread( + static void CreateProcessorOnRenderingThread( WorkerThread*, scoped_refptr<AudioWorkletHandler>, const String& name,
diff --git a/third_party/blink/renderer/modules/webaudio/biquad_filter_handler.cc b/third_party/blink/renderer/modules/webaudio/biquad_filter_handler.cc index eb864494..fa987de4 100644 --- a/third_party/blink/renderer/modules/webaudio/biquad_filter_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/biquad_filter_handler.cc
@@ -11,6 +11,7 @@ #include <memory> +#include "base/containers/span.h" #include "base/synchronization/lock.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/inspector/console_message.h" @@ -39,8 +40,15 @@ constexpr uint32_t kNumberOfChannels = 1; constexpr unsigned kDefaultNumberOfOutputChannels = 1; -bool HasConstantValues(float* values, int frames_to_process) { - if (frames_to_process <= 1) { +bool HasConstantValues( + base::span<float> values, + int spanification_suspected_redundant_frames_to_process) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK(spanification_suspected_redundant_frames_to_process == + static_cast<int>(values.size()), + base::NotFatalUntil::M143); + if (spanification_suspected_redundant_frames_to_process <= 1) { return true; } @@ -57,7 +65,9 @@ // Process 4 floats at a time using SIMD __m128 value_vec = _mm_set1_ps(value); // Start at 0 for byte alignment - for (processed_frames = 0; processed_frames < frames_to_process - 3; + for (processed_frames = 0; + processed_frames < + spanification_suspected_redundant_frames_to_process - 3; processed_frames += 4) { // Load 4 floats from memory __m128 input_vec = _mm_loadu_ps(&values[processed_frames]); @@ -72,7 +82,9 @@ // Process 4 floats at a time using SIMD float32x4_t value_vec = vdupq_n_f32(value); // Start at 0 for byte alignment - for (processed_frames = 0; processed_frames < frames_to_process - 3; + for (processed_frames = 0; + processed_frames < + spanification_suspected_redundant_frames_to_process - 3; processed_frames += 4) { // Load 4 floats from memory float32x4_t input_vec = vld1q_f32(&values[processed_frames]); @@ -88,7 +100,8 @@ } #endif // Fallback implementation without SIMD optimization - while (processed_frames < frames_to_process) { + while (processed_frames < + spanification_suspected_redundant_frames_to_process) { if (values[processed_frames] != value) { return false; } @@ -137,10 +150,9 @@ // Get the magnitude and phase response of the filter at the given // set of frequencies (in Hz). The phase response is in radians. - void GetFrequencyResponse(int n_frequencies, - const float* frequency_hz, - float* mag_response, - float* phase_response); + void GetFrequencyResponse(base::span<const float> frequency_hz, + base::span<float> mag_response, + base::span<float> phase_response); void CheckForDirtyCoefficients(); @@ -220,20 +232,20 @@ // given set of frequencies (in Hz). The phase response is in radians. This // must be called from the main thread. static void GetFrequencyResponse(BiquadDSPKernel& kernel, - int n_frequencies, - const float* frequency_hz, - float* mag_response, - float* phase_response); + base::span<const float> frequency_hz, + base::span<float> mag_response, + base::span<float> phase_response); bool RequiresTailProcessing() const; double TailTime() const; double LatencyTime() const; // Update the biquad coefficients with the given parameters - void UpdateCoefficients(int number_of_frames, - const float* frequency, - const float* q, - const float* gain, - const float* detune); + void UpdateCoefficients( + int spanification_suspected_redundant_number_of_frames, + base::span<const float> frequency, + base::span<const float> q, + base::span<const float> gain, + base::span<const float> detune); private: BiquadProcessor* GetBiquadProcessor() { @@ -297,30 +309,42 @@ HasConstantValues(q, frames_to_process) && HasConstantValues(gain, frames_to_process) && HasConstantValues(detune, frames_to_process); - - UpdateCoefficients(is_constant ? 1 : frames_to_process, cutoff_frequency, - q, gain, detune); + size_t needed_frames = is_constant ? 1 : frames_to_process; + UpdateCoefficients(needed_frames, + base::span(cutoff_frequency).first(needed_frames), + base::span(q).first(needed_frames), + base::span(gain).first(needed_frames), + base::span(detune).first(needed_frames)); } else { cutoff_frequency[0] = GetBiquadProcessor()->Parameter1().FinalValue(); q[0] = GetBiquadProcessor()->Parameter2().FinalValue(); gain[0] = GetBiquadProcessor()->Parameter3().FinalValue(); detune[0] = GetBiquadProcessor()->Parameter4().FinalValue(); - UpdateCoefficients(1, cutoff_frequency, q, gain, detune); + UpdateCoefficients(1, base::span(cutoff_frequency).first(1u), + base::span(q).first(1u), base::span(gain).first(1u), + base::span(detune).first(1u)); } } } -void BiquadDSPKernel::UpdateCoefficients(int number_of_frames, - const float* cutoff_frequency, - const float* q, - const float* gain, - const float* detune) { +void BiquadDSPKernel::UpdateCoefficients( + int spanification_suspected_redundant_number_of_frames, + base::span<const float> cutoff_frequency, + base::span<const float> q, + base::span<const float> gain, + base::span<const float> detune) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK(spanification_suspected_redundant_number_of_frames == + static_cast<int>(cutoff_frequency.size()), + base::NotFatalUntil::M143); // Convert from Hertz to normalized frequency 0 -> 1. double nyquist = Nyquist(); - biquad_.SetHasSampleAccurateValues(number_of_frames > 1); + biquad_.SetHasSampleAccurateValues( + spanification_suspected_redundant_number_of_frames > 1); - for (int k = 0; k < number_of_frames; ++k) { + for (int k = 0; k < spanification_suspected_redundant_number_of_frames; ++k) { double normalized_frequency = cutoff_frequency[k] / nyquist; // Offset frequency by detune. @@ -366,7 +390,7 @@ } } - UpdateTailTime(number_of_frames - 1); + UpdateTailTime(spanification_suspected_redundant_number_of_frames - 1); } void BiquadDSPKernel::UpdateTailTime(int coef_index) { @@ -409,30 +433,27 @@ } void BiquadDSPKernel::GetFrequencyResponse(BiquadDSPKernel& kernel, - int n_frequencies, - const float* frequency_hz, - float* mag_response, - float* phase_response) { + base::span<const float> frequency_hz, + base::span<float> mag_response, + base::span<float> phase_response) { // Only allow on the main thread because we don't want the audio thread to be // updating `kernel` while we're computing the response. DCHECK(IsMainThread()); - DCHECK_GE(n_frequencies, 0); - DCHECK(frequency_hz); - DCHECK(mag_response); - DCHECK(phase_response); + DCHECK(!frequency_hz.empty()); + DCHECK(!mag_response.empty()); + DCHECK(!phase_response.empty()); - Vector<float> frequency(n_frequencies); + Vector<float> frequency(frequency_hz.size()); double nyquist = kernel.Nyquist(); // Convert from frequency in Hz to normalized frequency (0 -> 1), // with 1 equal to the Nyquist frequency. - for (int k = 0; k < n_frequencies; ++k) { + for (size_t k = 0; k < frequency_hz.size(); ++k) { frequency[k] = frequency_hz[k] / nyquist; } - kernel.biquad_.GetFrequencyResponse(n_frequencies, frequency.data(), - mag_response, phase_response); + kernel.biquad_.GetFrequencyResponse(frequency, mag_response, phase_response); } bool BiquadDSPKernel::RequiresTailProcessing() const { @@ -660,10 +681,9 @@ } } -void BiquadProcessor::GetFrequencyResponse(int n_frequencies, - const float* frequency_hz, - float* mag_response, - float* phase_response) { +void BiquadProcessor::GetFrequencyResponse(base::span<const float> frequency_hz, + base::span<float> mag_response, + base::span<float> phase_response) { DCHECK(IsMainThread()); // Compute the frequency response on a separate temporary kernel @@ -693,10 +713,11 @@ detune = Parameter4().Value(); } - response_kernel->UpdateCoefficients(1, &cutoff_frequency, &q, &gain, &detune); - BiquadDSPKernel::GetFrequencyResponse(*response_kernel, n_frequencies, - frequency_hz, mag_response, - phase_response); + response_kernel->UpdateCoefficients( + 1, base::span_from_ref(cutoff_frequency), base::span_from_ref(q), + base::span_from_ref(gain), base::span_from_ref(detune)); + BiquadDSPKernel::GetFrequencyResponse(*response_kernel, frequency_hz, + mag_response, phase_response); } BiquadFilterHandler::BiquadFilterHandler(AudioNode& node, @@ -846,12 +867,11 @@ return Output(0).NumberOfChannels(); } -void BiquadFilterHandler::GetFrequencyResponse(int n_frequencies, - const float* frequency_hz, - float* mag_response, - float* phase_response) { - processor_->GetFrequencyResponse(n_frequencies, frequency_hz, mag_response, - phase_response); +void BiquadFilterHandler::GetFrequencyResponse( + base::span<const float> frequency_hz, + base::span<float> mag_response, + base::span<float> phase_response) { + processor_->GetFrequencyResponse(frequency_hz, mag_response, phase_response); } V8BiquadFilterType::Enum BiquadFilterHandler::Type() const { @@ -902,9 +922,16 @@ "fast parameter automation."}))); } -bool BiquadFilterHandler::HasConstantValuesForTesting(float* values, - int frames_to_process) { - return HasConstantValues(values, frames_to_process); +bool BiquadFilterHandler::HasConstantValuesForTesting( + base::span<float> values, + int spanification_suspected_redundant_frames_to_process) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK(spanification_suspected_redundant_frames_to_process == + static_cast<int>(values.size()), + base::NotFatalUntil::M143); + return HasConstantValues(values, + spanification_suspected_redundant_frames_to_process); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/biquad_filter_handler.h b/third_party/blink/renderer/modules/webaudio/biquad_filter_handler.h index 63969951..28e0b86f 100644 --- a/third_party/blink/renderer/modules/webaudio/biquad_filter_handler.h +++ b/third_party/blink/renderer/modules/webaudio/biquad_filter_handler.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_BIQUAD_FILTER_HANDLER_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_BIQUAD_FILTER_HANDLER_H_ +#include "base/containers/span.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/task/single_thread_task_runner.h" @@ -47,16 +48,16 @@ // Get the magnitude and phase response of the filter at the given // set of frequencies (in Hz). The phase response is in radians. - void GetFrequencyResponse(int n_frequencies, - const float* frequency_hz, - float* mag_response, - float* phase_response); + void GetFrequencyResponse(base::span<const float> frequency_hz, + base::span<float> mag_response, + base::span<float> phase_response); V8BiquadFilterType::Enum Type() const; void SetType(V8BiquadFilterType::Enum type); // Expose HasConstantValues for unit testing - MODULES_EXPORT static bool HasConstantValuesForTesting(float* values, - int frames_to_process); + MODULES_EXPORT static bool HasConstantValuesForTesting( + base::span<float> values, + int spanification_suspected_redundant_frames_to_process); private: BiquadFilterHandler(AudioNode&,
diff --git a/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc b/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc index ab46c72d..f640e4e9 100644 --- a/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc +++ b/third_party/blink/renderer/modules/webaudio/biquad_filter_node.cc
@@ -217,9 +217,9 @@ // If the length is 0, there's nothing to do. if (frequency_hz_length_as_int > 0) { - GetBiquadFilterHandler().GetFrequencyResponse( - frequency_hz_length_as_int, frequency_hz->Data(), mag_response->Data(), - phase_response->Data()); + GetBiquadFilterHandler().GetFrequencyResponse(frequency_hz->AsSpan(), + mag_response->AsSpan(), + phase_response->AsSpan()); } }
diff --git a/third_party/blink/renderer/modules/webaudio/iir_filter_handler.cc b/third_party/blink/renderer/modules/webaudio/iir_filter_handler.cc index 3ca748a3..3416893 100644 --- a/third_party/blink/renderer/modules/webaudio/iir_filter_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/iir_filter_handler.cc
@@ -44,25 +44,24 @@ // Get the magnitude and phase response of the filter at the given set of // frequencies (in Hz). The phase response is in radians. -void IIRFilterHandler::GetFrequencyResponse(int n_frequencies, - const float* frequency_hz, - float* mag_response, - float* phase_response) const { - DCHECK_GE(n_frequencies, 0); - DCHECK(frequency_hz); - DCHECK(mag_response); - DCHECK(phase_response); +void IIRFilterHandler::GetFrequencyResponse( + base::span<const float> frequency_hz, + base::span<float> mag_response, + base::span<float> phase_response) const { + DCHECK(!frequency_hz.empty()); + DCHECK(!mag_response.empty()); + DCHECK(!phase_response.empty()); - Vector<float> frequency(n_frequencies); + Vector<float> frequency(frequency_hz.size()); // Convert from frequency in Hz to normalized frequency (0 -> 1), // with 1 equal to the Nyquist frequency. - for (int k = 0; k < n_frequencies; ++k) { + for (size_t k = 0; k < frequency_hz.size(); ++k) { UNSAFE_TODO(frequency[k] = frequency_hz[k] / nyquist_frequency_); } - response_kernel_->GetFrequencyResponse(n_frequencies, frequency.data(), - mag_response, phase_response); + response_kernel_->GetFrequencyResponse(frequency, mag_response, + phase_response); } IIRFilterHandler::IIRFilterHandler(AudioNode& node,
diff --git a/third_party/blink/renderer/modules/webaudio/iir_filter_handler.h b/third_party/blink/renderer/modules/webaudio/iir_filter_handler.h index 6199836..1a557c8 100644 --- a/third_party/blink/renderer/modules/webaudio/iir_filter_handler.h +++ b/third_party/blink/renderer/modules/webaudio/iir_filter_handler.h
@@ -28,10 +28,9 @@ // Get the magnitude and phase response of the filter at the given // set of frequencies (in Hz). The phase response is in radians. - void GetFrequencyResponse(int n_frequencies, - const float* frequency_hz, - float* mag_response, - float* phase_response) const; + void GetFrequencyResponse(base::span<const float> frequency_hz, + base::span<float> mag_response, + base::span<float> phase_response) const; private: IIRFilterHandler(AudioNode&,
diff --git a/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc b/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc index 0b201969..f49a01b 100644 --- a/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc +++ b/third_party/blink/renderer/modules/webaudio/iir_filter_node.cc
@@ -224,9 +224,9 @@ // Nothing to do if the length is 0. if (frequency_hz_length_as_int > 0) { - GetIIRFilterHandler().GetFrequencyResponse( - frequency_hz_length_as_int, frequency_hz->Data(), mag_response->Data(), - phase_response->Data()); + GetIIRFilterHandler().GetFrequencyResponse(frequency_hz->AsSpan(), + mag_response->AsSpan(), + phase_response->AsSpan()); } }
diff --git a/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc b/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc index 66badc9..09d6a766 100644 --- a/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/oscillator_handler.cc
@@ -13,6 +13,7 @@ #include <array> #include <limits> +#include "base/containers/span.h" #include "base/synchronization/lock.h" #include "base/trace_event/typed_macros.h" #include "build/build_config.h" @@ -43,8 +44,16 @@ // Clamp the frequency value to lie with Nyquist frequency. For NaN, arbitrarily // clamp to +Nyquist. -void ClampFrequency(float* frequency, int frames_to_process, float nyquist) { - for (int k = 0; k < frames_to_process; ++k) { +void ClampFrequency(base::span<float> frequency, + int spanification_suspected_redundant_frames_to_process, + float nyquist) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK(spanification_suspected_redundant_frames_to_process == + static_cast<int>(frequency.size()), + base::NotFatalUntil::M143); + for (int k = 0; k < spanification_suspected_redundant_frames_to_process; + ++k) { float f = frequency[k]; if (std::isnan(f)) { @@ -344,7 +353,7 @@ } if (has_sample_accurate_values) { - ClampFrequency(phase_increments.data(), frames_to_process, + ClampFrequency(phase_increments, frames_to_process, Context()->sampleRate() / 2); // Convert from frequency to wavetable increment. vector_math::Vsmul(phase_increments.data(), 1, &final_scale, @@ -498,7 +507,8 @@ float frequency = frequency_->FinalValue(); const float detune_scale = DetuneToFrequencyMultiplier(detune_->FinalValue()); frequency *= detune_scale; - ClampFrequency(&frequency, 1, Context()->sampleRate() / 2); + ClampFrequency(base::span_from_ref(frequency), 1, + Context()->sampleRate() / 2); periodic_wave_->WaveDataForFundamentalFrequency( frequency, lower_wave_data, higher_wave_data, table_interpolation_factor); @@ -726,7 +736,8 @@ float detune = detune_->FinalValue(); float detune_scale = DetuneToFrequencyMultiplier(detune); frequency *= detune_scale; - ClampFrequency(&frequency, 1, Context()->sampleRate() / 2); + ClampFrequency(base::span_from_ref(frequency), 1, + Context()->sampleRate() / 2); periodic_wave_->WaveDataForFundamentalFrequency(frequency, lower_wave_data, higher_wave_data, table_interpolation_factor);
diff --git a/third_party/blink/renderer/modules/webaudio/panner_handler.cc b/third_party/blink/renderer/modules/webaudio/panner_handler.cc index db48cd9..4418eb46 100644 --- a/third_party/blink/renderer/modules/webaudio/panner_handler.cc +++ b/third_party/blink/renderer/modules/webaudio/panner_handler.cc
@@ -231,12 +231,12 @@ CHECK_EQ(render_quantum_frames, render_quantum_frames_expected); CHECK_LE(frames_to_process, render_quantum_frames_expected); - float panner_x[render_quantum_frames_expected]; - float panner_y[render_quantum_frames_expected]; - float panner_z[render_quantum_frames_expected]; - float orientation_x[render_quantum_frames_expected]; - float orientation_y[render_quantum_frames_expected]; - float orientation_z[render_quantum_frames_expected]; + std::array<float, render_quantum_frames_expected> panner_x; + std::array<float, render_quantum_frames_expected> panner_y; + std::array<float, render_quantum_frames_expected> panner_z; + std::array<float, render_quantum_frames_expected> orientation_x; + std::array<float, render_quantum_frames_expected> orientation_y; + std::array<float, render_quantum_frames_expected> orientation_z; std::array<double, render_quantum_frames_expected> azimuth; std::array<double, render_quantum_frames_expected> elevation; float total_gain[render_quantum_frames_expected];
diff --git a/third_party/blink/renderer/modules/webaudio/setsinkid_resolver.cc b/third_party/blink/renderer/modules/webaudio/setsinkid_resolver.cc deleted file mode 100644 index 8594d18..0000000 --- a/third_party/blink/renderer/modules/webaudio/setsinkid_resolver.cc +++ /dev/null
@@ -1,188 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/webaudio/setsinkid_resolver.h" - -#include "base/trace_event/trace_event.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_union_audiosinkinfo_string.h" -#include "third_party/blink/renderer/core/frame/local_dom_window.h" -#include "third_party/blink/renderer/modules/webaudio/audio_context.h" -#include "third_party/blink/renderer/modules/webaudio/realtime_audio_destination_node.h" -#include "third_party/blink/renderer/platform/audio/audio_utilities.h" -#include "third_party/blink/renderer/platform/wtf/text/strcat.h" - -namespace blink { - -SetSinkIdResolver::SetSinkIdResolver( - ScriptState* script_state, - AudioContext& audio_context, - const V8UnionAudioSinkOptionsOrString& sink_id) - : audio_context_(audio_context), - resolver_(MakeGarbageCollected<ScriptPromiseResolver<IDLUndefined>>( - script_state)) { - DCHECK(IsMainThread()); - - // Currently the only available AudioSinkOptions is a type of a silent sink, - // which can be specified by an empty descriptor constructor. - auto& frame_token = To<LocalDOMWindow>(audio_context_->GetExecutionContext()) - ->GetLocalFrameToken(); - if (sink_id.GetContentType() == - V8UnionAudioSinkOptionsOrString::ContentType::kAudioSinkOptions) { - sink_descriptor_ = WebAudioSinkDescriptor(frame_token); - } else { - sink_descriptor_ = - WebAudioSinkDescriptor(sink_id.GetAsString(), frame_token); - } - - TRACE_EVENT1("webaudio", "SetSinkIdResolver::SetSinkIdResolver", - "sink_id (after setting sink_descriptor_)", - audio_utilities::GetSinkIdForTracing(sink_descriptor_)); -} - -void SetSinkIdResolver::Trace(Visitor* visitor) const { - visitor->Trace(audio_context_); - visitor->Trace(resolver_); -} - -void SetSinkIdResolver::Start() { - TRACE_EVENT1("webaudio", "SetSinkIdResolver::Start", "sink_id", - audio_utilities::GetSinkIdForTracing(sink_descriptor_)); - DCHECK(IsMainThread()); - - if (!resolver_ || !resolver_->GetExecutionContext() || !audio_context_ || - audio_context_->IsContextCleared()) { - // No point in rejecting promise, as it will bail out upon detached - // context anyway. - return; - } - - // Refer to - // https://webaudio.github.io/web-audio-api/#validating-sink-identifier for - // sink_id/sink_descriptor validation steps. - if (sink_descriptor_ == audio_context_->GetSinkDescriptor()) { - OnSetSinkIdComplete(media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK); - } else if (!audio_context_->IsValidSinkDescriptor(sink_descriptor_)) { - OnSetSinkIdComplete( - media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND); - } else { - auto* audio_destination = audio_context_->destination(); - // A sanity check to make sure we have valid audio_destination node from - // `audio_context_`. - if (!audio_destination) { - OnSetSinkIdComplete( - media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL); - } else { - audio_context_->NotifySetSinkIdBegins(); - auto set_sink_id_completion_callback = WTF::BindOnce( - &SetSinkIdResolver::OnSetSinkIdComplete, WrapPersistent(this)); - auto set_sink_descriptor_callback = WTF::BindOnce( - &RealtimeAudioDestinationNode::SetSinkDescriptor, - WrapWeakPersistent( - static_cast<RealtimeAudioDestinationNode*>(audio_destination)), - sink_descriptor_, std::move(set_sink_id_completion_callback)); - audio_context_->GetExecutionContext() - ->GetTaskRunner(TaskType::kInternalMediaRealTime) - ->PostTask(FROM_HERE, std::move(set_sink_descriptor_callback)); - } - } -} - -void SetSinkIdResolver::Resolve() { - DCHECK(IsMainThread()); - DCHECK(resolver_); - resolver_->Resolve(); - resolver_ = nullptr; -} - -void SetSinkIdResolver::Reject(DOMException* exception) { - DCHECK(IsMainThread()); - DCHECK(resolver_); - resolver_->Reject(exception); - resolver_ = nullptr; -} - -void SetSinkIdResolver::Reject(v8::Local<v8::Value> value) { - DCHECK(IsMainThread()); - DCHECK(resolver_); - resolver_->Reject(value); - resolver_ = nullptr; -} - -ScriptPromise<IDLUndefined> SetSinkIdResolver::GetPromise() { - DCHECK(IsMainThread()); - DCHECK(resolver_); - return resolver_->Promise(); -} - -void SetSinkIdResolver::HandleOutputDeviceStatus( - media::OutputDeviceStatus status) { - ScriptState* script_state = resolver_->GetScriptState(); - ScriptState::Scope scope(script_state); - switch (status) { - case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_OK: - if (audio_context_ && !audio_context_->IsContextCleared()) { - // Update AudioContext's sink ID and fire the 'onsinkchange' event - audio_context_->NotifySetSinkIdIsDone(sink_descriptor_); - } - Resolve(); - return; - case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND: - Reject(V8ThrowDOMException::CreateOrEmpty( - script_state->GetIsolate(), DOMExceptionCode::kNotFoundError, - StrCat({"AudioContext.setSinkId(): failed: the device ", - String(sink_descriptor_.SinkId()), " is not found."}))); - return; - case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED: - Reject(V8ThrowDOMException::CreateOrEmpty( - script_state->GetIsolate(), DOMExceptionCode::kNotAllowedError, - StrCat({"AudioContext.setSinkId() failed: access to the device ", - String(sink_descriptor_.SinkId()), " is not permitted."}))); - return; - case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_TIMED_OUT: - Reject(V8ThrowDOMException::CreateOrEmpty( - script_state->GetIsolate(), DOMExceptionCode::kTimeoutError, - StrCat({"AudioContext.setSinkId() failed: the request for device ", - String(sink_descriptor_.SinkId()), " is timed out."}))); - return; - case media::OutputDeviceStatus::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL: - Reject(V8ThrowDOMException::CreateOrEmpty( - script_state->GetIsolate(), DOMExceptionCode::kInvalidStateError, - StrCat({"AudioContext.setSinkId() failed: the device ", - String(sink_descriptor_.SinkId()), " is not available."}))); - return; - } - NOTREACHED(); -} - -void SetSinkIdResolver::OnSetSinkIdComplete(media::OutputDeviceStatus status) { - TRACE_EVENT1("webaudio", "SetSinkIdResolver::OnSetSinkIdComplete", "sink_id", - audio_utilities::GetSinkIdForTracing(sink_descriptor_)); - DCHECK(IsMainThread()); - - if (!resolver_) { - return; - } - - auto* excecution_context = resolver_->GetExecutionContext(); - if (!excecution_context || excecution_context->IsContextDestroyed()) { - return; - } - - HandleOutputDeviceStatus(status); - - auto& resolvers = audio_context_->GetSetSinkIdResolver(); - resolvers.pop_front(); - if (!resolvers.empty() && (audio_context_->PendingDeviceListUpdates() == 0)) { - // Prevent potential stack overflow under heavy load by scheduling the next - // resolver start asynchronously instead of invoking it directly. - auto next_start_task = WTF::BindOnce( - &SetSinkIdResolver::Start, WrapWeakPersistent(resolvers.front().Get())); - audio_context_->GetExecutionContext() - ->GetTaskRunner(TaskType::kInternalMediaRealTime) - ->PostTask(FROM_HERE, std::move(next_start_task)); - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/setsinkid_resolver.h b/third_party/blink/renderer/modules/webaudio/setsinkid_resolver.h deleted file mode 100644 index 1e79e98..0000000 --- a/third_party/blink/renderer/modules/webaudio/setsinkid_resolver.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_SETSINKID_RESOLVER_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_SETSINKID_RESOLVER_H_ - -#include "media/base/output_device_info.h" -#include "third_party/blink/public/platform/web_audio_sink_descriptor.h" -#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" - -namespace blink { - -class AudioContext; -class V8UnionAudioSinkOptionsOrString; - -class SetSinkIdResolver final : public GarbageCollected<SetSinkIdResolver> { - public: - SetSinkIdResolver(ScriptState*, - AudioContext&, - const V8UnionAudioSinkOptionsOrString&); - SetSinkIdResolver(const SetSinkIdResolver&) = delete; - SetSinkIdResolver& operator=(const SetSinkIdResolver&) = delete; - ~SetSinkIdResolver() = default; - - void Trace(Visitor*) const; - - void Start(); - - // Resolves the promise and sets `resolver_` to nullptr. - void Resolve(); - - // Rejects the promise with a DOMException and sets `resolver_` to nullptr. - void Reject(DOMException* exception); - - // Rejects the promise with a v8::Local<v8::Value> and sets `resolver_` to - // nullptr. Used when creating an exception with - // V8ThrowDOMException::CreateOrEmpty. - void Reject(v8::Local<v8::Value>); - - ScriptPromise<IDLUndefined> GetPromise(); - - private: - // Will decide whether to resolve or reject the promise based on `status`. - // After this method returns, `resolver_` is set to nullptr. - void HandleOutputDeviceStatus(media::OutputDeviceStatus status); - - // This callback function is passed to 'AudioDestinationNode::SetSinkId()'. - // When the device status is okay, 'NotifySetSinkIdIsDone()' gets invoked. - void OnSetSinkIdComplete(media::OutputDeviceStatus status); - - WeakMember<AudioContext> audio_context_; - Member<ScriptPromiseResolver<IDLUndefined>> resolver_; - WebAudioSinkDescriptor sink_descriptor_; -}; -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_SETSINKID_RESOLVER_H_
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_data.cc b/third_party/blink/renderer/modules/webcodecs/audio_data.cc index ded6b7f..7c14fe7 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_data.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_data.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/modules/webcodecs/audio_data.h" #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/notreached.h" #include "base/numerics/checked_math.h" #include "base/numerics/safe_conversions.h" @@ -637,17 +638,17 @@ const int channel = copy_to_options->planeIndex(); CHECK_LT(channel, data_as_f32_bus_->channels()); - float* src_data = data_as_f32_bus_->channel(channel); - float* offset_src_data = UNSAFE_TODO(src_data + offset); - CHECK_LE(UNSAFE_TODO(offset_src_data + frame_count), - UNSAFE_TODO(src_data + data_as_f32_bus_->frames())); + const size_t num_frames = + base::checked_cast<size_t>(data_as_f32_bus_->frames()); + base::span<float> src_data = data_as_f32_bus_->channel_span(channel); + base::span<float> offset_src_data = src_data.subspan(offset); + CHECK_LE(offset_src_data.subspan(frame_count).data(), + src_data.subspan(num_frames).data()); switch (dest_format) { case media::kSampleFormatPlanarU8: { - uint8_t* dest_data = dest.data(); for (uint32_t i = 0; i < frame_count; ++i) { - UNSAFE_TODO(dest_data[i] = - media::UnsignedInt8SampleTypeTraits::FromFloat( - offset_src_data[i])); + dest[i] = + media::UnsignedInt8SampleTypeTraits::FromFloat(offset_src_data[i]); } return; } @@ -671,10 +672,10 @@ } case media::kSampleFormatPlanarF32: { int32_t* dest_data = reinterpret_cast<int32_t*>(dest.data()); - CHECK_LE(UNSAFE_TODO(offset_src_data + frame_count), - UNSAFE_TODO(src_data + data_as_f32_bus_->frames())); - UNSAFE_TODO( - memcpy(dest_data, offset_src_data, sizeof(float) * frame_count)); + CHECK_LE(offset_src_data.subspan(frame_count).data(), + src_data.subspan(num_frames).data()); + UNSAFE_TODO(memcpy(dest_data, offset_src_data.data(), + sizeof(float) * frame_count)); return; } default:
diff --git a/third_party/blink/renderer/modules/webcodecs/background_readback.cc b/third_party/blink/renderer/modules/webcodecs/background_readback.cc index a08b1d2..f63f595 100644 --- a/third_party/blink/renderer/modules/webcodecs/background_readback.cc +++ b/third_party/blink/renderer/modules/webcodecs/background_readback.cc
@@ -195,8 +195,8 @@ "media", "ReadbackRGBTextureBackedFrameToMemory", txt_frame.get(), "timestamp", txt_frame->timestamp()); - uint8_t* dst_pixels = - result->GetWritableVisibleData(media::VideoFrame::Plane::kARGB); + base::span<uint8_t> dst_pixels = + result->GetWritableVisiblePlaneData(media::VideoFrame::Plane::kARGB); int rgba_stide = result->stride(media::VideoFrame::Plane::kARGB); DCHECK_GT(rgba_stide, 0); @@ -261,7 +261,7 @@ uint32_t offset = dest_layout.Offset(0); uint32_t stride = dest_layout.Stride(0); - uint8_t* dst_pixels = dest_buffer.subspan(offset).data(); + base::span<uint8_t> dst_pixels = dest_buffer.subspan(offset); size_t max_bytes_written = stride * src_rect.height(); if (stride <= 0 || max_bytes_written > dest_buffer.size()) { DLOG(ERROR) << "Buffer is not sufficiently large for readback";
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 1d33d66..470fe86 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
@@ -1882,17 +1882,12 @@ .SharedImageInterface() ->GetCapabilities(); - const gfx::BufferFormat buffer_format = - viz::SinglePlaneSharedImageFormatToBufferFormat(format); - bool gmb_allowed = - gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, buffer_format) && - gpu::IsImageFromGpuMemoryBufferFormatSupported(buffer_format, - capabilities); + bool shared_image_format_supported = + gpu::IsFormatSupportedForSIWithNativeBuffer(format, capabilities); - // Either swap_chain or gpu memory buffer should be enabled for this be used. - // TODO(crbug.com/404887530) : Remove or Rename `gmb_allowed` since - // CanvasResourceProvider no longer uses GMBs. - if (!shared_image_capabilities.shared_image_swap_chain && !gmb_allowed) { + // Either swap_chain or shared image should be supported for this be used. + if (!shared_image_capabilities.shared_image_swap_chain && + !shared_image_format_supported) { return false; }
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 300c446..8530c505 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -845,8 +845,6 @@ "geometry/geometry_as_json.h", "geometry/geometry_hash_traits.h", "geometry/infinite_int_rect.h", - "geometry/layout_point.cc", - "geometry/layout_point.h", "geometry/layout_unit.cc", "geometry/layout_unit.h", "geometry/length.cc",
diff --git a/third_party/blink/renderer/platform/DEPS b/third_party/blink/renderer/platform/DEPS index d89c395..669e421b2 100644 --- a/third_party/blink/renderer/platform/DEPS +++ b/third_party/blink/renderer/platform/DEPS
@@ -10,6 +10,7 @@ "+base/containers/heap_array.h", "+base/containers/flat_map.h", "+base/containers/span.h", + "+base/containers/auto_spanification_helper.h", "+base/containers/span_or_size.h", "+base/cpu.h", "+base/files",
diff --git a/third_party/blink/renderer/platform/audio/biquad.cc b/third_party/blink/renderer/platform/audio/biquad.cc index 36711e3..50144ff 100644 --- a/third_party/blink/renderer/platform/audio/biquad.cc +++ b/third_party/blink/renderer/platform/audio/biquad.cc
@@ -33,15 +33,17 @@ #include "third_party/blink/renderer/platform/audio/biquad.h" +#include <stdio.h> + +#include <algorithm> +#include <complex> + +#include "base/containers/span.h" #include "build/build_config.h" #include "third_party/blink/renderer/platform/audio/audio_utilities.h" #include "third_party/blink/renderer/platform/audio/denormal_disabler.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h" #include "third_party/fdlibm/ieee754.h" - -#include <stdio.h> -#include <algorithm> -#include <complex> #if BUILDFLAG(IS_MAC) #include <Accelerate/Accelerate.h> #endif @@ -559,10 +561,13 @@ } } -void Biquad::GetFrequencyResponse(int n_frequencies, - const float* frequency, - float* mag_response, - float* phase_response) const { +void Biquad::GetFrequencyResponse(base::span<const float> frequency, + base::span<float> mag_response, + base::span<float> phase_response) const { + DCHECK(!frequency.empty()); + DCHECK(!mag_response.empty()); + DCHECK(!phase_response.empty()); + // Evaluate the Z-transform of the filter at given normalized // frequency from 0 to 1. (1 corresponds to the Nyquist // frequency.) @@ -586,7 +591,7 @@ double a1 = a1_[0]; double a2 = a2_[0]; - for (int k = 0; k < n_frequencies; ++k) { + for (size_t k = 0; k < frequency.size(); ++k) { if (frequency[k] < 0 || frequency[k] > 1) { // Out-of-bounds frequencies should return NaN. mag_response[k] = std::nanf("");
diff --git a/third_party/blink/renderer/platform/audio/biquad.h b/third_party/blink/renderer/platform/audio/biquad.h index c7c926e5..85ad3ca1 100644 --- a/third_party/blink/renderer/platform/audio/biquad.h +++ b/third_party/blink/renderer/platform/audio/biquad.h
@@ -30,7 +30,10 @@ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_BIQUAD_H_ #include <sys/types.h> + #include <complex> + +#include "base/containers/span.h" #include "build/build_config.h" #include "third_party/blink/renderer/platform/audio/audio_array.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -83,10 +86,9 @@ // Filter response at a set of n frequencies. The magnitude and // phase response are returned in magResponse and phaseResponse. // The phase response is in radians. - void GetFrequencyResponse(int n_frequencies, - const float* frequency, - float* mag_response, - float* phase_response) const; + void GetFrequencyResponse(base::span<const float> frequency, + base::span<float> mag_response, + base::span<float> phase_response) const; private: void SetNormalizedCoefficients(int,
diff --git a/third_party/blink/renderer/platform/audio/iir_filter.cc b/third_party/blink/renderer/platform/audio/iir_filter.cc index 974a1038..d43fcc919 100644 --- a/third_party/blink/renderer/platform/audio/iir_filter.cc +++ b/third_party/blink/renderer/platform/audio/iir_filter.cc
@@ -8,6 +8,7 @@ #include <complex> #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "third_party/blink/renderer/platform/audio/audio_utilities.h" #include "third_party/blink/renderer/platform/audio/vector_math.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h" @@ -116,10 +117,13 @@ } } -void IIRFilter::GetFrequencyResponse(int n_frequencies, - const float* frequency, - float* mag_response, - float* phase_response) { +void IIRFilter::GetFrequencyResponse(base::span<const float> frequency, + base::span<float> mag_response, + base::span<float> phase_response) { + DCHECK(!frequency.empty()); + DCHECK(!mag_response.empty()); + DCHECK(!phase_response.empty()); + // Evaluate the z-transform of the filter at the given normalized frequencies // from 0 to 1. (One corresponds to the Nyquist frequency.) // @@ -134,7 +138,7 @@ // the sums in H(z) is equivalent to evaluating a polynomial at the point // 1/z. - for (int k = 0; k < n_frequencies; ++k) { + for (size_t k = 0; k < frequency.size(); ++k) { if (UNSAFE_TODO(frequency[k]) < 0 || UNSAFE_TODO(frequency[k]) > 1) { // Out-of-bounds frequencies should return NaN. UNSAFE_TODO(mag_response[k]) = std::nanf("");
diff --git a/third_party/blink/renderer/platform/audio/iir_filter.h b/third_party/blink/renderer/platform/audio/iir_filter.h index 8938ec66..d355e226 100644 --- a/third_party/blink/renderer/platform/audio/iir_filter.h +++ b/third_party/blink/renderer/platform/audio/iir_filter.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_IIR_FILTER_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_AUDIO_IIR_FILTER_H_ +#include "base/containers/span.h" #include "base/memory/raw_ptr.h" #include "third_party/blink/renderer/platform/audio/audio_array.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -27,10 +28,9 @@ void Reset(); - void GetFrequencyResponse(int n_frequencies, - const float* frequency, - float* mag_response, - float* phase_response); + void GetFrequencyResponse(base::span<const float> frequency, + base::span<float> mag_response, + base::span<float> phase_response); // Compute the tail time of the IIR filter double TailTime(double sample_rate,
diff --git a/third_party/blink/renderer/platform/fonts/simple_font_data.cc b/third_party/blink/renderer/platform/fonts/simple_font_data.cc index 96ac75c7..1666138b 100644 --- a/third_party/blink/renderer/platform/fonts/simple_font_data.cc +++ b/third_party/blink/renderer/platform/fonts/simple_font_data.cc
@@ -490,7 +490,7 @@ // The cache didn't hit. Shift the list and create a new entry at `[0]`. for (wtf_size_t i = 1; i < std::size(han_kerning_cache_); ++i) { - UNSAFE_TODO(han_kerning_cache_[i] = std::move(han_kerning_cache_[i - 1])); + han_kerning_cache_[i] = std::move(han_kerning_cache_[i - 1]); } HanKerningCacheEntry& new_entry = han_kerning_cache_[0]; new_entry = {.locale = &locale, @@ -520,7 +520,7 @@ } DCHECK_EQ(bounds->size(), glyphs.size()); - SkFontGetBoundsForGlyphs(font_, glyphs, bounds->data()); + SkFontGetBoundsForGlyphs(font_, glyphs, *bounds); } float SimpleFontData::WidthForGlyph(Glyph glyph) const {
diff --git a/third_party/blink/renderer/platform/fonts/simple_font_data.h b/third_party/blink/renderer/platform/fonts/simple_font_data.h index 92256abc..a1764fd 100644 --- a/third_party/blink/renderer/platform/fonts/simple_font_data.h +++ b/third_party/blink/renderer/platform/fonts/simple_font_data.h
@@ -24,6 +24,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SIMPLE_FONT_DATA_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SIMPLE_FONT_DATA_H_ +#include <array> #include <memory> #include <mutex> #include <utility> @@ -224,7 +225,7 @@ bool is_horizontal; HanKerning::FontData data; }; - mutable HanKerningCacheEntry han_kerning_cache_[2]; + mutable std::array<HanKerningCacheEntry, 2> han_kerning_cache_; mutable FontHeight normalized_typo_ascent_descent_;
diff --git a/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc b/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc index 51b3b890..2e91edba 100644 --- a/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc +++ b/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h" +#include "base/containers/span.h" #include "build/build_config.h" #include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h" @@ -152,14 +153,14 @@ void SkFontGetBoundsForGlyphs(const SkFont& font, const Vector<Glyph, 256>& glyphs, - SkRect* bounds) { + base::span<SkRect> bounds) { #if BUILDFLAG(IS_APPLE) for (unsigned i = 0; i < glyphs.size(); i++) { SkFontGetBoundsForGlyph(font, glyphs[i], &bounds[i]); } #else static_assert(sizeof(Glyph) == 2, "Skia expects 2 bytes glyph id."); - font.getBounds(glyphs, {bounds, glyphs.size()}, nullptr); + font.getBounds(glyphs, {bounds.data(), glyphs.size()}, nullptr); if (!font.isSubpixel()) { for (unsigned i = 0; i < glyphs.size(); i++) {
diff --git a/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h b/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h index a1fb4e4c..16bc2fb9f 100644 --- a/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h +++ b/third_party/blink/renderer/platform/fonts/skia/skia_text_metrics.h
@@ -5,9 +5,10 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SKIA_SKIA_TEXT_METRICS_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SKIA_SKIA_TEXT_METRICS_H_ -#include "third_party/blink/renderer/platform/fonts/glyph.h" - #include <hb.h> + +#include "base/containers/span.h" +#include "third_party/blink/renderer/platform/fonts/glyph.h" #include "third_party/blink/renderer/platform/wtf/vector.h" #include "third_party/skia/include/core/SkRect.h" @@ -35,7 +36,7 @@ void SkFontGetBoundsForGlyph(const SkFont&, Glyph, SkRect* bounds); void SkFontGetBoundsForGlyphs(const SkFont&, const Vector<Glyph, 256>&, - SkRect*); + base::span<SkRect>); float SkFontGetWidthForGlyph(const SkFont&, Glyph); hb_position_t SkiaScalarToHarfBuzzPosition(SkScalar value);
diff --git a/third_party/blink/renderer/platform/geometry/layout_point.cc b/third_party/blink/renderer/platform/geometry/layout_point.cc deleted file mode 100644 index 144674a..0000000 --- a/third_party/blink/renderer/platform/geometry/layout_point.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2016 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/platform/geometry/layout_point.h" - -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" - -namespace blink { - -std::ostream& operator<<(std::ostream& ostream, - const DeprecatedLayoutPoint& point) { - return ostream << point.ToString(); -} - -String DeprecatedLayoutPoint::ToString() const { - return String::Format("%s,%s", X().ToString().Ascii().c_str(), - Y().ToString().Ascii().c_str()); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/platform/geometry/layout_point.h b/third_party/blink/renderer/platform/geometry/layout_point.h deleted file mode 100644 index cb8ce1b..0000000 --- a/third_party/blink/renderer/platform/geometry/layout_point.h +++ /dev/null
@@ -1,74 +0,0 @@ -/* - * Copyright (c) 2012, Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LAYOUT_POINT_H_ -#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LAYOUT_POINT_H_ - -#include <iosfwd> - -#include "third_party/blink/renderer/platform/geometry/layout_unit.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" -#include "ui/gfx/geometry/point_f.h" - -namespace blink { - -// This class is deprecated. PhysicalOffset or LogicalOffset should be used. -class PLATFORM_EXPORT DeprecatedLayoutPoint { - DISALLOW_NEW(); - - public: - constexpr DeprecatedLayoutPoint() = default; - constexpr DeprecatedLayoutPoint(LayoutUnit x, LayoutUnit y) : x_(x), y_(y) {} - constexpr explicit DeprecatedLayoutPoint(const gfx::PointF& point) - : x_(point.x()), y_(point.y()) {} - - // This is deleted to avoid unwanted lossy conversion from float or double to - // LayoutUnit or int. Use explicit LayoutUnit constructor for each parameter - // instead. - DeprecatedLayoutPoint(double, double) = delete; - - bool operator==(const DeprecatedLayoutPoint&) const = default; - - constexpr LayoutUnit X() const { return x_; } - constexpr LayoutUnit Y() const { return y_; } - - WTF::String ToString() const; - - private: - LayoutUnit x_, y_; -}; - -PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, - const DeprecatedLayoutPoint&); - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LAYOUT_POINT_H_
diff --git a/third_party/blink/renderer/platform/geometry/physical_offset.h b/third_party/blink/renderer/platform/geometry/physical_offset.h index 7cfcf64..5390f32a 100644 --- a/third_party/blink/renderer/platform/geometry/physical_offset.h +++ b/third_party/blink/renderer/platform/geometry/physical_offset.h
@@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_PHYSICAL_OFFSET_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_PHYSICAL_OFFSET_H_ -#include "third_party/blink/renderer/platform/geometry/layout_point.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "ui/gfx/geometry/point.h" @@ -68,17 +67,6 @@ return *this; } - // Conversions from/to existing code. New code prefers type safety for - // logical/physical distinctions. - constexpr explicit PhysicalFixedOffset(const DeprecatedLayoutPoint& point) - : left(point.X()), top(point.Y()) {} - - // Conversions from/to existing code. New code prefers type safety for - // logical/physical distinctions. - constexpr DeprecatedLayoutPoint FaultyToDeprecatedLayoutPoint() const { - return {left, top}; - } - explicit PhysicalFixedOffset(const gfx::Point& point) : left(point.x()), top(point.y()) {} explicit PhysicalFixedOffset(const gfx::Vector2d& vector)
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc index 3f89021..cae73ee0 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -103,19 +103,6 @@ return flush_for_image_listener; } -namespace { - -bool IsGMBAllowed(gfx::Size size, - viz::SharedImageFormat format, - const gpu::Capabilities& caps) { - const gfx::BufferFormat buffer_format = - viz::SinglePlaneSharedImageFormatToBufferFormat(format); - return gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, buffer_format) && - gpu::IsImageFromGpuMemoryBufferFormatSupported(buffer_format, caps); -} - -} // namespace - class CanvasResourceProvider::CanvasImageProvider : public cc::ImageProvider { public: CanvasImageProvider(cc::ImageDecodeCache* cache_n32, @@ -1312,23 +1299,22 @@ format = viz::SinglePlaneFormat::kRGBA_8888; } - // TODO(crbug.com/404887530) : Remove or Rename IsGMBAllowed() since - // CanvasResourceProvider no longer uses GMBs. - const bool is_gpu_memory_buffer_image_allowed = - is_gpu_compositing_enabled && IsGMBAllowed(size, format, capabilities); + const bool is_mappable_shared_image_allowed = + is_gpu_compositing_enabled && + gpu::IsFormatSupportedForSIWithNativeBuffer(format, capabilities); - if (raster_mode == RasterMode::kCPU && !is_gpu_memory_buffer_image_allowed) + if (raster_mode == RasterMode::kCPU && !is_mappable_shared_image_allowed) { return nullptr; + } // If we cannot use overlay, we have to remove the scanout flag and the // concurrent read write flag. const auto& shared_image_caps = context_provider_wrapper->ContextProvider() .SharedImageInterface() ->GetCapabilities(); - bool is_overlay_supported_via_gmb = - is_gpu_memory_buffer_image_allowed && + bool is_overlay_supported = + is_mappable_shared_image_allowed && (!is_accelerated || shared_image_caps.supports_scanout_shared_images); - bool is_overlay_supported = is_overlay_supported_via_gmb; #if BUILDFLAG(IS_WIN) if (base::FeatureList::IsEnabled(kUseCRPSIForLowLatencyOnWindows)) {
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc index ddce561..c57bcd4f 100644 --- a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc +++ b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc
@@ -8,6 +8,7 @@ #include <optional> #include <set> +#include "base/containers/span.h" #include "base/memory/singleton.h" #include "third_party/blink/renderer/platform/graphics/dark_mode_settings.h" #include "third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.h" @@ -259,7 +260,8 @@ features.is_colorful ? 1.0f : 0.0f, features.color_buckets_ratio, features.transparency_ratio, features.background_ratio}; - darkmode_tfnative_model::Inference(feature_list, &nn_out, &nn_temp); + darkmode_tfnative_model::Inference(feature_list, + base::span_from_ref(nn_out), &nn_temp); result = nn_out > 0 ? DarkModeResult::kApplyFilter : DarkModeResult::kDoNotApplyFilter; }
diff --git a/third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.cc b/third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.cc index 9ce6ded..40e586d 100644 --- a/third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.cc +++ b/third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.cc
@@ -7,6 +7,9 @@ #pragma allow_unsafe_buffers #endif +#include "base/containers/span.h" +#include "base/numerics/safe_conversions.h" + // This file is automatically generated using tfNative from a neural network, // trained by TensorFlow. Please do not edit. @@ -62,7 +65,7 @@ #define BENCHMARK_TIMER(...) // The size of a shape in terms of number of coefficients. -inline int ShapeSize(const int32_t rank, const int32_t* shape) { +inline int ShapeSize(const int32_t rank, base::span<const int32_t> shape) { int size = 1; for (int i = 0; i < rank; ++i) size *= shape[i]; @@ -73,10 +76,10 @@ // specify which axes are reduced. template <typename Tidx> int32_t GetReduceInnerSize(int32_t input_tensor_rank, - const int32_t* __restrict input_shape, + base::span<const int32_t> input_shape, int32_t index_tensor_rank, - const int32_t* __restrict index_shape, - const Tidx* __restrict index_values) { + base::span<const int32_t> index_shape, + base::span<const Tidx> index_values) { assert(index_tensor_rank <= 1); const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; int32_t inner_size = 1; @@ -88,34 +91,36 @@ template <typename T> void ConcatV2Args2(int32_t arg0_rank, - const int32_t* __restrict arg0_shape, - const T* __restrict arg0_values, + base::span<const int32_t> arg0_shape, + base::span<const T> arg0_values, int32_t arg1_rank, - const int32_t* __restrict arg1_shape, - const T* __restrict arg1_values, - const int32_t* __restrict axis_value, - T* __restrict output_values) { + base::span<const int32_t> arg1_shape, + base::span<const T> arg1_values, + base::span<const int32_t> axis_value, + base::span<T> output_values) { BENCHMARK_TIMER("ConcatV2Args2"); - const int axis = axis_value[0]; + const size_t axis = base::checked_cast<size_t>(axis_value[0]); const int num_lines = ShapeSize(axis, arg0_shape); - const int arg0_line_size = ShapeSize(arg0_rank - axis, arg0_shape + axis); - const int arg1_line_size = ShapeSize(arg1_rank - axis, arg1_shape + axis); + const size_t arg0_line_size = base::checked_cast<size_t>( + ShapeSize(arg0_rank - axis, arg0_shape.subspan(axis))); + const size_t arg1_line_size = base::checked_cast<size_t>( + ShapeSize(arg1_rank - axis, arg1_shape.subspan(axis))); for (int line = 0; line < num_lines; ++line) { - std::copy(arg0_values, arg0_values + arg0_line_size, output_values); - arg0_values += arg0_line_size; - output_values += arg0_line_size; - std::copy(arg1_values, arg1_values + arg1_line_size, output_values); - arg1_values += arg1_line_size; - output_values += arg1_line_size; + output_values.copy_prefix_from(arg0_values.first(arg0_line_size)); + arg0_values = arg0_values.subspan(arg0_line_size); + output_values = output_values.subspan(arg0_line_size); + output_values.copy_prefix_from(arg1_values.first(arg1_line_size)); + arg1_values = arg1_values.subspan(arg1_line_size); + output_values = output_values.subspan(arg1_line_size); } } template <typename T> -void Conv2DAsGemm(const int32_t* __restrict in_shape, - const T* __restrict in_values, - const int32_t* __restrict filter_shape, - const T* __restrict filter_values, - T* __restrict output_values) { +void Conv2DAsGemm(base::span<const int32_t> in_shape, + base::span<const T> in_values, + base::span<const int32_t> filter_shape, + base::span<const T> filter_values, + base::span<T> output_values) { BENCHMARK_TIMER("Conv2DAsGemm"); #if USE_EIGEN const auto in = ConstMatrixMap<T>(in_values, in_shape[0], in_shape[1]); @@ -128,6 +133,7 @@ const int32_t out_rows = in_shape[1]; const int32_t out_cols = filter_shape[3]; const int32_t dot_len = in_shape[0]; + auto output_iter = output_values.begin(); for (int row = 0; row < out_rows; ++row) { for (int col = 0; col < out_cols; ++col) { T value = 0; @@ -135,22 +141,22 @@ value += in_values[row * dot_len + i] * filter_values[i * out_cols + col]; } - *output_values++ = value; + *output_iter++ = value; } } #endif } template <typename T> -void DepthwiseConv2dNative(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, - const T* __restrict kernel_values, +void DepthwiseConv2dNative(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, + base::span<const T> kernel_values, int32_t stride_y, int32_t stride_x, int32_t out_height, int32_t out_width, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("DepthwiseConv2dNative"); // Give the shape values nicer names. assert(input_shape[3] == kernel_shape[2]); @@ -182,7 +188,7 @@ 1, // channel mult }; - T* out_write_ptr = output_values; + auto out_write_iter = output_values.begin(); for (int batch = 0; batch < batch_size; ++batch) { for (int out_y = 0; out_y < out_height; ++out_y) { for (int out_x = 0; out_x < out_width; ++out_x) { @@ -199,7 +205,7 @@ const int kernel_x_end = std::min(kernel_width, in_width - in_x_origin); for (int in_c = 0; in_c < in_depth; ++in_c) { - for (int mul_c = 0; mul_c < depth_mul; ++mul_c, ++out_write_ptr) { + for (int mul_c = 0; mul_c < depth_mul; ++mul_c, ++out_write_iter) { // Convolve. T sum = 0; for (int k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { @@ -221,7 +227,7 @@ sum += input_value * kernel_value; } } - *out_write_ptr = sum; + *out_write_iter = sum; } // mul_c } // in_c } // out_x @@ -230,13 +236,13 @@ } template <typename T> -void FullyConnected(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict weight_shape, - const T* __restrict weight_values, - const int32_t* __restrict bias_shape, - const T* __restrict bias_values, - T* __restrict output_values) { +void FullyConnected(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> weight_shape, + base::span<const T> weight_values, + base::span<const int32_t> bias_shape, + base::span<const T> bias_values, + base::span<T> output_values) { BENCHMARK_TIMER("FullyConnected"); #if USE_EIGEN const auto in = @@ -268,38 +274,39 @@ template <typename T, typename TIndex> void Gather(int params_rank, - const int32_t* __restrict params_shape, - const T* __restrict params_values, + base::span<const int32_t> params_shape, + base::span<const T> params_values, int indices_rank, - const int32_t* __restrict indices_shape, - const TIndex* __restrict indices_values, - T* __restrict output_values) { + base::span<const int32_t> indices_shape, + base::span<const TIndex> indices_values, + base::span<T> output_values) { BENCHMARK_TIMER("Gather"); const int num_indices = ShapeSize(indices_rank, indices_shape); const int num_params = params_shape[0]; - const int slice_size = ShapeSize(params_rank - 1, params_shape + 1); + const size_t slice_size = base::checked_cast<size_t>( + ShapeSize(params_rank - 1, params_shape.subspan(1u))); for (int i = 0; i < num_indices; ++i) { const int index = indices_values[i]; if (index < 0 || index >= num_params) { - std::fill(output_values, output_values + slice_size, 0); + std::ranges::fill(output_values.first(slice_size), 0); } else { - std::copy(params_values + index * slice_size, - params_values + index * slice_size + slice_size, output_values); + output_values.copy_prefix_from( + params_values.subspan(index * slice_size, slice_size)); } - output_values += slice_size; + output_values = output_values.subspan(slice_size); } } template <typename T, typename TIndex> -void Im2Col(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, +void Im2Col(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, int32_t stride_y, int32_t stride_x, int32_t out_height, int32_t out_width, - TIndex* output_shape, - T* __restrict output_values) { + base::span<TIndex> output_shape, + base::span<T> output_values) { BENCHMARK_TIMER("Im2Col"); // Give the shape values nicer names. assert(input_shape[3] == kernel_shape[2]); @@ -343,66 +350,70 @@ // Padding top. if (kernel_y_start != 0) { const int num_lines = kernel_y_start; - const int num_coeffs = num_lines * kernel_width * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(num_lines * kernel_width * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } for (int k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { // Padding left. if (kernel_x_start != 0) { - const int num_coeffs = kernel_x_start * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(kernel_x_start * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } // Valid values. { const int in_y = in_y_origin + k_y; const int in_x = in_x_origin + kernel_x_start; - const int num_coeffs = (kernel_x_end - kernel_x_start) * in_depth; + const size_t num_coeffs = base::checked_cast<size_t>( + (kernel_x_end - kernel_x_start) * in_depth); #if USE_TYPED_MEMSETMEMCPY - const int offset = - batch * batch_stride + in_y * y_stride + in_x * x_stride; - std::copy(input_values + offset, input_values + offset + num_coeffs, - output_values); + const size_t offset = base::checked_cast<size_t>( + batch * batch_stride + in_y * y_stride + in_x * x_stride); + output_values.copy_prefix_from( + input_values.subspan(offset, num_coeffs)); #else - std::memcpy(output_values, - input_values // Reusing the restricted pointer. + std::memcpy(output_values.data(), + input_values.data() // Reusing the restricted pointer. + batch * batch_stride // batch + in_y * y_stride // y + in_x * x_stride, // x num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } // Padding right. if (kernel_x_end != kernel_width) { const int num_coeffs = (kernel_width - kernel_x_end) * in_depth; #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } } // Padding bottom. if (kernel_y_end != kernel_height) { const int num_lines = kernel_height - kernel_y_end; - const int num_coeffs = num_lines * kernel_width * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(num_lines * kernel_width * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } } } @@ -410,15 +421,15 @@ } template <typename T> -void MaxPool(const int32_t* __restrict input_shape, - const T* __restrict input_values, +void MaxPool(base::span<const int32_t> input_shape, + base::span<const T> input_values, int32_t stride_y, int32_t stride_x, int32_t kernel_height, int32_t kernel_width, int32_t out_height, int32_t out_width, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("MaxPool"); // Give the shape values nicer names. const int batch_size = input_shape[0]; @@ -440,7 +451,7 @@ 1, // channel }; - T* out_write_ptr = output_values; + auto out_write_iter = output_values.begin(); for (int batch = 0; batch < batch_size; ++batch) { for (int out_y = 0; out_y < out_height; ++out_y) { for (int out_x = 0; out_x < out_width; ++out_x) { @@ -456,7 +467,7 @@ const int kernel_x_start = std::max(0, -in_x_origin); const int kernel_x_end = std::min(kernel_width, in_width - in_x_origin); - for (int chan = 0; chan < depth; ++chan, ++out_write_ptr) { + for (int chan = 0; chan < depth; ++chan, ++out_write_iter) { // Convolve. T max_value = std::numeric_limits<T>::lowest(); for (int k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { @@ -473,7 +484,7 @@ max_value = std::max(max_value, input_value); } // kernel_x } // kernel_y - *out_write_ptr = max_value; + *out_write_iter = max_value; } // chan } // out_x } // out_y @@ -482,9 +493,9 @@ template <typename T> void Memcpy(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - T* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<T> output_values) { BENCHMARK_TIMER("Memcpy"); const int size = ShapeSize(rank, input_shape); for (int i = 0; i < size; ++i) { @@ -494,11 +505,11 @@ template <typename T> void Softmax(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, + base::span<const int32_t> input_shape, + base::span<const T> input_values, const int32_t reduce_dim, - T* __restrict output_values, - T* __restrict scratch_values) { + base::span<T> output_values, + base::span<T> scratch_values) { BENCHMARK_TIMER("Softmax"); const int size = ShapeSize(rank, input_shape); if (rank == 2 && reduce_dim == 1) { @@ -533,9 +544,9 @@ // Returns the start position for a slice in a single dimension. template <typename T> int StridedSliceBegin(int range_mask, - const T* __restrict range_values, - const T* __restrict strides, - const int32_t* __restrict input_shape, + base::span<const T> range_values, + base::span<const T> strides, + base::span<const int32_t> input_shape, int dim) { const bool is_explicit = 0 == (range_mask & (1 << dim)); if (is_explicit) { @@ -549,9 +560,9 @@ // Returns the end position for a slice in a single dimension. template <typename T> int StridedSliceEnd(int range_mask, - const T* __restrict range_values, - const T* __restrict strides, - const int32_t* __restrict input_shape, + base::span<const T> range_values, + base::span<const T> strides, + base::span<const int32_t> input_shape, int dim) { const bool is_explicit = 0 == (range_mask & (1 << dim)); if (is_explicit) { @@ -564,14 +575,14 @@ template <typename T, typename TIdx> void StridedSlice(const int32_t input_rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const TIdx* __restrict begin, - const TIdx* __restrict end, - const TIdx* __restrict strides, + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const TIdx> begin, + base::span<const TIdx> end, + base::span<const TIdx> strides, int32_t begin_mask, int32_t end_mask, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("StridedSlice"); const int MAX_RANK = 8; assert(input_rank < MAX_RANK); @@ -606,7 +617,7 @@ // Find out how large the blocks are that we can copy contiguously. (All // dimensions on the right for which we fetch the full range) int last_sliced_dim = input_rank - 1; - int block_size = 1; + size_t block_size = 1; for (int dim = input_rank - 1; dim >= 0 && dim_is_full_range[dim]; --dim) { block_size *= input_shape[dim]; last_sliced_dim--; @@ -620,7 +631,7 @@ while (read_pos[0] != dim_end[0]) { // Compute the read offset for the current position. - int32_t read_offset = 0; + size_t read_offset = 0; for (int dim = 0; dim <= last_sliced_dim; ++dim) { const int addr_stride = dim_addr_strides[dim]; if (read_pos[dim] < 0) { @@ -631,13 +642,13 @@ } #if USE_TYPED_MEMSETMEMCPY - std::copy(input_values + read_offset, - input_values + read_offset + block_size, output_values); + output_values.copy_prefix_from( + input_values.subspan(read_offset, block_size)); #else - std::memcpy(output_values, input_values + read_offset, + std::memcpy(output_values.data(), input_values.data() + read_offset, block_size * sizeof(T)); #endif - output_values += block_size; + output_values = output_values.subspan(block_size); // Advance the read position. for (int dim = last_sliced_dim; dim >= 0; --dim) { @@ -650,10 +661,10 @@ } template <typename T> -void TransposeRank3(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict perm, - T* __restrict output_values) { +void TransposeRank3(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> perm, + base::span<T> output_values) { BENCHMARK_TIMER("TransposeRank3"); const std::array<int32_t, 3> in_strides = { input_shape[1] * input_shape[2], @@ -685,10 +696,10 @@ } template <typename T> -void TransposeRank4(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict perm, - T* __restrict output_values) { +void TransposeRank4(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> perm, + base::span<T> output_values) { BENCHMARK_TIMER("TransposeRank4"); const std::array<int32_t, 4> in_strides = { input_shape[1] * input_shape[2] * input_shape[3], @@ -727,13 +738,13 @@ template <typename T, typename TIdx, typename TDepth> void OneHot(const int32_t input_rank, - const int32_t* __restrict input_shape, - const TIdx* __restrict input_values, + base::span<const int32_t> input_shape, + base::span<const TIdx> input_values, const TDepth* __restrict depth, const T* __restrict on_value, const T* __restrict off_value, const int32_t axis, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("OneHot"); const int32_t num_elements = ShapeSize(input_rank, input_shape); // We can assume axis >= 0 in this implementation. @@ -754,12 +765,12 @@ template <typename T, typename TIdx, typename TDepth> void OneHotLastDim(const int32_t input_rank, - const int32_t* __restrict input_shape, - const TIdx* __restrict input_values, + base::span<const int32_t> input_shape, + base::span<const TIdx> input_values, const TDepth* __restrict depth, const T* __restrict on_value, const T* __restrict off_value, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("OneHotLastDim"); const int32_t num_elements = ShapeSize(input_rank, input_shape); int32_t write_offset = 0; @@ -780,25 +791,25 @@ #if USE_EIGEN -#define SIMPLE_UNARY_OP(OP_NAME, _, EXPR_EIGEN) \ - template <typename T> \ - void OP_NAME(const int32_t rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, \ - T* __restrict output_values) { \ - BENCHMARK_TIMER(#OP_NAME); \ - const int size = ShapeSize(rank, input_shape); \ - auto values = ConstRowVectorMap<T>(input_values, size).array(); \ - auto output = RowVectorMap<T>(output_values, size).array(); \ - output = EXPR_EIGEN; \ +#define SIMPLE_UNARY_OP(OP_NAME, _, EXPR_EIGEN) \ + template <typename T> \ + void OP_NAME(const int32_t rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, \ + base::span<T> output_values) { \ + BENCHMARK_TIMER(#OP_NAME); \ + const int size = ShapeSize(rank, input_shape); \ + auto values = ConstRowVectorMap<T>(input_values.data(), size).array(); \ + auto output = RowVectorMap<T>(output_values.data(), size).array(); \ + output = EXPR_EIGEN; \ } #else #define SIMPLE_UNARY_OP(OP_NAME, EXPR, _) \ template <typename T> \ - void OP_NAME(const int32_t rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, \ - T* __restrict output_values) { \ + void OP_NAME(const int32_t rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, \ + base::span<T> output_values) { \ BENCHMARK_TIMER(#OP_NAME); \ const int size = ShapeSize(rank, input_shape); \ for (int i = 0; i < size; ++i) { \ @@ -847,19 +858,19 @@ template <typename T, typename OP> void OpNoBroadcast(const int32_t left_rank, - const int32_t* __restrict left_shape, - const T* __restrict left_values, + base::span<const int32_t> left_shape, + base::span<const T> left_values, const int32_t right_rank, - const int32_t* __restrict right_shape, - const T* __restrict right_values, - T* __restrict output_values, + base::span<const int32_t> right_shape, + base::span<const T> right_values, + base::span<T> output_values, OP op) { BENCHMARK_TIMER(op.name, "NoBroadcast"); const int32_t size = ShapeSize(left_rank, left_shape); #if USE_EIGEN - auto lhs = ConstRowVectorMap<T>(left_values, size).array(); - auto rhs = ConstRowVectorMap<T>(right_values, size).array(); - auto output = RowVectorMap<T>(output_values, size).array(); + auto lhs = ConstRowVectorMap<T>(left_values.data(), size).array(); + auto rhs = ConstRowVectorMap<T>(right_values.data(), size).array(); + auto output = RowVectorMap<T>(output_values.data(), size).array(); op.apply(lhs, rhs, output); #else for (int32_t i = 0; i < size; ++i) { @@ -870,12 +881,12 @@ template <typename T, typename OP> void OpInnerBroadcast(int32_t left_rank, - const int32_t* __restrict left_shape, - const T* __restrict left_values, + base::span<const int32_t> left_shape, + base::span<const T> left_values, int32_t right_rank, - const int32_t* __restrict right_shape, - const T* __restrict right_values, - T* __restrict output_values, + base::span<const int32_t> right_shape, + base::span<const T> right_values, + base::span<T> output_values, OP op) { BENCHMARK_TIMER(op.name, "InnerBroadcast"); const int32_t output_size = ShapeSize(left_rank, left_shape); @@ -884,13 +895,13 @@ #if USE_EIGEN if (inner_size == 1) { // Apply the same value to all elements. - auto left = ConstMatrixMap<T>(left_values, inner_size, outer_size); - auto output = MatrixMap<T>(output_values, inner_size, outer_size); + auto left = ConstMatrixMap<T>(left_values.data(), inner_size, outer_size); + auto output = MatrixMap<T>(output_values.data(), inner_size, outer_size); op.apply(left.array(), right_values[0], output.array()); } else { - auto left = ConstMatrixMap<T>(left_values, inner_size, outer_size); - auto right = ConstRowVectorMap<T>(right_values, inner_size); - auto output = MatrixMap<T>(output_values, inner_size, outer_size); + auto left = ConstMatrixMap<T>(left_values.data(), inner_size, outer_size); + auto right = ConstRowVectorMap<T>(right_values.data(), inner_size); + auto output = MatrixMap<T>(output_values.data(), inner_size, outer_size); for (int32_t col = 0; col < outer_size; col++) { op.apply(left.col(col).array(), right.array(), output.col(col).array()); } @@ -909,7 +920,9 @@ template <typename T> \ struct Op##OP_NAME { \ const char* name = #OP_NAME; \ - T operator()(const T lhs, const T rhs) { return EXPR; } \ + T operator()(const T lhs, const T rhs) { \ + return EXPR; \ + } \ template <typename X, typename Y, typename Z> \ void apply(const X& lhs, const Y& rhs, Z out) { \ out = EXPR_EIGEN; \ @@ -917,19 +930,19 @@ }; \ template <typename T> \ void OP_NAME##NoBroadcast( \ - const int32_t left_rank, const int32_t* __restrict left_shape, \ - const T* __restrict left_values, const int32_t right_rank, \ - const int32_t* __restrict right_shape, const T* __restrict right_values, \ - T* __restrict output_values) { \ + const int32_t left_rank, base::span<const int32_t> left_shape, \ + base::span<const T> left_values, const int32_t right_rank, \ + base::span<const int32_t> right_shape, base::span<const T> right_values, \ + base::span<T> output_values) { \ OpNoBroadcast(left_rank, left_shape, left_values, right_rank, right_shape, \ right_values, output_values, Op##OP_NAME<T>()); \ } \ template <typename T> \ void OP_NAME##InnerBroadcast( \ - const int32_t left_rank, const int32_t* __restrict left_shape, \ - const T* __restrict left_values, const int32_t right_rank, \ - const int32_t* __restrict right_shape, const T* __restrict right_values, \ - T* __restrict output_values) { \ + const int32_t left_rank, base::span<const int32_t> left_shape, \ + base::span<const T> left_values, const int32_t right_rank, \ + base::span<const int32_t> right_shape, base::span<const T> right_values, \ + base::span<T> output_values) { \ OpInnerBroadcast(left_rank, left_shape, left_values, right_rank, \ right_shape, right_values, output_values, \ Op##OP_NAME<T>()); \ @@ -955,10 +968,10 @@ #define REDUCE_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \ template <typename T, typename Tidx> \ void OP_NAME##InnerReduce( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ BENCHMARK_TIMER(#OP_NAME, "InnerReduce"); \ const int32_t inner_size = \ GetReduceInnerSize(input_rank, input_shape, index_tensor_rank, \ @@ -979,10 +992,10 @@ } \ template <typename T, typename Tidx> \ void OP_NAME##GenericReduceRank4( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ assert(input_rank == 4); \ assert(index_tensor_rank <= 1); \ BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank4"); \ @@ -1039,11 +1052,11 @@ template <typename T> void DequantizeMinCombined(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const float* __restrict min_range, - const float* __restrict max_range, - float* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const float> min_range, + base::span<const float> max_range, + base::span<float> output_values) { BENCHMARK_TIMER("DequantizeMinCombined"); const int size = ShapeSize(rank, input_shape); const float offset = @@ -1064,11 +1077,11 @@ template <typename T> void DequantizeMinFirst(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const float* __restrict min_range, - const float* __restrict max_range, - float* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const float> min_range, + base::span<const float> max_range, + base::span<float> output_values) { BENCHMARK_TIMER("DequantizeMinFirst"); const int size = ShapeSize(rank, input_shape); const float range_scale = (max_range[0] - min_range[0]) / @@ -1152,8 +1165,8 @@ int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2] = {1, 1}; void Inference( - const float* __restrict input0 /* shape: 1,4 */, - float* __restrict logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: + base::span<const float> input0 /* shape: 1,4 */, + base::span<float> logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: 1,1 */ , FixedAllocations* __restrict fixed) {
diff --git a/third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.h b/third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.h index 6eb0c67e..09c4a322 100644 --- a/third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.h +++ b/third_party/blink/renderer/platform/graphics/darkmode/darkmode_classifier.h
@@ -23,8 +23,8 @@ extern int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2]; void Inference( - const float* __restrict input0 /* shape: 1,4 */, - float* __restrict logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: + base::span<const float> input0 /* shape: 1,4 */, + base::span<float> logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: 1,1 */ , FixedAllocations* __restrict fixed);
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc index 77df39f..4086132 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -1979,12 +1979,13 @@ // format matches shared image format. This is necessary for Graphite where // IOSurfaces are always used to allow sharing between ANGLE and Dawn. if (color_buffer_format_ == viz::SinglePlaneFormat::kRGBA_8888 && - gpu::IsImageFromGpuMemoryBufferFormatSupported( - gfx::BufferFormat::BGRA_8888, ContextProvider()->GetCapabilities())) { + gpu::IsFormatSupportedForSIWithNativeBuffer( + viz::SinglePlaneFormat::kBGRA_8888, + ContextProvider()->GetCapabilities())) { color_buffer_format_ = viz::SinglePlaneFormat::kBGRA_8888; } else if (color_buffer_format_ == viz::SinglePlaneFormat::kRGBX_8888 && - gpu::IsImageFromGpuMemoryBufferFormatSupported( - gfx::BufferFormat::BGRX_8888, + gpu::IsFormatSupportedForSIWithNativeBuffer( + viz::SinglePlaneFormat::kBGRX_8888, ContextProvider()->GetCapabilities())) { color_buffer_format_ = viz::SinglePlaneFormat::kBGRX_8888; } @@ -2028,17 +2029,15 @@ // Intel GPUs (i8xx) don't support RGBX overlays. if (color_buffer_format_ == viz::SinglePlaneFormat::kRGBX_8888 && allow_bgrx && - gpu::IsImageFromGpuMemoryBufferFormatSupported( - gfx::BufferFormat::BGRX_8888, + gpu::IsFormatSupportedForSIWithNativeBuffer( + viz::SinglePlaneFormat::kBGRX_8888, ContextProvider()->GetCapabilities())) { color_buffer_format_ = viz::SinglePlaneFormat::kBGRX_8888; } #endif // !BUILDFLAG(IS_ANDROID) - if (gpu::IsImageFromGpuMemoryBufferFormatSupported( - viz::SinglePlaneSharedImageFormatToBufferFormat( - color_buffer_format_), - ContextProvider()->GetCapabilities())) { + if (gpu::IsFormatSupportedForSIWithNativeBuffer( + color_buffer_format_, ContextProvider()->GetCapabilities())) { usage = usage | gpu::SHARED_IMAGE_USAGE_SCANOUT; if (low_latency_enabled()) { usage = usage | gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE;
diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc index 684f6f8..13124e84 100644 --- a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc +++ b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc
@@ -201,7 +201,8 @@ shared_image->mailbox(), shared_image->GetTextureTarget(), image_origin, image_size, src_point, info, temp_argb_frame->stride(media::VideoFrame::Plane::kARGB), - temp_argb_frame->GetWritableVisibleData(media::VideoFrame::Plane::kARGB), + temp_argb_frame->GetWritableVisiblePlaneData( + media::VideoFrame::Plane::kARGB), WTF::BindOnce(&StaticBitmapImageToVideoFrameCopier::OnARGBPixelsReadAsync, weak_ptr_factory_.GetWeakPtr(), image, temp_argb_frame, std::move(callback))); @@ -236,11 +237,11 @@ gfx::Rect(image_size), shared_image->surface_origin() != kTopLeft_GrSurfaceOrigin, output_frame->stride(media::VideoFrame::Plane::kY), - output_frame->GetWritableVisibleData(media::VideoFrame::Plane::kY), + output_frame->GetWritableVisiblePlaneData(media::VideoFrame::Plane::kY), output_frame->stride(media::VideoFrame::Plane::kU), - output_frame->GetWritableVisibleData(media::VideoFrame::Plane::kU), + output_frame->GetWritableVisiblePlaneData(media::VideoFrame::Plane::kU), output_frame->stride(media::VideoFrame::Plane::kV), - output_frame->GetWritableVisibleData(media::VideoFrame::Plane::kV), + output_frame->GetWritableVisiblePlaneData(media::VideoFrame::Plane::kV), gfx::Point(0, 0), WTF::BindOnce(&StaticBitmapImageToVideoFrameCopier::OnReleaseMailbox, weak_ptr_factory_.GetWeakPtr(), image),
diff --git a/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc b/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc index 2a5a622..3381e80a 100644 --- a/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc +++ b/third_party/blink/renderer/platform/p2p/filtering_network_manager_test.cc
@@ -16,6 +16,7 @@ #include <vector> #include "base/check.h" +#include "base/containers/span.h" #include "base/memory/raw_ptr_exclusion.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" @@ -202,8 +203,8 @@ this, &FilteringNetworkManagerTest::OnNetworksChanged); } - void RunTests(TestEntry* tests, size_t size) { - for (size_t i = 0; i < size; ++i) { + void RunTests(base::span<TestEntry> tests) { + for (size_t i = 0; i < tests.size(); ++i) { EXPECT_EQ(tests[i].expected_result, ProcessEvent(tests[i].event)) << " in step: " << i; } @@ -306,7 +307,7 @@ {kMockNetworksChangedWithSameNetwork, kNoSignal}, }; - RunTests(tests, std::size(tests)); + RunTests(tests); } // Test that multiple routes request is blocked and signaled right after @@ -333,7 +334,7 @@ {kStopUpdating, kNoSignal}, }; - RunTests(tests, std::size(tests)); + RunTests(tests); } // Test that multiple routes request is blocked and signaled right after @@ -358,7 +359,7 @@ {kMockNetworksChangedWithNewNetwork, kNoSignal}, }; - RunTests(tests, std::size(tests)); + RunTests(tests); } // Test that after permissions have been denied, a network change signal from @@ -378,7 +379,7 @@ {kStopUpdating, kNoSignal}, }; - RunTests(tests, std::size(tests)); + RunTests(tests); } // Test that multiple routes request is granted and signaled right after @@ -405,7 +406,7 @@ {kMockNetworksChangedWithNewNetwork, kNoSignal}, }; - RunTests(tests, std::size(tests)); + RunTests(tests); } // Test that multiple routes request is granted and signaled right after @@ -431,7 +432,7 @@ {kMockNetworksChangedWithNewNetwork, kNoSignal}, }; - RunTests(tests, std::size(tests)); + RunTests(tests); } // Test that multiple routes request is granted and signaled right after @@ -455,7 +456,7 @@ {kMockNetworksChangedWithNewNetwork, kNoSignal}, }; - RunTests(tests, std::size(tests)); + RunTests(tests); } // Test that the networks provided by the GetNetworks() and @@ -474,7 +475,7 @@ // ENUMERATION_ALLOWED. {kStartUpdating, kSignalEnumerationAllowed}, }; - RunTests(setup_steps, std::size(setup_steps)); + RunTests(setup_steps); std::vector<const webrtc::Network*> networks = network_manager_->GetNetworks();
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 cd60778..a5a11159 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
@@ -454,17 +454,14 @@ // We fill SpatialLayer only in temporal layer or spatial layer encoding. switch (codec_settings.codecType) { - case webrtc::kVideoCodecH264: - if (scalability_mode.has_value() && - *scalability_mode != webrtc::ScalabilityMode::kL1T1) { - DVLOG(1) - << "H264 temporal layers not yet supported by HW codecs, but use" - << " HW codecs and leave the fallback decision to a webrtc client" - << " by seeing metadata in webrtc::CodecSpecificInfo"; - - return true; + case webrtc::kVideoCodecH264: { + int number_of_temporal_layers = 1; + if (!IsValidTemporalSVC(scalability_mode, number_of_temporal_layers)) { + return false; } - break; + return SetLayerConfigForTemporalScalability( + codec_settings, *spatial_layers, number_of_temporal_layers); + } case webrtc::kVideoCodecVP8: { int number_of_temporal_layers = 1; if (!IsValidTemporalSVC(scalability_mode, number_of_temporal_layers)) {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 591d7630..5a8bf48b 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1105,8 +1105,7 @@ // info. name: "ControlledFrame", public: true, - status: "experimental", - base_feature_status: "disabled", + status: "stable", }, { name: "CookieDeprecationFacilitatedTesting", @@ -2378,13 +2377,6 @@ status: "experimental", }, { - // Don't create LayoutMultiColumnFlowThread objects, or any of the other - // legacy multicol objects. - name: "FlowThreadLess", - depends_on: ["LayoutBoxVisualLocation"], - status: "stable", - }, - { name: "FluentOverlayScrollbars", // The associated base feature is defined in // ui/native_theme/native_theme_features.cc. @@ -2723,7 +2715,7 @@ }, { name: "IndexedDbGetAllRecords", - status: "experimental", + status: "stable", }, { name: "InertElementNonEditable", @@ -2877,14 +2869,6 @@ status: "stable", }, { - // LayoutBox::PhysicalLocation() to return a truly visual offset - the - // offset of its first fragment relatively to the first fragment of its - // containing block, also when block-fragmented (used to be in the - // "stitched" flow-thread coordinate space). - name: "LayoutBoxVisualLocation", - status: "stable", - }, - { name: "LayoutFlexNewRowAlgorithm", status: "stable", },
diff --git a/third_party/blink/renderer/platform/testing/image_decode_to_nia.cc b/third_party/blink/renderer/platform/testing/image_decode_to_nia.cc index 5eca3c29..eab77314 100644 --- a/third_party/blink/renderer/platform/testing/image_decode_to_nia.cc +++ b/third_party/blink/renderer/platform/testing/image_decode_to_nia.cc
@@ -4,6 +4,8 @@ #include <array> +#include "base/containers/span.h" + // This program converts an image from stdin (e.g. a JPEG, PNG, etc.) to stdout // (in the NIA/NIE format, a trivial image file format). // @@ -38,14 +40,14 @@ #include "third_party/blink/renderer/platform/wtf/shared_buffer.h" #include "third_party/skia/include/core/SkColor.h" -static inline void set_u32le(uint8_t* ptr, uint32_t val) { +static inline void set_u32le(base::span<uint8_t> ptr, uint32_t val) { ptr[0] = val >> 0; UNSAFE_TODO(ptr[1]) = val >> 8; UNSAFE_TODO(ptr[2]) = val >> 16; UNSAFE_TODO(ptr[3]) = val >> 24; } -static inline void set_u64le(uint8_t* ptr, uint64_t val) { +static inline void set_u64le(base::span<uint8_t> ptr, uint64_t val) { ptr[0] = val >> 0; UNSAFE_TODO(ptr[1]) = val >> 8; UNSAFE_TODO(ptr[2]) = val >> 16; @@ -57,13 +59,13 @@ } void write_nix_header(uint32_t magic_u32le, uint32_t width, uint32_t height) { - uint8_t data[16]; - set_u32le(UNSAFE_TODO(data + 0), magic_u32le); - set_u32le(UNSAFE_TODO(data + 4), + std::array<uint8_t, 16> data; + set_u32le(data, magic_u32le); + set_u32le(base::span<uint8_t>(data).subspan(4u), 0x346E62FF); // 4 bytes per pixel non-premul BGRA. - set_u32le(UNSAFE_TODO(data + 8), width); - set_u32le(UNSAFE_TODO(data + 12), height); - UNSAFE_TODO(fwrite(data, 1, 16, stdout)); + set_u32le(base::span<uint8_t>(data).subspan(8u), width); + set_u32le(base::span<uint8_t>(data).subspan(12u), height); + UNSAFE_TODO(fwrite(data.data(), 1, 16, stdout)); } bool write_nia_duration(uint64_t total_duration_micros) { @@ -77,9 +79,9 @@ } d *= flicks_per_ten_micros; - uint8_t data[8]; - set_u64le(UNSAFE_TODO(data + 0), d); - UNSAFE_TODO(fwrite(data, 1, 8, stdout)); + std::array<uint8_t, 8> data; + set_u64le(data, d); + UNSAFE_TODO(fwrite(data.data(), 1, 8, stdout)); return true; } @@ -110,9 +112,9 @@ void write_nia_padding(uint32_t width, uint32_t height) { // 4 bytes of padding when the width and height are both odd. if (width & height & 1) { - uint8_t data[4]; - set_u32le(UNSAFE_TODO(data + 0), 0); - UNSAFE_TODO(fwrite(data, 1, 4, stdout)); + std::array<uint8_t, 4> data; + set_u32le(data, 0); + UNSAFE_TODO(fwrite(data.data(), 1, 4, stdout)); } } @@ -129,19 +131,19 @@ // useful to canonicalize still images' "number of animation loops" to 0. bool override_num_animation_loops = frame_count <= 1; - uint8_t data[8]; + std::array<uint8_t, 8> data; // kAnimationNone means a still image. if (override_num_animation_loops || (repetition_count == blink::kAnimationNone) || (repetition_count == blink::kAnimationLoopInfinite)) { - set_u32le(UNSAFE_TODO(data + 0), 0); + set_u32le(data, 0); } else { // NIA's loop count and Chromium/Skia's repetition count differ by one. See // https://github.com/google/wuffs/blob/master/doc/spec/nie-spec.md#nii-footer - set_u32le(UNSAFE_TODO(data + 0), 1 + repetition_count); + set_u32le(data, 1 + repetition_count); } - set_u32le(UNSAFE_TODO(data + 4), 0x80000000); - UNSAFE_TODO(fwrite(data, 1, 8, stdout)); + set_u32le(base::span<uint8_t>(data).subspan(4u), 0x80000000); + UNSAFE_TODO(fwrite(data.data(), 1, 8, stdout)); } int main(int argc, char* argv[]) {
diff --git a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc index d94127b17..23a1548 100644 --- a/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc +++ b/third_party/blink/renderer/platform/widget/input/main_thread_event_queue_unittest.cc
@@ -14,6 +14,7 @@ #include "base/auto_reset.h" #include "base/compiler_specific.h" #include "base/containers/adapters.h" +#include "base/containers/span.h" #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/memory/raw_ref.h" @@ -1560,7 +1561,7 @@ } MainThreadEventQueueTest& test; - const SyntheticWebTouchEvent* touch_moves; + base::span<const SyntheticWebTouchEvent> touch_moves; bool consume_touch_start = false; bool consume_first_touch_move = false; };
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index 0dbd43c..eda7879 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -144,7 +144,7 @@ 'base::StringPiece', 'base::SubstringSetMatcher', 'base::SysInfo', - 'base::SystemMemoryInfoKB', + 'base::SystemMemoryInfo', 'base::ThreadChecker', 'base::ThreadTicks', 'base::ThreadType', @@ -1668,8 +1668,7 @@ 'allowed': [ 'gfx::BufferFormat', 'gpu::ENABLE_WEBGL_TIMER_QUERY_EXTENSIONS', - 'gpu::IsImageFromGpuMemoryBufferFormatSupported', - 'gpu::IsImageSizeValidForGpuMemoryBufferFormat', + 'gpu::IsFormatSupportedForSIWithNativeBuffer', 'viz::SinglePlaneSharedImageFormatToBufferFormat', ], },
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 877b541d..1e9d3ec6 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2548,7 +2548,7 @@ # SharedWorker interface crbug.com/40290702 [ Android ] external/wpt/background-fetch/idlharness.https.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Android ] external/wpt/content-index/idlharness.https.any.sharedworker.html [ Failure ] -crbug.com/40290702 [ Android ] external/wpt/cookie-store/idlharness.https.any.sharedworker.html [ Failure ] +crbug.com/40290702 [ Android ] external/wpt/cookiestore/idlharness.https.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Android ] external/wpt/dom/idlharness.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Android ] external/wpt/encoding/idlharness.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Android ] external/wpt/event-timing/idlharness.any.sharedworker.html [ Failure ] @@ -2567,7 +2567,7 @@ crbug.com/40290702 [ Android ] external/wpt/xhr/idlharness.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Webview ] external/wpt/background-fetch/idlharness.https.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Webview ] external/wpt/content-index/idlharness.https.any.sharedworker.html [ Failure ] -crbug.com/40290702 [ Webview ] external/wpt/cookie-store/idlharness.https.any.sharedworker.html [ Failure ] +crbug.com/40290702 [ Webview ] external/wpt/cookiestore/idlharness.https.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Webview ] external/wpt/dom/idlharness.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Webview ] external/wpt/encoding/idlharness.any.sharedworker.html [ Failure ] crbug.com/40290702 [ Webview ] external/wpt/event-timing/idlharness.any.sharedworker.html [ Failure ] @@ -7035,7 +7035,7 @@ crbug.com/1375147 [ Win ] virtual/media-foundation-for-clear-dcomp/media/controls/singletap-on-overlay-closes-overflow-menu.html [ Failure ] crbug.com/1396079 [ Mac ] inspector-protocol/memory/forcibly-purge-javascript-memory.js [ Crash Failure ] crbug.com/1406027 [ Win ] virtual/media-foundation-for-clear-dcomp/media/controls/overflow-menu-hide-on-resize.html [ Failure ] -crbug.com/1289607 [ Linux ] external/wpt/cookie-store/cookieStore_subscribe_arguments.https.any.html [ Failure ] +crbug.com/1289607 external/wpt/cookiestore/cookieStore_subscribe_arguments.https.any.html [ Pass Failure ] crbug.com/1408294 [ Debug Linux ] virtual/gpu/external/wpt/mediacapture-record/MediaRecorder-canvas-media-source.https.html [ Failure ] crbug.com/1229708 fast/events/pointerevents/pointer-event-in-slop-region.html [ Failure Pass ] crbug.com/1406896 [ Debug Linux ] http/tests/inspector-protocol/cpu-profiler/record-cpu-profile-with-cpu-throttling.js [ Crash ] @@ -7054,13 +7054,10 @@ crbug.com/1446711 [ Mac ] media/controls/playback-speed-menu.html [ Timeout ] crbug.com/1446711 [ Win ] virtual/media-foundation-for-clear-dcomp/media/controls/accessibility-playback-speed-button.html [ Timeout ] crbug.com/1472813 [ Mac ] virtual/close-watcher/external/wpt/close-watcher/user-activation-shared.html?CloseWatcher [ Timeout ] -crbug.com/1492172 [ Win ] external/wpt/soft-navigation-heuristics/softnav-before-lcp-paint.tentative.html [ Failure ] crbug.com/1491472 [ Mac ] virtual/shared-storage-fenced-frame-mparch/http/tests/inspector-protocol/shared-storage/debugger-pause-on-first-script.js [ Skip Timeout ] crbug.com/1462683 [ Mac13-arm64 ] virtual/threaded/external/wpt/long-animation-frame/tentative/loaf-iframe-self.html [ Skip Timeout ] crbug.com/1462683 [ Mac12-arm64 ] virtual/threaded/external/wpt/long-animation-frame/tentative/loaf-iframe-self.html [ Skip Timeout ] -crbug.com/1455262 virtual/threaded/external/wpt/soft-navigation-heuristics/navigation-api-view-transition.tentative.html [ Crash Failure Pass Skip ] -crbug.com/1455262 virtual/view-transition-mpa-serialization/external/wpt/soft-navigation-heuristics/navigation-api-view-transition.tentative.html [ Crash Failure Pass Skip ] crbug.com/324293120 [ Debug Linux ] external/wpt/webstorage/event_case_sensitive.html [ Failure Pass ] # Sheriff 2022-10-07 @@ -7776,7 +7773,6 @@ [ Debug Mac13 ] http/tests/devtools/elements/styles-4/styles-source-lines-inline.js [ Skip Timeout ] [ Debug Mac13 ] virtual/threaded/printing/page-count-layout-overflow.html [ Skip Timeout ] [ Debug Mac13 ] virtual/threaded/fast/idleToBlob/OffscreenCanvas-convertToBlob-2d-worker.html [ Skip Timeout ] -[ Debug Mac13 ] external/wpt/soft-navigation-heuristics/back.tentative.html [ Skip Timeout ] [ Debug Mac13 ] fast/forms/label/label-event-order.html [ Failure ] [ Debug Mac13 ] virtual/threaded-prefer-compositing/fast/scroll-snap/root-scroller-snap-behaviour/smooth-scroll-snaps-visual-viewport.html [ Skip Timeout ] [ Debug Mac13 ] virtual/threaded/animations/stability/keyframe-timing-function-unset-crash.html [ Skip Timeout ] @@ -9050,7 +9046,8 @@ crbug.com/359319433 [ Mac15 ] external/wpt/secure-payment-confirmation/authentication-requires-user-activation.https.html [ Failure Pass Skip ] crbug.com/359319433 [ Mac15-arm64 ] external/wpt/secure-payment-confirmation/authentication-requires-user-activation.https.html [ Failure Pass Skip ] crbug.com/359319433 [ Mac ] external/wpt/secure-payment-confirmation/enrollment-in-iframe.sub.https.html [ Failure Pass Skip ] -crbug.com/359319433 [ Mac ] external/wpt/secure-payment-confirmation/enrollment.https.html [ Failure Pass Skip ] +# Gardener 2025-08-06 this test is also flaky on the other bots +crbug.com/359319433 external/wpt/secure-payment-confirmation/enrollment.https.html [ Failure Pass Skip ] # Gardener 2024-08-13 crbug.com/358437652 [ Linux ] external/wpt/dom/events/scrolling/wheel-event-transactions-multiple-action-chains.html [ Failure ] @@ -9409,7 +9406,6 @@ # Gardener 2025-03-06 crbug.com/400726001 [ Win ] external/wpt/css/css-ruby/ruby-text-combine-upright-002b.html [ Failure Pass ] crbug.com/400726001 [ Mac14 ] external/wpt/css/css-ruby/ruby-text-combine-upright-002b.html [ Failure Pass ] -crbug.com/395503013 [ Mac ] external/wpt/soft-navigation-heuristics/first-interaction-not-softnav.tentative.html [ Failure Pass Timeout ] # Gardener 2025-03-07 crbug.com/397311089 [ Debug Linux ] external/wpt/fetch/fetch-later/new-window.tentative.https.window.html [ Pass Timeout ] @@ -9554,7 +9550,6 @@ crbug.com/392657736 virtual/script-src-hashes-v1-enabled/external/wpt/content-security-policy/unsafe-eval/tentative/eval-allowed-by-hash-long-script.sub.html [ Pass ] # Gardener 2025-06-16 -crbug.com/424918655 [ Mac ] external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image.html [ Failure Pass ] crbug.com/420596996 [ Win ] virtual/webnn-service-with-gpu/external/wpt/webnn/conformance_tests/parallel-dispatch.https.any.serviceworker.html?gpu [ Failure Pass ] # <object> loaded HTML doesn't receive drag and drop events @@ -9573,13 +9568,6 @@ # Gardener 2025-06-26 crbug.com/427778335 [ Linux ] external/wpt/html/semantics/forms/the-select-element/customizable-select/select-appearance-button-after-text.tentative.html [ Failure Pass ] -crbug.com/427766096 virtual/soft-navigation-heuristics-pre-paint-attribution/external/wpt/soft-navigation-heuristics/load-classic-script-history-push.tentative.html [ Failure Pass ] -crbug.com/427679620 virtual/soft-navigation-heuristics-pre-paint-attribution/external/wpt/soft-navigation-heuristics/load-module-script-history-push.tentative.html [ Failure Pass ] -crbug.com/427612820 external/wpt/soft-navigation-heuristics/load-module-script-history-push.tentative.html [ Failure Pass ] -crbug.com/427612820 external/wpt/soft-navigation-heuristics/load-classic-script-history-push.tentative.html [ Failure Pass ] -# Flaky soft-navigation-heuristics WPT test which was ported from LCP (under investigation) -crbug.com/426391960 virtual/soft-navigation-heuristics-pre-paint-attribution/external/wpt/soft-navigation-heuristics/lcp/tentative/broken-image-icon.html [ Failure Pass ] -crbug.com/426391960 external/wpt/soft-navigation-heuristics/lcp/tentative/broken-image-icon.html [ Failure Pass ] # Gardener 2025-07-03 crbug.com/429394126 [ Win11-arm64 ] external/wpt/storage-access-api/requestStorageAccess-nested-cross-site-iframe.sub.https.window.html [ Failure Timeout ] @@ -9595,6 +9583,16 @@ crbug.com/429392773 external/wpt/scroll-animations/animation-trigger/* [ Failure Timeout ] crbug.com/429392773 external/wpt/scroll-animations/animation-trigger/parsing/* [ Pass ] +# Flaky Soft Navigation Heuristics tests +crbug.com/1455262 virtual/threaded/external/wpt/soft-navigation-heuristics/navigation-api-view-transition.tentative.html [ Crash Failure Pass Skip ] +crbug.com/1455262 virtual/view-transition-mpa-serialization/external/wpt/soft-navigation-heuristics/navigation-api-view-transition.tentative.html [ Crash Failure Pass Skip ] +[ Debug Mac13 ] external/wpt/soft-navigation-heuristics/back.tentative.html [ Skip Timeout ] +crbug.com/395503013 [ Mac ] external/wpt/soft-navigation-heuristics/first-interaction-not-softnav.tentative.html [ Failure Pass Timeout ] +crbug.com/424918655 [ Mac ] external/wpt/soft-navigation-heuristics/lcp/tentative/contracted-image.html [ Failure Pass ] +# Flaky soft-navigation-heuristics WPT test which was ported from LCP (under investigation) +crbug.com/426391960 virtual/soft-navigation-heuristics-pre-paint-attribution/external/wpt/soft-navigation-heuristics/lcp/tentative/broken-image-icon.html [ Failure Pass ] +crbug.com/426391960 external/wpt/soft-navigation-heuristics/lcp/tentative/broken-image-icon.html [ Failure Pass ] + # Gardener 2025-07-09 crbug.com/430344948 [ Mac14-arm64 ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.html?cpu [ Failure Pass ] crbug.com/430344948 [ Mac14-arm64 ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?cpu [ Failure Pass ] @@ -9648,5 +9646,10 @@ crbug.com/40253082 [ Mac14 ] virtual/controls-refresh-hc/fast/forms/color-scheme/select/select-multiple-appearance-basic.html [ Failure ] # Gardener 2025-08-04 -crbug.com/436140064 [ Win ] images/png-crbug423310049.html [ Failure ] crbug.com/436163716 [ Win ] external/wpt/secure-payment-confirmation/enrollment-in-iframe.sub.https.html [ Failure Crash Timeout ] + +# Gardener 2025-08-05 +crbug.com/436615917 inspector-protocol/timeline/long-animation-frame-trace-visual-update.js [ Failure Pass ] + +# Gardener 2025-08-06 +crbug.com/436534724 external/wpt/resource-timing/tentative/document-initiated.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/TestLists/content_shell.filter b/third_party/blink/web_tests/TestLists/content_shell.filter index 2cd6667..74217171 100644 --- a/third_party/blink/web_tests/TestLists/content_shell.filter +++ b/third_party/blink/web_tests/TestLists/content_shell.filter
@@ -43,7 +43,7 @@ external/wpt/compat/webkit-box-rtl-flex.html external/wpt/console/console-log-large-array.any.html external/wpt/content-security-policy/report-hash/* -external/wpt/cookie-store/cookieStore_subscribe_arguments.https.any.html +external/wpt/cookiestore/cookieStore_subscribe_arguments.https.any.html external/wpt/cookies/attributes/attributes-ctl.sub.html external/wpt/cookies/attributes/domain.sub.html external/wpt/css/compositing/mix-blend-mode/mix-blend-mode-animation.html
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index f1b21ca3..7f2126a 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -650,6 +650,25 @@ "expires": "never" }, { + "prefix": "file-system-access-write-mode", + "platforms": [ + "Linux", + "Mac", + "Win" + ], + "bases": [ + "external/wpt/file-system-access", + "external/wpt/fs" + ], + "args": [ + "--enable-features=FileSystemAccessWriteMode" + ], + "expires": "Sep 10, 2026", + "owners": [ + "mych@chromium.org" + ] + }, + { "prefix": "delay-async-when-lcp-in-html", "platforms": [ "Linux",
diff --git a/third_party/blink/web_tests/external/wpt/FileAPI/reading-data-section/filereader_events.any-expected.txt b/third_party/blink/web_tests/external/wpt/FileAPI/reading-data-section/filereader_events.any-expected.txt deleted file mode 100644 index b9adde79..0000000 --- a/third_party/blink/web_tests/external/wpt/FileAPI/reading-data-section/filereader_events.any-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] events are dispatched in the correct order for an empty blob - assert_equals: Expected load event, but got progress event instead expected "load" but got "progress" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/FileAPI/reading-data-section/filereader_events.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/FileAPI/reading-data-section/filereader_events.any.worker-expected.txt deleted file mode 100644 index b9adde79..0000000 --- a/third_party/blink/web_tests/external/wpt/FileAPI/reading-data-section/filereader_events.any.worker-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] events are dispatched in the correct order for an empty blob - assert_equals: Expected load event, but got progress event instead expected "load" but got "progress" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-invalid.html index ef2d31b..9f9f173 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-invalid.html
@@ -27,6 +27,9 @@ test_invalid_value("grid-template-columns", 'repeat(auto-fill, 10px) repeat(auto-fit, 20%)'); test_invalid_value("grid-template-columns", '[auto] 1px'); test_invalid_value("grid-template-columns", '-5fr repeat(auto-fill, auto)'); +test_invalid_value("grid-template-columns", '-10px repeat(auto-fill, min-content)'); +test_invalid_value("grid-template-columns", '-20% repeat(auto-fit, max-content)'); +test_invalid_value("grid-template-columns", 'repeat(auto-fill, fit-content)'); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-auto-valid.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-auto-valid.tentative.html deleted file mode 100644 index 126e705..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-auto-valid.tentative.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"> -<title>CSS Grid Layout Test: parsing grid-template-columns with valid values</title> -<link rel="help" href="https://drafts.csswg.org/css-grid-3/#masonry-intrinsic-repeat"> -<meta name="assert" content="grid-template-columns supports the full grammar 'none | <track-list> | <auto-track-list>'."> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/css/support/parsing-testcommon.js"></script> -</head> -<body> -<script> -// <auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <auto-or-fixed-size> ]+ <line-names>? ) -// <auto-or-fixed-size> = [<fixed-size> | auto] -test_valid_value("grid-template-columns", 'repeat(auto-fill, auto)'); -test_valid_value("grid-template-columns", 'repeat(auto-fit, auto 100px auto)'); -test_valid_value("grid-template-columns", 'repeat(auto-fill, minmax(30px, 5fr) [two] auto)'); -test_valid_value("grid-template-columns", 'repeat(auto-fit, [three] auto [four])'); -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-intrinsic-valid.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-intrinsic-valid.tentative.html new file mode 100644 index 0000000..eb5b826 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-intrinsic-valid.tentative.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: parsing grid-template-columns with valid values</title> +<link rel="help" href="https://drafts.csswg.org/css-grid-3/#masonry-intrinsic-repeat"> +<meta name="assert" content="grid-template-columns supports the full grammar 'none | <track-list> | <auto-track-list>'."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +</head> +<body> +<script> +// <auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <intrinsic-or-fixed-size> ]+ <line-names>? ) +// <intrinsic-or-fixed-size> = [<fixed-size> | <intrinsic-size>] +test_valid_value("grid-template-columns", 'repeat(auto-fill, auto)'); +test_valid_value("grid-template-columns", 'repeat(auto-fit, auto 100px auto)'); +test_valid_value("grid-template-columns", 'repeat(auto-fill, minmax(30px, 5fr) [two] auto)'); +test_valid_value("grid-template-columns", 'repeat(auto-fit, [three] auto [four])'); + +test_valid_value("grid-template-columns", 'repeat(auto-fill, min-content)'); +test_valid_value("grid-template-columns", 'repeat(auto-fit, min-content 100px min-content)'); +test_valid_value("grid-template-columns", 'repeat(auto-fill, minmax(30px, 5fr) [two] min-content)'); +test_valid_value("grid-template-columns", 'repeat(auto-fit, [three] min-content [four])'); + +test_valid_value("grid-template-columns", 'repeat(auto-fill, max-content)'); +test_valid_value("grid-template-columns", 'repeat(auto-fit, max-content 100px max-content)'); +test_valid_value("grid-template-columns", 'repeat(auto-fill, minmax(30px, 5fr) [two] max-content)'); +test_valid_value("grid-template-columns", 'repeat(auto-fit, [three] max-content [four])'); + +test_valid_value("grid-template-columns", 'repeat(auto-fill, fit-content(200px))'); +test_valid_value("grid-template-columns", 'repeat(auto-fit, fit-content(200px) 100px fit-content(200px))'); +test_valid_value("grid-template-columns", 'repeat(auto-fill, minmax(30px, 5fr) [two] fit-content(200px))'); +test_valid_value("grid-template-columns", 'repeat(auto-fit, [three] fit-content(200px) [four])'); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-invalid.html index d023c36..192b392d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-invalid.html
@@ -27,6 +27,9 @@ test_invalid_value("grid-template-rows", 'repeat(auto-fill, 10px) repeat(auto-fit, 20%)'); test_invalid_value("grid-template-rows", '[auto] 1px'); test_invalid_value("grid-template-rows", '-10px repeat(auto-fit, auto)'); +test_invalid_value("grid-template-rows", '-10px repeat(auto-fill, min-content)'); +test_invalid_value("grid-template-rows", '-20% repeat(auto-fit, max-content)'); +test_invalid_value("grid-template-rows", 'repeat(auto-fill, fit-content)'); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-auto-valid.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-auto-valid.tentative.html deleted file mode 100644 index ad8871f4..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-auto-valid.tentative.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<html> -<head> -<meta charset="utf-8"> -<title>CSS Grid Layout Test: parsing grid-template-rows with valid values</title> -<link rel="help" href="https://drafts.csswg.org/css-grid-3/#masonry-intrinsic-repeat"> -<meta name="assert" content="grid-template-rows supports the full grammar 'none | <track-list> | <auto-track-list>'."> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/css/support/parsing-testcommon.js"></script> -</head> -<body> -<script> -// <auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <auto-or-fixed-size> ]+ <line-names>? ) -// <auto-or-fixed-size> = [<fixed-size> | auto] -test_valid_value("grid-template-rows", 'repeat(auto-fill, auto)'); -test_valid_value("grid-template-rows", 'repeat(auto-fit, auto 100px auto)'); -test_valid_value("grid-template-rows", 'repeat(auto-fill, minmax(30px, 5fr) [two] auto)'); -test_valid_value("grid-template-rows", 'repeat(auto-fit, [three] auto [four])'); -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-intrinsic-valid.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-intrinsic-valid.tentative.html new file mode 100644 index 0000000..a3975eb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-intrinsic-valid.tentative.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: parsing grid-template-rows with valid values</title> +<link rel="help" href="https://drafts.csswg.org/css-grid-3/#masonry-intrinsic-repeat"> +<meta name="assert" content="grid-template-rows supports the full grammar 'none | <track-list> | <auto-track-list>'."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +</head> +<body> +<script> +// <auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <intrinsic-or-fixed-size> ]+ <line-names>? ) +// <intrinsic-or-fixed-size> = [<fixed-size> | <intrinsic-size>] +test_valid_value("grid-template-rows", 'repeat(auto-fill, auto)'); +test_valid_value("grid-template-rows", 'repeat(auto-fit, auto 100px auto)'); +test_valid_value("grid-template-rows", 'repeat(auto-fill, minmax(30px, 5fr) [two] auto)'); +test_valid_value("grid-template-rows", 'repeat(auto-fit, [three] auto [four])'); + +test_valid_value("grid-template-rows", 'repeat(auto-fill, min-content)'); +test_valid_value("grid-template-rows", 'repeat(auto-fit, min-content 100px min-content)'); +test_valid_value("grid-template-rows", 'repeat(auto-fill, minmax(30px, 5fr) [two] min-content)'); +test_valid_value("grid-template-rows", 'repeat(auto-fit, [three] min-content [four])'); + +test_valid_value("grid-template-rows", 'repeat(auto-fill, max-content)'); +test_valid_value("grid-template-rows", 'repeat(auto-fit, max-content 100px max-content)'); +test_valid_value("grid-template-rows", 'repeat(auto-fill, minmax(30px, 5fr) [two] max-content)'); +test_valid_value("grid-template-rows", 'repeat(auto-fit, [three] max-content [four])'); + + +test_valid_value("grid-template-rows", 'repeat(auto-fill, fit-content(200px))'); +test_valid_value("grid-template-rows", 'repeat(auto-fit, fit-content(200px) 100px fit-content(200px))'); +test_valid_value("grid-template-rows", 'repeat(auto-fill, minmax(30px, 5fr) [two] fit-content(200px))'); +test_valid_value("grid-template-rows", 'repeat(auto-fit, [three] fit-content(200px) [four])'); +</script> +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-mixins/mixins-including-mixins-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-mixins/contents-rule-expected.txt similarity index 69% rename from third_party/blink/web_tests/external/wpt/css/css-mixins/mixins-including-mixins-expected.txt rename to third_party/blink/web_tests/external/wpt/css/css-mixins/contents-rule-expected.txt index 76499a0..0361b791 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-mixins/mixins-including-mixins-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-mixins/contents-rule-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -[FAIL] CSS Mixins: Mixins depending on other mixins +[FAIL] @contents is ignored if there is no @contents parameter assert_equals: expected "rgb(0, 128, 0)" but got "rgb(0, 0, 0)" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-mixins/contents-rule.html b/third_party/blink/web_tests/external/wpt/css/css-mixins/contents-rule.html new file mode 100644 index 0000000..abd380e1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-mixins/contents-rule.html
@@ -0,0 +1,87 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Mixins: Mixins depending on other mixins</title> + <link rel="help" href="https://drafts.csswg.org/css-mixins-1/#apply-rule"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <style> + @mixin --m1(@contents) { + @contents; + } + #e1 { + color: red; + @apply --m1 { color: green; } + } + + @mixin --m2(@contents) { + @contents + } + #e2 { + color: red; + @apply --m1 { color: green; } + } + + @mixin --m3(@contents) { + &.a { + @contents { color: blue; } + } + } + .b { + color: red; + @apply --m3 { color: green; } + } + + @mixin --m4(@contents) { + &.c { + @contents { color: green; } + } + } + .d { + color: red; + @apply --m4; + } + + @mixin --m5 { + @contents { color: red !important; } + color: green; + } + #e4 { + @apply --m5 { color: red !important; } + } + </style> + </head> + <body> + <div id="e1">This text should be green.</div> + <div id="e2">This text should be green.</div> + <div class="a b" id="e3">This text should be green.</div> + <div class="c d" id="e4">This text should be green.</div> + <div id="e5">This text should be green.</div> + <script> + test(() => { + let target = document.getElementById('e1'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, 'Simple @contents with no fallback'); + + test(() => { + let target = document.getElementById('e2'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, 'Implicit semicolon after @contents, at end of block'); + + test(() => { + let target = document.getElementById('e3'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, 'Block in @apply overrides fallback'); + + test(() => { + let target = document.getElementById('e4'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, 'Fallback is used if @apply has no block'); + + test(() => { + let target = document.getElementById('e5'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, '@contents is ignored if there is no @contents parameter'); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-mixins/cross-stylesheet.html b/third_party/blink/web_tests/external/wpt/css/css-mixins/cross-stylesheet.html new file mode 100644 index 0000000..0c8d9be --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-mixins/cross-stylesheet.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Mixins: Mixin from another stylesheet</title> + <link rel="help" href="https://drafts.csswg.org/css-mixins-1/#using-mixins"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <style> + div { + color: red; + @apply --m1; + } + </style> + <style> + @mixin --m1() { + color: green; + } + </style> + </head> + <body> + <div><div class="cls" id="target">This text should be green.</div></div> + <script> + test(() => { + let target = document.getElementById('target'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-mixins/shadow-dom-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-mixins/shadow-dom-expected.txt new file mode 100644 index 0000000..996922f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-mixins/shadow-dom-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Style in shadow DOM should have access to outside non-adopted mixins + assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-mixins/shadow-dom.html b/third_party/blink/web_tests/external/wpt/css/css-mixins/shadow-dom.html new file mode 100644 index 0000000..f3f62ba --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-mixins/shadow-dom.html
@@ -0,0 +1,75 @@ +<!DOCTYPE html> +<html> + <head> + <title>CSS Mixins: Shadow DOM</title> + <link rel="help" href="https://drafts.csswg.org/css-mixins-1/#defining-mixins"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <style> + @mixin --exists-only-outside-shadow() { + color: green; + } + #e4 { + color: green; + @apply --in-shadow; + } + </style> + </head> + <body> + <div id="host"> + <template shadowrootmode="open"> + <style> + #e1 { + color: red; + @apply --exists-only-outside-shadow; + } + #e2 { + color: red; + @apply --m1; + } + #e3 { + color: red; + @apply --exists-only-in-adopted; + } + </style> + <style> + @mixin --m1() { + color: green; + } + @mixin --in-shadow() { + color: red; + } + </style> + <div id="e1">This text should be green.</div> + <div id="e2">This text should be green.</div> + <div id="e3">This text should be green.</div> + </template> + </div> + <div id="e4">This text should be green.</div> + <script> + const sheet = new CSSStyleSheet(); + sheet.replaceSync('@mixin --exists-only-in-adopted() { color: green; }'); + document.getElementById('host').shadowRoot.adoptedStyleSheets = [sheet]; + + test(() => { + let target = document.getElementById('host').shadowRoot.getElementById('e1'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, 'Style in shadow DOM should have access to outside non-adopted mixins'); + + test(() => { + let target = document.getElementById('host').shadowRoot.getElementById('e2'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, 'Style in shadow DOM should have access to inside mixins'); + + test(() => { + let target = document.getElementById('host').shadowRoot.getElementById('e3'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, 'Style in shadow DOM should have access to mixins from adopted stylesheets'); + + test(() => { + let target = document.getElementById('e4'); + assert_equals(getComputedStyle(target).color, 'rgb(0, 128, 0)'); + }, 'Style outside shadow DOM should _not_ have access to inside mixins'); + </script> + </body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/starting-style-first-letter-crash.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/starting-style-first-letter-crash.html new file mode 100644 index 0000000..b0193d0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/starting-style-first-letter-crash.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://issues.chromium.org/issues/435225409"> + +<style> +@starting-style { + div::first-letter { + color: red; + } +} +</style> + +<div>hello world</div>
diff --git a/third_party/blink/web_tests/external/wpt/fedcm/fedcm-login-status/login-page-broken.https.html b/third_party/blink/web_tests/external/wpt/fedcm/fedcm-login-status/login-page-broken.https.html index 06be5e4..445b9e4 100644 --- a/third_party/blink/web_tests/external/wpt/fedcm/fedcm-login-status/login-page-broken.https.html +++ b/third_party/blink/web_tests/external/wpt/fedcm/fedcm-login-status/login-page-broken.https.html
@@ -17,6 +17,7 @@ await select_manifest(t, test_options); let cred_promise = navigator.credentials.get(test_options); + const cred_check = promise_rejects_dom(t, 'NetworkError', cred_promise); let type = await fedcm_get_dialog_type_promise(t); assert_equals(type, "ConfirmIdpLogin"); @@ -29,6 +30,6 @@ // Because the login page never sends a signin status header, we // expect a promise rejection. - return promise_rejects_dom(t, 'NetworkError', cred_promise); + return cred_check; }, 'Tests that the promise does get resolved if a login page does not send a signin status header.'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/current-patch.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/current-patch.html index dc6a14b..8a1aa6d 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/current-patch.html +++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/current-patch.html
@@ -13,7 +13,7 @@ assert_equals(placeholder.currentPatch, null, "no patch active, currentPatch should be null"); doc.write('<template id=patchy patchfor="placeholder">'); const {currentPatch} = placeholder; - assert_true(currentPatch instanceof PatchStatus); + assert_true(currentPatch instanceof Patch); const {finished, source} = currentPatch; assert_true(source instanceof HTMLTemplateElement); assert_equals(source.id, "patchy");
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/patch-range.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/patch-range.html index bf05c2b..4cb80a2b 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/patch-range.html +++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/patch-range.html
@@ -21,7 +21,7 @@ const writable = placeholder.patchBetween(first, last); const response = new Response("<span id=middle>Content</span>", {headers: {"Content-Type": "text/html"}}); response.body.pipeTo(writable); - assert_true(placeholder.currentPatch instanceof PatchStatus, "currentPatch should be a PatchStatus right after connecting a stream"); + assert_true(placeholder.currentPatch instanceof Patch, "currentPatch should be a Patch right after connecting a stream"); await placeholder.currentPatch.finished; assert_equals(placeholder.currentPatch, null); const middle = placeholder.querySelector("#middle"); @@ -40,7 +40,7 @@ const writable = placeholder.patchAfter(first); const response = new Response("<span id=middle>Content</span>", {headers: {"Content-Type": "text/html"}}); response.body.pipeTo(writable); - assert_true(placeholder.currentPatch instanceof PatchStatus, "currentPatch should be a PatchStatus right after connecting a stream"); + assert_true(placeholder.currentPatch instanceof Patch, "currentPatch should be a Patch right after connecting a stream"); await placeholder.currentPatch.finished; assert_equals(placeholder.currentPatch, null); const middle = placeholder.querySelector("#middle"); @@ -59,7 +59,7 @@ const writable = placeholder.patchBefore(last); const response = new Response("<span id=middle>Content</span>", {headers: {"Content-Type": "text/html"}}); response.body.pipeTo(writable); - assert_true(placeholder.currentPatch instanceof PatchStatus, "currentPatch should be a PatchStatus right after connecting a stream"); + assert_true(placeholder.currentPatch instanceof Patch, "currentPatch should be a Patch right after connecting a stream"); await placeholder.currentPatch.finished; assert_equals(placeholder.currentPatch, null); const middle = placeholder.querySelector("#middle"); @@ -78,7 +78,7 @@ const writable = placeholder.patchAfter(last); const response = new Response("<span id=middle>Content</span>", {headers: {"Content-Type": "text/html"}}); response.body.pipeTo(writable); - assert_true(placeholder.currentPatch instanceof PatchStatus, "currentPatch should be a PatchStatus right after connecting a stream"); + assert_true(placeholder.currentPatch instanceof Patch, "currentPatch should be a Patch right after connecting a stream"); await placeholder.currentPatch.finished; assert_equals(placeholder.currentPatch, null); const middle = placeholder.querySelector("#middle"); @@ -97,7 +97,7 @@ const writable = placeholder.patchBefore(first); const response = new Response("<span id=middle>Content</span>", {headers: {"Content-Type": "text/html"}}); response.body.pipeTo(writable); - assert_true(placeholder.currentPatch instanceof PatchStatus, "currentPatch should be a PatchStatus right after connecting a stream"); + assert_true(placeholder.currentPatch instanceof Patch, "currentPatch should be a Patch right after connecting a stream"); await placeholder.currentPatch.finished; assert_equals(placeholder.currentPatch, null); const middle = placeholder.querySelector("#middle");
diff --git a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/patch-self.html b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/patch-self.html index e5938b6..68abc96 100644 --- a/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/patch-self.html +++ b/third_party/blink/web_tests/external/wpt/html/dom/partial-updates/tentative/patch-self.html
@@ -15,7 +15,7 @@ assert_true(writable instanceof WritableStream, "node.patchSelf() returns a writable stream"); const response = new Response("Content", {headers: {"Content-Type": "text/html"}}); response.body.pipeTo(writable); - assert_true(placeholder.currentPatch instanceof PatchStatus, "currentPatch should be a PatchStatus right after connecting a stream"); + assert_true(placeholder.currentPatch instanceof Patch, "currentPatch should be a Patch right after connecting a stream"); await placeholder.currentPatch.finished; assert_equals(placeholder.textContent, "Content"); assert_equals(placeholder.currentPatch, null); @@ -29,7 +29,7 @@ const writer = writable.getWriter(); await writer.write("Text"); const {currentPatch} = placeholder; - assert_true(currentPatch instanceof PatchStatus, "currentPatch should be a PatchStatus right after connecting a stream"); + assert_true(currentPatch instanceof Patch, "currentPatch should be a Patch right after connecting a stream"); writer.close(); await currentPatch.finished; assert_equals(placeholder.textContent, "Text");
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt b/third_party/blink/web_tests/fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt index f925a28..6970b19 100644 --- a/third_party/blink/web_tests/fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt +++ b/third_party/blink/web_tests/fast/css-grid-layout/grid-element-auto-repeat-get-set-expected.txt
@@ -63,6 +63,14 @@ PASS element.style.gridTemplateColumns is "repeat(auto-fit, minmax(20px, 30px) auto)" PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none" PASS element.style.gridTemplateRows is "repeat(auto-fit, minmax(20px, 30px) auto)" +PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none" +PASS element.style.gridTemplateColumns is "repeat(auto-fill, 20px min-content)" +PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none" +PASS element.style.gridTemplateRows is "repeat(auto-fill, 20px min-content)" +PASS getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none" +PASS element.style.gridTemplateColumns is "repeat(auto-fit, max-content 2em)" +PASS getComputedStyle(element, '').getPropertyValue('grid-template-rows') is "none" +PASS element.style.gridTemplateRows is "repeat(auto-fit, max-content 2em)" Test invalid repeat syntax. @@ -82,8 +90,6 @@ PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none" PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none" PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none" -PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none" -PASS window.getComputedStyle(element, '').getPropertyValue('grid-template-columns') is "none" PASS successfullyParsed is true TEST COMPLETE
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/grid-element-auto-repeat-get-set.html b/third_party/blink/web_tests/fast/css-grid-layout/grid-element-auto-repeat-get-set.html index b982d04..7a0b69f 100644 --- a/third_party/blink/web_tests/fast/css-grid-layout/grid-element-auto-repeat-get-set.html +++ b/third_party/blink/web_tests/fast/css-grid-layout/grid-element-auto-repeat-get-set.html
@@ -28,6 +28,8 @@ testGridDefinitionsSetJSValues("repeat(auto-fill, auto [foo bar] 10px)", "repeat(auto-fill, auto [foo bar] 10px)", "none", "none"); testGridDefinitionsSetJSValues("repeat(auto-fit, [bar] auto)", "repeat(auto-fit, [bar] auto)", "none", "none"); testGridDefinitionsSetJSValues("repeat(auto-fit, minmax(20px, 30px) auto)", "repeat(auto-fit, minmax(20px, 30px) auto)", "none", "none"); + testGridDefinitionsSetJSValues("repeat(auto-fill, 20px min-content)", "repeat(auto-fill, 20px min-content)", "none", "none"); + testGridDefinitionsSetJSValues("repeat(auto-fit, max-content 2em)", "repeat(auto-fit, max-content 2em)", "none", "none"); debug(""); debug("Test invalid repeat syntax."); @@ -40,11 +42,9 @@ } testInvalidSyntax("repeat(auto-fill, 1fr)"); - testInvalidSyntax("repeat(auto-fill, 20px min-content)"); testInvalidSyntax("repeat(auto-fill,)"); testInvalidSyntax("repeat(auto-fill, [foo])"); testInvalidSyntax("repeat(auto-fit, 1fr)"); - testInvalidSyntax("repeat(auto-fit, max-content 2em)"); testInvalidSyntax("repeat(auto-fit,)"); testInvalidSyntax("repeat(auto-fit, [foo])");
diff --git a/third_party/blink/web_tests/images/png-crbug423310049.html b/third_party/blink/web_tests/images/png-crbug423310049.html deleted file mode 100644 index 94df631..0000000 --- a/third_party/blink/web_tests/images/png-crbug423310049.html +++ /dev/null
@@ -1,12 +0,0 @@ -<!DOCTYPE html> -In https://crbug.com/423310049 the color space transformation wasn't quite -right - with the test image below the symptom was that yellow and cyan -bands were swapped (magenta and black bands were preserved). -<p> -The test image below was created by -<ul> - <li>Taking IHDR, IDAT, and IEND chunks from basn2c08 from the PNG test suite - <li>Taking iCCP chunk from the repro image from https://crbug.com/423310049 -</ul> -<hr> -<img src="resources/crbug423310049.png">
diff --git a/third_party/blink/web_tests/platform/linux/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/linux/images/png-crbug423310049-expected.png deleted file mode 100644 index 548f1e1..0000000 --- a/third_party/blink/web_tests/platform/linux/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/png-crbug423310049-expected.png deleted file mode 100644 index dc3f404..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/exotic-color-space/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/png-crbug423310049-expected.png deleted file mode 100644 index 33ae7623..0000000 --- a/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac12/virtual/shared-storage-fenced-frame-mparch/external/wpt/shared-storage/select-url-saved-query-cross-origin-multi-query.tentative.https.sub-expected.txt b/third_party/blink/web_tests/platform/mac-mac12/virtual/shared-storage-fenced-frame-mparch/external/wpt/shared-storage/select-url-saved-query-cross-origin-multi-query.tentative.https.sub-expected.txt deleted file mode 100644 index 89ce38d..0000000 --- a/third_party/blink/web_tests/platform/mac-mac12/virtual/shared-storage-fenced-frame-mparch/external/wpt/shared-storage/select-url-saved-query-cross-origin-multi-query.tentative.https.sub-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -[FAIL] for selectURL(), multiple saved queries can be handled simultaneously. - promise_test: Unhandled rejection with value: object "Error: {"selectURLStatus":"Error: assert_equals: expected \\"frame1_loaded\\" but got \\"frame0_loaded\\"","origin":"https://www.web-platform.test:8444","query":"query1","mockResultIndex":1,"module":"simple-module","operation":"test-slow-url-selection-operation","urlCount":4,"savedExpected":true,"successExpected":true}" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/png-crbug423310049-expected.png deleted file mode 100644 index 2c8b9af..0000000 --- a/third_party/blink/web_tests/platform/mac-mac15-arm64/virtual/gpu-rasterization/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac/images/png-crbug423310049-expected.png deleted file mode 100644 index bbd341a..0000000 --- a/third_party/blink/web_tests/platform/mac/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/png-crbug423310049-expected.png deleted file mode 100644 index 8b31bd3..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/png-crbug423310049-expected.png deleted file mode 100644 index c183cfe..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/win/images/png-crbug423310049-expected.png deleted file mode 100644 index a5f2bc1f..0000000 --- a/third_party/blink/web_tests/platform/win/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/png-crbug423310049-expected.png deleted file mode 100644 index 5a20637..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/png-crbug423310049-expected.png deleted file mode 100644 index 946d2db..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/web-bluetooth-new-permissions-backend/external/wpt/bluetooth/bidi/server/getPrimaryServices/blocklisted-services.https.window-expected.txt b/third_party/blink/web_tests/platform/win/virtual/web-bluetooth-new-permissions-backend/external/wpt/bluetooth/bidi/server/getPrimaryServices/blocklisted-services.https.window-expected.txt deleted file mode 100644 index 5b37deb..0000000 --- a/third_party/blink/web_tests/platform/win/virtual/web-bluetooth-new-permissions-backend/external/wpt/bluetooth/bidi/server/getPrimaryServices/blocklisted-services.https.window-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -All subtests passed and are omitted for brevity. -See https://chromium.googlesource.com/chromium/src/+/HEAD/docs/testing/writing_web_tests.md#Text-Test-Baselines for details. -Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/win10/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/win10/images/png-crbug423310049-expected.png deleted file mode 100644 index 88d42ac..0000000 --- a/third_party/blink/web_tests/platform/win10/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win10/virtual/exotic-color-space/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/win10/virtual/exotic-color-space/images/png-crbug423310049-expected.png deleted file mode 100644 index 81724b9..0000000 --- a/third_party/blink/web_tests/platform/win10/virtual/exotic-color-space/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/external/wpt/bluetooth/bidi/server/getPrimaryServices/blocklisted-services.https.window-expected.txt b/third_party/blink/web_tests/platform/win11-arm64/external/wpt/bluetooth/bidi/server/getPrimaryServices/blocklisted-services.https.window-expected.txt deleted file mode 100644 index 7c50eb03..0000000 --- a/third_party/blink/web_tests/platform/win11-arm64/external/wpt/bluetooth/bidi/server/getPrimaryServices/blocklisted-services.https.window-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -Harness Error. harness_status.status = 1 , harness_status.message = Traceback (most recent call last):\n File "C:\\b\\s\\w\\ir\\third_party\\wpt_tools\\wpt\\tools\\wptrunner\\wptrunner\\executors\\base.py", line 773, in process_action\n action_handler = self.actions[action]\n ~~~~~~~~~~~~^^^^^^^^\nKeyError: 'bidi.session.subscribe'\n\nThe above exception was the direct cause of the following exception:\n\nTraceback (most recent call last):\n File "C:\\b\\s\\w\\ir\\third_party\\wpt_tools\\wpt\\tools\\wptrunner\\wptrunner\\executors\\executorwebdriver.py", line 984, in run_func\n self.result = True, self.func(self.protocol, self.url, self.timeout)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "C:\\b\\s\\w\\ir\\third_party\\wpt_tools\\wpt\\tools\\wptrunner\\wptrunner\\executors\\executorwebdriver.py", line 1187, in do_testharness\n raw_results = self.run_testdriver(protocol, url, timeout)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "C:\\b\\s\\w\\ir\\third_party\\wpt_tools\\wpt\\tools\\wptrunner\\wptrunner\\executors\\executorwebdriver.py", line 1104, in run_testdriver\n done, rv = handler(test_driver_message)\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File "C:\\b\\s\\w\\ir\\third_party\\wpt_tools\\wpt\\tools\\wptrunner\\wptrunner\\executors\\base.py", line 761, in __call__\n return callback(url, payload)\n ^^^^^^^^^^^^^^^^^^^^^^\n File "C:\\b\\s\\w\\ir\\third_party\\wpt_tools\\wpt\\tools\\wptrunner\\wptrunner\\executors\\base.py", line 775, in process_action\n raise ValueError(f"Unknown action {action}") from e\nValueError: Unknown action bidi.session.subscribe\n -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/win11-arm64/images/png-crbug423310049-expected.png b/third_party/blink/web_tests/platform/win11-arm64/images/png-crbug423310049-expected.png deleted file mode 100644 index 8e53544..0000000 --- a/third_party/blink/web_tests/platform/win11-arm64/images/png-crbug423310049-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-auto-valid.tentative-expected.txt b/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-auto-valid.tentative-expected.txt deleted file mode 100644 index 9a44e0df..0000000 --- a/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-auto-valid.tentative-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This is a testharness.js-based test. -[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, auto)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, auto 100px auto)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, minmax(30px, 5fr) [two] auto)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, [three] auto [four])" should set the property value - assert_not_equals: property should be set got disallowed value "" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-intrinsic-valid.tentative-expected.txt b/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-intrinsic-valid.tentative-expected.txt new file mode 100644 index 0000000..faf78ea --- /dev/null +++ b/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-columns-repeat-intrinsic-valid.tentative-expected.txt
@@ -0,0 +1,35 @@ +This is a testharness.js-based test. +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, auto)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, auto 100px auto)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, minmax(30px, 5fr) [two] auto)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, [three] auto [four])" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, min-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, min-content 100px min-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, minmax(30px, 5fr) [two] min-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, [three] min-content [four])" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, max-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, max-content 100px max-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, minmax(30px, 5fr) [two] max-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, [three] max-content [four])" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, fit-content(200px))" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, fit-content(200px) 100px fit-content(200px))" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fill, minmax(30px, 5fr) [two] fit-content(200px))" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-columns'] = "repeat(auto-fit, [three] fit-content(200px) [four])" should set the property value + assert_not_equals: property should be set got disallowed value "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-auto-valid.tentative-expected.txt b/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-auto-valid.tentative-expected.txt deleted file mode 100644 index ea51b4b..0000000 --- a/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-auto-valid.tentative-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -This is a testharness.js-based test. -[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, auto)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, auto 100px auto)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, minmax(30px, 5fr) [two] auto)" should set the property value - assert_not_equals: property should be set got disallowed value "" -[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, [three] auto [four])" should set the property value - assert_not_equals: property should be set got disallowed value "" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-intrinsic-valid.tentative-expected.txt b/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-intrinsic-valid.tentative-expected.txt new file mode 100644 index 0000000..e9de5b5 --- /dev/null +++ b/third_party/blink/web_tests/virtual/disable-css-masonry-layout/external/wpt/css/css-grid/parsing/grid-template-rows-repeat-intrinsic-valid.tentative-expected.txt
@@ -0,0 +1,35 @@ +This is a testharness.js-based test. +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, auto)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, auto 100px auto)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, minmax(30px, 5fr) [two] auto)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, [three] auto [four])" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, min-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, min-content 100px min-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, minmax(30px, 5fr) [two] min-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, [three] min-content [four])" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, max-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, max-content 100px max-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, minmax(30px, 5fr) [two] max-content)" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, [three] max-content [four])" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, fit-content(200px))" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, fit-content(200px) 100px fit-content(200px))" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fill, minmax(30px, 5fr) [two] fit-content(200px))" should set the property value + assert_not_equals: property should be set got disallowed value "" +[FAIL] e.style['grid-template-rows'] = "repeat(auto-fit, [three] fit-content(200px) [four])" should set the property value + assert_not_equals: property should be set got disallowed value "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/file-system-access-write-mode/README.md b/third_party/blink/web_tests/virtual/file-system-access-write-mode/README.md new file mode 100644 index 0000000..1c1b18f --- /dev/null +++ b/third_party/blink/web_tests/virtual/file-system-access-write-mode/README.md
@@ -0,0 +1,3 @@ +# File System Access Write Mode + +This virtual test suite runs with `--enable-features=FileSystemAccessWriteMode`.
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 393e53da..a2f152e 100644 --- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1005,6 +1005,7 @@ method get method getAll method getAllKeys + method getAllRecords method getKey method openCursor method openKeyCursor @@ -1038,6 +1039,7 @@ method get method getAll method getAllKeys + method getAllRecords method getKey method index method openCursor @@ -1051,6 +1053,12 @@ method constructor setter onblocked setter onupgradeneeded +interface IDBRecord + attribute @@toStringTag + getter key + getter primaryKey + getter value + method constructor interface IDBRequest : EventTarget attribute @@toStringTag getter error
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 70d6a4d..5e0040d 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1056,6 +1056,7 @@ [Worker] method get [Worker] method getAll [Worker] method getAllKeys +[Worker] method getAllRecords [Worker] method getKey [Worker] method openCursor [Worker] method openKeyCursor @@ -1089,6 +1090,7 @@ [Worker] method get [Worker] method getAll [Worker] method getAllKeys +[Worker] method getAllRecords [Worker] method getKey [Worker] method index [Worker] method openCursor @@ -1102,6 +1104,12 @@ [Worker] method constructor [Worker] setter onblocked [Worker] setter onupgradeneeded +[Worker] interface IDBRecord +[Worker] attribute @@toStringTag +[Worker] getter key +[Worker] getter primaryKey +[Worker] getter value +[Worker] method constructor [Worker] interface IDBRequest : EventTarget [Worker] attribute @@toStringTag [Worker] getter error
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 426e61c..4fe12637 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -5004,6 +5004,7 @@ method get method getAll method getAllKeys + method getAllRecords method getKey method openCursor method openKeyCursor @@ -5037,6 +5038,7 @@ method get method getAll method getAllKeys + method getAllRecords method getKey method index method openCursor @@ -5050,6 +5052,12 @@ method constructor setter onblocked setter onupgradeneeded +interface IDBRecord + attribute @@toStringTag + getter key + getter primaryKey + getter value + method constructor interface IDBRequest : EventTarget attribute @@toStringTag getter error
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt index 83bc648..51c5ad4 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -951,6 +951,7 @@ [Worker] method get [Worker] method getAll [Worker] method getAllKeys +[Worker] method getAllRecords [Worker] method getKey [Worker] method openCursor [Worker] method openKeyCursor @@ -984,6 +985,7 @@ [Worker] method get [Worker] method getAll [Worker] method getAllKeys +[Worker] method getAllRecords [Worker] method getKey [Worker] method index [Worker] method openCursor @@ -997,6 +999,12 @@ [Worker] method constructor [Worker] setter onblocked [Worker] setter onupgradeneeded +[Worker] interface IDBRecord +[Worker] attribute @@toStringTag +[Worker] getter key +[Worker] getter primaryKey +[Worker] getter value +[Worker] method constructor [Worker] interface IDBRequest : EventTarget [Worker] attribute @@toStringTag [Worker] getter error
diff --git a/third_party/blink/web_tests/webaudio/AudioNode/tail-connections.html b/third_party/blink/web_tests/webaudio/AudioNode/tail-connections.html index 8042ad0..b6fe682c 100644 --- a/third_party/blink/web_tests/webaudio/AudioNode/tail-connections.html +++ b/third_party/blink/web_tests/webaudio/AudioNode/tail-connections.html
@@ -1,133 +1,116 @@ <!doctype html> <html> <head> - <title> - Test Reconnection of Tail-Processing Nodes - </title> + <title>Test Reconnection of Tail-Processing Nodes</title> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> - <script src="../resources/audit.js"></script> <script src="../resources/audit-util.js"></script> </head> - <body> <script> - let audit = Audit.createTaskRunner(); - - audit.define( - { - test: 'Test Compressor', - label: 'Reconnect graph to DynamicsCompressor before end of tail' - }, - (task, should) => { - // Arbitrary sample rate - const sampleRate = 16000; - - // These constants taken from dyanmics_compress_kernel.{cc,h}. - const preDelayFrames = 1024; - const meteringReleaseTime = 0.325; - const tailTime = 5 * meteringReleaseTime; - const latencyTime = preDelayFrames / sampleRate; - const tailProcessingTime = tailTime + latencyTime; - - // The DynamicsCompressorNode has a tail + latency time of a little - // over 1.68 sec, so make the duration longer than that. - const renderDuration = 3; - - let context = new OfflineAudioContext( - 1, renderDuration * sampleRate, sampleRate); - - - runTest(context, should, { - testNodeName: 'DynamicsCompressorNode', - nodeOptions: null, - suspendTime: 2, - tailProcessingTime: tailProcessingTime - }).then(() => task.done()); - }); - - audit.define( - { - test: 'Test Biquad', - label: 'Reconnect graph to Biquad before end of tail' - }, - (task, should) => { - let renderDuration = 1; - let sampleRate = 16384; - - let context = new OfflineAudioContext( - 1, renderDuration * sampleRate, sampleRate); - - // Taken from BiquadFilter/tail-time-lowpass.html - let filterOptions = { - type: 'lowpass', - Q: 40, - frequency: sampleRate / 4 - }; - let tailProcessingTime = 2079.4 / context.sampleRate; - - runTest(context, should, { - testNodeName: 'BiquadFilterNode', - nodeOptions: filterOptions, - suspendTime: .5, - tailProcessingTime: tailProcessingTime - }).then(() => task.done()); - - }); - // Run a test using the given test node that has a tail time. // |options| is a dictionary with the following members: - // testNodeName: name of the node (used as a constructor) - // nodeOptiosn: any options needed to create the node with the right - // properties. - // suspendTime: Time at which oscillator should start. - // tailProcessingTime: Length of the tail of the node, in sec. - function runTest(context, should, options) { + // testNodeName: name of the node (used as a constructor) + // nodeOptions: any options needed to create the node + // suspendTime: Time at which oscillator should start + // tailProcessingTime: Length of the tail of the node, in sec + async function runTest(context, options) { // This test basically taken from the repro case in crbug.com/829767 - let osc = new OscillatorNode(context); - let g0 = new GainNode(context); - let g1 = new GainNode(context); - let g2 = new GainNode(context); - let g3 = new GainNode(context); - let testNode = + const osc = new OscillatorNode(context); + const g0 = new GainNode(context); + const g1 = new GainNode(context); + const g2 = new GainNode(context); + const g3 = new GainNode(context); + const testNode = new window[options.testNodeName](context, options.nodeOptions); osc.connect(g0) - .connect(g1) - .connect(testNode) - .connect(g2) - .connect(g3) - .connect(context.destination); + .connect(g1) + .connect(testNode) + .connect(g2) + .connect(g3) + .connect(context.destination); // Disconnect the rest of the graph from g0. This should place the // test node on the internal tail processing list. g0.disconnect(); - // Now reconnect g0 to the graph.. This should re-enable the test node + // Now reconnect g0 to the graph. This should re-enable the test node // output and remove it from the tail list. g0.connect(g1); - // Start the source after the tail time of the test node. - context.suspend(options.suspendTime) - .then(() => { - // Sanity check that we start the oscillator after the tail - // processing time. - should(context.currentTime, 'Oscillator start time') - .beGreaterThanOrEqualTo(options.tailProcessingTime); - osc.start(); - }) - .then(() => context.resume()); - - return context.startRendering().then(renderedBuffer => { - // Just check that the output isn't silence. If things are working - // after reconnecting, there should be non-zero output. - should( - renderedBuffer.getChannelData(0), - `Output of ${options.testNodeName}`) - .notBeConstantValueOf(0); + // Schedule suspension at suspendTime + // Note: We avoid using `await` for suspend/resume because time in an + // OfflineAudioContext does not advance until `startRendering()` + // is called. Using `await` here would cause a deadlock, + // since the suspend time is never reached. + context.suspend(options.suspendTime).then(() => { + // Validate suspend time occurs after tail time + assert_greater_than_equal( + options.suspendTime, + options.tailProcessingTime, + 'Oscillator start time should be >= tail processing time'); + osc.start(); + context.resume(); }); + + const renderedBuffer = await context.startRendering(); + + // Just check that the output isn't silence. If things are working + // after reconnecting, there should be non-zero output. + const outputData = renderedBuffer.getChannelData(0); + const isSilent = outputData.every(sample => sample === 0); + + assert_false( + isSilent, + `Output of ${options.testNodeName} should not be all zeros`); } - audit.run(); + promise_test(async t => { + const sampleRate = 16000; + // These constants taken from dynamics_compress_kernel.{cc,h}. + const preDelayFrames = 1024; + const meteringReleaseTime = 0.325; + const tailTime = 5 * meteringReleaseTime; + const latencyTime = preDelayFrames / sampleRate; + const tailProcessingTime = tailTime + latencyTime; + + // The DynamicsCompressorNode has a tail + latency time of ~1.68 s. + // Use 3 s render duration to exceed it. + const renderDuration = 3; + + const context = new OfflineAudioContext( + 1, renderDuration * sampleRate, sampleRate); + + await runTest(context, { + testNodeName: 'DynamicsCompressorNode', + nodeOptions: null, + suspendTime: 2, + tailProcessingTime: tailProcessingTime + }); + }, 'Reconnect graph to DynamicsCompressor before end of tail'); + + promise_test(async t => { + const sampleRate = 16384; + const renderDuration = 1; + + const context = new OfflineAudioContext( + 1, renderDuration * sampleRate, sampleRate); + + // Taken from BiquadFilter/tail-time-lowpass.html + const filterOptions = { + type: 'lowpass', + Q: 40, + frequency: sampleRate / 4 + }; + const tailProcessingTime = 2079.4 / sampleRate; + + await runTest(context, { + testNodeName: 'BiquadFilterNode', + nodeOptions: filterOptions, + suspendTime: 0.5, + tailProcessingTime: tailProcessingTime + }); + }, 'Reconnect graph to Biquad before end of tail'); </script> </body> </html>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index cef22e6..06c4a45 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -7239,15 +7239,15 @@ getter name getter password method constructor -interface PatchEvent : Event - attribute @@toStringTag - getter patch - method constructor -interface PatchStatus +interface Patch attribute @@toStringTag getter finished getter source method constructor +interface PatchEvent : Event + attribute @@toStringTag + getter patch + method constructor interface Path2D attribute @@toStringTag method addPath
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/editing-markers-ignored-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/editing-markers-ignored-ref.html new file mode 100644 index 0000000..2250382 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/editing-markers-ignored-ref.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw editing markers - ref</title> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true">Composition with an active-suggestion and a suggestion.</div> + </div> +</canvas> +<script> + function runTest() { + canvas.getContext("2d").drawElement(child, 0, 0); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/editing-markers-ignored.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/editing-markers-ignored.html new file mode 100644 index 0000000..a5acd95 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/editing-markers-ignored.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw editing markers</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="editing-markers-ignored-ref.html"> +<meta name="assert" value="When preserving privacy for readback, do not draw markers for editing."> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true">Composition with an active-suggestion and a suggestion.</div> + </div> +</canvas> +<script> + function runTest() { + if (typeof internals !== 'undefined') { + // To run this test from content_shell you can use + // "--expose-internals-for-testing" command flag. + const composition_range = createRangeForTextOnly(editable, 0, 12); + internals.addCompositionMarker(composition_range, "blue", "thin", "solid", + "lightblue", "darkblue"); + + const active_suggestion_range = createRangeForTextOnly(editable, 20, 37); + internals.addActiveSuggestionMarker(active_suggestion_range, "green", + "thin", "darkgreen"); + + const suggestion_range = createRangeForTextOnly(editable, 44, 54); + internals.addSuggestionMarker(suggestion_range, ["suggestion"], "red", + "pink", "thin", "darkred"); + } + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/glic-markers-ignored-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/glic-markers-ignored-ref.html new file mode 100644 index 0000000..92b6509d --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/glic-markers-ignored-ref.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw GLIC markers - ref</title> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true">Text added by GLIC.</div> + </div> +</canvas> +<script> + function runTest() { + canvas.getContext("2d").drawElement(child, 0, 0); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/glic-markers-ignored.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/glic-markers-ignored.html new file mode 100644 index 0000000..4eee5dd1 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/glic-markers-ignored.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw GLIC markers</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="glic-markers-ignored-ref.html"> +<meta name="assert" value="When preserving privacy for readback, do not draw markers for GLIC."> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true">Text added by GLIC.</div> + </div> +</canvas> +<script> + function runTest() { + if (typeof internals !== 'undefined') { + // To run this test from content_shell you can use + // "--expose-internals-for-testing" command flag. + const range = createRangeForTextOnly(editable, 0, 18); + internals.setMarker(document, range, "glic"); + } + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/grammar-ignored-overlay-path-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/grammar-ignored-overlay-path-ref.html new file mode 100644 index 0000000..cc553f6 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/grammar-ignored-overlay-path-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw grammar with custom highlights - ref</title> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true" spellcheck="true" lang="en">Many thing can happen.</div> + </div> +</canvas> +<script> + function runTest() { + let r = new Range(); + r.setStart(document.body, 0); + r.setEnd(document.body, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/grammar-ignored-overlay-path.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/grammar-ignored-overlay-path.html new file mode 100644 index 0000000..410e6336 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/grammar-ignored-overlay-path.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw grammar with custom highlights</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="grammar-ignored-overlay-path-ref.html"> +<meta name="assert" value="When preserving privacy for readback, do not draw grammar markers when using the highlight overlay painting path (triggered by the custom highlight)."> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } + ::grammar-error { + background-color: lime; + color: green; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true">Many thing can happen.</div> + </div> +</canvas> +<script> + function runTest() { + addGrammarMarker(editable, 5, 10) + + let r = new Range(); + r.setStart(document.body, 0); + r.setEnd(document.body, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/search-text-ignored-overlay-path-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/search-text-ignored-overlay-path-ref.html new file mode 100644 index 0000000..14d9f6b9 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/search-text-ignored-overlay-path-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw search-text with custom highlights - ref</title> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true" spellcheck="true" lang="en">Many things can happen.</div> + </div> +</canvas> +<script> + function runTest() { + let r = new Range(); + r.setStart(document.body, 0); + r.setEnd(document.body, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/search-text-ignored-overlay-path.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/search-text-ignored-overlay-path.html new file mode 100644 index 0000000..60c9cdd --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/search-text-ignored-overlay-path.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw serach-text with custom highlights</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="search-text-ignored-overlay-path-ref.html"> +<meta name="assert" value="When preserving privacy for readback, do not draw search-text markers when using the highlight overlay painting path (triggered by the custom highlight)."> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } + ::search-text { + background-color: lime; + color: green; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true">Many things can happen.</div> + </div> +</canvas> +<script> + function runTest() { + addSearchTextMarker(editable, 5, 11) + + let r = new Range(); + r.setStart(document.body, 0); + r.setEnd(document.body, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-alone-with-decorations-painted-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-alone-with-decorations-painted-ref.html new file mode 100644 index 0000000..6b4c00b --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-alone-with-decorations-painted-ref.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback draws selection - ref</title> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + :focus { + outline: none; + } + #child { + width: 100px; + height: 100px; + background: green; + position: absolute; + left: 8px; + top: 8px; + } + #canvas { + background: grey; + } + ::selection { + background-color: lime; + color: green; + text-decoration: 2px red underline; + text-shadow: pink 2px 5px; + } +</style> +<canvas id=canvas width="200" height="200"></canvas> +<div id="child"> + <div id="editable" contenteditable="true">Many things can happen.</div> +</div> +<script> + function runTest() { + setSelection(editable, 5, 11) + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-alone-with-decorations-painted.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-alone-with-decorations-painted.html new file mode 100644 index 0000000..cc37c6b2 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-alone-with-decorations-painted.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback draws selection</title> +<link rel="help" href="https://drafts.csswg.org/css-highlight-api-1/"> +<link rel="match" href="selection-alone-with-decorations-painted-ref.html"> +<meta name="assert" value="When preserving privacy for readback, draw selection when it has decorations and shadows."> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + :focus { + outline: none; + } + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::selection { + background-color: lime; + color: green; + text-decoration: 2px red underline; + text-shadow: pink 2px 5px; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true">Many things can happen.</div> + </div> +</canvas> +<script> + function runTest() { + setSelection(editable, 5, 11) + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-painted-overlay-path-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-painted-overlay-path-ref.html new file mode 100644 index 0000000..2496419 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-painted-overlay-path-ref.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback draws selection with custom highlights - ref</title> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + #child { + width: 100px; + height: 100px; + background: green; + position: absolute; + left: 8px; + top: 8px; + } + :focus { + outline: none; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } + ::selection { + background-color: lime; + color: green; + text-decoration: 2px red underline; + text-shadow: pink 2px 5px; + } +</style> +<canvas id=canvas width="200" height="200"></canvas> +<div id="child"> + <div id="editable" contenteditable="true">Many things can happen.</div> +</div> +<script> + function runTest() { + setSelection(editable, 5, 11) + + let r = new Range(); + r.setStart(editable, 0); + r.setEnd(editable, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-painted-overlay-path.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-painted-overlay-path.html new file mode 100644 index 0000000..a7e07b1 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/selection-painted-overlay-path.html
@@ -0,0 +1,50 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback draws selection with custom highlights</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="selection-painted-overlay-path-ref.html"> +<meta name="assert" value="When preserving privacy for readback, do draw selection when using the highlight overlay painting path (triggered by the custom highlight)."> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + :focus { + outline: none; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } + ::selection { + background-color: lime; + color: green; + text-decoration: 2px red underline; + text-shadow: pink 2px 5px; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true">Many things can happen.</div> + </div> +</canvas> +<script> + function runTest() { + setSelection(editable, 5, 11) + + let r = new Range(); + r.setStart(editable, 0); + r.setEnd(editable, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-fast-path-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-fast-path-ref.html new file mode 100644 index 0000000..f9b396bc --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-fast-path-ref.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw spelling - ref</title> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true" spellcheck="true" lang="en">Many theng can happen.</div> + </div> +</canvas> +<script> + function runTest() { + canvas.getContext("2d").drawElement(child, 0, 0); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-fast-path.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-fast-path.html new file mode 100644 index 0000000..c89cbeff --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-fast-path.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw spelling</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="spelling-ignored-fast-path-ref.html"> +<meta name="assert" value="When preserving privacy for readback, do not draw spelling markers when using the fast path."> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true" spellcheck="true" lang="en">Many theng can happen.</div> + </div> +</canvas> +<script> + function runTest() { + addSpellingMarker(editable, 5, 10) + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-overlay-path-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-overlay-path-ref.html new file mode 100644 index 0000000..72c05a0 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-overlay-path-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw spelling with custom highlights - ref</title> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true" spellcheck="true" lang="en">Many theng can happen.</div> + </div> +</canvas> +<script> + function runTest() { + let r = new Range(); + r.setStart(document.body, 0); + r.setEnd(document.body, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-overlay-path.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-overlay-path.html new file mode 100644 index 0000000..067f6292 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/spelling-ignored-overlay-path.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw spelling with custom highlights</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="spelling-ignored-overlay-path-ref.html"> +<meta name="assert" value="When preserving privacy for readback, do not draw spelling markers when using the highlight overlay painting path (triggered by the custom highlight)."> +<script src="/wpt_internal/css/support/markers.js"></script> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } + ::spelling-error { + background-color: lime; + color: green; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div id="editable" contenteditable="true" spellcheck="true" lang="en">Many theng can happen.</div> + </div> +</canvas> +<script> + function runTest() { + addSpellingMarker(editable, 5, 10) + + let r = new Range(); + r.setStart(document.body, 0); + r.setEnd(document.body, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/target-text-ignored-overlay-path-ref.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/target-text-ignored-overlay-path-ref.html new file mode 100644 index 0000000..cbdeaba9ab --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/target-text-ignored-overlay-path-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw target-text with custom highlights - ref</title> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div>Match with more</div> + </div> +</canvas> +<script> + function runTest() { + let r = new Range(); + r.setStart(document.body, 0); + r.setEnd(document.body, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/target-text-ignored-overlay-path.html b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/target-text-ignored-overlay-path.html new file mode 100644 index 0000000..31c02a2 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/html/canvas/drawElement/allow-readback/target-text-ignored-overlay-path.html
@@ -0,0 +1,44 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>drawElement with allowReadback does not draw target-text with custom highlights</title> +<link rel="help" href="https://github.com/WICG/html-in-canvas"> +<link rel="author" href="mailto:schenney@chromium.org"> +<link rel="match" href="target-text-ignored-overlay-path-ref.html"> +<meta name="assert" value="When preserving privacy for readback, do not draw target text markers when using the highlight overlay painting path (triggered by the custom highlight)."> +<style> + #child { + width: 100px; + height: 100px; + background: green; + } + #canvas { + background: grey; + } + ::highlight(example-highlight) { + background-color: yellow; + color: blue; + } + ::target-text { + color: lime; + background-color: green; + } +</style> +<canvas id=canvas width="200" height="200" layoutsubtree> + <div id="child"> + <div>Match with more</div> + </div> +</canvas> +<script> + function runTest() { + window.location.hash = "#:~:text=Match"; + + let r = new Range(); + r.setStart(document.body, 0); + r.setEnd(document.body, 1); + CSS.highlights.set("example-highlight", new Highlight(r)); + + canvas.getContext("2d").drawElement(child, 0, 0, { allowReadback: true }); + } + + onload = () => runTest(); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/isolated-permissions-policy-stable/permissions_policy.https.html b/third_party/blink/web_tests/wpt_internal/isolated-permissions-policy-stable/permissions_policy.https.html index 6e0d432..1beecde 100644 --- a/third_party/blink/web_tests/wpt_internal/isolated-permissions-policy-stable/permissions_policy.https.html +++ b/third_party/blink/web_tests/wpt_internal/isolated-permissions-policy-stable/permissions_policy.https.html
@@ -89,6 +89,7 @@ ] const isolated_policies = [ + 'controlled-frame', 'direct-sockets', 'direct-sockets-private', 'usb-unrestricted',
diff --git a/third_party/boringssl/src b/third_party/boringssl/src index d55aba9..6cd35e8 160000 --- a/third_party/boringssl/src +++ b/third_party/boringssl/src
@@ -1 +1 @@ -Subproject commit d55aba9db303cf2b445b29645c941671bc7ffdf8 +Subproject commit 6cd35e8ba6aa0b8bb3eaff35a7aa6b6385e34fa0
diff --git a/third_party/compiler-rt/src b/third_party/compiler-rt/src index afc28bd..693bb2c 160000 --- a/third_party/compiler-rt/src +++ b/third_party/compiler-rt/src
@@ -1 +1 @@ -Subproject commit afc28bd7ad797280bd1b31f532745c1a33862738 +Subproject commit 693bb2c75d48037e5ce35c61d3cbde3cf59622b6
diff --git a/third_party/dawn b/third_party/dawn index 86578e2..fb93247 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit 86578e2fc035b73a2853b6a0639b1ef347ee9bad +Subproject commit fb93247bf550691da20ff349400839499c744a01
diff --git a/third_party/depot_tools b/third_party/depot_tools index b66d188..55b7745 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit b66d188607bca258f277b7a4410c7302c48b8193 +Subproject commit 55b7745daa200ac8f8956da2478841335168d874
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 50d1618..11d8228 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 50d161857a463c22b6631b3a134a52833e626187 +Subproject commit 11d82284b93d46bc94adcd42d8adbabe8f7569bf
diff --git a/third_party/federated_compute/BUILD.gn b/third_party/federated_compute/BUILD.gn new file mode 100644 index 0000000..545fe36 --- /dev/null +++ b/third_party/federated_compute/BUILD.gn
@@ -0,0 +1,35 @@ +# 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. + +config("confidential_compute_include") { + include_dirs = [ "src" ] +} + +source_set("confidential_compute") { + public = [ + "src/fcp/base/base_name.h", + "src/fcp/base/digest.h", + "src/fcp/base/monitoring.h", + "src/fcp/confidentialcompute/cose.h", + "src/fcp/confidentialcompute/crypto.h", + ] + + sources = [ + "src/fcp/base/base_name.cc", + "src/fcp/base/digest.cc", + "src/fcp/base/monitoring.cc", + "src/fcp/confidentialcompute/cose.cc", + "src/fcp/confidentialcompute/crypto.cc", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + + public_configs = [ ":confidential_compute_include" ] + + deps = [ + "//third_party/abseil-cpp:absl", + "//third_party/boringssl", + ] +}
diff --git a/third_party/federated_compute/OWNERS b/third_party/federated_compute/OWNERS new file mode 100644 index 0000000..f6c81f50 --- /dev/null +++ b/third_party/federated_compute/OWNERS
@@ -0,0 +1,2 @@ +zhouzj@google.com +dembski@google.com
diff --git a/third_party/federated_compute/README.chromium b/third_party/federated_compute/README.chromium new file mode 100644 index 0000000..47e72237 --- /dev/null +++ b/third_party/federated_compute/README.chromium
@@ -0,0 +1,16 @@ +Name: federated-compute +URL: https://github.com/google-parfait/federated-compute/ +Version: N/A +Date: 2025-07-30 +Revision: d9608bf1a16ee03a5451e15c8f3e262617472a38 +Update Mechanism: Manual +License: Apache-2.0 +License File: src/LICENSE +Shipped: yes +Security Critical: yes + +Description: +Libraries for executing federated programs and computations. + +Local Modifications: +None
diff --git a/third_party/federated_compute/src b/third_party/federated_compute/src new file mode 160000 index 0000000..d9608bf --- /dev/null +++ b/third_party/federated_compute/src
@@ -0,0 +1 @@ +Subproject commit d9608bf1a16ee03a5451e15c8f3e262617472a38
diff --git a/third_party/ipcz/src/BUILD.gn b/third_party/ipcz/src/BUILD.gn index 6efce3bd..6168346 100644 --- a/third_party/ipcz/src/BUILD.gn +++ b/third_party/ipcz/src/BUILD.gn
@@ -198,6 +198,7 @@ "util/stack_trace.h", "util/strong_alias.h", "util/unique_ptr_comparator.h", + "util/unsafe_buffers.h", ] sources = [ "util/ref_counted.cc" ]
diff --git a/third_party/ipcz/src/api.cc b/third_party/ipcz/src/api.cc index 3fb6146..a77db08 100644 --- a/third_party/ipcz/src/api.cc +++ b/third_party/ipcz/src/api.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include <cstddef> #include <cstring> #include <memory> @@ -24,6 +19,7 @@ #include "ipcz/parcel_wrapper.h" #include "ipcz/router.h" #include "util/ref_counted.h" +#include "util/unsafe_buffers.h" extern "C" { @@ -397,7 +393,7 @@ return IPCZ_RESULT_INVALID_ARGUMENT; } - memcpy(api, &kCurrentAPI, kVersion0APISize); + IPCZ_UNSAFE_TODO(memcpy(api, &kCurrentAPI, kVersion0APISize)); return IPCZ_RESULT_OK; }
diff --git a/third_party/ipcz/src/api_test.cc b/third_party/ipcz/src/api_test.cc index 60c54c7..5d66ab3 100644 --- a/third_party/ipcz/src/api_test.cc +++ b/third_party/ipcz/src/api_test.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include <cstring> #include <string> @@ -15,6 +10,7 @@ #include "reference_drivers/sync_reference_driver.h" #include "test/test.h" #include "testing/gtest/include/gtest/gtest.h" +#include "util/unsafe_buffers.h" namespace ipcz { namespace { @@ -450,7 +446,8 @@ EXPECT_EQ(IPCZ_RESULT_OK, ipcz().BeginPut(a, IPCZ_NO_FLAGS, nullptr, &out_data, &num_bytes, &put)); EXPECT_EQ(kMessage.size(), num_bytes); - memcpy(const_cast<void*>(out_data), kMessage.data(), kMessage.size()); + IPCZ_UNSAFE_TODO( + memcpy(const_cast<void*>(out_data), kMessage.data(), kMessage.size())); EXPECT_EQ(IPCZ_RESULT_OK, ipcz().EndPut(a, put, num_bytes, nullptr, 0, IPCZ_NO_FLAGS, nullptr)); @@ -500,7 +497,8 @@ ipcz().BeginPut(a, IPCZ_NO_FLAGS, nullptr, &out_data1, &num_bytes1, &transaction1)); EXPECT_EQ(kMessage1.size(), num_bytes1); - memcpy(const_cast<void*>(out_data1), kMessage1.data(), kMessage1.size()); + IPCZ_UNSAFE_TODO( + memcpy(const_cast<void*>(out_data1), kMessage1.data(), kMessage1.size())); size_t num_bytes2 = kMessage2.size(); volatile void* out_data2; @@ -509,7 +507,8 @@ ipcz().BeginPut(a, IPCZ_NO_FLAGS, nullptr, &out_data2, &num_bytes2, &transaction2)); EXPECT_EQ(kMessage2.size(), num_bytes2); - memcpy(const_cast<void*>(out_data2), kMessage2.data(), kMessage2.size()); + IPCZ_UNSAFE_TODO( + memcpy(const_cast<void*>(out_data2), kMessage2.data(), kMessage2.size())); size_t num_bytes3 = kMessage3.size(); volatile void* out_data3; @@ -518,7 +517,8 @@ ipcz().BeginPut(a, IPCZ_NO_FLAGS, nullptr, &out_data3, &num_bytes3, &transaction3)); EXPECT_EQ(kMessage3.size(), num_bytes3); - memcpy(const_cast<void*>(out_data3), kMessage3.data(), kMessage3.size()); + IPCZ_UNSAFE_TODO( + memcpy(const_cast<void*>(out_data3), kMessage3.data(), kMessage3.size())); // Complete them out-of-order. They should arrive in the order in which they // were completed rather than the order in which they were started.
diff --git a/third_party/ipcz/src/box_test.cc b/third_party/ipcz/src/box_test.cc index 46131a4..27f080d 100644 --- a/third_party/ipcz/src/box_test.cc +++ b/third_party/ipcz/src/box_test.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <cstring> #include <memory> #include <string_view> @@ -17,6 +12,7 @@ #include "third_party/abseil-cpp/absl/base/macros.h" #include "third_party/abseil-cpp/absl/types/span.h" #include "util/ref_counted.h" +#include "util/unsafe_buffers.h" namespace ipcz { namespace { @@ -223,8 +219,8 @@ auto* header = static_cast<volatile Header*>(data); header->name_length = static_cast<size_t>(portal.name_.size()); - memcpy(const_cast<Header*>(header + 1), portal.name_.data(), - portal.name_.size()); + IPCZ_UNSAFE_TODO(memcpy(const_cast<Header*>(header + 1), + portal.name_.data(), portal.name_.size())); handles[0] = std::exchange(portal.portal_, IPCZ_INVALID_HANDLE); return IPCZ_RESULT_OK; }
diff --git a/third_party/ipcz/src/fuzzer/fuzzer.cc b/third_party/ipcz/src/fuzzer/fuzzer.cc index e2f65ad..4b7bf55 100644 --- a/third_party/ipcz/src/fuzzer/fuzzer.cc +++ b/third_party/ipcz/src/fuzzer/fuzzer.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "fuzzer/fuzzer.h" - #include <algorithm> #include <array> #include <cstddef> @@ -18,10 +11,12 @@ #include <vector> #include "fuzzer/driver.h" +#include "fuzzer/fuzzer.h" #include "ipcz/ipcz.h" #include "third_party/abseil-cpp/absl/base/macros.h" #include "third_party/abseil-cpp/absl/types/span.h" #include "util/ref_counted.h" +#include "util/unsafe_buffers.h" namespace ipcz::fuzzer { @@ -466,8 +461,8 @@ const auto bytes = memory->bytes(); const size_t offset = (4ul * config_.target_offset) % bytes.size(); const size_t size = std::min(bytes.size() - offset, fuzz_data_.size()); - std::copy(fuzz_data_.begin(), fuzz_data_.begin() + size, - bytes.begin() + offset); + std::copy(fuzz_data_.begin(), IPCZ_UNSAFE_TODO(fuzz_data_.begin() + size), + IPCZ_UNSAFE_TODO(bytes.begin() + offset)); } }
diff --git a/third_party/ipcz/src/ipcz/block_allocator.cc b/third_party/ipcz/src/ipcz/block_allocator.cc index f66526d..19647ef 100644 --- a/third_party/ipcz/src/ipcz/block_allocator.cc +++ b/third_party/ipcz/src/ipcz/block_allocator.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "ipcz/block_allocator.h" - #include <array> #include <atomic> #include <cstddef> @@ -17,9 +10,11 @@ #include <limits> #include <thread> +#include "ipcz/block_allocator.h" #include "ipcz/ipcz.h" #include "third_party/abseil-cpp/absl/base/macros.h" #include "util/safe_math.h" +#include "util/unsafe_buffers.h" namespace ipcz { @@ -86,7 +81,7 @@ // By zeroing the entire region, every block effectively points to its // immediate successor as the next free block. See comments on the `next` // field if BlockHeader. - memset(region_.data(), 0, region_.size()); + IPCZ_UNSAFE_TODO(memset(region_.data(), 0, region_.size())); // Ensure that the last block points back to the unallocable first block, // indicating the end of the free-list.
diff --git a/third_party/ipcz/src/ipcz/block_allocator_test.cc b/third_party/ipcz/src/ipcz/block_allocator_test.cc index 9b85c126..1cbe976 100644 --- a/third_party/ipcz/src/ipcz/block_allocator_test.cc +++ b/third_party/ipcz/src/ipcz/block_allocator_test.cc
@@ -2,21 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "ipcz/block_allocator.h" - #include <atomic> #include <cstring> #include <set> #include <thread> #include <vector> +#include "ipcz/block_allocator.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/span.h" +#include "util/unsafe_buffers.h" namespace ipcz { namespace { @@ -43,7 +38,7 @@ for (size_t i = 0; i < allocator().capacity(); ++i) { void* block = allocator().Allocate(); ASSERT_TRUE(block); - memset(block, 0xaa, kBlockSize); + IPCZ_UNSAFE_TODO(memset(block, 0xaa, kBlockSize)); auto [it, inserted] = blocks.insert(block); EXPECT_TRUE(inserted); } @@ -55,9 +50,9 @@ // bytes, as all blocks were allocated and filled completely. constexpr size_t kNumAllocatedBytes = kPageSize - kBlockSize; char expected_data[kNumAllocatedBytes]; - memset(expected_data, 0xaa, kNumAllocatedBytes); - EXPECT_EQ(0, memcmp(allocator().region().data() + kBlockSize, expected_data, - kNumAllocatedBytes)); + IPCZ_UNSAFE_TODO(memset(expected_data, 0xaa, kNumAllocatedBytes)); + IPCZ_UNSAFE_TODO(EXPECT_EQ(0, memcmp(allocator().region().data() + kBlockSize, + expected_data, kNumAllocatedBytes))); for (void* block : blocks) { EXPECT_TRUE(allocator().Free(block)); @@ -117,12 +112,12 @@ for (size_t j = 0; j < kNumAllocationsPerIteration; ++j) { if (auto* p = static_cast<std::atomic<uint32_t>*>(allocator().Allocate())) { - allocations[num_allocations++] = p; + IPCZ_UNSAFE_TODO(allocations[num_allocations++]) = p; p->store(id, std::memory_order_relaxed); } } for (size_t j = 0; j < num_allocations; ++j) { - std::atomic<uint32_t>* p = allocations[j]; + std::atomic<uint32_t>* p = IPCZ_UNSAFE_TODO(allocations[j]); EXPECT_EQ(id, p->load(std::memory_order_relaxed)); EXPECT_TRUE(allocator().Free(p)); }
diff --git a/third_party/ipcz/src/ipcz/fragment_test.cc b/third_party/ipcz/src/ipcz/fragment_test.cc index a1d730c..a8335a4 100644 --- a/third_party/ipcz/src/ipcz/fragment_test.cc +++ b/third_party/ipcz/src/ipcz/fragment_test.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "ipcz/fragment.h" - #include <algorithm> #include <cstring> #include <limits> @@ -18,8 +11,10 @@ #include "ipcz/buffer_id.h" #include "ipcz/driver_memory.h" #include "ipcz/driver_memory_mapping.h" +#include "ipcz/fragment.h" #include "reference_drivers/sync_reference_driver.h" #include "testing/gtest/include/gtest/gtest.h" +#include "util/unsafe_buffers.h" namespace ipcz { namespace { @@ -31,14 +26,16 @@ TEST_F(FragmentTest, FromDescriptorUnsafe) { char kBuffer[] = "Hello, world!"; - Fragment f = Fragment::FromDescriptorUnsafe({BufferId{0}, 1, 4}, kBuffer + 1); + Fragment f = Fragment::FromDescriptorUnsafe({BufferId{0}, 1, 4}, + IPCZ_UNSAFE_TODO(kBuffer + 1)); EXPECT_FALSE(f.is_null()); EXPECT_FALSE(f.is_pending()); EXPECT_EQ(1u, f.offset()); EXPECT_EQ(4u, f.size()); EXPECT_EQ("ello", std::string(f.bytes().begin(), f.bytes().end())); - f = Fragment::FromDescriptorUnsafe({BufferId{0}, 7, 6}, kBuffer + 7); + f = Fragment::FromDescriptorUnsafe({BufferId{0}, 7, 6}, + IPCZ_UNSAFE_TODO(kBuffer + 7)); EXPECT_FALSE(f.is_null()); EXPECT_FALSE(f.is_pending()); EXPECT_EQ(7u, f.offset()); @@ -93,7 +90,7 @@ const char kData[] = "0123456789abcdef"; DriverMemory memory(kTestDriver, std::size(kData)); auto mapping = memory.Map(); - memcpy(mapping.bytes().data(), kData, std::size(kData)); + IPCZ_UNSAFE_TODO(memcpy(mapping.bytes().data(), kData, std::size(kData))); Fragment f = Fragment::MappedFromDescriptor({BufferId{0}, 2, 11}, mapping); EXPECT_FALSE(f.is_null());
diff --git a/third_party/ipcz/src/ipcz/message.cc b/third_party/ipcz/src/ipcz/message.cc index 5142626..436473c8 100644 --- a/third_party/ipcz/src/ipcz/message.cc +++ b/third_party/ipcz/src/ipcz/message.cc
@@ -2,12 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "ipcz/message.h" #include <cstddef> #include <cstdint> #include <cstdlib> @@ -17,11 +11,13 @@ #include "ipcz/driver_object.h" #include "ipcz/driver_transport.h" #include "ipcz/ipcz.h" +#include "ipcz/message.h" #include "third_party/abseil-cpp/absl/base/macros.h" #include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #include "third_party/abseil-cpp/absl/container/inlined_vector.h" #include "third_party/abseil-cpp/absl/types/span.h" #include "util/safe_math.h" +#include "util/unsafe_buffers.h" namespace ipcz { @@ -353,7 +349,7 @@ // Copy the data into a local message object to avoid any TOCTOU issues in // case `data` is in unsafe shared memory. received_data_.emplace(data.size()); - memcpy(received_data_->data(), data.data(), data.size()); + IPCZ_UNSAFE_TODO(memcpy(received_data_->data(), data.data(), data.size())); data_ = received_data_->bytes(); // The message must at least be large enough to encode a v0 MessageHeader.
diff --git a/third_party/ipcz/src/ipcz/message_test.cc b/third_party/ipcz/src/ipcz/message_test.cc index e430e002..d2153099 100644 --- a/third_party/ipcz/src/ipcz/message_test.cc +++ b/third_party/ipcz/src/ipcz/message_test.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "ipcz/message.h" - #include <cstdint> #include <queue> #include <utility> @@ -17,6 +10,7 @@ #include "ipcz/driver_object.h" #include "ipcz/driver_transport.h" #include "ipcz/ipcz.h" +#include "ipcz/message.h" #include "ipcz/message_test_types.h" #include "ipcz/node.h" #include "ipcz/test_messages.h" @@ -24,6 +18,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "util/ref_counted.h" +#include "util/unsafe_buffers.h" namespace ipcz { namespace { @@ -52,7 +47,8 @@ size_t num_handles, uint32_t, const void*) { const uint8_t* bytes = static_cast<const uint8_t*>(data); received_messages_.push( - {{bytes, bytes + num_bytes}, {handles, handles + num_handles}}); + {{bytes, IPCZ_UNSAFE_TODO(bytes + num_bytes)}, + {handles, IPCZ_UNSAFE_TODO(handles + num_handles)}}); return IPCZ_RESULT_OK; }); @@ -227,7 +223,8 @@ 0x42425555}; DriverObject in_objects[std::size(kObjectHandles)]; for (size_t i = 0; i < std::size(kObjectHandles); ++i) { - in_objects[i] = DriverObject(test::kMockDriver, kObjectHandles[i]); + IPCZ_UNSAFE_TODO(in_objects[i]) = + DriverObject(test::kMockDriver, IPCZ_UNSAFE_TODO(kObjectHandles[i])); } test::msg::MessageWithDriverObjectArray in; @@ -242,7 +239,7 @@ auto objects = out.GetDriverObjectArrayView(out.v0()->objects); EXPECT_EQ(3u, objects.size()); for (size_t i = 0; i < objects.size(); ++i) { - EXPECT_EQ(kObjectHandles[i], objects[i].release()); + IPCZ_UNSAFE_TODO(EXPECT_EQ(kObjectHandles[i], objects[i].release())); } } @@ -331,7 +328,8 @@ 0x42425555}; DriverObject in_objects[std::size(kObjectHandles)]; for (size_t i = 0; i < std::size(kObjectHandles); ++i) { - in_objects[i] = DriverObject(test::kMockDriver, kObjectHandles[i]); + IPCZ_UNSAFE_TODO(in_objects[i]) = + DriverObject(test::kMockDriver, IPCZ_UNSAFE_TODO(kObjectHandles[i])); } test::msg::MessageWithDriverArrayAndExtraObject in;
diff --git a/third_party/ipcz/src/ipcz/node.cc b/third_party/ipcz/src/ipcz/node.cc index 726de99..2e04a2e 100644 --- a/third_party/ipcz/src/ipcz/node.cc +++ b/third_party/ipcz/src/ipcz/node.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "ipcz/node.h" - #include <optional> #include <utility> #include <vector> @@ -17,6 +10,7 @@ #include "ipcz/features.h" #include "ipcz/ipcz.h" #include "ipcz/link_side.h" +#include "ipcz/node.h" #include "ipcz/node_connector.h" #include "ipcz/node_link.h" #include "ipcz/node_link_memory.h" @@ -28,6 +22,7 @@ #include "third_party/abseil-cpp/absl/types/span.h" #include "util/log.h" #include "util/ref_counted.h" +#include "util/unsafe_buffers.h" namespace ipcz { @@ -41,8 +36,8 @@ const IpczCreateNodeOptions* options) { IpczCreateNodeOptions copied_options = {0}; if (options) { - memcpy(&copied_options, options, - std::min(options->size, sizeof(copied_options))); + IPCZ_UNSAFE_TODO(memcpy(&copied_options, options, + std::min(options->size, sizeof(copied_options)))); } copied_options.size = sizeof(copied_options); return copied_options; @@ -465,7 +460,8 @@ accept.v0()->source = from_node; accept.v0()->data = accept.AllocateArray<uint8_t>(data.size()); accept.v0()->padding = 0; - memcpy(accept.GetArrayData(accept.v0()->data), data.data(), data.size()); + IPCZ_UNSAFE_TODO( + memcpy(accept.GetArrayData(accept.v0()->data), data.data(), data.size())); accept.v0()->driver_objects = accept.AppendDriverObjects(relay.driver_objects()); link->Transmit(accept);
diff --git a/third_party/ipcz/src/ipcz/node_link.cc b/third_party/ipcz/src/ipcz/node_link.cc index 5f245d9..96887a1 100644 --- a/third_party/ipcz/src/ipcz/node_link.cc +++ b/third_party/ipcz/src/ipcz/node_link.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "ipcz/node_link.h" - #include <algorithm> #include <atomic> #include <cstddef> @@ -26,6 +19,7 @@ #include "ipcz/message.h" #include "ipcz/node.h" #include "ipcz/node_connector.h" +#include "ipcz/node_link.h" #include "ipcz/node_link_memory.h" #include "ipcz/node_messages.h" #include "ipcz/parcel.h" @@ -38,6 +32,7 @@ #include "util/log.h" #include "util/ref_counted.h" #include "util/safe_math.h" +#include "util/unsafe_buffers.h" namespace ipcz { @@ -278,8 +273,9 @@ relay.v0()->destination = to_node; relay.v0()->data = relay.AllocateArray<uint8_t>(message.data_view().size()); relay.v0()->padding = 0; - memcpy(relay.GetArrayData(relay.v0()->data), message.data_view().data(), - message.data_view().size()); + IPCZ_UNSAFE_TODO(memcpy(relay.GetArrayData(relay.v0()->data), + message.data_view().data(), + message.data_view().size())); relay.v0()->driver_objects = relay.AppendDriverObjects(message.driver_objects()); Transmit(relay);
diff --git a/third_party/ipcz/src/ipcz/parcel_wrapper.cc b/third_party/ipcz/src/ipcz/parcel_wrapper.cc index e85762c..5bbd525 100644 --- a/third_party/ipcz/src/ipcz/parcel_wrapper.cc +++ b/third_party/ipcz/src/ipcz/parcel_wrapper.cc
@@ -2,19 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - #include "ipcz/parcel_wrapper.h" - #include "ipcz/driver_object.h" #include "ipcz/driver_transport.h" #include "ipcz/ipcz.h" #include "ipcz/node.h" #include "ipcz/node_link.h" #include "util/ref_counted.h" +#include "util/unsafe_buffers.h" namespace ipcz { @@ -76,7 +71,7 @@ return IPCZ_RESULT_RESOURCE_EXHAUSTED; } - memcpy(data, parcel_->data_view().data(), data_size); + IPCZ_UNSAFE_TODO(memcpy(data, parcel_->data_view().data(), data_size)); parcel_->ConsumeHandles(absl::MakeSpan(handles, handles_size)); if (parcel) {
diff --git a/third_party/ipcz/src/ipcz/remote_router_link.cc b/third_party/ipcz/src/ipcz/remote_router_link.cc index c81f438..2f8f25dd 100644 --- a/third_party/ipcz/src/ipcz/remote_router_link.cc +++ b/third_party/ipcz/src/ipcz/remote_router_link.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "ipcz/remote_router_link.h" - #include <algorithm> #include <sstream> #include <utility> @@ -20,9 +13,11 @@ #include "ipcz/node_link_memory.h" #include "ipcz/node_messages.h" #include "ipcz/parcel.h" +#include "ipcz/remote_router_link.h" #include "ipcz/router.h" #include "util/log.h" #include "util/safe_math.h" +#include "util/unsafe_buffers.h" namespace ipcz { @@ -275,8 +270,8 @@ accept.GetArrayView<RouterDescriptor>(accept.v0()->new_routers); if (!inline_parcel_data.empty()) { - memcpy(inline_parcel_data.data(), parcel->data_view().data(), - parcel->data_size()); + IPCZ_UNSAFE_TODO(memcpy(inline_parcel_data.data(), + parcel->data_view().data(), parcel->data_size())); } // Serialize attached objects. We accumulate the Routers of all attached @@ -287,7 +282,8 @@ // Explicitly zero the descriptor memory since there may be padding bits // within and we'll be copying the full contents into message data below. - memset(descriptors.data(), 0, descriptors.size() * sizeof(descriptors[0])); + IPCZ_UNSAFE_TODO(memset(descriptors.data(), 0, + descriptors.size() * sizeof(descriptors[0]))); size_t portal_index = 0; for (size_t i = 0; i < objects.size(); ++i) { @@ -333,8 +329,8 @@ // Copy all the serialized router descriptors into the message. Our local // copy will supply inputs for BeginProxyingToNewRouter() calls below. if (!descriptors.empty()) { - memcpy(new_routers.data(), descriptors.data(), - new_routers.size() * sizeof(new_routers[0])); + IPCZ_UNSAFE_TODO(memcpy(new_routers.data(), descriptors.data(), + new_routers.size() * sizeof(new_routers[0]))); } if (must_split_parcel) {
diff --git a/third_party/ipcz/src/ipcz/router.cc b/third_party/ipcz/src/ipcz/router.cc index cd50c66f..fcdce716 100644 --- a/third_party/ipcz/src/ipcz/router.cc +++ b/third_party/ipcz/src/ipcz/router.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "ipcz/router.h" - #include <algorithm> #include <cstddef> #include <cstring> @@ -20,6 +13,7 @@ #include "ipcz/node_link.h" #include "ipcz/parcel_wrapper.h" #include "ipcz/remote_router_link.h" +#include "ipcz/router.h" #include "ipcz/sequence_number.h" #include "ipcz/trap_event_dispatcher.h" #include "third_party/abseil-cpp/absl/base/macros.h" @@ -28,6 +22,7 @@ #include "util/log.h" #include "util/multi_mutex_lock.h" #include "util/safe_math.h" +#include "util/unsafe_buffers.h" namespace ipcz { @@ -403,7 +398,8 @@ std::unique_ptr<Parcel> parcel = AllocateOutboundParcel(data.size(), /*allow_partial=*/false); if (!data.empty()) { - memcpy(parcel->data_view().data(), data.data(), data.size()); + IPCZ_UNSAFE_TODO( + memcpy(parcel->data_view().data(), data.data(), data.size())); } parcel->CommitData(data.size()); parcel->SetObjects(std::move(objects)); @@ -541,7 +537,7 @@ } if (data_size > 0) { - memcpy(data, p->data_view().data(), data_size); + IPCZ_UNSAFE_TODO(memcpy(data, p->data_view().data(), data_size)); } const bool ok = inbound_parcels_.Pop(consumed_parcel);
diff --git a/third_party/ipcz/src/ipcz/sequenced_queue_test.cc b/third_party/ipcz/src/ipcz/sequenced_queue_test.cc index 9983ac3a..d7bcf70 100644 --- a/third_party/ipcz/src/ipcz/sequenced_queue_test.cc +++ b/third_party/ipcz/src/ipcz/sequenced_queue_test.cc
@@ -2,19 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "ipcz/sequenced_queue.h" - #include <string> #include "ipcz/sequence_number.h" +#include "ipcz/sequenced_queue.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/base/macros.h" +#include "util/unsafe_buffers.h" namespace ipcz { namespace { @@ -154,11 +149,12 @@ SequenceNumber(12), SequenceNumber(15), SequenceNumber(13), SequenceNumber(14)}; for (SequenceNumber n : kMessageSequence) { - EXPECT_TRUE(q.Push(SequenceNumber(n), kEntries[n.value()])); + IPCZ_UNSAFE_TODO( + EXPECT_TRUE(q.Push(SequenceNumber(n), kEntries[n.value()]))); std::string s; while (q.Pop(s)) { EXPECT_EQ(*next_expected_pop, s); - ++next_expected_pop; + IPCZ_UNSAFE_TODO(++next_expected_pop); } }
diff --git a/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.cc b/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.cc index b44b4e5b..7f73ee3 100644 --- a/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.cc +++ b/third_party/ipcz/src/reference_drivers/single_process_reference_driver_base.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "reference_drivers/single_process_reference_driver_base.h" - #include <cstddef> #include <cstdint> #include <cstring> @@ -18,8 +11,10 @@ #include "ipcz/ipcz.h" #include "reference_drivers/object.h" #include "reference_drivers/random.h" +#include "reference_drivers/single_process_reference_driver_base.h" #include "third_party/abseil-cpp/absl/base/macros.h" #include "util/ref_counted.h" +#include "util/unsafe_buffers.h" namespace ipcz::reference_drivers { @@ -30,7 +25,7 @@ public: explicit InProcessMemory(size_t size) : size_(size), data_(new uint8_t[size]) { - memset(&data_[0], 0, size_); + IPCZ_UNSAFE_TODO(memset(&data_[0], 0, size_)); } size_t size() const { return size_; }
diff --git a/third_party/ipcz/src/reference_drivers/socket_transport.cc b/third_party/ipcz/src/reference_drivers/socket_transport.cc index ee948df1..f08a43c 100644 --- a/third_party/ipcz/src/reference_drivers/socket_transport.cc +++ b/third_party/ipcz/src/reference_drivers/socket_transport.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "reference_drivers/socket_transport.h" - #include <fcntl.h> #include <poll.h> #include <stdio.h> @@ -26,11 +19,13 @@ #include "reference_drivers/file_descriptor.h" #include "reference_drivers/handle_eintr.h" +#include "reference_drivers/socket_transport.h" #include "third_party/abseil-cpp/absl/synchronization/mutex.h" #include "third_party/abseil-cpp/absl/types/span.h" #include "util/log.h" #include "util/ref_counted.h" #include "util/safe_math.h" +#include "util/unsafe_buffers.h" namespace ipcz::reference_drivers { @@ -233,7 +228,8 @@ size_t next_descriptor = 0; for (const FileDescriptor& fd : message.descriptors) { ABSL_ASSERT(fd.is_valid()); - reinterpret_cast<int*>(CMSG_DATA(cmsg))[next_descriptor++] = fd.get(); + IPCZ_UNSAFE_TODO( + reinterpret_cast<int*>(CMSG_DATA(cmsg))[next_descriptor++]) = fd.get(); } for (;;) { @@ -353,7 +349,7 @@ const int* fds = reinterpret_cast<int*>(CMSG_DATA(cmsg)); descriptors.resize(num_fds); for (size_t i = 0; i < num_fds; ++i) { - descriptors[i] = FileDescriptor(fds[i]); + descriptors[i] = FileDescriptor(IPCZ_UNSAFE_TODO(fds[i])); } } }
diff --git a/third_party/ipcz/src/reference_drivers/socket_transport_test.cc b/third_party/ipcz/src/reference_drivers/socket_transport_test.cc index 96696ed..a7db482 100644 --- a/third_party/ipcz/src/reference_drivers/socket_transport_test.cc +++ b/third_party/ipcz/src/reference_drivers/socket_transport_test.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "reference_drivers/socket_transport.h" - #include <string_view> #include <tuple> #include <vector> @@ -16,9 +9,11 @@ #include "build/build_config.h" #include "reference_drivers/file_descriptor.h" #include "reference_drivers/memfd_memory.h" +#include "reference_drivers/socket_transport.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/synchronization/notification.h" +#include "util/unsafe_buffers.h" namespace ipcz::reference_drivers { namespace { @@ -107,8 +102,9 @@ // Make sure messages arrive in the order they were sent. std::fill(expected_values.begin(), expected_values.end(), next_expected_value++); - EXPECT_EQ(0, memcmp(message.data.data(), expected_bytes.data(), - kMessageNumBytes)); + IPCZ_UNSAFE_TODO(EXPECT_EQ( + 0, + memcmp(message.data.data(), expected_bytes.data(), kMessageNumBytes))); // Finish only once the last expected message is received. if (next_expected_value == kNumMessages) {
diff --git a/third_party/ipcz/src/reference_drivers/sync_reference_driver_test.cc b/third_party/ipcz/src/reference_drivers/sync_reference_driver_test.cc index cc14f86..939404d 100644 --- a/third_party/ipcz/src/reference_drivers/sync_reference_driver_test.cc +++ b/third_party/ipcz/src/reference_drivers/sync_reference_driver_test.cc
@@ -2,20 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "reference_drivers/sync_reference_driver.h" - #include <cstddef> #include <functional> #include <string> #include <vector> #include "ipcz/api_object.h" +#include "reference_drivers/sync_reference_driver.h" #include "testing/gtest/include/gtest/gtest.h" +#include "util/unsafe_buffers.h" namespace ipcz::reference_drivers { namespace { @@ -70,7 +65,8 @@ const std::string message(reinterpret_cast<const char*>(data), num_bytes); std::vector<IpczDriverHandle> handles(num_driver_handles); - std::copy(driver_handles, driver_handles + num_driver_handles, + std::copy(driver_handles, + IPCZ_UNSAFE_TODO(driver_handles + num_driver_handles), handles.begin()); return handlers.on_message( {.data = std::move(message), .handles = std::move(handles)});
diff --git a/third_party/ipcz/src/standalone/BUILD.gn b/third_party/ipcz/src/standalone/BUILD.gn index 19c1fc2..47b02f25ff 100644 --- a/third_party/ipcz/src/standalone/BUILD.gn +++ b/third_party/ipcz/src/standalone/BUILD.gn
@@ -8,6 +8,7 @@ public = [ "base/logging.h", "base/stack_trace.h", + "base/unsafe_buffers.h", ] sources = [
diff --git a/third_party/ipcz/src/standalone/base/stack_trace.cc b/third_party/ipcz/src/standalone/base/stack_trace.cc index 46fe97e4..e36cdc5 100644 --- a/third_party/ipcz/src/standalone/base/stack_trace.cc +++ b/third_party/ipcz/src/standalone/base/stack_trace.cc
@@ -2,16 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/390223051): Remove C-library calls to fix the errors. -#pragma allow_unsafe_libc_calls -#endif - -#include "standalone/base/stack_trace.h" - #include <string> #include <vector> +#include "standalone/base/stack_trace.h" +#include "standalone/base/unsafe_buffers.h" #include "third_party/abseil-cpp/absl/base/macros.h" #include "third_party/abseil-cpp/absl/debugging/stacktrace.h" #include "third_party/abseil-cpp/absl/debugging/symbolize.h" @@ -48,7 +43,7 @@ const size_t length = strlen(symbolized); const size_t index = buffer.size(); buffer.resize(buffer.size() + length + 1); - memcpy(&buffer[index], symbolized, length); + IPCZ_UNSAFE_TODO(memcpy(&buffer[index], symbolized, length)); buffer[index + length] = '\n'; } return std::string(buffer.begin(), buffer.end());
diff --git a/third_party/ipcz/src/standalone/base/unsafe_buffers.h b/third_party/ipcz/src/standalone/base/unsafe_buffers.h new file mode 100644 index 0000000..c81d4e6f --- /dev/null +++ b/third_party/ipcz/src/standalone/base/unsafe_buffers.h
@@ -0,0 +1,41 @@ +// 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 IPCZ_SRC_STANDALONE_BASE_UNSAFE_BUFFERS_H_ +#define IPCZ_SRC_STANDALONE_BASE_UNSAFE_BUFFERS_H_ + +// Standlone version of safe buffer macros for ipcz. + +// Annotates a function or class data member indicating it can lead to +// out-of-bounds accesses (OOB) if given incorrect inputs. +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::unsafe_buffer_usage) +#define IPCZ_UNSAFE_BUFFER_USAGE [[clang::unsafe_buffer_usage]] +#endif +#endif + +#ifndef IPCZ_UNSAFE_BUFFER_USAGE +#define IPCZ_UNSAFE_BUFFER_USAGE +#endif + +// Annotates code indicating that it should be permanently exempted from +// `-Wunsafe-buffer-usage`. +#if defined(__clang__) +// clang-format off +#define IPCZ_UNSAFE_BUFFERS(...) \ + _Pragma("clang unsafe_buffer_usage begin") \ + __VA_ARGS__ \ + _Pragma("clang unsafe_buffer_usage end") +// clang-format on +#endif + +#ifndef IPCZ_UNSAFE_BUFFERS +#define IPCZ_UNSAFE_BUFFERS(...) __VA_ARGS__ +#endif + +// Annotates code indicating that it should be temporarily exempted from +// `-Wunsafe-buffer-usage`. +#define IPCZ_UNSAFE_TODO(...) IPCZ_UNSAFE_BUFFERS(__VA_ARGS__) + +#endif // IPCZ_SRC_STANDALONE_BASE_UNSAFE_BUFFERS_H_
diff --git a/third_party/ipcz/src/test/test_child_launcher.cc b/third_party/ipcz/src/test/test_child_launcher.cc index 8a821f7..c033508 100644 --- a/third_party/ipcz/src/test/test_child_launcher.cc +++ b/third_party/ipcz/src/test/test_child_launcher.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/393091624): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - -#include "test/test_child_launcher.h" - #include <sys/resource.h> #include <sys/types.h> #include <sys/wait.h> @@ -20,10 +13,12 @@ #include "reference_drivers/handle_eintr.h" #include "test/multinode_test.h" +#include "test/test_child_launcher.h" #include "testing/multiprocess_func_list.h" #include "third_party/abseil-cpp/absl/base/macros.h" #include "third_party/abseil-cpp/absl/strings/str_cat.h" #include "util/safe_math.h" +#include "util/unsafe_buffers.h" namespace ipcz::test { @@ -99,7 +94,7 @@ ArgList& args = GetArgList(); args.resize(argc); for (int i = 0; i < argc; ++i) { - std::string_view value(argv[i]); + std::string_view value(IPCZ_UNSAFE_TODO(argv[i])); if (value.rfind(kTestChildSwitchPrefix) != std::string::npos) { GetTestNodeName() = value.substr(kTestChildSwitchPrefix.size()); } else if (value.rfind(kSocketFdSwitchPrefix) != std::string::npos) {
diff --git a/third_party/ipcz/src/util/unsafe_buffers.h b/third_party/ipcz/src/util/unsafe_buffers.h new file mode 100644 index 0000000..f141ede02 --- /dev/null +++ b/third_party/ipcz/src/util/unsafe_buffers.h
@@ -0,0 +1,20 @@ +// 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 IPCZ_SRC_UTIL_UNSAFE_BUFFERS_H_ +#define IPCZ_SRC_UTIL_UNSAFE_BUFFERS_H_ + +// Version of safe buffer macros for ipcz. + +#if defined(IPCZ_STANDALONE) +#include "standalone/base/unsafe_buffers.h" // nogncheck +#else // IPCZ_STANDALONE +#include "base/compiler_specific.h" // nogncheck + +#define IPCZ_UNSAFE_BUFFER_USAGE UNSAFE_BUFFER_USAGE +#define IPCZ_UNSAFE_BUFFERS(...) UNSAFE_BUFFERS(__VA_ARGS__) +#define IPCZ_UNSAFE_TODO(...) UNSAFE_TODO(__VA_ARGS__) +#endif // IPCZ_STANDALONE + +#endif // IPCZ_SRC_UTIL_UNSAFE_BUFFERS_H_
diff --git a/third_party/jetstream/main b/third_party/jetstream/main index 553d3f7f..67cfc6e 160000 --- a/third_party/jetstream/main +++ b/third_party/jetstream/main
@@ -1 +1 @@ -Subproject commit 553d3f7faca708ed7c30ac8fee1c57c7eb027740 +Subproject commit 67cfc6e50c5c8760cb81fb9378a25217a06d1e55
diff --git a/third_party/lens_server_proto/BUILD.gn b/third_party/lens_server_proto/BUILD.gn index ddd8581..f02ada5 100644 --- a/third_party/lens_server_proto/BUILD.gn +++ b/third_party/lens_server_proto/BUILD.gn
@@ -5,6 +5,8 @@ import("//third_party/protobuf/proto_library.gni") _proto_files = [ + "aim_communication.proto", + "aim_query.proto", "lens_overlay_client_context.proto", "lens_overlay_client_logs.proto", "lens_overlay_client_platform.proto", @@ -38,6 +40,7 @@ "lens_overlay_translate_stickiness_signals.proto", "lens_overlay_video_context_input_params.proto", "lens_overlay_video_params.proto", + "lens_overlay_visual_input_type.proto", "lens_overlay_visual_search_interaction_data.proto", "lens_overlay_visual_search_interaction_log_data.proto", ]
diff --git a/third_party/lens_server_proto/aim_communication.proto b/third_party/lens_server_proto/aim_communication.proto new file mode 100644 index 0000000..8d7b5b83 --- /dev/null +++ b/third_party/lens_server_proto/aim_communication.proto
@@ -0,0 +1,65 @@ +// 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. + +syntax = 'proto3'; + +option optimize_for = LITE_RUNTIME; + +package lens; + +import "aim_query.proto"; + +// Feature Capabilities shared between AIM and Client. Both sides need to +// support a feature for it to WAI. Sent in the handshake request/response so +// both ends of communication are aware of what features to support. +enum FeatureCapability { + // Default value. The only supported feature is sending a query from the + // client to AIM. + DEFAULT = 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// Client -> AIM messages +//////////////////////////////////////////////////////////////////////////////// + +// Message clients send to AIM to initiate a handshake. Sent continuously on +// page load until AIM acknowledges with a HandshakeResponse. +message HandshakePing { + // The list of features supports by this client. + repeated FeatureCapability capabilities = 1; +} + +// Message from client to AIM to submit a query. +message SubmitQuery { + // The set of data that's required to generate a response from the LLM. + // Queries can be unimodal (text only or image only) or multimodal (e.g. text + // + image). + QueryPayload payload = 1; +} + +//////////////////////////////////////////////////////////////////////////////// +// AIM -> Client messages +//////////////////////////////////////////////////////////////////////////////// + +// Message AIM sends to clients to confirm a handshake, at which point the +// client can send messages to AIM knowing they will be delivered. +message HandshakeResponse { + // The list of features supported by this AIM instance. + repeated FeatureCapability capabilities = 1; +} + +// The message for clients to send messages to AIM. +message ClientToAimMessage { + oneof event_message { + HandshakePing handshake_ping = 1; + SubmitQuery submit_query = 2; + } +} + +// The message for AIM to send messages to native clients. +message AimToClientMessage { + oneof event_message { + HandshakeResponse handshake_response = 1; + } +}
diff --git a/third_party/lens_server_proto/aim_query.proto b/third_party/lens_server_proto/aim_query.proto new file mode 100644 index 0000000..90dd54d4 --- /dev/null +++ b/third_party/lens_server_proto/aim_query.proto
@@ -0,0 +1,48 @@ +// 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. + +syntax = 'proto3'; + +option optimize_for = LITE_RUNTIME; + +package lens; + +import "lens_overlay_request_id.proto"; +import "lens_overlay_visual_input_type.proto"; + +// The collection of parameters required to execute a Lens query as part of AI +// Mode. +message LensImageQueryData { + // ID for subsequent search requests. + string search_session_id = 1; + + // A preformatted request ID to send for the current Lens query. + LensOverlayRequestId request_id = 2; + + // The type of visual input provided for the query. + LensOverlayVisualInputType visual_input_type = 4; + + // Deprecated fields to match the Silk LensImageQueryData. + reserved 3, 5; +} + +// The set of data that's required to generate a response from the LLM. +message QueryPayload { + // The input source of the query text. + enum QueryTextSource { + QUERY_TEXT_SOURCE_UNSPECIFIED = 0; + QUERY_TEXT_SOURCE_KEYBOARD_INPUT = 1; + } + // The user query. + string query_text = 1; + + // The input source of the query text. + QueryTextSource query_text_source = 3; + + // Query data returned if Lens was invoked. + repeated LensImageQueryData lens_image_query_data = 2; + + // Deprecated fields to match the Silk QueryPayload. + reserved 5, 7; +}
diff --git a/third_party/lens_server_proto/lens_overlay_client_logs.proto b/third_party/lens_server_proto/lens_overlay_client_logs.proto index 3fa88e8..399ff3a0 100644 --- a/third_party/lens_server_proto/lens_overlay_client_logs.proto +++ b/third_party/lens_server_proto/lens_overlay_client_logs.proto
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -syntax = 'proto2'; +syntax = 'proto3'; option optimize_for = LITE_RUNTIME; @@ -13,7 +13,7 @@ message LensOverlayClientLogs { // The phase latency metadata for any image preprocessing required for the // request. - optional LensOverlayPhaseLatenciesMetadata phase_latencies_metadata = 1; + LensOverlayPhaseLatenciesMetadata phase_latencies_metadata = 1; enum LensOverlayEntryPoint { UNKNOWN_ENTRY_POINT = 0; @@ -30,13 +30,13 @@ } // The Lens Overlay entry point used to access lens. - optional LensOverlayEntryPoint lens_overlay_entry_point = 2; + LensOverlayEntryPoint lens_overlay_entry_point = 2; // A unique identifier for associating events logged by lens asynchronously. - optional uint64 paella_id = 3; + uint64 paella_id = 3; // Whether the user has disabled metrics collection. - optional bool metrics_collection_disabled = 5; + bool metrics_collection_disabled = 5; reserved 4; }
diff --git a/third_party/lens_server_proto/lens_overlay_request_id.proto b/third_party/lens_server_proto/lens_overlay_request_id.proto index 734003af..63d73b0 100644 --- a/third_party/lens_server_proto/lens_overlay_request_id.proto +++ b/third_party/lens_server_proto/lens_overlay_request_id.proto
@@ -39,7 +39,7 @@ // Information about where to route the request. LensOverlayRoutingInfo routing_info = 6; - // The Epoch Micro Wall time when the request id is built. + // The Epoch Micro Wall time when the request is built. uint64 time_usec = 7; enum MediaType {
diff --git a/third_party/lens_server_proto/lens_overlay_visual_input_type.proto b/third_party/lens_server_proto/lens_overlay_visual_input_type.proto new file mode 100644 index 0000000..9228198 --- /dev/null +++ b/third_party/lens_server_proto/lens_overlay_visual_input_type.proto
@@ -0,0 +1,20 @@ +// 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. + +syntax = 'proto3'; + +option optimize_for = LITE_RUNTIME; + +package lens; + +// Input type for the visual search request. +enum LensOverlayVisualInputType { + VISUAL_INPUT_TYPE_UNKNOWN = 0; + + VISUAL_INPUT_TYPE_PDF = 4; + + VISUAL_INPUT_TYPE_WEBPAGE = 5; + + reserved 1, 2, 3; +}
diff --git a/third_party/libaom/README.chromium b/third_party/libaom/README.chromium index 064aea9..c29a5ca18 100644 --- a/third_party/libaom/README.chromium +++ b/third_party/libaom/README.chromium
@@ -2,7 +2,7 @@ Short Name: libaom URL: https://aomedia.googlesource.com/aom/ Version: N/A -Revision: 930f7e2b9c58779edb2aa1ffb6f55a64fb6fd7fd +Revision: 1f097193b0353e32c5f0b010642d89d146234804 CPEPrefix: cpe:/a:aomedia:aomedia:3.12.1 License: BSD-2-Clause, Patent License Android Compatible: yes
diff --git a/third_party/libaom/source/config/config/aom_version.h b/third_party/libaom/source/config/config/aom_version.h index 9733842f..490d0b8 100644 --- a/third_party/libaom/source/config/config/aom_version.h +++ b/third_party/libaom/source/config/config/aom_version.h
@@ -14,9 +14,9 @@ #define VERSION_MAJOR 3 #define VERSION_MINOR 12 #define VERSION_PATCH 1 -#define VERSION_EXTRA "244-g930f7e2b9c" +#define VERSION_EXTRA "247-g1f097193b0" #define VERSION_PACKED \ ((VERSION_MAJOR << 16) | (VERSION_MINOR << 8) | (VERSION_PATCH)) -#define VERSION_STRING_NOSP "3.12.1-244-g930f7e2b9c" -#define VERSION_STRING " 3.12.1-244-g930f7e2b9c" +#define VERSION_STRING_NOSP "3.12.1-247-g1f097193b0" +#define VERSION_STRING " 3.12.1-247-g1f097193b0" #endif // AOM_VERSION_H_
diff --git a/third_party/libaom/source/libaom b/third_party/libaom/source/libaom index 930f7e2..1f09719 160000 --- a/third_party/libaom/source/libaom +++ b/third_party/libaom/source/libaom
@@ -1 +1 @@ -Subproject commit 930f7e2b9c58779edb2aa1ffb6f55a64fb6fd7fd +Subproject commit 1f097193b0353e32c5f0b010642d89d146234804
diff --git a/third_party/libyuv b/third_party/libyuv index cdd3bae..b7d97d5 160000 --- a/third_party/libyuv +++ b/third_party/libyuv
@@ -1 +1 @@ -Subproject commit cdd3bae84818e78466fec1ce954eead8f403d10c +Subproject commit b7d97d5f3f8f897b88872b6935e4c996b955bc1f
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium index fb732533..5e5a045 100644 --- a/third_party/metrics_proto/README.chromium +++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Metrics Protos Short Name: metrics_proto URL: This is the canonical public repository -Version: 788932306 -Date: 2025-07-30 +Version: 791249536 +Date: 2025-08-05 License: BSD-3-Clause License File: LICENSE Shipped: yes
diff --git a/third_party/metrics_proto/dwa/deidentified_web_analytics.proto b/third_party/metrics_proto/dwa/deidentified_web_analytics.proto index a47a62c..4030278 100644 --- a/third_party/metrics_proto/dwa/deidentified_web_analytics.proto +++ b/third_party/metrics_proto/dwa/deidentified_web_analytics.proto
@@ -22,9 +22,7 @@ // Temporary identifier that gets generated once a day. optional fixed64 dwa_ephemeral_id = 2; - // A list of page load events, one entry per page load. - // This field should be cleared when a report is sent, its content should be - // encrypted and placed in encrypted_page_load_events. + // This field should not be used. Use `dwa_events` instead. repeated PageLoadEvents page_load_events = 3; reserved 4; @@ -112,7 +110,7 @@ repeated DeidentifiedWebAnalyticsEvent events = 1; } -// Next tag: 7 +// Next tag: 10 message DeidentifiedWebAnalyticsEvent { // A hash of the event name/type (such as "ReportingAPIUsage"). // Uses the same hash function as UMA. @@ -157,6 +155,7 @@ repeated EntryMetrics metrics = 3; } + // This field should not be used. Use `content_hash` and `metrics` instead. repeated ContentMetric content_metrics = 2; // Field trials that we want to associate with this event, name id and @@ -165,4 +164,18 @@ // Coarse system information associated with this event. optional CoarseSystemInfo coarse_system_info = 4; + + // A hash of the content (e.g. hash("example.com")). + // Uses the same hash function as UMA. + // http://cs.chromium.org/chromium/src/base/metrics/metrics_hashes.cc?q=HashMetricName + optional fixed64 content_hash = 7; + + // A single metric, which is defined by a name hash and a value. + message Metric { + optional fixed64 name_hash = 1; + + optional int64 value = 2; + } + + repeated Metric metric = 9; }
diff --git a/third_party/metrics_proto/private_metrics/private_metrics.proto b/third_party/metrics_proto/private_metrics/private_metrics.proto index db1925f..7b585f3 100644 --- a/third_party/metrics_proto/private_metrics/private_metrics.proto +++ b/third_party/metrics_proto/private_metrics/private_metrics.proto
@@ -69,7 +69,7 @@ // A report containing unencrypted private metrics data. The unencrypted report // does not leave the client. -// Next tag: 3 +// Next tag: 4 message PrivateMetricReport { // A temporary unique identifier that changes every epoch. One epoch is a // period of 24 hours. This is generated and managed by the Private Metrics @@ -96,4 +96,8 @@ // Each report is composed of a collection of events. repeated Event events = 2; + + // The epoch the report is associated with. Reports may only be processed with + // other reports from the same epoch. + optional fixed64 epoch_id = 3; }
diff --git a/third_party/perfetto b/third_party/perfetto index 79987e4..27062b5 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit 79987e4753ec3572794821544b5f00a1e1b08fa8 +Subproject commit 27062b54dde5b49c79f4b85e0a21bde2345219a8
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn index 612e57b..d4886b22 100644 --- a/third_party/protobuf/BUILD.gn +++ b/third_party/protobuf/BUILD.gn
@@ -43,7 +43,15 @@ include_dirs = [ "src" ] } -component("protobuf_lite") { +# On Android, we must use a static library to avoid symbol conflicts with +# the system's version of protobuf. +if (is_android) { + _protobuf_lite_target_type = "static_library" +} else { + _protobuf_lite_target_type = "component" +} + +target(_protobuf_lite_target_type, "protobuf_lite") { sources = protobuf_lite_sources public = protobuf_headers @@ -76,7 +84,7 @@ public_deps = [ "${protobuf_abseil_dir}:absl" ] # Required for component builds. See http://crbug.com/172800. - if (is_component_build) { + if (is_component_build && _protobuf_lite_target_type == "component") { public_configs += [ ":protobuf_use_dlls" ] defines = [ "LIBPROTOBUF_EXPORTS" ] }
diff --git a/third_party/re2/src b/third_party/re2/src index c2c6a2e..85c7c0f 160000 --- a/third_party/re2/src +++ b/third_party/re2/src
@@ -1 +1 @@ -Subproject commit c2c6a2eb663fe21e0cd9f2b1886821bdecb1e988 +Subproject commit 85c7c0fb1163b0bd83a7951f5a205ee7b489e33e
diff --git a/third_party/rust/chromium_crates_io/Cargo.lock b/third_party/rust/chromium_crates_io/Cargo.lock index fe966ff..58a1ef66 100644 --- a/third_party/rust/chromium_crates_io/Cargo.lock +++ b/third_party/rust/chromium_crates_io/Cargo.lock
@@ -1277,7 +1277,7 @@ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "yoke",
diff --git a/third_party/rust/chromium_crates_io/gnrt_config.toml b/third_party/rust/chromium_crates_io/gnrt_config.toml index 65fe866..0933385e 100644 --- a/third_party/rust/chromium_crates_io/gnrt_config.toml +++ b/third_party/rust/chromium_crates_io/gnrt_config.toml
@@ -362,11 +362,6 @@ allow_unsafe = true [crate.libc] -ban_features = [ - # `extra_traits` feature is banned because of - # https://github.com/rust-lang/libc/issues/3560 - 'extra_traits', -] # `libc` crate is implicitly trusted because it comes from # https://github.com/rust-lang/ (and we already implicitly trust maintainers of # `rustc`).
diff --git a/third_party/rust/chromium_crates_io/patches/zerovec/0001-Patch-ZeroVec-Default-impl.patch b/third_party/rust/chromium_crates_io/patches/zerovec/0001-Patch-ZeroVec-Default-impl.patch deleted file mode 100644 index 98fa0cc0..0000000 --- a/third_party/rust/chromium_crates_io/patches/zerovec/0001-Patch-ZeroVec-Default-impl.patch +++ /dev/null
@@ -1,28 +0,0 @@ -From 20c7c22542eb98cf61293cfc9de0e7f4c3a96155 Mon Sep 17 00:00:00 2001 -From: Manish Goregaokar <manishearth@google.com> -Date: Thu, 31 Jul 2025 03:00:50 +0000 -Subject: [PATCH] Patch ZeroVec Default impl - -https://github.com/unicode-org/icu4x/pull/6661.patch - -Change-Id: I4247e6eaaad8a76182e2faae903ca8564e982ee8 ---- - .../vendor/zerovec-v0_11/src/varzerovec/vec.rs | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/vec.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/vec.rs -index c3261264fb773..49e3104a7f1ab 100644 ---- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/vec.rs -+++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/vec.rs -@@ -192,7 +192,7 @@ impl<'a, T: ?Sized + VarULE, F: VarZeroVecFormat> From<VarZeroVec<'a, T, F>> - } - } - --impl<T: VarULE + ?Sized> Default for VarZeroVec<'_, T> { -+impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Default for VarZeroVec<'_, T, F> { - #[inline] - fn default() -> Self { - Self::new() --- -2.50.1.565.gc32cd1483b-goog -
diff --git a/third_party/rust/chromium_crates_io/supply-chain/config.toml b/third_party/rust/chromium_crates_io/supply-chain/config.toml index 31faa04..444bbc1 100644 --- a/third_party/rust/chromium_crates_io/supply-chain/config.toml +++ b/third_party/rust/chromium_crates_io/supply-chain/config.toml
@@ -485,7 +485,7 @@ [policy."zerovec-derive:0.11.1"] criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] -[policy."zerovec:0.11.2"] +[policy."zerovec:0.11.4"] criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] [policy."zip:4.3.0"]
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/.cargo_vcs_info.json index a9bad1f5..c29e0ccc 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/.cargo_vcs_info.json +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/.cargo_vcs_info.json
@@ -1,6 +1,6 @@ { "git": { - "sha1": "5e404744dd6c9dd7f86aac82586e3fa98ea75f7f" + "sha1": "23b31cd3b6fe6d6d58e9211e0c87689194638efd" }, "path_in_vcs": "utils/zerovec" } \ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.lock b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.lock index 6f38b90..8bc57cb 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.lock +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.lock
@@ -897,7 +897,7 @@ [[package]] name = "zerovec" -version = "0.11.2" +version = "0.11.4" dependencies = [ "bincode", "criterion",
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.toml index 6264b8b..4ffb8cc08 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.toml +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.toml
@@ -13,7 +13,7 @@ edition = "2021" rust-version = "1.82" name = "zerovec" -version = "0.11.2" +version = "0.11.4" authors = ["The ICU4X Project Developers"] build = false include = [
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.toml.orig index e6d4c559..1c62aa7 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.toml.orig +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/Cargo.toml.orig
@@ -5,7 +5,7 @@ [package] name = "zerovec" description = "Zero-copy vector backed by a byte array" -version = "0.11.2" +version = "0.11.4" categories = ["rust-patterns", "memory-management", "caching", "no-std", "data-structures"] keywords = ["zerocopy", "serialization", "zero-copy", "serde"]
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/algorithms.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/algorithms.rs index 30102e6..2478b3d 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/algorithms.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/algorithms.rs
@@ -62,7 +62,7 @@ /// # Arguments /// /// * `key_hashes` - [`ExactSizeIterator`] over the hashed key values -#[allow(clippy::indexing_slicing, clippy::unwrap_used)] +#[expect(clippy::indexing_slicing, clippy::unwrap_used)] pub fn compute_displacements( key_hashes: impl ExactSizeIterator<Item = u64>, ) -> (Vec<(u32, u32)>, Vec<usize>) {
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/mod.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/mod.rs index c30c6224..608e637 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/mod.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/mod.rs
@@ -71,11 +71,11 @@ let hash = compute_hash(key.borrow()); let (g, f0, f1) = split_hash64(hash, self.len()); - #[allow(clippy::unwrap_used)] // g is in-range + #[expect(clippy::unwrap_used)] // g is in-range let (d0, d1) = self.displacements.get(g).unwrap(); let index = compute_index((f0, f1), (d0, d1), self.displacements.len() as u32)?; - #[allow(clippy::unwrap_used)] // index is in 0..self.keys.len() + #[expect(clippy::unwrap_used)] // index is in 0..self.keys.len() let found = self.keys.zvl_get(index).unwrap(); if K::Container::zvl_get_as_t(found, |found| found == key.borrow()) { Some(index) @@ -136,9 +136,9 @@ > { (0..self.len()).map(|index| { ( - #[allow(clippy::unwrap_used)] // index is in range + #[expect(clippy::unwrap_used)] // index is in range self.keys.zvl_get(index).unwrap(), - #[allow(clippy::unwrap_used)] // index is in range + #[expect(clippy::unwrap_used)] // index is in range self.values.zvl_get(index).unwrap(), ) }) @@ -148,7 +148,7 @@ pub fn iter_keys<'b>( &'b self, ) -> impl ExactSizeIterator<Item = &'b <K as ZeroMapKV<'a>>::GetType> { - #[allow(clippy::unwrap_used)] // index is in range + #[expect(clippy::unwrap_used)] // index is in range (0..self.len()).map(|index| self.keys.zvl_get(index).unwrap()) } @@ -156,7 +156,7 @@ pub fn iter_values<'b>( &'b self, ) -> impl ExactSizeIterator<Item = &'b <V as ZeroMapKV<'a>>::GetType> { - #[allow(clippy::unwrap_used)] // index is in range + #[expect(clippy::unwrap_used)] // index is in range (0..self.len()).map(|index| self.values.zvl_get(index).unwrap()) } }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/serde.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/serde.rs index 0938dcd..0ed2b1a4 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/serde.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/hashmap/serde.rs
@@ -119,6 +119,8 @@ ); } + // TODO(#6588): Fix sensitivity to host endianness. + #[cfg(target_endian = "little")] #[test] fn test_serde_valid_deser_zhm() { let hm = make_zerohashmap(); @@ -132,6 +134,8 @@ ); } + // TODO(#6588): Fix sensitivity to host endianness. + #[cfg(target_endian = "little")] #[test] fn test_bincode_zhm() { let hm = make_zerohashmap();
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/borrowed.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/borrowed.rs index 9a3c2444a..9edecd9 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/borrowed.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/borrowed.rs
@@ -222,13 +222,13 @@ /// Produce an ordered iterator over keys pub fn iter_keys(self) -> impl Iterator<Item = &'a <K as ZeroMapKV<'a>>::GetType> { - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() (0..self.keys.zvl_len()).map(move |idx| self.keys.zvl_get(idx).unwrap()) } /// Produce an iterator over values, ordered by keys pub fn iter_values(self) -> impl Iterator<Item = &'a <V as ZeroMapKV<'a>>::GetType> { - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() == values.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() == values.zvl_len() (0..self.values.zvl_len()).map(move |idx| self.values.zvl_get(idx).unwrap()) } } @@ -257,9 +257,9 @@ ) -> impl Iterator<Item = (&'a <K as ZeroMapKV<'a>>::GetType, V)> { (0..self.keys.zvl_len()).map(move |idx| { ( - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() self.keys.zvl_get(idx).unwrap(), - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() self.values.get(idx).unwrap(), ) }) @@ -273,14 +273,13 @@ { /// Similar to [`Self::iter()`] except it returns a direct copy of the keys values instead of references /// to `K::ULE` and `V::ULE`, in cases when `K` and `V` are fixed-size - #[allow(clippy::needless_lifetimes)] // Lifetime is necessary in impl Trait pub fn iter_copied(self) -> impl Iterator<Item = (K, V)> + 'a { let len = self.keys.zvl_len(); (0..len).map(move |idx| { ( - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() ZeroSlice::get(self.keys, idx).unwrap(), - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() ZeroSlice::get(self.values, idx).unwrap(), ) })
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/kv.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/kv.rs index d14fb81..9ca675fd 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/kv.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/kv.rs
@@ -3,6 +3,7 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use super::vecs::{MutableZeroVecLike, ZeroVecLike}; +use crate::ule::vartuple::VarTupleULE; use crate::ule::*; use crate::vecs::{VarZeroSlice, VarZeroVec}; use crate::zerovec::{ZeroSlice, ZeroVec}; @@ -14,7 +15,6 @@ /// implementing your own [`AsULE`] or [`VarULE`] type you may wish to implement /// this trait. // this lifetime should be a GAT on Container once that is possible -#[allow(clippy::upper_case_acronyms)] // KV is not an acronym pub trait ZeroMapKV<'a> { /// The container that can be used with this type: [`ZeroVec`] or [`VarZeroVec`]. type Container: MutableZeroVecLike< @@ -88,6 +88,17 @@ type OwnedType = Box<OptionVarULE<T>>; } +impl<'a, A, B> ZeroMapKV<'a> for VarTupleULE<A, B> +where + A: AsULE + 'static, + B: VarULE + ?Sized, +{ + type Container = VarZeroVec<'a, VarTupleULE<A, B>>; + type Slice = VarZeroSlice<VarTupleULE<A, B>>; + type GetType = VarTupleULE<A, B>; + type OwnedType = Box<VarTupleULE<A, B>>; +} + impl<'a> ZeroMapKV<'a> for str { type Container = VarZeroVec<'a, str>; type Slice = VarZeroSlice<str>;
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/map.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/map.rs index 1dc9741..6276cc1b 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/map.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/map.rs
@@ -296,9 +296,9 @@ > { (0..self.keys.zvl_len()).map(move |idx| { ( - #[allow(clippy::unwrap_used)] // idx is in-range + #[expect(clippy::unwrap_used)] // idx is in-range self.keys.zvl_get(idx).unwrap(), - #[allow(clippy::unwrap_used)] // idx is in-range + #[expect(clippy::unwrap_used)] // idx is in-range self.values.zvl_get(idx).unwrap(), ) }) @@ -308,7 +308,7 @@ pub fn iter_keys<'b>( &'b self, ) -> impl ExactSizeIterator<Item = &'b <K as ZeroMapKV<'a>>::GetType> { - #[allow(clippy::unwrap_used)] // idx is in-range + #[expect(clippy::unwrap_used)] // idx is in-range (0..self.keys.zvl_len()).map(move |idx| self.keys.zvl_get(idx).unwrap()) } @@ -316,7 +316,7 @@ pub fn iter_values<'b>( &'b self, ) -> impl ExactSizeIterator<Item = &'b <V as ZeroMapKV<'a>>::GetType> { - #[allow(clippy::unwrap_used)] // idx is in-range + #[expect(clippy::unwrap_used)] // idx is in-range (0..self.values.zvl_len()).map(move |idx| self.values.zvl_get(idx).unwrap()) } } @@ -446,7 +446,7 @@ pub fn insert_var_v<VE: EncodeAsVarULE<V>>(&mut self, key: &K, value: &VE) -> Option<Box<V>> { match self.keys.zvl_binary_search(key) { Ok(index) => { - #[allow(clippy::unwrap_used)] // binary search + #[expect(clippy::unwrap_used)] // binary search let ret = self.values.get(index).unwrap().to_boxed(); self.values.make_mut().replace(index, value); Some(ret) @@ -512,7 +512,7 @@ let ule = self.values.zvl_get(index)?; let mut result = Option::<V>::None; V::Container::zvl_get_as_t(ule, |v| result.replace(*v)); - #[allow(clippy::unwrap_used)] // `zvl_get_as_t` guarantees that the callback is invoked + #[expect(clippy::unwrap_used)] // `zvl_get_as_t` guarantees that the callback is invoked Some(result.unwrap()) } } @@ -529,9 +529,9 @@ ) -> impl Iterator<Item = (&'b <K as ZeroMapKV<'a>>::GetType, V)> { (0..self.keys.zvl_len()).map(move |idx| { ( - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() self.keys.zvl_get(idx).unwrap(), - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() ZeroSlice::get(&*self.values, idx).unwrap(), ) }) @@ -545,15 +545,14 @@ { /// Similar to [`Self::iter()`] except it returns a direct copy of the keys values instead of references /// to `K::ULE` and `V::ULE`, in cases when `K` and `V` are fixed-size - #[allow(clippy::needless_lifetimes)] // Lifetime is necessary in impl Trait pub fn iter_copied<'b>(&'b self) -> impl Iterator<Item = (K, V)> + 'b { let keys = &self.keys; let values = &self.values; (0..keys.len()).map(move |idx| { ( - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() ZeroSlice::get(&**keys, idx).unwrap(), - #[allow(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() + #[expect(clippy::unwrap_used)] // idx in 0..keys.zvl_len() = values.zvl_len() ZeroSlice::get(&**values, idx).unwrap(), ) })
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/mod.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/mod.rs index fcad0cf..2ac640ec 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/mod.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/mod.rs
@@ -6,7 +6,7 @@ mod borrowed; mod kv; -#[allow(clippy::module_inception)] // module is purely internal +#[expect(clippy::module_inception)] // module is purely internal pub(crate) mod map; mod vecs;
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/serde.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/serde.rs index b542b77..2cde95c 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/serde.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/serde.rs
@@ -72,7 +72,7 @@ K: ZeroMapKV<'a> + ?Sized + Ord, V: ZeroMapKV<'a> + ?Sized, { - #[allow(clippy::type_complexity)] // it's a marker type, complexity doesn't matter + #[expect(clippy::type_complexity)] // it's a marker type, complexity doesn't matter marker: PhantomData<fn() -> (&'a K::OwnedType, &'a V::OwnedType)>, }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/vecs.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/vecs.rs index e236bea..d88d494 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/vecs.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map/vecs.rs
@@ -74,7 +74,7 @@ if let Some(first) = self.zvl_get(0) { let mut prev = first; for i in 1..self.zvl_len() { - #[allow(clippy::unwrap_used)] // looping over the valid indices + #[expect(clippy::unwrap_used)] // looping over the valid indices let curr = self.zvl_get(i).unwrap(); if Self::get_cmp_get(prev, curr) != Ordering::Less { return false; @@ -295,7 +295,7 @@ T::from_unaligned(self.with_mut(|v| v.remove(index))) } fn zvl_replace(&mut self, index: usize, value: &T) -> T { - #[allow(clippy::indexing_slicing)] + #[expect(clippy::indexing_slicing)] let unaligned = self.with_mut(|vec| { debug_assert!(index < vec.len()); mem::replace(&mut vec[index], value.to_unaligned()) @@ -330,7 +330,7 @@ self.as_maybe_borrowed() } - #[allow(clippy::indexing_slicing)] // documented panic + #[expect(clippy::indexing_slicing)] // documented panic fn zvl_permute(&mut self, permutation: &mut [usize]) { assert_eq!(permutation.len(), self.zvl_len()); @@ -467,7 +467,7 @@ fn zvl_remove(&mut self, index: usize) -> Box<T> { let vec = self.make_mut(); debug_assert!(index < vec.len()); - #[allow(clippy::unwrap_used)] + #[expect(clippy::unwrap_used)] let old = vec.get(index).unwrap().to_boxed(); vec.remove(index); old @@ -475,7 +475,7 @@ fn zvl_replace(&mut self, index: usize, value: &T) -> Box<T> { let vec = self.make_mut(); debug_assert!(index < vec.len()); - #[allow(clippy::unwrap_used)] + #[expect(clippy::unwrap_used)] let old = vec.get(index).unwrap().to_boxed(); vec.replace(index, value); old @@ -513,7 +513,7 @@ } } - #[allow(clippy::unwrap_used)] // documented panic + #[expect(clippy::unwrap_used)] // documented panic fn zvl_permute(&mut self, permutation: &mut [usize]) { assert_eq!(permutation.len(), self.zvl_len());
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/cursor.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/cursor.rs index 2c1f1121..ce1d2dc 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/cursor.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/cursor.rs
@@ -88,7 +88,7 @@ /// assert_eq!(map.get0("one").unwrap().key0(), "one"); /// ``` pub fn key0(&self) -> &'l K0::GetType { - #[allow(clippy::unwrap_used)] // safe by invariant on `self.key0_index` + #[expect(clippy::unwrap_used)] // safe by invariant on `self.key0_index` self.keys0.zvl_get(self.key0_index).unwrap() } @@ -107,7 +107,7 @@ > + ExactSizeIterator + '_ { let range = self.get_range(); - #[allow(clippy::unwrap_used)] // `self.get_range()` returns a valid range + #[expect(clippy::unwrap_used)] // `self.get_range()` returns a valid range range.map(move |idx| { ( self.keys1.zvl_get(idx).unwrap(), @@ -126,7 +126,7 @@ ), > + ExactSizeIterator { let range = self.get_range(); - #[allow(clippy::unwrap_used)] // `self.get_range()` returns a valid range + #[expect(clippy::unwrap_used)] // `self.get_range()` returns a valid range range.map(move |idx| { ( self.keys1.zvl_get(idx).unwrap(), @@ -141,10 +141,10 @@ let start = if self.key0_index == 0 { 0 } else { - #[allow(clippy::unwrap_used)] // protected by the debug_assert above + #[expect(clippy::unwrap_used)] // protected by the debug_assert above self.joiner.get(self.key0_index - 1).unwrap() }; - #[allow(clippy::unwrap_used)] // protected by the debug_assert above + #[expect(clippy::unwrap_used)] // protected by the debug_assert above let limit = self.joiner.get(self.key0_index).unwrap(); // These two assertions are true based on the invariants of ZeroMap2d debug_assert!(start < limit); @@ -191,7 +191,7 @@ ) -> impl DoubleEndedIterator<Item = (&'l <K1 as ZeroMapKV<'a>>::GetType, V)> + ExactSizeIterator + '_ { let range = self.get_range(); - #[allow(clippy::unwrap_used)] // `self.get_range()` returns a valid range + #[expect(clippy::unwrap_used)] // `self.get_range()` returns a valid range range.map(move |idx| { ( self.keys1.zvl_get(idx).unwrap(), @@ -228,7 +228,7 @@ ) -> impl DoubleEndedIterator<Item = (&'l <K1 as ZeroMapKV<'a>>::GetType, V)> + ExactSizeIterator { let range = self.get_range(); - #[allow(clippy::unwrap_used)] // `self.get_range()` returns a valid range + #[expect(clippy::unwrap_used)] // `self.get_range()` returns a valid range range.map(move |idx| { ( self.keys1.zvl_get(idx).unwrap(), @@ -241,7 +241,7 @@ let ule = self.values.zvl_get(index)?; let mut result = Option::<V>::None; V::Container::zvl_get_as_t(ule, |v| result.replace(*v)); - #[allow(clippy::unwrap_used)] // `zvl_get_as_t` guarantees that the callback is invoked + #[expect(clippy::unwrap_used)] // `zvl_get_as_t` guarantees that the callback is invoked Some(result.unwrap()) } } @@ -267,7 +267,7 @@ /// ``` pub fn get1(&self, key1: &K1) -> Option<&'l V::GetType> { let key1_index = self.get_key1_index(key1)?; - #[allow(clippy::unwrap_used)] // key1_index is valid + #[expect(clippy::unwrap_used)] // key1_index is valid Some(self.values.zvl_get(key1_index).unwrap()) } @@ -283,7 +283,7 @@ /// ``` pub fn get1_by(&self, predicate: impl FnMut(&K1) -> Ordering) -> Option<&'l V::GetType> { let key1_index = self.get_key1_index_by(predicate)?; - #[allow(clippy::unwrap_used)] // key1_index is valid + #[expect(clippy::unwrap_used)] // key1_index is valid Some(self.values.zvl_get(key1_index).unwrap()) } @@ -293,7 +293,7 @@ debug_assert!(range.start < range.end); // '<' because every key0 should have a key1 debug_assert!(range.end <= self.keys1.zvl_len()); let start = range.start; - #[allow(clippy::expect_used)] // protected by the debug_assert above + #[expect(clippy::expect_used)] // protected by the debug_assert above let binary_search_result = self .keys1 .zvl_binary_search_in_range_by(predicate, range) @@ -307,7 +307,7 @@ debug_assert!(range.start < range.end); // '<' because every key0 should have a key1 debug_assert!(range.end <= self.keys1.zvl_len()); let start = range.start; - #[allow(clippy::expect_used)] // protected by the debug_assert above + #[expect(clippy::expect_used)] // protected by the debug_assert above let binary_search_result = self .keys1 .zvl_binary_search_in_range(key1, range)
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/map.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/map.rs index caf1bb1..1d6bd0ed 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/map.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/map.rs
@@ -242,7 +242,7 @@ /// Shifts all joiner ranges from key0_index onward one index up fn joiner_expand(&mut self, key0_index: usize) { - #[allow(clippy::expect_used)] // slice overflow + #[expect(clippy::expect_used)] // slice overflow self.joiner .to_mut_slice() .iter_mut() @@ -314,7 +314,7 @@ debug_assert!(range.start <= range.end); // '<=' because we may have inserted a new key0 debug_assert!(range.end <= self.keys1.zvl_len()); let range_start = range.start; - #[allow(clippy::unwrap_used)] // by debug_assert! invariants + #[expect(clippy::unwrap_used)] // by debug_assert! invariants let index = range_start + match self.keys1.zvl_binary_search_in_range(key1, range).unwrap() { Ok(index) => return Some(self.values.zvl_replace(range_start + index, value)), @@ -349,7 +349,7 @@ debug_assert!(range.start < range.end); // '<' because every key0 should have a key1 debug_assert!(range.end <= self.keys1.zvl_len()); let is_singleton_range = range.start + 1 == range.end; - #[allow(clippy::unwrap_used)] // by debug_assert invariants + #[expect(clippy::unwrap_used)] // by debug_assert invariants let index = range.start + self .keys1 @@ -408,10 +408,10 @@ } // The unwraps are protected by the fact that we are not empty - #[allow(clippy::unwrap_used)] + #[expect(clippy::unwrap_used)] let last_key0 = self.keys0.zvl_get(self.keys0.zvl_len() - 1).unwrap(); let key0_cmp = K0::Container::t_cmp_get(key0, last_key0); - #[allow(clippy::unwrap_used)] + #[expect(clippy::unwrap_used)] let last_key1 = self.keys1.zvl_get(self.keys1.zvl_len() - 1).unwrap(); let key1_cmp = K1::Container::t_cmp_get(key1, last_key1); @@ -433,12 +433,12 @@ _ => {} } - #[allow(clippy::expect_used)] // slice overflow + #[expect(clippy::expect_used)] // slice overflow let joiner_value = u32::try_from(self.keys1.zvl_len() + 1) .expect("Attempted to add more than 2^32 elements to a ZeroMap2d"); // All OK to append - #[allow(clippy::unwrap_used)] + #[expect(clippy::unwrap_used)] if key0_cmp == Ordering::Greater { self.keys0.zvl_push(key0); self.joiner @@ -459,7 +459,7 @@ // INTERNAL ROUTINES FOLLOW // #[cfg(debug_assertions)] - #[allow(clippy::unwrap_used)] // this is an assertion function + #[expect(clippy::unwrap_used)] // this is an assertion function pub(crate) fn check_invariants(&self) { debug_assert_eq!(self.keys0.zvl_len(), self.joiner.len()); debug_assert_eq!(self.keys1.zvl_len(), self.values.zvl_len()); @@ -563,7 +563,7 @@ } else { debug_assert!(key0_index <= self.joiner.len()); // The unwrap is protected by the debug_assert above and key0_index != 0 - #[allow(clippy::unwrap_used)] + #[expect(clippy::unwrap_used)] self.joiner.get(key0_index - 1).unwrap() }; self.keys0.zvl_insert(key0_index, key0);
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/serde.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/serde.rs index 183f01a4..0f3a3fc 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/serde.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/map2d/serde.rs
@@ -101,7 +101,7 @@ K1: ZeroMapKV<'a> + ?Sized + Ord, V: ZeroMapKV<'a> + ?Sized, { - #[allow(clippy::type_complexity)] // it's a marker type, complexity doesn't matter + #[expect(clippy::type_complexity)] // it's a marker type, complexity doesn't matter marker: PhantomData<fn() -> (&'a K0::OwnedType, &'a K1::OwnedType, &'a V::OwnedType)>, } @@ -172,7 +172,6 @@ } struct TupleVecMapVisitor<K1, V> { - #[allow(clippy::type_complexity)] // it's a marker type, complexity doesn't matter marker: PhantomData<fn() -> (K1, V)>, }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/chars.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/chars.rs index ceab80c..cf66ad6 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/chars.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/chars.rs
@@ -84,7 +84,7 @@ // Validate the bytes for chunk in bytes.chunks_exact(3) { // TODO: Use slice::as_chunks() when stabilized - #[allow(clippy::indexing_slicing)] + #[expect(clippy::indexing_slicing)] // Won't panic because the chunks are always 3 bytes long let u = u32::from_le_bytes([chunk[0], chunk[1], chunk[2], 0]); char::try_from(u).map_err(|_| UleError::parse::<Self>())?;
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/encode.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/encode.rs index b940f8cf..db9bf12 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/encode.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/encode.rs
@@ -80,7 +80,7 @@ fn encode_var_ule_write(&self, mut dst: &mut [u8]) { debug_assert_eq!(self.encode_var_ule_len(), dst.len()); self.encode_var_ule_as_slices(move |slices| { - #[allow(clippy::indexing_slicing)] // by debug_assert + #[expect(clippy::indexing_slicing)] // by debug_assert for slice in slices { dst[..slice.len()].copy_from_slice(slice); dst = &mut dst[slice.len()..]; @@ -253,7 +253,7 @@ unimplemented!() } - #[allow(clippy::unwrap_used)] // TODO(#1410): Rethink length errors in VZV. + #[expect(clippy::unwrap_used)] // TODO(#1410): Rethink length errors in VZV. fn encode_var_ule_len(&self) -> usize { crate::varzerovec::components::compute_serializable_len::<T, E, F>(self).unwrap() as usize }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/macros.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/macros.rs index 955b1eb..86c82ab 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/macros.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/macros.rs
@@ -15,7 +15,7 @@ let mut result = [$default; N]; let mut i = 0; // Won't panic because i < N and arr has length N - #[allow(clippy::indexing_slicing)] + #[expect(clippy::indexing_slicing)] while i < N { result[i] = $single(arr[i]); i += 1;
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/mod.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/mod.rs index e2ce16c3..629fe62 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/mod.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/mod.rs
@@ -147,7 +147,6 @@ /// /// Keep in mind that `&[Self]` and `&[u8]` may have different lengths. #[inline] - #[allow(clippy::wrong_self_convention)] // https://github.com/rust-lang/rust-clippy/issues/7219 fn slice_as_bytes(slice: &[Self]) -> &[u8] { unsafe { slice::from_raw_parts(slice as *const [Self] as *const u8, mem::size_of_val(slice))
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/multi.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/multi.rs index 0468cba..26e4ca4 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/multi.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/multi.rs
@@ -24,7 +24,7 @@ impl<const LEN: usize, Format: VarZeroVecFormat> MultiFieldsULE<LEN, Format> { /// Compute the amount of bytes needed to support elements with lengths `lengths` #[inline] - #[allow(clippy::expect_used)] // See #1410 + #[expect(clippy::expect_used)] // See #1410 pub fn compute_encoded_len_for(lengths: [usize; LEN]) -> usize { let lengths = lengths.map(BlankSliceEncoder); crate::varzerovec::components::compute_serializable_len_without_length::<_, _, Format>(
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/niche.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/niche.rs index 35b3c40..4e81e3d 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/niche.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/niche.rs
@@ -158,7 +158,7 @@ /// /// The implementors guarantee that `N == core::mem::size_of::<Self>()` /// [`repr(transparent)`] guarantees that the layout is same as [`Option<U>`] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(transparent)] #[allow(clippy::exhaustive_structs)] // newtype #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/option.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/option.rs index 42fcc69a..353e441 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/option.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/option.rs
@@ -79,7 +79,7 @@ return Err(UleError::length::<Self>(bytes.len())); } for chunk in bytes.chunks(size) { - #[allow(clippy::indexing_slicing)] // `chunk` will have enough bytes to fit Self + #[expect(clippy::indexing_slicing)] // `chunk` will have enough bytes to fit Self match chunk[0] { // https://doc.rust-lang.org/reference/types/boolean.html // Rust booleans are always size 1, align 1 values with valid bit patterns 0x0 or 0x1 @@ -179,7 +179,7 @@ if slice.is_empty() { return Err(UleError::length::<Self>(slice.len())); } - #[allow(clippy::indexing_slicing)] // slice already verified to be nonempty + #[expect(clippy::indexing_slicing)] // slice already verified to be nonempty match slice[0] { // https://doc.rust-lang.org/reference/types/boolean.html // Rust booleans are always size 1, align 1 values with valid bit patterns 0x0 or 0x1 @@ -224,7 +224,7 @@ } } - #[allow(clippy::indexing_slicing)] // This method is allowed to panic when lengths are invalid + #[expect(clippy::indexing_slicing)] // This method is allowed to panic when lengths are invalid fn encode_var_ule_write(&self, dst: &mut [u8]) { if let Some(ref inner) = *self { debug_assert!(
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/tuple.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/tuple.rs index 0aba71c..b98333c 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/tuple.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/ule/tuple.rs
@@ -56,7 +56,7 @@ $( let j = i; i += mem::size_of::<$t>(); - #[allow(clippy::indexing_slicing)] // length checked + #[expect(clippy::indexing_slicing)] // length checked <$t>::validate_bytes(&chunk[j..i])?; )+ }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/components.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/components.rs index d5ff8c11..d100182 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/components.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/components.rs
@@ -36,7 +36,6 @@ /// /// Do not implement this trait, its internals may be changed in the future, /// and all of its associated items are hidden from the docs. -#[allow(clippy::missing_safety_doc)] // no safety section for you, don't implement this trait period #[doc(hidden)] pub unsafe trait IntegerULE: ULE { /// The error to show when unable to construct a vec @@ -432,7 +431,7 @@ /// This method is NOT allowed to call any other methods on VarZeroVecComponents since all other methods /// assume that the slice has been passed through check_indices_and_things #[inline] - #[allow(clippy::len_zero)] // more explicit to enforce safety invariants + #[expect(clippy::len_zero)] // more explicit to enforce safety invariants fn check_indices_and_things(self) -> Result<(), VarZeroVecFormatError> { if self.len() == 0 { if self.things.len() > 0 { @@ -729,12 +728,12 @@ // The first index is always 0. We don't write it, or update the idx offset. if i != 0 { let idx_limit = idx_offset + F::Index::SIZE; - #[allow(clippy::indexing_slicing)] // Function contract allows panicky behavior + #[expect(clippy::indexing_slicing)] // Function contract allows panicky behavior let idx_slice = &mut output[idx_offset..idx_limit]; // VZV expects data offsets to be stored relative to the first data block let idx = dat_offset - first_dat_offset; assert!(idx <= F::Index::MAX_VALUE as usize); - #[allow(clippy::expect_used)] // this function is explicitly panicky + #[expect(clippy::expect_used)] // this function is explicitly panicky let bytes_to_write = F::Index::iule_from_usize(idx).expect(F::Index::TOO_LARGE_ERROR); idx_slice.copy_from_slice(ULE::slice_as_bytes(&[bytes_to_write])); @@ -742,7 +741,7 @@ } let dat_limit = dat_offset + element_len; - #[allow(clippy::indexing_slicing)] // Function contract allows panicky behavior + #[expect(clippy::indexing_slicing)] // Function contract allows panicky behavior let dat_slice = &mut output[dat_offset..dat_limit]; element.encode_var_ule_write(dat_slice); debug_assert_eq!(T::validate_bytes(dat_slice), Ok(())); @@ -770,12 +769,12 @@ return; } assert!(elements.len() <= F::Len::MAX_VALUE as usize); - #[allow(clippy::expect_used)] // This function is explicitly panicky + #[expect(clippy::expect_used)] // This function is explicitly panicky let num_elements_ule = F::Len::iule_from_usize(elements.len()).expect(F::Len::TOO_LARGE_ERROR); - #[allow(clippy::indexing_slicing)] // Function contract allows panicky behavior + #[expect(clippy::indexing_slicing)] // Function contract allows panicky behavior output[0..F::Len::SIZE].copy_from_slice(ULE::slice_as_bytes(&[num_elements_ule])); - #[allow(clippy::indexing_slicing)] // Function contract allows panicky behavior + #[expect(clippy::indexing_slicing)] // Function contract allows panicky behavior write_serializable_bytes_without_length::<T, A, F>(elements, &mut output[F::Len::SIZE..]); }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/databake.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/databake.rs index 5886a00..1eec39d 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/databake.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/databake.rs
@@ -13,7 +13,8 @@ quote! { zerovec::vecs::VarZeroVec16::new() } } else { let bytes = databake::Bake::bake(&self.as_bytes(), env); - // Safe because self.as_bytes is a safe input + // Safety: bytes was obtained from a VarZeroVec via as_bytes() above, + // and thus is valid for unchecked construction. quote! { unsafe { zerovec::vecs::VarZeroVec16::from_bytes_unchecked(#bytes) } } } } @@ -26,7 +27,8 @@ quote! { zerovec::vecs::VarZeroVec32::new() } } else { let bytes = databake::Bake::bake(&self.as_bytes(), env); - // Safe because self.as_bytes is a safe input + // Safety: bytes was obtained from a VarZeroVec via as_bytes() above, + // and thus is valid for unchecked construction. quote! { unsafe { zerovec::vecs::VarZeroVec32::from_bytes_unchecked(#bytes) } } } } @@ -51,7 +53,8 @@ quote! { zerovec::vecs::VarZeroSlice16::new_empty() } } else { let bytes = databake::Bake::bake(&self.as_bytes(), env); - // Safe because self.as_bytes is a safe input + // Safety: bytes was obtained from a VarZeroSlice via as_bytes() above, + // and thus is valid for unchecked construction. quote! { unsafe { zerovec::vecs::VarZeroSlice16::from_bytes_unchecked(#bytes) } } } } @@ -64,7 +67,8 @@ quote! { zerovec::vecs::VarZeroSlice32::new_empty() } } else { let bytes = databake::Bake::bake(&self.as_bytes(), env); - // Safe because self.as_bytes is a safe input + // Safety: bytes was obtained from a VarZeroSlice via as_bytes() above, + // and thus is valid for unchecked construction. quote! { unsafe { zerovec::vecs::VarZeroSlice32::from_bytes_unchecked(#bytes) } } } }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/lengthless.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/lengthless.rs index ff43307..9659efb 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/lengthless.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/lengthless.rs
@@ -110,7 +110,7 @@ // get_indices_size() returns the start of the things slice, and get_things_range() // returns a range in-bounds of the things slice - #[allow(clippy::indexing_slicing)] + #[expect(clippy::indexing_slicing)] &mut self.entire_slice[offset..][range] } }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/serde.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/serde.rs index 7657ba4..a7f5004b 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/serde.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/serde.rs
@@ -13,7 +13,7 @@ use serde::ser::{Serialize, SerializeSeq, Serializer}; struct VarZeroVecVisitor<T: ?Sized, F: VarZeroVecFormat> { - #[allow(clippy::type_complexity)] // this is a private marker type, who cares + #[expect(clippy::type_complexity)] // this is a private marker type, who cares marker: PhantomData<(fn() -> Box<T>, F)>, }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/slice.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/slice.rs index 2305c86..6c34737 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/slice.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/slice.rs
@@ -459,7 +459,7 @@ impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Index<usize> for VarZeroSlice<T, F> { type Output = T; fn index(&self, index: usize) -> &Self::Output { - #[allow(clippy::panic)] // documented + #[expect(clippy::panic)] // documented match self.get(index) { Some(x) => x, None => panic!(
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/vec.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/vec.rs index 49e3104..b9be27c8 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/vec.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/varzerovec/vec.rs
@@ -395,7 +395,7 @@ if elements.is_empty() { VarZeroSlice::new_empty().into() } else { - #[allow(clippy::unwrap_used)] // TODO(#1410) Better story for fallibility + #[expect(clippy::unwrap_used)] // TODO(#1410) Better story for fallibility VarZeroVecOwned::try_from_elements(elements).unwrap().into() } }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/yoke_impls.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/yoke_impls.rs index ced30a6..edcd081 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/yoke_impls.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/yoke_impls.rs
@@ -107,7 +107,6 @@ } /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate -#[allow(clippy::transmute_ptr_to_ptr)] #[cfg(feature = "alloc")] unsafe impl<'a, K, V> Yokeable<'a> for ZeroMap<'static, K, V> where @@ -154,7 +153,6 @@ } /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate -#[allow(clippy::transmute_ptr_to_ptr)] #[cfg(feature = "alloc")] unsafe impl<'a, K, V> Yokeable<'a> for ZeroMapBorrowed<'static, K, V> where @@ -201,7 +199,6 @@ } /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate -#[allow(clippy::transmute_ptr_to_ptr)] #[cfg(feature = "alloc")] unsafe impl<'a, K0, K1, V> Yokeable<'a> for ZeroMap2d<'static, K0, K1, V> where @@ -250,7 +247,6 @@ } /// This impl requires enabling the optional `yoke` Cargo feature of the `zerovec` crate -#[allow(clippy::transmute_ptr_to_ptr)] #[cfg(feature = "alloc")] unsafe impl<'a, K0, K1, V> Yokeable<'a> for ZeroMap2dBorrowed<'static, K0, K1, V> where @@ -314,7 +310,7 @@ #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))] struct DeriveTest_ZeroVec<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: ZeroVec<'data, u16>, + pub _data: ZeroVec<'data, u16>, } #[test] @@ -334,7 +330,7 @@ #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))] struct DeriveTest_ZeroSlice<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: &'data ZeroSlice<u16>, + pub _data: &'data ZeroSlice<u16>, } #[test] @@ -354,7 +350,7 @@ #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))] struct DeriveTest_VarZeroVec<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: VarZeroVec<'data, str>, + pub _data: VarZeroVec<'data, str>, } #[test] @@ -374,7 +370,7 @@ #[cfg_attr(feature = "databake", databake(path = zerovec::yoke_impls::test))] struct DeriveTest_VarZeroSlice<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: &'data VarZeroSlice<str>, + pub _data: &'data VarZeroSlice<str>, } #[test] @@ -395,7 +391,7 @@ #[yoke(prove_covariance_manually)] struct DeriveTest_ZeroMap<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: ZeroMap<'data, [u8], str>, + pub _data: ZeroMap<'data, [u8], str>, } #[test] @@ -422,7 +418,7 @@ #[yoke(prove_covariance_manually)] struct DeriveTest_ZeroMapBorrowed<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: ZeroMapBorrowed<'data, [u8], str>, + pub _data: ZeroMapBorrowed<'data, [u8], str>, } #[test] @@ -449,7 +445,7 @@ #[yoke(prove_covariance_manually)] struct DeriveTest_ZeroMapWithULE<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: ZeroMap<'data, ZeroSlice<u32>, str>, + pub _data: ZeroMap<'data, ZeroSlice<u32>, str>, } #[test] @@ -476,7 +472,7 @@ #[yoke(prove_covariance_manually)] struct DeriveTest_ZeroMap2d<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: ZeroMap2d<'data, u16, u16, str>, + pub _data: ZeroMap2d<'data, u16, u16, str>, } #[test] @@ -505,7 +501,7 @@ #[yoke(prove_covariance_manually)] struct DeriveTest_ZeroMap2dBorrowed<'data> { #[cfg_attr(feature = "serde", serde(borrow))] - _data: ZeroMap2dBorrowed<'data, u16, u16, str>, + pub _data: ZeroMap2dBorrowed<'data, u16, u16, str>, } #[test]
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/databake.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/databake.rs index ad6c8e30..6c9402df 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/databake.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/databake.rs
@@ -13,6 +13,8 @@ quote! { zerovec::ZeroVec::new() } } else { let bytes = databake::Bake::bake(&self.as_bytes(), env); + // Safety: bytes was obtained from a ZeroVec via as_bytes() above, + // and thus is valid for unchecked construction. quote! { unsafe { zerovec::ZeroVec::from_bytes_unchecked(#bytes) } } } } @@ -31,6 +33,8 @@ quote! { zerovec::ZeroSlice::new_empty() } } else { let bytes = databake::Bake::bake(&self.as_bytes(), env); + // Safety: bytes was obtained from a ZeroSlice via as_bytes() above, + // and thus is valid for unchecked construction. quote! { unsafe { zerovec::ZeroSlice::from_bytes_unchecked(#bytes) } } } }
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/mod.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/mod.rs index 01d728b1..6a85984 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/mod.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/mod.rs
@@ -165,6 +165,17 @@ // this always represents a valid vector Vec::from_raw_parts(self.buf.as_ptr() as *mut U, len, self.capacity) } + + fn truncate(&mut self, max: usize) { + // SAFETY: The elements in buf are `ULE`, so they don't need to be dropped + // even if we own them. + self.buf = unsafe { + NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut( + self.buf.as_mut().as_mut_ptr(), + core::cmp::min(max, self.buf.as_ref().len()), + )) + }; + } } #[cfg(feature = "alloc")] @@ -1068,6 +1079,13 @@ Cow::Borrowed(slice) } } + + /// Truncates this vector to `min(self.len(), max)`. + #[inline] + pub fn truncated(mut self, max: usize) -> Self { + self.vector.truncate(max); + self + } } #[cfg(feature = "alloc")]
diff --git a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/slice.rs b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/slice.rs index 33188f7..c8fc576 100644 --- a/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/slice.rs +++ b/third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/src/zerovec/slice.rs
@@ -393,7 +393,7 @@ return Some(( first, // `unwrap()` must succeed, because `first()` returned `Some`. - #[allow(clippy::unwrap_used)] + #[expect(clippy::unwrap_used)] self.get_subslice(1..self.len()).unwrap(), )); } @@ -410,6 +410,10 @@ fn next(&mut self) -> Option<T> { self.0.next().copied().map(T::from_unaligned) } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.0.size_hint() + } } impl<'a, T: AsULE> ExactSizeIterator for ZeroSliceIter<'a, T> {
diff --git a/third_party/rust/zerovec/v0_11/BUILD.gn b/third_party/rust/zerovec/v0_11/BUILD.gn index 1fc78f2..e30ce243 100644 --- a/third_party/rust/zerovec/v0_11/BUILD.gn +++ b/third_party/rust/zerovec/v0_11/BUILD.gn
@@ -73,7 +73,7 @@ cargo_pkg_name = "zerovec" cargo_pkg_description = "Zero-copy vector backed by a byte array" cargo_pkg_repository = "https://github.com/unicode-org/icu4x" - cargo_pkg_version = "0.11.2" + cargo_pkg_version = "0.11.4" allow_unsafe = true
diff --git a/third_party/rust/zerovec/v0_11/README.chromium b/third_party/rust/zerovec/v0_11/README.chromium index f8bb7c2..1f44b2e8 100644 --- a/third_party/rust/zerovec/v0_11/README.chromium +++ b/third_party/rust/zerovec/v0_11/README.chromium
@@ -1,7 +1,7 @@ Name: zerovec URL: https://crates.io/crates/zerovec -Version: 0.11.2 -Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f +Version: 0.11.4 +Revision: 23b31cd3b6fe6d6d58e9211e0c87689194638efd Update Mechanism: Manual License: Unicode-3.0 License File: //third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/LICENSE
diff --git a/third_party/skia b/third_party/skia index 1d458db1c..724306d 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 1d458db1cd0d4739c4e15977113b769296342d85 +Subproject commit 724306df8a6703bd212017f3c4b2978665add579
diff --git a/third_party/spirv-headers/src b/third_party/spirv-headers/src index 97e96f9..a7361ef 160000 --- a/third_party/spirv-headers/src +++ b/third_party/spirv-headers/src
@@ -1 +1 @@ -Subproject commit 97e96f9e9defeb4bba3cfbd034dec516671dd7a3 +Subproject commit a7361efd139bf65de0e86d43b01b01e0b34d387f
diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src index 3aeaaa0..cb2f796 160000 --- a/third_party/spirv-tools/src +++ b/third_party/spirv-tools/src
@@ -1 +1 @@ -Subproject commit 3aeaaa088d37b86cff036eee1a9bf452abad7d9d +Subproject commit cb2f796b2d6da09a4fea123b061f177f767e63c8
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index 6316acd..1909eee 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit 6316acd63c017e93d4e589ba465a9181d780bced +Subproject commit 1909eee37eb8bec071d0d37a9a79d30cef17253f
diff --git a/third_party/vulkan-loader/src b/third_party/vulkan-loader/src index ffd25df..046e658 160000 --- a/third_party/vulkan-loader/src +++ b/third_party/vulkan-loader/src
@@ -1 +1 @@ -Subproject commit ffd25df8da11ee13627a9a00d9efb0f6d3aab9ed +Subproject commit 046e658417e1c1454791c1f080e26c6a22e1dd78
diff --git a/third_party/webrtc b/third_party/webrtc index 8f712e0..15152cd 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 8f712e0ae30b56cd52166dfb50c2937d2223db1a +Subproject commit 15152cd7782178a65f862b82cb6957af8d464207
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium index f0c57c3..b07cb3c4 100644 --- a/third_party/wpt_tools/README.chromium +++ b/third_party/wpt_tools/README.chromium
@@ -2,7 +2,7 @@ Short Name: wpt URL: https://github.com/web-platform-tests/wpt/ Version: N/A -Revision: 274305f54b764b53060fe959cbf1628b29a635ee +Revision: ee9d78498bdb6b4b4a431a4dc8a9e04d2d4cb64d Update Mechanism: Autoroll License: BSD-3-Clause Security Critical: no
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt index bdb6820c..a2d1852 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt
@@ -9,3 +9,4 @@ requests==2.32.3 types-requests==2.32.0.20241016 urllib3==2.2.2 +aioquic==1.2.0
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py index 29f415a..2324e04 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -896,7 +896,8 @@ "lsan_max_stack_depth": test.lsan_max_stack_depth, "mozleak_allowed": self.leak_check and test.mozleak_allowed, "mozleak_thresholds": self.leak_check and test.mozleak_threshold, - "special_powers": self.specialpowers_path and test.url_base == "/_mozilla/"} + "special_powers": self.specialpowers_path and test.url_base == "/_mozilla/", + "testdriver": True if test.test_type == "testharness" else getattr(test, "testdriver", False)} return self._settings def start(self, group_metadata=None, **kwargs): @@ -926,7 +927,8 @@ return ExecutorBrowser, {"marionette_port": self.instance.marionette_port, "extensions": extensions, "supports_devtools": True, - "supports_window_resize": True} + "supports_window_resize": True, + "testdriver": self._settings["testdriver"]} def check_crash(self, process, test): return log_gecko_crashes(self.logger, @@ -1056,7 +1058,8 @@ "lsan_allowed": test.lsan_allowed, "lsan_max_stack_depth": test.lsan_max_stack_depth, "mozleak_allowed": self.leak_check and test.mozleak_allowed, - "mozleak_thresholds": self.leak_check and test.mozleak_threshold} + "mozleak_thresholds": self.leak_check and test.mozleak_threshold, + "testdriver": False} @property def port(self):
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py index 050a96477..4977e23 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
@@ -11,7 +11,7 @@ cmd_arg, browser_command) from ..executors.executormarionette import (MarionetteTestharnessExecutor, # noqa: F401 - MarionetteRefTestExecutor, # noqa: F401 + MarionetteRefTestExecutorAndroid, # noqa: F401 MarionetteCrashtestExecutor, # noqa: F401 MarionetteWdspecExecutor) # noqa: F401 from .base import (Browser, @@ -30,7 +30,7 @@ "browser": {None: "FirefoxAndroidBrowser", "wdspec": "FirefoxAndroidWdSpecBrowser"}, "executor": {"testharness": "MarionetteTestharnessExecutor", - "reftest": "MarionetteRefTestExecutor", + "reftest": "MarionetteRefTestExecutorAndroid", "crashtest": "MarionetteCrashtestExecutor", "wdspec": "MarionetteWdspecExecutor"}, "browser_kwargs": "browser_kwargs", @@ -271,7 +271,8 @@ "lsan_max_stack_depth": test.lsan_max_stack_depth, "mozleak_allowed": self.leak_check and test.mozleak_allowed, "mozleak_thresholds": self.leak_check and test.mozleak_threshold, - "special_powers": self.specialpowers_path and test.url_base == "/_mozilla/"} + "special_powers": self.specialpowers_path and test.url_base == "/_mozilla/", + "testdriver": test.test_type == "testharness"} return self._settings def start(self, **kwargs): @@ -370,7 +371,8 @@ # that doesn't work on Android; instead they are in the profile "extensions": [], "supports_devtools": False, - "supports_window_resize": False} + "supports_window_resize": False, + "testdriver": self._settings["testdriver"]} def check_crash(self, process, test): if not os.environ.get("MINIDUMP_STACKWALK", "") and self.stackwalk_binary:
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py index 3284e6c..ced41b5 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py
@@ -287,7 +287,7 @@ self.sanitizer_enabled = sanitizer_enabled self.reuse_window = reuse_window - def get_or_create_test_window(self, protocol): + def create_test_window(self, protocol): test_window = self.protocol.testharness.persistent_test_window if test_window: try: @@ -303,7 +303,7 @@ protocol.base.set_window(protocol.testharness.runner_handle) test_window = self.protocol.testharness.persistent_test_window = None if not test_window: - test_window = super().get_or_create_test_window(protocol) + test_window = super().create_test_window(protocol) if self.reuse_window: self.logger.info(f"Created new test window {test_window}") # Without `--reuse-window`, each testharness test always creates a
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py index 93b26a73..3607960 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -27,27 +27,27 @@ ActionSequenceProtocolPart, AssertsProtocolPart, BaseProtocolPart, - TestharnessProtocolPart, - PrefsProtocolPart, - Protocol, - StorageProtocolPart, - SelectorProtocolPart, ClickProtocolPart, CookiesProtocolPart, - SendKeysProtocolPart, - TestDriverProtocolPart, CoverageProtocolPart, - GenerateTestReportProtocolPart, - VirtualAuthenticatorProtocolPart, - WindowProtocolPart, - SetPermissionProtocolPart, - PrintProtocolPart, DebugProtocolPart, - VirtualSensorProtocolPart, DevicePostureProtocolPart, - VirtualPressureSourceProtocolPart, DisplayFeaturesProtocolPart, + GenerateTestReportProtocolPart, + PrefsProtocolPart, + PrintProtocolPart, + Protocol, + SelectorProtocolPart, + SendKeysProtocolPart, + SetPermissionProtocolPart, + StorageProtocolPart, + TestDriverProtocolPart, + TestharnessProtocolPart, + VirtualAuthenticatorProtocolPart, + VirtualPressureSourceProtocolPart, + VirtualSensorProtocolPart, WebExtensionsProtocolPart, + WindowProtocolPart, merge_dicts) @@ -474,6 +474,22 @@ def setup(self): self.marionette = self.parent.marionette + def run(self, url, script_resume, test_window=None): + if test_window is None: + test_window = self.parent.base.current_window + + handler = MarionetteCallbackHandler(self.logger, self.parent, test_window) + self.parent.marionette.navigate(url) + while True: + result = self.get_next_message(url, script_resume, test_window) + if result is None: + # This can happen if we get an content process crash + return None + done, rv = handler(result) + if done: + break + return rv + def send_message(self, cmd_id, message_type, status, message=None): obj = { "cmd_id": cmd_id, @@ -484,6 +500,10 @@ obj["message"] = str(message) self.parent.base.execute_script("window.postMessage(%s, '*')" % json.dumps(obj)) + def get_next_message(self, url, script_resume, test_window): + return self.parent.base.execute_script( + script_resume, args=[strip_server(url)], asynchronous=True) + def _switch_to_frame(self, index_or_elem): try: self.marionette.switch_to_frame(index_or_elem) @@ -729,6 +749,7 @@ def remove_virtual_pressure_source(self, source_type): raise NotImplementedError("remove_virtual_pressure_source not yet implemented") + class MarionetteDisplayFeaturesProtocolPart(DisplayFeaturesProtocolPart): def setup(self): self.marionette = self.parent.marionette @@ -846,7 +867,7 @@ return True def on_environment_change(self, old_environment, new_environment): - #Unset all the old prefs + # Unset all the old prefs for name in old_environment.get("prefs", {}).keys(): value = self.executor.original_pref_values[name] if value is None: @@ -1021,17 +1042,7 @@ if self.debug_test and self.browser.supports_devtools: self.protocol.debug.load_devtools() - handler = MarionetteCallbackHandler(self.logger, protocol, test_window) - protocol.marionette.navigate(url) - while True: - result = protocol.base.execute_script( - self.script_resume, args=[strip_server(url)], asynchronous=True) - if result is None: - # This can happen if we get an content process crash - return None - done, rv = handler(result) - if done: - break + rv = protocol.testdriver.run(url, self.script_resume, test_window=test_window) if self.protocol.coverage.is_enabled: self.protocol.coverage.dump() @@ -1041,6 +1052,7 @@ class MarionetteRefTestExecutor(RefTestExecutor): is_print = False + supports_testdriver = True def __init__(self, logger, browser, server_config, timeout_multiplier=1, screenshot_cache=None, close_after_done=True, @@ -1059,18 +1071,11 @@ self.protocol = MarionetteProtocol(self, browser, capabilities, timeout_multiplier, kwargs["e10s"], ccov) - self.implementation = self.get_implementation(reftest_internal) - self.implementation_kwargs = {} - if reftest_internal: - self.implementation_kwargs["screenshot"] = reftest_screenshot - self.implementation_kwargs["chrome_scope"] = False - # Older versions of Gecko require switching to chrome scope to run refests - if browser_version is not None: - try: - major_version = int(browser_version.split(".")[0]) - self.implementation_kwargs["chrome_scope"] = major_version < 82 - except ValueError: - pass + implementation, implementation_kwargs = self.get_implementation(reftest_internal, + reftest_screenshot, + browser_version) + self.implementation = implementation + self.implementation_kwargs = implementation_kwargs self.close_after_done = close_after_done self.has_window = False self.original_pref_values = {} @@ -1083,9 +1088,22 @@ with open(os.path.join(here, "test-wait.js")) as f: self.wait_script = f.read() % {"classname": "reftest-wait"} - def get_implementation(self, reftest_internal): - return (InternalRefTestImplementation if reftest_internal - else RefTestImplementation)(self) + def get_implementation(self, reftest_internal, reftest_screenshot, browser_version): + kwargs = {} + if reftest_internal and not self.browser.testdriver: + cls = InternalRefTestImplementation + kwargs["screenshot"] = reftest_screenshot + kwargs["chrome_scope"] = False + # Older versions of Gecko require switching to chrome scope to run refests + if browser_version is not None: + try: + major_version = int(browser_version.split(".")[0]) + kwargs["chrome_scope"] = major_version < 82 + except ValueError: + pass + else: + cls = RefTestImplementation + return cls(self), kwargs def setup(self, runner, protocol=None): super().setup(runner, protocol) @@ -1179,9 +1197,7 @@ self.extra_timeout).run() def _screenshot(self, protocol, url, timeout): - protocol.marionette.navigate(url) - - protocol.base.execute_script(self.wait_script, asynchronous=True) + protocol.testdriver.run(url, self.wait_script) screenshot = protocol.marionette.screenshot(full=False) # strip off the data:img/png, part of the url @@ -1191,6 +1207,13 @@ return screenshot +class MarionetteRefTestExecutorAndroid(MarionetteRefTestExecutor): + # Android doesn't support window resize, so we can't use the external reftest implementation. + # That is only used for testdriver so we have a version that will skip those tests specifically + # for Android. + supports_testdriver = False + + class InternalRefTestImplementation(RefTestImplementation): def __init__(self, executor): self.timeout_multiplier = executor.timeout_multiplier @@ -1257,6 +1280,8 @@ class MarionetteCrashtestExecutor(CrashtestExecutor): + supports_testdriver = True + def __init__(self, logger, browser, server_config, timeout_multiplier=1, debug_info=None, capabilities=None, debug=False, ccov=False, **kwargs): @@ -1315,8 +1340,7 @@ if self.protocol.coverage.is_enabled: self.protocol.coverage.reset() - protocol.base.load(url) - protocol.base.execute_script(self.wait_script, asynchronous=True) + protocol.testdriver.run(url, self.wait_script) if self.protocol.coverage.is_enabled: self.protocol.coverage.dump() @@ -1327,6 +1351,7 @@ class MarionettePrintRefTestExecutor(MarionetteRefTestExecutor): is_print = True + supports_testdriver = False def __init__(self, logger, browser, server_config, timeout_multiplier=1, screenshot_cache=None, close_after_done=True, @@ -1355,10 +1380,6 @@ if not isinstance(self.implementation, InternalRefTestImplementation): self.protocol.pdf_print.load_runner() - def get_implementation(self, reftest_internal): - return (InternalRefTestImplementation if reftest_internal - else RefTestImplementation)(self) - def screenshot(self, test, viewport_size, dpi, page_ranges): # https://github.com/web-platform-tests/wpt/issues/7140 assert dpi is None
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservo.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservo.py index 7b0a64a6..d983cf0 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservo.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorservo.py
@@ -173,7 +173,10 @@ prefix = "ALERT: RESULT: " decoded_line = line.decode("utf8", "replace") if decoded_line.startswith(prefix): - self.result_data = json.loads(decoded_line[len(prefix):]) + try: + self.result_data = json.loads(decoded_line[len(prefix):]) + except json.JSONDecodeError as error: + self.logger.error(f"Could not process test output JSON: {error}") self.result_flag.set() else: ServoExecutor.on_output(self, line)
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py index dbf985cf..e4127f1 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
@@ -592,6 +592,107 @@ def setup(self): self.webdriver = self.parent.webdriver + def run(self, url, script_resume, test_window=None): + # If protocol implements `bidi_events`, remove all the existing subscriptions. + if hasattr(self.parent, 'bidi_events'): + # Use protocol loop to run the async cleanup. + self.parent.loop.run_until_complete(self.parent.bidi_events.unsubscribe_all()) + + if test_window is None: + test_window = self.parent.base.current_window + + # Exceptions occurred outside the main loop. + unexpected_exceptions = [] + + if hasattr(self.parent, 'bidi_events'): + # If protocol implements `bidi_events`, forward all the events to test_driver. + async def process_bidi_event(method, params): + try: + self.logger.debug(f"Received bidi event: {method}, {params}") + if hasattr(self.parent, 'bidi_browsing_context') and method == "browsingContext.userPromptOpened" and \ + params["context"] == test_window: + # User prompts of the test window are handled separately. In classic + # implementation, this user prompt always causes an exception when + # `protocol.testdriver.get_next_message()` is called. In BiDi it's not the + # case, as the BiDi protocol allows sending commands even with the user + # prompt opened. However, the user prompt can block the testdriver JS + # execution and cause a dead loop. To overcome this issue, the user prompt + # of the test window is always dismissed and the test is failing. + try: + await self.parent.bidi_browsing_context.handle_user_prompt(params["context"]) + except Exception as e: + if "no such alert" in str(e): + # The user prompt is already dismissed by WebDriver BiDi server. Ignore the exception. + pass + else: + # The exception is unexpected. Re-raising it to handle it in the main loop. + raise e + raise Exception("Unexpected user prompt in test window: %s" % params) + else: + self.send_message(-1, "event", method, json.dumps({ + "params": params, + "method": method})) + except Exception as e: + # As the event listener is async, the exceptions should be added to the list to be processed in the + # main loop. + self.logger.error("BiDi event processing failed: %s" % e) + unexpected_exceptions.append(e) + + self.parent.bidi_events.add_event_listener(None, process_bidi_event) + self.parent.loop.run_until_complete(self.parent.bidi_events.subscribe(['browsingContext.userPromptOpened'], None)) + + # If possible, support async actions. + if hasattr(self.parent, 'loop'): + handler = WebDriverAsyncCallbackHandler(self.logger, self.parent, test_window, self.parent.loop) + else: + handler = WebDriverCallbackHandler(self.logger, self.parent, test_window) + + self.webdriver.url = url + + while True: + if len(unexpected_exceptions) > 0: + # TODO: what to do if there are more then 1 unexpected exceptions? + raise unexpected_exceptions[0] + + test_driver_message = self.get_next_message(url, script_resume, test_window) + self.logger.debug("Receive message from testdriver: %s" % test_driver_message) + + # As of 2019-03-29, WebDriver does not define expected behavior for + # cases where the browser crashes during script execution: + # + # https://github.com/w3c/webdriver/issues/1308 + if not isinstance(test_driver_message, list) or len(test_driver_message) != 3: + try: + is_alive = self.parent.is_alive() + except webdriver_error.WebDriverException: + is_alive = False + if not is_alive: + raise Exception("Browser crashed during script execution.") + + # In case of WebDriver Classic, a user prompt created after starting execution of the resume script will + # resolve the script with `null` [1, 2]. In that case, cycle this event loop and handle the prompt the next + # time the resume script executes. + # + # [1]: Step 5.3 of https://www.w3.org/TR/webdriver/#execute-async-script + # [2]: https://www.w3.org/TR/webdriver/#dfn-execute-a-function-body + if test_driver_message is None: + continue + + done, rv = handler(test_driver_message) + if done: + break + + # If protocol implements `bidi_events`, remove all the existing subscriptions. + if hasattr(self.parent, 'bidi_events'): + # Use protocol loop to run the async cleanup. + self.parent.loop.run_until_complete(self.parent.bidi_events.unsubscribe_all()) + + if len(unexpected_exceptions) > 0: + # TODO: what to do if there are more then 1 unexpected exceptions? + raise unexpected_exceptions[0] + + return rv + def get_next_message(self, url, script_resume, test_window): if hasattr(self.parent, "bidi_script"): # If `bidi_script` is available, the messages can be handled via BiDi. @@ -1012,115 +1113,7 @@ self.result_flag.set() -class TestDriverExecutorMixin: - def __init__(self, script_resume: str): - self.script_resume = script_resume - - def run_testdriver(self, protocol, url, timeout): - # If protocol implements `bidi_events`, remove all the existing subscriptions. - if hasattr(protocol, 'bidi_events'): - # Use protocol loop to run the async cleanup. - protocol.loop.run_until_complete(protocol.bidi_events.unsubscribe_all()) - - test_window = self.get_or_create_test_window(protocol) - # Exceptions occurred outside the main loop. - unexpected_exceptions = [] - - if hasattr(protocol, 'bidi_events'): - # If protocol implements `bidi_events`, forward all the events to test_driver. - async def process_bidi_event(method, params): - try: - self.logger.debug(f"Received bidi event: {method}, {params}") - if hasattr(protocol, 'bidi_browsing_context') and method == "browsingContext.userPromptOpened" and \ - params["context"] == test_window: - # User prompts of the test window are handled separately. In classic - # implementation, this user prompt always causes an exception when - # `protocol.testdriver.get_next_message()` is called. In BiDi it's not the - # case, as the BiDi protocol allows sending commands even with the user - # prompt opened. However, the user prompt can block the testdriver JS - # execution and cause a dead loop. To overcome this issue, the user prompt - # of the test window is always dismissed and the test is failing. - try: - await protocol.bidi_browsing_context.handle_user_prompt(params["context"]) - except Exception as e: - if "no such alert" in str(e): - # The user prompt is already dismissed by WebDriver BiDi server. Ignore the exception. - pass - else: - # The exception is unexpected. Re-raising it to handle it in the main loop. - raise e - raise Exception("Unexpected user prompt in test window: %s" % params) - else: - protocol.testdriver.send_message(-1, "event", method, json.dumps({ - "params": params, - "method": method})) - except Exception as e: - # As the event listener is async, the exceptions should be added to the list to be processed in the - # main loop. - self.logger.error("BiDi event processing failed: %s" % e) - unexpected_exceptions.append(e) - - protocol.bidi_events.add_event_listener(None, process_bidi_event) - protocol.loop.run_until_complete(protocol.bidi_events.subscribe(['browsingContext.userPromptOpened'], None)) - - # If possible, support async actions. - if hasattr(protocol, 'loop'): - handler = WebDriverAsyncCallbackHandler(self.logger, protocol, test_window, protocol.loop) - else: - handler = WebDriverCallbackHandler(self.logger, protocol, test_window) - - protocol.webdriver.url = url - - while True: - if len(unexpected_exceptions) > 0: - # TODO: what to do if there are more then 1 unexpected exceptions? - raise unexpected_exceptions[0] - - test_driver_message = protocol.testdriver.get_next_message(url, self.script_resume, - test_window) - self.logger.debug("Receive message from testdriver: %s" % test_driver_message) - - # As of 2019-03-29, WebDriver does not define expected behavior for - # cases where the browser crashes during script execution: - # - # https://github.com/w3c/webdriver/issues/1308 - if not isinstance(test_driver_message, list) or len(test_driver_message) != 3: - try: - is_alive = protocol.is_alive() - except webdriver_error.WebDriverException: - is_alive = False - if not is_alive: - raise Exception("Browser crashed during script execution.") - - # In case of WebDriver Classic, a user prompt created after starting execution of the resume script will - # resolve the script with `null` [1, 2]. In that case, cycle this event loop and handle the prompt the next - # time the resume script executes. - # - # [1]: Step 5.3 of https://www.w3.org/TR/webdriver/#execute-async-script - # [2]: https://www.w3.org/TR/webdriver/#dfn-execute-a-function-body - if test_driver_message is None: - continue - - done, rv = handler(test_driver_message) - if done: - break - - # If protocol implements `bidi_events`, remove all the existing subscriptions. - if hasattr(protocol, 'bidi_events'): - # Use protocol loop to run the async cleanup. - protocol.loop.run_until_complete(protocol.bidi_events.unsubscribe_all()) - - if len(unexpected_exceptions) > 0: - # TODO: what to do if there are more then 1 unexpected exceptions? - raise unexpected_exceptions[0] - - return rv - - def get_or_create_test_window(self, protocol): - return protocol.base.current_window - - -class WebDriverTestharnessExecutor(TestharnessExecutor, TestDriverExecutorMixin): +class WebDriverTestharnessExecutor(TestharnessExecutor): supports_testdriver = True protocol_cls = WebDriverProtocol @@ -1133,8 +1126,7 @@ debug_info=debug_info) self.protocol = self.protocol_cls(self, browser, capabilities) with open(os.path.join(here, "testharness_webdriver_resume.js")) as f: - script_resume = f.read() - TestDriverExecutorMixin.__init__(self, script_resume) + self.script_resume = f.read() with open(os.path.join(here, "window-loaded.js")) as f: self.window_loaded_script = f.read() @@ -1177,6 +1169,8 @@ # The previous test may not have closed its old windows (if something # went wrong or if cleanup_after_test was False), so clean up here. protocol.testharness.close_old_windows() + + test_window = self.create_test_window(protocol) # Restore the window to the initial position if self.initial_window_size: try: @@ -1184,7 +1178,7 @@ except Exception: pass - raw_results = self.run_testdriver(protocol, url, timeout) + raw_results = protocol.testdriver.run(url, self.script_resume, test_window) extra = {} if counters := self._check_for_leaks(protocol): extra["leak_counters"] = counters @@ -1213,7 +1207,7 @@ finally: protocol.base.set_window(protocol.testharness.runner_handle) - def get_or_create_test_window(self, protocol): + def create_test_window(self, protocol): test_window = protocol.base.create_window() protocol.base.set_window(test_window) # Wait until about:blank has been loaded @@ -1221,7 +1215,7 @@ return test_window -class WebDriverRefTestExecutor(RefTestExecutor, TestDriverExecutorMixin): +class WebDriverRefTestExecutor(RefTestExecutor): protocol_cls = WebDriverProtocol supports_testdriver = True @@ -1247,8 +1241,7 @@ self.debug_test = debug_test with open(os.path.join(here, "test-wait.js")) as f: - wait_script = f.read() % {"classname": "reftest-wait"} - TestDriverExecutorMixin.__init__(self, wait_script) + self.wait_script = f.read() % {"classname": "reftest-wait"} def reset(self): self.implementation.reset() @@ -1295,7 +1288,7 @@ def _screenshot(self, protocol, url, timeout): # There's nothing we want from the "complete" message, so discard the # return value. - self.run_testdriver(protocol, url, timeout) + protocol.testdriver.run(url, self.wait_script) screenshot = self.protocol.webdriver.screenshot() if screenshot is None: @@ -1342,7 +1335,7 @@ def _render(self, protocol, url, timeout): # There's nothing we want from the "complete" message, so discard the # return value. - self.run_testdriver(protocol, url, timeout) + protocol.testdriver.run(url, self.wait_script) pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size) screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges) @@ -1354,7 +1347,7 @@ return screenshots -class WebDriverCrashtestExecutor(CrashtestExecutor, TestDriverExecutorMixin): +class WebDriverCrashtestExecutor(CrashtestExecutor): protocol_cls = WebDriverProtocol supports_testdriver = True @@ -1374,8 +1367,7 @@ capabilities=capabilities) with open(os.path.join(here, "test-wait.js")) as f: - wait_script = f.read() % {"classname": "test-wait"} - TestDriverExecutorMixin.__init__(self, wait_script) + self.wait_script = f.read() % {"classname": "test-wait"} def do_test(self, test): timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None @@ -1396,7 +1388,7 @@ def do_crashtest(self, protocol, url, timeout): # There's nothing we want from the "complete" message, so discard the # return value. - self.run_testdriver(protocol, url, timeout) + protocol.testdriver.run(url, self.wait_script) result = {"status": "PASS", "message": None} if (leak_part := getattr(protocol, "leak", None)) and (counters := leak_part.check()): result["extra"] = {"leak_counters": counters}
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py index d745b31..8af313d 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/protocol.py
@@ -761,6 +761,29 @@ name = "testdriver" @abstractmethod + def run(self, url, script_resume, test_window=None): + """Run a test using the testdriver protocol + + :param str url: URL of the test + :param str script_resume: Script to run implementing the browser + side of the protocol + :param test_window: Optional test window handle, otherwise the + current active window is used. + :returns: Test result data""" + pass + + @abstractmethod + def get_next_message(self, url, script_resume, test_window): + """Get the next message from the browser + + :param str url: URL of the current test + :param str script_resume: Script implementing the browsr + side of the protocol. + :param test_window: Window handle of the test window + :returns: Testdriver message dict""" + pass + + @abstractmethod def send_message(self, cmd_id, message_type, status, message=None): """Send a testdriver message to the browser.
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py index 75788f7..7169a75 100755 --- a/tools/clang/scripts/build.py +++ b/tools/clang/scripts/build.py
@@ -1146,7 +1146,7 @@ # Train by building some C++ code. # - # pgo_training-1.ii is a preprocessed (on Linux) version of + # pgo_training-3.ii is a preprocessed (on Linux) version of # src/third_party/blink/renderer/core/layout/layout_object.cc, selected # because it's a large translation unit in Blink, which is normally the # slowest part of Chromium to compile. Using this, we get ~20% shorter @@ -1167,11 +1167,11 @@ # from PGO as well. Perhaps the training could be done asynchronously by # dedicated buildbots that upload profiles to the cloud. with timer.time('pgo training'): - training_source = 'pgo_training-1.ii' + training_source = 'pgo_training-3.ii' with open(training_source, 'wb') as f: DownloadUrl(CDS_URL + '/' + training_source, f) train_cmd = [os.path.join(LLVM_INSTRUMENTED_DIR, 'bin', 'clang++'), - '-target', 'x86_64-unknown-unknown', '-O2', '-g', '-std=c++14', + '-target', 'x86_64-unknown-unknown', '-O2', '-g', '-std=c++20', '-fno-exceptions', '-fno-rtti', '-w', '-c', training_source] if sys.platform == 'darwin': train_cmd.extend(['-isysroot', isysroot])
diff --git a/tools/clang/spanify/Spanifier.cpp b/tools/clang/spanify/Spanifier.cpp index e1399fd29..0bb35ee 100644 --- a/tools/clang/spanify/Spanifier.cpp +++ b/tools/clang/spanify/Spanifier.cpp
@@ -92,9 +92,9 @@ // that the `loc` is at a macro argument of the exceptional macros (EXPECT_ and // ASSERT_ family). // Tests are in: gtest-macro-original.cc -static bool IsInExcludedMacro(clang::SourceLocation loc, - const clang::ASTContext& ast_context, - const clang::SourceManager& source_manager) { +bool IsInExcludedMacro(clang::SourceLocation loc, + const clang::ASTContext& ast_context, + const clang::SourceManager& source_manager) { if (!loc.isMacroID()) [[likely]] { return false; } @@ -505,11 +505,10 @@ Emit(llvm::formatv("f {0} {1} {2}\n", lhs_key, rhs_key, replacement)); } -static std::string GetReplacementDirective( - const clang::SourceRange& replacement_range, - std::string replacement_text, - const clang::SourceManager& source_manager, - int precedence = kNeutralPrecedence) { +std::string GetReplacementDirective(const clang::SourceRange& replacement_range, + std::string replacement_text, + const clang::SourceManager& source_manager, + int precedence = kNeutralPrecedence) { clang::tooling::Replacement replacement( source_manager, clang::CharSourceRange::getCharRange(replacement_range), replacement_text); @@ -551,22 +550,18 @@ return node; } -// The semantics of `getBeginLoc()` and `getEndLoc()` are somewhat -// surprising (e.g. https://stackoverflow.com/a/59718238). This function -// tries to do the least surprising thing, specializing for +// Returns a function that, given the SourceLocation argument, tries to get the +// spelling location (= the original code location before macro expansion) if +// the given SourceLocation is at a macro argument. // -// * `clang::MemberExpr` -// * `clang::DeclRefExpr` -// * `clang::CallExpr` +// Note that `source_manager` and `lang_opts` arguments must outlive the +// returned function because the returned function references them. // -// and defaults to returning the range of token `expr`. -clang::SourceRange getExprRange(const clang::Expr* expr, - const clang::SourceManager& source_manager, - const clang::LangOptions& lang_opts) { - // When the given `loc` is inside a macro expansion, tries to get the spelling - // location (= the original code location before the macro expansion). - // Tests are in: gtest-macro-original.cc - auto ToSpellingLoc = [&](clang::SourceLocation loc) -> clang::SourceLocation { +// Tests are in: gtest-macro-original.cc +std::function<clang::SourceLocation(clang::SourceLocation)> GetSpellingLocFunc( + const clang::SourceManager& source_manager [[clang::lifetimebound]], + const clang::LangOptions& lang_opts [[clang::lifetimebound]]) { + return [&](clang::SourceLocation loc) -> clang::SourceLocation { if (!loc.isMacroID()) [[likely]] { return loc; } @@ -576,15 +571,30 @@ } return loc.isValid() && loc.isFileID() ? loc : original_loc; }; +} - if (const auto* member_expr = clang::dyn_cast<clang::MemberExpr>(expr)) { +// The semantics of `getBeginLoc()` and `getEndLoc()` are somewhat +// surprising (e.g. https://stackoverflow.com/a/59718238). This function +// tries to do the least surprising thing, specializing for +// +// * `clang::MemberExpr` +// * `clang::DeclRefExpr` +// * `clang::CallExpr` +// +// and defaults to returning the range of token `expr`. +clang::SourceRange GetExprRange(const clang::Expr& expr, + const clang::SourceManager& source_manager, + const clang::LangOptions& lang_opts) { + auto ToSpellingLoc = GetSpellingLocFunc(source_manager, lang_opts); + + if (const auto* member_expr = clang::dyn_cast<clang::MemberExpr>(&expr)) { clang::SourceLocation member_loc = ToSpellingLoc(member_expr->getMemberLoc()); size_t member_name_length = member_expr->getMemberDecl()->getName().size(); return {member_loc, member_loc.getLocWithOffset(member_name_length)}; } - if (const auto* decl_ref = clang::dyn_cast<clang::DeclRefExpr>(expr)) { + if (const auto* decl_ref = clang::dyn_cast<clang::DeclRefExpr>(&expr)) { assert(decl_ref->getBeginLoc() == decl_ref->getEndLoc() && "DeclRefExpr doesn't have the expected end loc."); clang::SourceLocation begin_loc = ToSpellingLoc(decl_ref->getBeginLoc()); @@ -592,7 +602,7 @@ return {begin_loc, begin_loc.getLocWithOffset(name.size())}; } - if (const auto* call_expr = clang::dyn_cast<clang::CallExpr>(expr)) { + if (const auto* call_expr = clang::dyn_cast<clang::CallExpr>(&expr)) { // Disclaimer: This doesn't support edge cases like following. // #define MY_MACRO(func) func // MY_MACRO(func)(arg1, arg2); @@ -601,24 +611,24 @@ ToSpellingLoc(call_expr->getRParenLoc()).getLocWithOffset(1)}; } - if (auto* binary_op = clang::dyn_cast<clang::BinaryOperator>(expr)) { + if (auto* binary_op = clang::dyn_cast<clang::BinaryOperator>(&expr)) { // Disclaimer: This doesn't support edge cases like following. // #define MY_MACRO(arg) arg // MY_MACRO(1) + 2; // The returned range will be `1) + 2`. // MY_MACRO(1 +) 2; // The returned range will be `1 +) 2`. return { - ToSpellingLoc(expr->getBeginLoc()), - getExprRange(binary_op->getRHS(), source_manager, lang_opts).getEnd()}; + ToSpellingLoc(expr.getBeginLoc()), + GetExprRange(*binary_op->getRHS(), source_manager, lang_opts).getEnd()}; } if (auto* uett_expr = - clang::dyn_cast<clang::UnaryExprOrTypeTraitExpr>(expr)) { + clang::dyn_cast<clang::UnaryExprOrTypeTraitExpr>(&expr)) { if (uett_expr->getKind() == clang::UETT_SizeOf) { // Somehow in case of sizeof expr, the last token is not included in the // source range. So skip the next token after the end loc. - assert(expr->getBeginLoc() != expr->getEndLoc()); - clang::SourceLocation begin_loc = ToSpellingLoc(expr->getBeginLoc()); - clang::SourceLocation end_loc = ToSpellingLoc(expr->getEndLoc()); + assert(expr.getBeginLoc() != expr.getEndLoc()); + clang::SourceLocation begin_loc = ToSpellingLoc(expr.getBeginLoc()); + clang::SourceLocation end_loc = ToSpellingLoc(expr.getEndLoc()); size_t token_length = clang::Lexer::MeasureTokenLength(end_loc, source_manager, lang_opts); return {begin_loc, end_loc.getLocWithOffset(token_length)}; @@ -626,9 +636,9 @@ } // Somehow single token expressions do not have the expected end location. - assert(expr->getBeginLoc() == expr->getEndLoc() && + assert(expr.getBeginLoc() == expr.getEndLoc() && "Defaults to a single token expr."); - clang::SourceLocation begin_loc = ToSpellingLoc(expr->getBeginLoc()); + clang::SourceLocation begin_loc = ToSpellingLoc(expr.getBeginLoc()); size_t token_length = clang::Lexer::MeasureTokenLength(begin_loc, source_manager, lang_opts); return {begin_loc, begin_loc.getLocWithOffset(token_length)}; @@ -651,43 +661,55 @@ // type* ptr = reinterpret_cast<type*>(buf); where buf needs to be rewritten // to span and ptr doesn't. The `.data()` call is added right after buffer as // follows: type* ptr = reinterpret_cast<type*>(buf.data()); -static clang::SourceRange getSourceRange( - const MatchFinder::MatchResult& result) { +clang::SourceRange getSourceRange(const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const clang::LangOptions& lang_opts = result.Context->getLangOpts(); + + auto ToSpellingLoc = GetSpellingLocFunc(source_manager, lang_opts); + if (auto* op = result.Nodes.getNodeAs<clang::UnaryOperator>("unaryOperator")) { if (op->isPostfix()) { - return {op->getBeginLoc(), op->getEndLoc().getLocWithOffset(2)}; + return {ToSpellingLoc(op->getBeginLoc()), + ToSpellingLoc(op->getEndLoc()).getLocWithOffset(2)}; } auto* expr = result.Nodes.getNodeAs<clang::Expr>("rhs_expr"); - return {op->getBeginLoc(), - getExprRange(expr, source_manager, lang_opts).getEnd()}; + // Disclaimer: This doesn't support edge cases like following. + // #define MACRO(var) var + // ++MACRO(rhs); // The range will be `++MACRO(rhs`. + return {ToSpellingLoc(op->getBeginLoc()), + GetExprRange(*expr, source_manager, lang_opts).getEnd()}; } + if (auto* op = result.Nodes.getNodeAs<clang::Expr>("binaryOperator")) { auto* sub_expr = result.Nodes.getNodeAs<clang::Expr>("binary_op_rhs"); - auto end_loc = getExprRange(sub_expr, source_manager, lang_opts).getEnd(); - return {op->getBeginLoc(), end_loc}; + auto end_loc = GetExprRange(*sub_expr, source_manager, lang_opts).getEnd(); + // Disclaimer: This doesn't support edge cases like following. + // #define MACRO(var) var + // MACRO(lhs) + MACRO(rhs); // The range will be `lhs) + MACRO(rhs`. + return {ToSpellingLoc(op->getBeginLoc()), end_loc}; } + if (auto* op = result.Nodes.getNodeAs<clang::CXXOperatorCallExpr>( "raw_ptr_operator++")) { auto* callee = op->getDirectCallee(); if (callee->getNumParams() == 0) { // postfix op++ on raw_ptr; auto* expr = result.Nodes.getNodeAs<clang::Expr>("rhs_expr"); return clang::SourceRange( - getExprRange(expr, source_manager, lang_opts).getEnd()); + GetExprRange(*expr, source_manager, lang_opts).getEnd()); } - return clang::SourceRange(op->getEndLoc().getLocWithOffset(2)); + return clang::SourceRange( + ToSpellingLoc(op->getEndLoc()).getLocWithOffset(2)); } if (auto* expr = result.Nodes.getNodeAs<clang::Expr>("rhs_expr")) { return clang::SourceRange( - getExprRange(expr, source_manager, lang_opts).getEnd()); + GetExprRange(*expr, source_manager, lang_opts).getEnd()); } if (auto* size_expr = result.Nodes.getNodeAs<clang::Expr>("size_node")) { return clang::SourceRange( - getExprRange(size_expr, source_manager, lang_opts).getEnd()); + GetExprRange(*size_expr, source_manager, lang_opts).getEnd()); } // Not supposed to get here. @@ -703,57 +725,8 @@ assert(false && "Unexpected match in getSourceRange()"); } -static void maybeUpdateSourceRangeIfInMacro( - const clang::SourceManager& source_manager, - const MatchFinder::MatchResult& result, - clang::SourceRange& range) { - if (!range.isValid() || !range.getBegin().isMacroID()) { - return; - } - // We need to find the reference to the object that might be getting - // accessed and rewritten to find the location to rewrite. SpellingLocation - // returns a different position if the source was pointing into the macro - // definition. See clang::SourceManager for details but relevant section: - // - // "Spelling locations represent where the bytes corresponding to a token came - // from and expansion locations represent where the location is in the user's - // view. In the case of a macro expansion, for example, the spelling location - // indicates where the expanded token came from and the expansion location - // specifies where it was expanded." - auto* rhs_decl_ref = - result.Nodes.getNodeAs<clang::DeclRefExpr>("declRefExpr"); - if (!rhs_decl_ref) { - return; - } - // We're extracting the spellingLocation's position and then we'll move the - // location forward by the length of the variable. This will allow us to - // insert .data() at the end of the decl_ref. - clang::SourceLocation correct_start = - source_manager.getSpellingLoc(rhs_decl_ref->getLocation()); - - bool invalid_line, invalid_col = false; - auto line = - source_manager.getSpellingLineNumber(correct_start, &invalid_line); - auto col = - source_manager.getSpellingColumnNumber(correct_start, &invalid_col); - assert(correct_start.isValid() && !invalid_line && !invalid_col && - "Unable to get SpellingLocation info"); - // Get the name and find the end of the decl_ref. - std::string name = rhs_decl_ref->getFoundDecl()->getNameAsString(); - clang::SourceLocation correct_end = source_manager.translateLineCol( - source_manager.getFileID(correct_start), line, col + name.size()); - assert(correct_end.isValid() && - "Incorrectly got an End SourceLocation for macro"); - // This returns at the end of the variable being referenced so we can - // insert .data(), if we wanted it wrapped in params (variable).data() - // we'd need {correct_start, correct_end} but this doesn't seem needed in - // macros tested on so far. - range = clang::SourceRange{correct_end}; -} - -static std::string getNodeFromPointerTypeLoc( - const clang::PointerTypeLoc* type_loc, - const MatchFinder::MatchResult& result) { +std::string getNodeFromPointerTypeLoc(const clang::PointerTypeLoc* type_loc, + 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(); @@ -826,7 +799,7 @@ return key; } -static std::string getNodeFromRawPtrTypeLoc( +std::string getNodeFromRawPtrTypeLoc( const clang::TemplateSpecializationTypeLoc* raw_ptr_type_loc, const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; @@ -849,7 +822,7 @@ // Example: // void fct(int arr[]) => void fct(base::span<int> arr) // void fct(int arr[3]) => void fct(base::span<int, 3> arr) -static std::string getNodeFromFunctionArrayParameter( +std::string getNodeFromFunctionArrayParameter( const clang::TypeLoc* type_loc, const clang::ParmVarDecl* param_decl, const MatchFinder::MatchResult& result) { @@ -896,8 +869,8 @@ return key; } -static std::string getNodeFromDecl(const clang::DeclaratorDecl* decl, - const MatchFinder::MatchResult& result) { +std::string getNodeFromDecl(const clang::DeclaratorDecl* decl, + const MatchFinder::MatchResult& result) { clang::SourceManager& source_manager = *result.SourceManager; const clang::ASTContext& ast_context = *result.Context; @@ -936,7 +909,7 @@ return key; } -static void DecaySpanToPointer(const MatchFinder::MatchResult& result) { +void DecaySpanToPointer(const MatchFinder::MatchResult& result) { const clang::Expr* deref_expr = result.Nodes.getNodeAs<clang::Expr>("deref_expr"); const clang::SourceManager& source_manager = *result.SourceManager; @@ -964,7 +937,7 @@ kDecaySpanToPointerPrecedence)); } -static clang::SourceLocation GetBinaryOperationOperatorLoc( +clang::SourceLocation GetBinaryOperationOperatorLoc( const clang::Expr* expr, const MatchFinder::MatchResult& result) { if (auto* binary_op = clang::dyn_cast_or_null<clang::BinaryOperator>(expr)) { @@ -1010,7 +983,7 @@ using SubspanExprReplacement = std::variant<std::monostate, RangedReplacement, CheckedCastReplacement>; -static SubspanExprReplacement GetSubspanExprReplacement( +SubspanExprReplacement GetSubspanExprReplacement( const clang::Expr* expr, const MatchFinder::MatchResult& result, std::string_view key) { @@ -1027,7 +1000,7 @@ const clang::SourceManager& source_manager = *result.SourceManager; const clang::SourceRange range = - getExprRange(expr, source_manager, result.Context->getLangOpts()); + GetExprRange(*expr, source_manager, result.Context->getLangOpts()); if (const auto* integer_literal = clang::dyn_cast<clang::IntegerLiteral>(expr)) { @@ -1057,8 +1030,8 @@ // #define MACRO() (will_be_span + offset) // // See test: 'span-frontier-macro-original.cc' -static void AdaptBinaryOpInMacro(const MatchFinder::MatchResult& result, - const std::string& key) { +void AdaptBinaryOpInMacro(const MatchFinder::MatchResult& result, + const std::string& key) { const clang::SourceManager& source_manager = *result.SourceManager; const clang::ASTContext& ast_context = *result.Context; const auto& lang_opts = ast_context.getLangOpts(); @@ -1076,7 +1049,7 @@ EmitReplacement( key, GetReplacementDirective( - getExprRange(decl_ref, source_manager, lang_opts).getEnd(), + GetExprRange(*decl_ref, source_manager, lang_opts).getEnd(), ".data()", source_manager)); clang::CharSourceRange macro_range = @@ -1094,7 +1067,7 @@ // Closes an open `base::span(` if present. // Returns a `.subspan(` opener. // Opens a `base::checked_cast(` if necessary. -static std::string CreateSubspanOpener( +std::string CreateSubspanOpener( std::string_view prefix, const SubspanExprReplacement* subspan_expr_replacement) { std::string_view maybe_checked_cast_opener = ""; @@ -1108,7 +1081,7 @@ // Returns a `.subspan(` closer. // Closes an open `base::checked_cast(` if necessary, // or appends a `u` to the integer literal expression. -static std::string CreateSubspanCloser( +std::string CreateSubspanCloser( const SubspanExprReplacement* subspan_expr_replacement) { std::string_view maybe_closer = ""; if (const auto* replacement = @@ -1121,7 +1094,7 @@ return llvm::formatv("{0})", maybe_closer); } -static void AdaptBinaryOperation(const MatchFinder::MatchResult& result) { +void AdaptBinaryOperation(const MatchFinder::MatchResult& result) { const clang::ASTContext& ast_context = *result.Context; const clang::SourceManager& source_manager = *result.SourceManager; const auto* binary_operation = @@ -1193,8 +1166,8 @@ {binary_operator_begin, binary_operator_begin.getLocWithOffset(1)}, subspan_opener, source_manager, -kAdaptBinaryOperationPrecedence)); - const clang::SourceRange operator_rhs_range = getExprRange( - binary_op_RHS, source_manager, result.Context->getLangOpts()); + const clang::SourceRange operator_rhs_range = GetExprRange( + *binary_op_RHS, source_manager, result.Context->getLangOpts()); std::string subspan_closer = CreateSubspanCloser(&subspan_expr_replacement); EmitReplacement(key, GetReplacementDirective( @@ -1209,7 +1182,7 @@ source_manager)); } -static void AdaptBinaryPlusEqOperation(const MatchFinder::MatchResult& result) { +void AdaptBinaryPlusEqOperation(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(); @@ -1224,9 +1197,9 @@ // respectively. auto* lhs_expr = result.Nodes.getNodeAs<clang::Expr>("rhs_expr"); auto* binary_op_RHS = result.Nodes.getNodeAs<clang::Expr>("binary_op_RHS"); - auto lhs_expr_range = getExprRange(lhs_expr, source_manager, lang_opts); + auto lhs_expr_range = GetExprRange(*lhs_expr, source_manager, lang_opts); auto binary_op_rhs_range = - getExprRange(binary_op_RHS, source_manager, lang_opts); + GetExprRange(*binary_op_RHS, source_manager, lang_opts); auto source_range = clang::SourceRange(lhs_expr_range.getEnd(), binary_op_rhs_range.getBegin()); @@ -1260,7 +1233,7 @@ // if(expr) => if(!expr.empty()) // if(!expr) => if(expr.empty()) // Tests are in: operator-bool-original.cc -static void DecaySpanToBooleanOp(const MatchFinder::MatchResult& result) { +void DecaySpanToBooleanOp(const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const std::string& key = GetRHS(result); @@ -1459,8 +1432,8 @@ // Handles code that passes address to a local variable as a single element // buffer. Wrap it with a span of size=1. Tests are in // single-element-buffer-original.cc. -static void EmitSingleVariableSpan(const std::string& key, - const MatchFinder::MatchResult& result) { +void EmitSingleVariableSpan(const std::string& key, + const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const auto& lang_opts = result.Context->getLangOpts(); @@ -1487,7 +1460,7 @@ source_manager, kEmitSingleVariableSpanPrecedence)); EmitReplacement( key, GetReplacementDirective( - getExprRange(operand_expr, source_manager, lang_opts).getEnd(), + GetExprRange(*operand_expr, source_manager, lang_opts).getEnd(), ")", source_manager, -kEmitSingleVariableSpanPrecedence)); } @@ -1507,10 +1480,9 @@ // // Tests are in: unsafe-function-to-macro-original.cc and // //base/containers/auto_spanification_helper_unittest.cc -static void EmitUnsafeCxxMethodCall( - const std::string& key, - const clang::CXXMemberCallExpr* member_call_expr, - const MatchFinder::MatchResult& result) { +void EmitUnsafeCxxMethodCall(const std::string& key, + const clang::CXXMemberCallExpr* member_call_expr, + const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const auto* method_decl = GetNodeOrCrash<clang::CXXMethodDecl>( @@ -1583,9 +1555,9 @@ // // Tests are in: unsafe-function-to-macro-original.cc and // //base/containers/auto_spanification_helper_unittest.cc -static void EmitUnsafeFreeFuncCall(const std::string& key, - const clang::CallExpr* call_expr, - const MatchFinder::MatchResult& result) { +void EmitUnsafeFreeFuncCall(const std::string& key, + const clang::CallExpr* call_expr, + const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const auto* function_decl = GetNodeOrCrash<clang::FunctionDecl>( @@ -1610,9 +1582,9 @@ kBaseAutoSpanificationHelperIncludePath)); } -static void EmitUnsafeFunctionCall(const std::string& key, - const clang::CallExpr* call_expr, - const MatchFinder::MatchResult& result) { +void EmitUnsafeFunctionCall(const std::string& key, + const clang::CallExpr* call_expr, + const MatchFinder::MatchResult& result) { if (const clang::CXXMemberCallExpr* member_call_expr = clang::dyn_cast<clang::CXXMemberCallExpr>(call_expr)) { EmitUnsafeCxxMethodCall(key, member_call_expr, result); @@ -1632,9 +1604,9 @@ // separately. // // Tests are in: array-tests-original.cc -static void EmitCArrayIterCallExpr(const std::string& key, - const clang::CallExpr* call_expr, - const MatchFinder::MatchResult& result) { +void EmitCArrayIterCallExpr(const std::string& key, + const clang::CallExpr* call_expr, + const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const clang::LangOptions& lang_opts = result.Context->getLangOpts(); @@ -1674,8 +1646,8 @@ kBaseAutoSpanificationHelperIncludePath)); } -static std::string getNodeFromSizeExpr(const clang::Expr* size_expr, - const MatchFinder::MatchResult& result) { +std::string getNodeFromSizeExpr(const clang::Expr* size_expr, + const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const std::string key = NodeKey(size_expr, source_manager); @@ -1770,7 +1742,7 @@ // Get the source range of the operand (the 'ptr' part). clang::SourceRange operand_range = - getExprRange(operand->IgnoreParenImpCasts(), source_manager, lang_opts); + GetExprRange(*operand->IgnoreParenImpCasts(), source_manager, lang_opts); assert(operand_range.isValid()); clang::SourceLocation operator_end_loc = clang::Lexer::getLocForEndOfToken( @@ -1872,12 +1844,6 @@ const auto& lang_opts = ast_context.getLangOpts(); auto rep_range = clang::SourceRange(getSourceRange(result).getEnd()); - // If we're inside a macro the rep_range computed above is going to be - // incorrect because it will point into the file where the macro is defined. - // We need to get the "SpellingLocation", and then we figure out the end of - // the parameter so we can insert .data() at the end if needed. - maybeUpdateSourceRangeIfInMacro(source_manager, result, rep_range); - std::string initial_text = clang::Lexer::getSourceText( clang::CharSourceRange::getCharRange(rep_range), source_manager, @@ -2075,7 +2041,7 @@ return result.str(); } -static const clang::Expr* GetInitExpr(const clang::DeclaratorDecl* decl) { +const clang::Expr* GetInitExpr(const clang::DeclaratorDecl* decl) { const clang::Expr* init_expr = nullptr; if (auto* var_decl = clang::dyn_cast_or_null<clang::VarDecl>(decl)) { init_expr = var_decl->getInit(); @@ -2287,7 +2253,7 @@ closing_brackets_replacement_directive); } -static bool IsMutable(const clang::DeclaratorDecl* decl) { +bool IsMutable(const clang::DeclaratorDecl* decl) { if (const auto* field_decl = clang::dyn_cast_or_null<clang::FieldDecl>(decl)) { return field_decl->isMutable(); @@ -2295,22 +2261,21 @@ return false; } -static bool IsConstexpr(const clang::DeclaratorDecl* decl) { +bool IsConstexpr(const clang::DeclaratorDecl* decl) { if (const auto* var_decl = clang::dyn_cast_or_null<clang::VarDecl>(decl)) { return var_decl->isConstexpr(); } return false; } -static bool IsInlineVarDecl(const clang::DeclaratorDecl* decl) { +bool IsInlineVarDecl(const clang::DeclaratorDecl* decl) { if (const auto* var_decl = clang::dyn_cast_or_null<clang::VarDecl>(decl)) { return var_decl->isInlineSpecified(); } return false; } -static bool IsStaticLocalOrStaticStorageClass( - const clang::DeclaratorDecl* decl) { +bool IsStaticLocalOrStaticStorageClass(const clang::DeclaratorDecl* decl) { if (const auto* var_decl = clang::dyn_cast_or_null<clang::VarDecl>(decl)) { return var_decl->isStaticLocal() || var_decl->getStorageClass() == clang::SC_Static; @@ -2579,8 +2544,7 @@ // it == std::begin(c_array) // it != std::end(c_array) // Tests are in: array-tests-original.cc -static void RewriteComparisonWithCArrayIter( - const MatchFinder::MatchResult& result) { +void RewriteComparisonWithCArrayIter(const MatchFinder::MatchResult& result) { const clang::SourceManager& source_manager = *result.SourceManager; const clang::CallExpr* call_expr = GetNodeOrCrash<clang::CallExpr>( result, "c_array_iter_call_expr",
diff --git a/tools/clang/spanify/apply-successful-rewrites.py b/tools/clang/spanify/apply-successful-rewrites.py index e470c98..54b26ac 100755 --- a/tools/clang/spanify/apply-successful-rewrites.py +++ b/tools/clang/spanify/apply-successful-rewrites.py
@@ -190,7 +190,7 @@ print(f'switching to {branch_name}') run(f'git branch -D {branch_name} 1>/dev/null 2>/dev/null', exit_on_error=False) - run(f'git new-branch --upstream BRANCHES[0] {branch_name} 2>&1') + run(f'git new-branch --upstream {BRANCHES[-1]} {branch_name} 2>&1') BRANCHES.append(branch_name) @@ -324,12 +324,13 @@ # the result is already know. def CheckPatchesForTarget(target, args, patches, scratch_dir, label) -> bool: global CACHE + working = lambda x: x == CacheResult.COMPILED # If we've already compiled this set of patches for this target we can skip # we know the result. result = CACHE.Result(target, patches) if result != CacheResult.NOT_CACHED: print('returning cached result: ' + str(result)) - return result + return working(result) CreateNewBranch(f'spanification_apply_patches_{label}') applied = ApplyEdits(patches, scratch_dir, label) compiled = False @@ -337,8 +338,8 @@ compiled = CompileCurrentBranch(f'out/{target}') PopBranch() # Cache the result. - WriteResultToCache(target, patches, applied, compiled) - return CACHE.Result(target, patches) + CACHE.WriteResultToCache(target, patches, applied, compiled) + return working(CACHE.Result(target, patches)) def HandleLen2BaseCase(target, args, base, to_try, scratch_dir, @@ -346,7 +347,7 @@ assert len(to_try) == 2, "Invalid length passed" err_msg = "base has to be a tuple of all ints." assert isinstance(base, tuple), err_msg - assert all(ininstance(b, int) for b in base), err_msg + assert all(isinstance(b, int) for b in base), err_msg left_patch = to_try[0] left_patches = base + (left_patch, ) @@ -468,8 +469,6 @@ # whatever the current state is, all future branches will be based on it. assert len(BRANCHES) == 0 BRANCHES.append("spanification-base-for-rewrite") - run(f'git branch -D {BRANCHES[0]} 1>/dev/null 2>/dev/null', - exit_on_error=False) run(f'git checkout {BRANCHES[0]} 1>/dev/null 2>/dev/null') CreateNewBranch(f'spanification_apply_patches_base')
diff --git a/tools/clang/unsafe_pragma_rewriter/rewrite_directory.py b/tools/clang/unsafe_pragma_rewriter/rewrite_directory.py index 99320f1..36216b8 100755 --- a/tools/clang/unsafe_pragma_rewriter/rewrite_directory.py +++ b/tools/clang/unsafe_pragma_rewriter/rewrite_directory.py
@@ -22,6 +22,10 @@ dest="build_dir", default="out/Debug", help="Specify the build directory, defaults to out/Debug") + parser.add_argument("-f", + dest="force", + action="store_true", + help="skip conditional compilation checks.") parser.add_argument("-v", dest="verbose", action="store_true", @@ -32,6 +36,7 @@ args = parser.parse_args() build_dir = args.build_dir directory = args.directory + force = args.force verbose = args.verbose print("Checking GN build arg configuration ...") @@ -87,23 +92,24 @@ print("Files containing unsafe pragmas:") print("\n".join(source_files), "\n") - iffy_cmd = ["grep", "-Pc", "^#if(?! DCHECK_IS_ON\\(\\))"] + source_files - iffy = subprocess.check_output(iffy_cmd, text=True).strip() - iffy_lines = iffy.splitlines() if iffy else [] - iffy_files = [x.split(":")[0] for x in iffy_lines if x.split(":")[1] != "1"] - if iffy_files: + if not force: + iffy_cmd = ["grep", "-Pc", "^#if(?! DCHECK_IS_ON\\(\\))"] + source_files + iffy = subprocess.check_output(iffy_cmd, text=True).strip() + iffy_lines = iffy.splitlines() if iffy else [] + iffy_files = [x.split(":")[0] for x in iffy_lines if x.split(":")[1] != "1"] + if iffy_files: + if verbose: + print("Skipping conditionally-compiled files:") + print("\n".join(iffy_files), "\n") + source_files = [x for x in source_files if not x in set(iffy_files)] + + if not source_files: + print("No remaining files") + sys.exit(1) + if verbose: - print("Skipping conditionally-compiled files:") - print("\n".join(iffy_files), "\n") - source_files = [x for x in source_files if not x in set(iffy_files)] - - if not source_files: - print("No remaining files") - sys.exit(1) - - if verbose: - print("Remaining files after excluding #ifdefs:") - print("\n".join(source_files), "\n") + print("Remaining files after excluding #ifdefs:") + print("\n".join(source_files), "\n") # Starting with all files in the directory, find the ones that are # able to be compiled on this platform/configurarion by asking ninja
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index d5701ab..99e020ae 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -3731,6 +3731,16 @@ <description>The survey infobar was displayed.</description> </action> +<action name="Android.WindowManager.ChangeWindowName"> + <owner>aishwaryarj@google.com</owner> + <owner>rathomas@google.com</owner> + <description> + User tapped 'Save' on the dialog opened via the 3-dot menu on the in-app + window manager to successfully save and change the name of a Chrome window + and dismiss the dialog. + </description> +</action> + <action name="Android.WindowManager.CloseWindow"> <owner>jinsukkim@chromium.org</owner> <owner>twellington@chromium.org</owner> @@ -3740,6 +3750,15 @@ </description> </action> +<action name="Android.WindowManager.NameWindow"> + <owner>aishwaryarj@google.com</owner> + <owner>rathomas@google.com</owner> + <description> + User tapped 'Name' on the 3-dot menu on the in-app window manager to name a + Chrome window. + </description> +</action> + <action name="Android.WindowManager.NewWindow"> <owner>jinsukkim@chromium.org</owner> <owner>twellington@chromium.org</owner> @@ -3767,6 +3786,16 @@ </description> </action> +<action name="Android.WindowManager.SaveWindowName"> + <owner>aishwaryarj@google.com</owner> + <owner>rathomas@google.com</owner> + <description> + User tapped 'Save' on the dialog opened via the 3-dot menu on the in-app + window manager to successfully save the name of a Chrome window and dismiss + the dialog. + </description> +</action> + <action name="Android.WindowManager.SecondaryMenu"> <owner>jinsukkim@chromium.org</owner> <owner>twellington@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index e3940dc..ee4e0f8 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -12921,6 +12921,7 @@ <int value="-434474445" label="OmniboxSteadyStateBackgroundColor:enabled"/> <int value="-433879402" label="EnableAmbientAuthenticationInIncognito:disabled"/> + <int value="-433775463" label="EnforceManagementDisclaimer:enabled"/> <int value="-431617217" label="ArcGhostWindowNewStyle:disabled"/> <int value="-431553693" label="ChangePasswordAffiliationInfo:disabled"/> <int value="-430369215" label="AssistPersonalInfo:disabled"/> @@ -17454,6 +17455,7 @@ <int value="1228054141" label="OverrideUnsupportedPageLanguageForHrefTranslate:enabled"/> <int value="1228115769" label="SiteCharacteristicsDatabase:disabled"/> + <int value="1228384801" label="EnforceManagementDisclaimer:disabled"/> <int value="1228958037" label="FedCmWithStorageAccessAPI:enabled"/> <int value="1229299518" label="SingleTabMode:disabled"/> <int value="1229388323" label="AutofillEnableGoogleIssuedCard:disabled"/>
diff --git a/tools/metrics/histograms/histograms_xml_files.gni b/tools/metrics/histograms/histograms_xml_files.gni index ad24617..8084ce4 100644 --- a/tools/metrics/histograms/histograms_xml_files.gni +++ b/tools/metrics/histograms/histograms_xml_files.gni
@@ -287,6 +287,7 @@ "//tools/metrics/histograms/metadata/uma/enums.xml", "//tools/metrics/histograms/metadata/uma/histograms.xml", "//tools/metrics/histograms/metadata/update_engine/histograms.xml", + "//tools/metrics/histograms/metadata/user_data_importer/enums.xml", "//tools/metrics/histograms/metadata/user_data_importer/histograms.xml", "//tools/metrics/histograms/metadata/user_education/histograms.xml", "//tools/metrics/histograms/metadata/v8/enums.xml",
diff --git a/tools/metrics/histograms/metadata/android/enums.xml b/tools/metrics/histograms/metadata/android/enums.xml index 1a3de18..5df75aa 100644 --- a/tools/metrics/histograms/metadata/android/enums.xml +++ b/tools/metrics/histograms/metadata/android/enums.xml
@@ -668,6 +668,7 @@ <int value="156" label="WebSettingsCompat.getBackForwardCacheSettings"/> <int value="157" label="BackForwardCacheSettings.getTimeoutInSeconds"/> <int value="158" label="BackForwardCacheSettings.getMaxPagesInCache"/> + <int value="159" label="Profile.preconnect"/> <!-- LINT.ThenChange(/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromiumFactory.java:ApiCall) --> </enum>
diff --git a/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml b/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml index f81dec6..e7370ba9 100644 --- a/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml +++ b/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml
@@ -47,7 +47,7 @@ <histogram name="Conversions.AggregatableDebugReport.ProcessResult" enum="ConversionAggregatableDebugReportProcessResult" - expires_after="2025-08-24"> + expires_after="2026-02-04"> <owner>linnan@chromium.org</owner> <owner>measurement-api-dev+metrics@google.com</owner> <summary> @@ -60,7 +60,7 @@ <histogram name="Conversions.AggregatableDebugReporting.SourceRegistrationError" enum="ConversionAggregatableDebugReportingRegistrationError" - expires_after="2025-08-24"> + expires_after="2026-02-04"> <owner>linnan@chromium.org</owner> <owner>measurement-api-dev+metrics@google.com</owner> <summary> @@ -73,7 +73,7 @@ <histogram name="Conversions.AggregatableDebugReporting.TriggerRegistrationError" enum="ConversionAggregatableDebugReportingRegistrationError" - expires_after="2025-08-24"> + expires_after="2026-02-04"> <owner>linnan@chromium.org</owner> <owner>measurement-api-dev+metrics@google.com</owner> <summary> @@ -95,7 +95,7 @@ </histogram> <histogram name="Conversions.AggregatableKeysPerSource" units="keys" - expires_after="2025-08-24"> + expires_after="2026-02-04"> <owner>linnan@chromium.org</owner> <owner>measurement-api-dev+metrics@google.com</owner> <summary> @@ -137,7 +137,7 @@ </histogram> <histogram name="Conversions.AggregatableReport.DroppedKeysPercentage" - units="%" expires_after="2025-08-24"> + units="%" expires_after="2026-02-04"> <owner>linnan@chromium.org</owner> <owner>measurement-api-dev+metrics@google.com</owner> <summary> @@ -268,7 +268,7 @@ </histogram> <histogram name="Conversions.AggregatableReport.TotalBudgetPerReport" - units="budget consumed" expires_after="2025-08-20"> + units="budget consumed" expires_after="2026-02-04"> <owner>linnan@chromium.org</owner> <owner>measurement-api-dev+metrics@google.com</owner> <summary> @@ -1215,7 +1215,7 @@ </histogram> <histogram name="Conversions.SourceDestinationLimitResult" - enum="AttributionSourceDestinationLimitResult" expires_after="2025-08-24"> + enum="AttributionSourceDestinationLimitResult" expires_after="2026-02-04"> <owner>linnan@chromium.org</owner> <owner>measurement-api-dev+metrics@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/autofill/enums.xml b/tools/metrics/histograms/metadata/autofill/enums.xml index aa134acc..f140cb9 100644 --- a/tools/metrics/histograms/metadata/autofill/enums.xml +++ b/tools/metrics/histograms/metadata/autofill/enums.xml
@@ -3224,6 +3224,7 @@ <enum name="BnplSuggestionNotShownReason"> <int value="0" label="Amount extraction failure"/> <int value="1" label="Checkout amount not supported"/> + <int value="2" label="Amount extraction timeout"/> </enum> <!-- LINT.IfChange(BnplTosDialogResult) -->
diff --git a/tools/metrics/histograms/metadata/blink/enums.xml b/tools/metrics/histograms/metadata/blink/enums.xml index feceb74..a09963b 100644 --- a/tools/metrics/histograms/metadata/blink/enums.xml +++ b/tools/metrics/histograms/metadata/blink/enums.xml
@@ -6258,6 +6258,8 @@ <int value="5624" label="HTMLControlledFrameElement"/> <int value="5625" label="SlowDeserialization"/> <int value="5626" label="SharedWorkerStartOnAndroid"/> + <int value="5627" label="LocalNetworkAccessWithinSharedWorker"/> + <int value="5628" label="LocalNetworkAccessWithinDedicatedWorker"/> </enum> <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom:WebFeature) -->
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml index 6f6586f3..6f2adaa0 100644 --- a/tools/metrics/histograms/metadata/gpu/histograms.xml +++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -312,6 +312,18 @@ </summary> </histogram> +<histogram name="GPU.Android.HasEGLDupNativeFenceFunction" enum="Boolean" + expires_after="M145"> + <owner>boliu@chromium.org</owner> + <owner>vasilyt@chromium.org</owner> + <owner>chrome-gpu-metric-alerts@google.com</owner> + <summary> + Recordes whether the eglDupNativeFenceFDANDROIDFn function is exported. + Recorded once on eglDisplay init, which is basically once on GPU process + start. + </summary> +</histogram> + <histogram name="GPU.ANGLE.Buffer11CPUMemoryMB" units="MB" expires_after="2020-05-10"> <owner>cwallez@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/mobile/enums.xml b/tools/metrics/histograms/metadata/mobile/enums.xml index 4fae275..8b17585 100644 --- a/tools/metrics/histograms/metadata/mobile/enums.xml +++ b/tools/metrics/histograms/metadata/mobile/enums.xml
@@ -464,6 +464,7 @@ <int value="0" label="EditedCardHolderName"/> <int value="1" label="EditedExpirationMonth"/> <int value="2" label="EditedExpirationYear"/> + <int value="3" label="EditedCvc"/> </enum> <enum name="MobileMessagesTranslateBannerEvent">
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml index 1a12156..dcfb29fa 100644 --- a/tools/metrics/histograms/metadata/page/histograms.xml +++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -3633,7 +3633,7 @@ </histogram> <histogram name="PageLoad.Internal.PageLoadTimingStatus{Condition}" - enum="PageLoadTimingStatus" expires_after="2025-09-14"> + enum="PageLoadTimingStatus" expires_after="2026-08-01"> <owner>toyoshim@chromium.org</owner> <owner>src/components/page_load_metrics/OWNERS</owner> <owner>src/content/browser/preloading/prerender/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/password/enums.xml b/tools/metrics/histograms/metadata/password/enums.xml index ee9212db..d4d653726 100644 --- a/tools/metrics/histograms/metadata/password/enums.xml +++ b/tools/metrics/histograms/metadata/password/enums.xml
@@ -1043,12 +1043,12 @@ The user explicitly asked to move multiple passwords at once in Settings. Recorded only on Win/Mac/Linux. </int> - <int value="3" label="kUserOptedInAfterSavingLocally"> + <int value="3" label="(obsolete) kUserOptedInAfterSavingLocally"> After saving a password locally, the user opted in to saving this and future passwords in the account. Recorded only on Win/Mac/Linux. </int> <int value="4" - label="kExplicitlyTriggeredForSinglePasswordInDetailsInSettings"> + label="(obsolete)ExplicitlyTriggeredForSinglePasswordInDetailsInSettings"> The user explicitly asked to move a password to account store from password details page. </int>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index ce64f10..a68e1f1 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -329,7 +329,7 @@ <histogram name="PasswordGeneration.EditsInGeneratedPassword.AlteredLengthIncreased" - enum="GeneratedPasswordAlteredLengthIncreased" expires_after="2025-08-24"> + enum="GeneratedPasswordAlteredLengthIncreased" expires_after="2026-02-28"> <owner>kazinova@google.com</owner> <owner>vasilii@chromium.org</owner> <summary> @@ -340,7 +340,7 @@ </histogram> <histogram name="PasswordGeneration.EditsInGeneratedPassword.AttributesMask" - enum="EditsInGeneratedPasswordMask" expires_after="2025-08-24"> + enum="EditsInGeneratedPasswordMask" expires_after="2026-02-28"> <owner>kazinova@google.com</owner> <owner>vasilii@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/performance_manager/enums.xml b/tools/metrics/histograms/metadata/performance_manager/enums.xml index c82d409..f20b393 100644 --- a/tools/metrics/histograms/metadata/performance_manager/enums.xml +++ b/tools/metrics/histograms/metadata/performance_manager/enums.xml
@@ -26,6 +26,25 @@ <enums> +<!-- LINT.IfChange(ChildScenarioMappingResult) --> + +<enum name="ChildScenarioMappingResult"> + <int value="0" label="Success"/> + <int value="1" label="Invalid Handle"/> + <int value="2" label="System Error"/> +</enum> + +<!-- LINT.ThenChange(//components/performance_manager/scenario_api/performance_scenario_memory.cc:ChildScenarioMappingResult) --> + +<!-- LINT.IfChange(CreateScenarioMemoryResult) --> + +<enum name="CreateScenarioMemoryResult"> + <int value="0" label="Success"/> + <int value="1" label="System Error"/> +</enum> + +<!-- LINT.ThenChange(//components/performance_manager/scenarios/performance_scenario_data.cc:CreateScenarioMemoryResult) --> + <enum name="EfficiencyMode"> <int value="0" label="Normal"/> <int value="1" label="High Efficiency"/>
diff --git a/tools/metrics/histograms/metadata/performance_manager/histograms.xml b/tools/metrics/histograms/metadata/performance_manager/histograms.xml index 9aaf070..1e84d71 100644 --- a/tools/metrics/histograms/metadata/performance_manager/histograms.xml +++ b/tools/metrics/histograms/metadata/performance_manager/histograms.xml
@@ -135,6 +135,28 @@ <token key="CoreType" variants="CoreType"/> </histogram> +<histogram name="PerformanceManager.ChildScenarioMappingResult" + enum="ChildScenarioMappingResult" expires_after="2025-12-31"> + <owner>joenotcharles@google.com</owner> + <owner>chrome-catan@google.com</owner> + <summary> + The result of an attempt to map the shared memory for performance scenarios + in a child process. Recorded when a child process receives a shared memory + region from the browser process to map. If the result is kSystemError, + PerformanceManager.ChildScenarioMappingSystemError is also logged. + </summary> +</histogram> + +<histogram name="PerformanceManager.ChildScenarioMappingSystemError" + units="system error code" expires_after="2025-12-31"> + <owner>joenotcharles@google.com</owner> + <owner>chrome-catan@google.com</owner> + <summary> + The system error code when PerformanceManager.ChildScenarioMappingResult is + kSystemError. + </summary> +</histogram> + <histogram name="PerformanceManager.CPUMonitorMemoryUse.{ResourceContextType}.{ResourceContextState}" units="KB" expires_after="2025-09-07"> @@ -161,6 +183,29 @@ </token> </histogram> +<histogram name="PerformanceManager.CreateScenarioMemoryResult" + enum="CreateScenarioMemoryResult" expires_after="2025-12-31"> + <owner>joenotcharles@google.com</owner> + <owner>chrome-catan@google.com</owner> + <summary> + The result of an attempt to create the shared memory for performance + scenarios in the browser process. Recorded when a PerformanceScenarioData is + created for a process, shortly after the process starts. If the result is + kSystemError, PerformanceManager.CreateScenarioMemorySystemError is also + logged. + </summary> +</histogram> + +<histogram name="PerformanceManager.CreateScenarioMemorySystemError" + units="system error code" expires_after="2025-12-31"> + <owner>joenotcharles@google.com</owner> + <owner>chrome-catan@google.com</owner> + <summary> + The system error code when PerformanceManager.CreateScenarioMemoryResult is + kSystemError. + </summary> +</histogram> + <histogram name="PerformanceManager.DiskStats.UserDataDirFreeSpaceMb" units="MB" expires_after="2025-08-24"> <owner>anthonyvd@chromium.org</owner> @@ -204,6 +249,31 @@ </summary> </histogram> +<histogram + name="PerformanceManager.InitializeChildProcessCoordination.RequestCount" + units="count" expires_after="2025-12-31"> + <owner>joenotcharles@google.com</owner> + <owner>chrome-catan@google.com</owner> + <summary> + The number of times a child process has requested to initialize its + coordination with the browser process. Logged just after the process starts. + </summary> +</histogram> + +<histogram + name="PerformanceManager.InitializeChildProcessCoordination.ResponseCount" + units="count" expires_after="2025-12-31"> + <owner>joenotcharles@google.com</owner> + <owner>chrome-catan@google.com</owner> + <summary> + The number of times a child process has received a response from the browser + process after requesting to initialize its coordination. The difference + between this and + PerformanceManager.InitializeChildProcessCoordination.RequestCount is the + number of requests that did not receive a response. + </summary> +</histogram> + <histogram name="PerformanceManager.InputScenarioChanges{InputScenario}" enum="InputScenarioUpdateReason" expires_after="2026-04-07"> <owner>kraskevich@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml index 7ac3007..356094c 100644 --- a/tools/metrics/histograms/metadata/storage/histograms.xml +++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -1250,7 +1250,7 @@ </histogram> <histogram name="Storage.InterestGroup.AdProtoSerializationTime" units="ms" - expires_after="2025-08-24"> + expires_after="2026-02-05"> <owner>caraitto@chromium.org</owner> <owner>pauljensen@chromium.org</owner> <summary> @@ -1499,7 +1499,7 @@ </histogram> <histogram name="Storage.SharedStorage.AsyncIterator.EntriesQueuedCount" - units="Entries" expires_after="2025-08-10"> + units="Entries" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1510,7 +1510,7 @@ </histogram> <histogram name="Storage.SharedStorage.AsyncIterator.IteratedEntriesBenchmarks" - units="BenchmarksMet" expires_after="2025-12-14"> + units="BenchmarksMet" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1522,7 +1522,7 @@ </histogram> <histogram name="Storage.SharedStorage.AsyncIterator.ReceivedEntriesBenchmarks" - units="BenchmarksMet" expires_after="2025-12-14"> + units="BenchmarksMet" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1535,7 +1535,7 @@ </histogram> <histogram name="Storage.SharedStorage.BatchUpdateMethod.HasLockOption" - enum="BooleanPresent" expires_after="2025-12-21"> + enum="BooleanPresent" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1546,7 +1546,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.Destruction" - enum="BooleanDestroyed" expires_after="2025-12-21"> + enum="BooleanDestroyed" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1560,7 +1560,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.Error" enum="SqliteErrorCode" - expires_after="2025-12-31"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1574,7 +1574,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.BytesUsed.PerOrigin.Max" - units="B" expires_after="2025-08-10"> + units="B" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1590,7 +1590,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.BytesUsed.PerOrigin.Median" - units="B" expires_after="2025-12-31"> + units="B" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1606,7 +1606,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.BytesUsed.PerOrigin.Min" - units="B" expires_after="2025-08-10"> + units="B" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1622,7 +1622,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.BytesUsed.PerOrigin.Q1" - units="B" expires_after="2025-08-10"> + units="B" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1638,7 +1638,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.BytesUsed.PerOrigin.Q3" - units="B" expires_after="2025-08-10"> + units="B" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1653,7 +1653,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.FileBacked.BytesUsed.Total.KB" - units="KB" expires_after="2025-12-31"> + units="KB" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1675,7 +1675,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.FileBacked.FileSize.GB" - units="GB" expires_after="2025-08-10"> + units="GB" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1688,7 +1688,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.FileBacked.FileSize.KB" - units="KB" expires_after="2025-12-14"> + units="KB" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1702,7 +1702,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.NumEntries.PerOrigin.Max" - units="Entries" expires_after="2025-08-10"> + units="Entries" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1717,7 +1717,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.NumEntries.PerOrigin.Median" - units="Entries" expires_after="2025-08-10"> + units="Entries" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1732,7 +1732,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.NumEntries.PerOrigin.Min" - units="Entries" expires_after="2025-08-10"> + units="Entries" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1747,7 +1747,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.NumEntries.PerOrigin.Q1" - units="Entries" expires_after="2025-08-10"> + units="Entries" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1763,7 +1763,7 @@ <histogram name="Storage.SharedStorage.Database.FileBacked.NumEntries.PerOrigin.Q3" - units="Entries" expires_after="2025-08-10"> + units="Entries" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1778,7 +1778,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.FileBacked.NumEntries.Total" - units="Entries" expires_after="2025-08-10"> + units="Entries" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1791,7 +1791,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.FileBacked.NumOrigins" - units="Origins" expires_after="2025-08-10"> + units="Origins" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1805,7 +1805,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.IsFileBacked" - enum="BooleanIsFileBacked" expires_after="2025-08-10"> + enum="BooleanIsFileBacked" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1817,7 +1817,7 @@ </histogram> <histogram name="Storage.SharedStorage.Database.Timing.OpenImpl" units="ms" - expires_after="2025-12-31"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1830,7 +1830,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.AddModule" units="ms" - expires_after="2025-12-14"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1844,7 +1844,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.Append" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1856,7 +1856,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.BatchUpdate" units="ms" - expires_after="2025-12-31"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1868,7 +1868,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.Clear" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1880,7 +1880,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.Delete" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1894,7 +1894,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.Get" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1907,7 +1907,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.Run" units="ms" - expires_after="2025-12-07"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1921,7 +1921,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.Run.ExecutedInWorklet" - units="ms" expires_after="2025-12-14"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1934,7 +1934,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.SelectURL" units="ms" - expires_after="2025-12-14"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1949,7 +1949,7 @@ <histogram name="Storage.SharedStorage.Document.Timing.SelectURL.ExecutedInWorklet" - units="ms" expires_after="2025-12-14"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1965,7 +1965,7 @@ </histogram> <histogram name="Storage.SharedStorage.Document.Timing.Set" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1977,7 +1977,7 @@ </histogram> <histogram name="Storage.SharedStorage.DocumentServiceBind.IsSecureFrame" - enum="BooleanSecure" expires_after="2025-12-31"> + enum="BooleanSecure" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -1989,7 +1989,7 @@ <histogram name="Storage.SharedStorage.HeaderObserver.CreatedOpaqueOriginForPrefsCheck" - enum="Boolean" expires_after="2025-12-14"> + enum="Boolean" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2006,7 +2006,7 @@ <histogram name="Storage.SharedStorage.HeaderObserver.PermissionsPolicyDoubleCheckStatus" enum="SharedStorageHeaderObserverPermissionsPolicyDoubleCheckStatus" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2021,7 +2021,7 @@ </histogram> <histogram name="Storage.SharedStorage.InterestGroups.InBrowserRetrievalTime" - units="ms" expires_after="2025-12-31"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2033,7 +2033,7 @@ </histogram> <histogram name="Storage.SharedStorage.InterestGroups.ResultStatus" - enum="SharedStorageInterestGroupsResultStatus" expires_after="2025-12-31"> + enum="SharedStorageInterestGroupsResultStatus" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2044,7 +2044,7 @@ </histogram> <histogram name="Storage.SharedStorage.InterestGroups.TimeToResolve" units="ms" - expires_after="2025-12-31"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2056,7 +2056,7 @@ <histogram name="Storage.SharedStorage.OnDataClearedForOrigin.DataDurationInDays" - units="days" expires_after="2025-09-10"> + units="days" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2081,7 +2081,7 @@ </histogram> <histogram name="Storage.SharedStorage.OnShutdown.NumSqlErrors" units="Errors" - expires_after="2025-12-14"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2094,7 +2094,7 @@ <histogram name="Storage.SharedStorage.OnShutdown.RecoveryFromInitFailureAttempted" - enum="BooleanAttempted" expires_after="2025-12-14"> + enum="BooleanAttempted" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2107,7 +2107,7 @@ </histogram> <histogram name="Storage.SharedStorage.OnShutdown.RecoveryOnDiskAttempted" - enum="BooleanAttempted" expires_after="2025-08-10"> + enum="BooleanAttempted" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2120,7 +2120,7 @@ </histogram> <histogram name="Storage.SharedStorage.Run.DataDeserialization.Time" units="ms" - expires_after="2025-12-28"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2131,7 +2131,7 @@ </histogram> <histogram name="Storage.SharedStorage.Run.DataSerialization.SizeKB" units="KB" - expires_after="2025-10-26"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2142,7 +2142,7 @@ </histogram> <histogram name="Storage.SharedStorage.Run.DataSerialization.Time" units="ms" - expires_after="2025-12-28"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2153,7 +2153,7 @@ </histogram> <histogram name="Storage.SharedStorage.SelectURL.DataDeserialization.Time" - units="ms" expires_after="2025-08-24"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2164,7 +2164,7 @@ </histogram> <histogram name="Storage.SharedStorage.SelectURL.DataSerialization.SizeKB" - units="KB" expires_after="2025-10-26"> + units="KB" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2175,7 +2175,7 @@ </histogram> <histogram name="Storage.SharedStorage.SelectURL.DataSerialization.Time" - units="ms" expires_after="2025-12-28"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2186,7 +2186,7 @@ </histogram> <histogram name="Storage.SharedStorage.SelectURL.UrlsLength" units="count" - expires_after="2025-12-28"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2199,7 +2199,7 @@ </histogram> <histogram name="Storage.SharedStorage.Timing.UrlMappingDuringNavigation" - units="ms" expires_after="2025-08-10"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2210,7 +2210,7 @@ </histogram> <histogram name="Storage.SharedStorage.UpdateMethod.HasLockOption" - enum="BooleanPresent" expires_after="2025-12-21"> + enum="BooleanPresent" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2222,7 +2222,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Context.IsDefined" - enum="Boolean" expires_after="2025-08-10"> + enum="Boolean" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2234,7 +2234,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.DestroyedStatus" - enum="SharedStorageWorkletDestroyedStatus" expires_after="2025-12-14"> + enum="SharedStorageWorkletDestroyedStatus" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2247,7 +2247,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Error.Type" - enum="SharedStorageWorkletErrorType" expires_after="2025-12-14"> + enum="SharedStorageWorkletErrorType" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2261,7 +2261,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.NavigatorLocksInvoked" - enum="Boolean" expires_after="2025-12-21"> + enum="Boolean" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2272,7 +2272,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.NumPerPage" - units="WorkletsCreated" expires_after="2025-12-14"> + units="WorkletsCreated" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2286,7 +2286,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.SelectURL.BudgetStatus" - enum="SharedStorageSelectUrlBudgetStatus" expires_after="2025-08-10"> + enum="SharedStorageSelectUrlBudgetStatus" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2300,7 +2300,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.SelectURL.CallsPerPage" - units="SelectURLCallsPerPage" expires_after="2025-08-10"> + units="SelectURLCallsPerPage" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2318,7 +2318,7 @@ <histogram name="Storage.SharedStorage.Worklet.Timing.AbsoluteUsefulResourceDuration" - units="ms" expires_after="2025-12-28"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2331,7 +2331,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Append" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2343,7 +2343,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.BatchUpdate" units="ms" - expires_after="2025-12-31"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2355,7 +2355,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Clear" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2367,7 +2367,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Delete" units="ms" - expires_after="2025-12-14"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2379,7 +2379,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Entries.Next" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2394,7 +2394,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Get" units="ms" - expires_after="2025-12-14"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2409,7 +2409,7 @@ <histogram name="Storage.SharedStorage.Worklet.Timing.KeepAliveEndedDueToOperationsFinished.KeepAliveDuration" - units="ms" expires_after="2025-12-14"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2422,7 +2422,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Keys.Next" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2437,7 +2437,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Length" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2451,7 +2451,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.RemainingBudget" - units="ms" expires_after="2025-08-10"> + units="ms" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2466,7 +2466,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Set" units="ms" - expires_after="2025-12-14"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2478,7 +2478,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.UsefulResourceDuration" - units="%" expires_after="2026-02-01"> + units="%" expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> @@ -2491,7 +2491,7 @@ </histogram> <histogram name="Storage.SharedStorage.Worklet.Timing.Values.Next" units="ms" - expires_after="2025-08-10"> + expires_after="2026-02-05"> <owner>cammie@chromium.org</owner> <owner>yaoxia@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/user_data_importer/enums.xml b/tools/metrics/histograms/metadata/user_data_importer/enums.xml new file mode 100644 index 0000000..e9e1326 --- /dev/null +++ b/tools/metrics/histograms/metadata/user_data_importer/enums.xml
@@ -0,0 +1,74 @@ +<!-- +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. +--> + +<!-- + +This file describes the enumerations referenced by entries in histograms.xml for +this directory. Some enums may instead be listed in the central enums.xml file +at src/tools/metrics/histograms/enums.xml when multiple files use them. + +For best practices on writing enumerations descriptions, see +https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md#Enum-Histograms + +Please follow the instructions in the OWNERS file in this directory to find a +reviewer. If no OWNERS file exists, please consider signing up at +go/reviewing-metrics (Googlers only), as all subdirectories are expected to +have an OWNERS file. As a last resort you can send the CL to +chromium-metrics-reviews@google.com. +--> + +<histogram-configuration> + +<enums> + +<!-- LINT.IfChange(UserDataImportBookmarksError) --> + +<enum name="UserDataImportBookmarksError"> + <int value="0" label="Failed to Read"/> + <int value="1" label="Input Too Big"/> + <int value="2" label="Parsing Failed"/> + <int value="3" label="Timeout"/> + <int value="4" label="Other"/> +</enum> + +<!-- LINT.ThenChange(//components/user_data_importer/utility/importer_metrics_recorder.h:BookmarksImportError) --> + +<!-- LINT.IfChange(UserDataImportOutcome) --> + +<enum name="UserDataImportOutcome"> + <int value="0" label="Not Present"/> + <int value="1" label="Failure"/> + <int value="2" label="Success"/> +</enum> + +<!-- LINT.ThenChange(//components/user_data_importer/utility/importer_metrics_recorder.h:ImportOutcome) --> + +<!-- LINT.IfChange(UserDataImportPasswordsError) --> + +<enum name="UserDataImportPasswordsError"> + <int value="0" label="Failed to Read"/> + <int value="1" label="Input Too Big"/> + <int value="2" label="Parsing Failed"/> + <int value="3" label="Timeout"/> + <int value="4" label="Other"/> +</enum> + +<!-- LINT.ThenChange(//components/user_data_importer/utility/importer_metrics_recorder.h:PasswordsImportError) --> + +<!-- LINT.IfChange(UserDataImportTotalFailureError) --> + +<enum name="UserDataImportTotalFailureError"> + <int value="0" label="No File Provided"/> + <int value="1" label="File Too Big"/> + <int value="2" label="Unzip Failed"/> + <int value="3" label="Other"/> +</enum> + +<!-- LINT.ThenChange(//components/user_data_importer/utility/safari_data_importer.cc:TotalFailureError) --> + +</enums> + +</histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/user_data_importer/histograms.xml b/tools/metrics/histograms/metadata/user_data_importer/histograms.xml index 970960f..210b31c 100644 --- a/tools/metrics/histograms/metadata/user_data_importer/histograms.xml +++ b/tools/metrics/histograms/metadata/user_data_importer/histograms.xml
@@ -22,17 +22,99 @@ <histograms> +<!-- LINT.IfChange(ImportDataType) --> + <variants name="ImportDataType"> <variant name="Bookmarks" summary="Bookmarks"/> <variant name="History" summary="History"/> <variant name="NotSupported" summary="Not supported"/> + <variant name="Passwords" summary="Passwords data type."/> + <variant name="PaymentCards" summary="Payment cards data type."/> <variant name="ReadingList" summary="Reading list"/> </variants> +<!-- LINT.ThenChange(//components/user_data_importer/utility/importer_metrics_recorder.h:ImportDataType) --> + +<!-- LINT.IfChange(ImportSource) --> + <variants name="ImportSource"> <variant name="OSMigration" summary="Data import from an OS migration."/> + <variant name="Safari" summary="Importing data exported by Safari."/> </variants> +<!-- LINT.ThenChange(//components/user_data_importer/utility/importer_metrics_recorder.h:ImportSource) --> + +<histogram name="UserDataImporter.{ImportSource}.Bookmarks.Error" + enum="UserDataImportBookmarksError" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + Records the specific error encountered when parsing bookmarks. This is + independent of other data types; it's possible for this to fail but another + data type to subsequently be imported. + </summary> + <token key="ImportSource" variants="ImportSource"/> +</histogram> + +<histogram name="UserDataImporter.{ImportSource}.FlowDuration" units="ms" + expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + The total time taken for the user data import process to complete, end to + end, once the input file(s) have been presented to the importer. Note that + this may include time waiting for UI actions in some cases. + </summary> + <token key="ImportSource" variants="ImportSource"/> +</histogram> + +<histogram name="UserDataImporter.{ImportSource}.Passwords.Error" + enum="UserDataImportPasswordsError" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + Records the specific error encountered when preparing passwords, generally + indicating an issue with parsing. This is independent of other data types; + it's possible for this to fail but another data type to subsequently be + imported. + </summary> + <token key="ImportSource" variants="ImportSource"/> +</histogram> + +<histogram name="UserDataImporter.{ImportSource}.TotalFailureError" + enum="UserDataImportTotalFailureError" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + Records the specific error which caused the entire import process to fail, + if such an error occurred. An error in this histogram would indicate that no + data was successfully imported for any data type. + </summary> + <token key="ImportSource" variants="ImportSource"/> +</histogram> + +<histogram name="UserDataImporter.{ImportSource}.TotalFileSize" units="KB" + expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + The total size of the input file or data package provided for the user data + import process, in KB. + </summary> + <token key="ImportSource" variants="ImportSource"/> +</histogram> + +<histogram name="UserDataImporter.{ImportSource}.{ImportDataType}.FileSize" + units="KB" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + The size of the data to be imported for this data type, in KB. + </summary> + <token key="ImportSource" variants="ImportSource"/> + <token key="ImportDataType" variants="ImportDataType"/> +</histogram> + <histogram name="UserDataImporter.{ImportSource}.{ImportDataType}.Flow" enum="BooleanStartedCompleted" expires_after="2025-11-30"> <owner>fsenra@google.com</owner> @@ -57,6 +139,20 @@ </histogram> <histogram + name="UserDataImporter.{ImportSource}.{ImportDataType}.ImportDuration" + units="ms" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + The time taken to import the data into the Chrome backends. Note that other + parts of the flow, like UI steps, file IO, parsing, etc. may have occurred + before this step, so this is not necessarily a total duration. + </summary> + <token key="ImportSource" variants="ImportSource"/> + <token key="ImportDataType" variants="ImportDataType"/> +</histogram> + +<histogram name="UserDataImporter.{ImportSource}.{ImportDataType}.ImportedCount" units="count" expires_after="2025-11-30"> <owner>fsenra@google.com</owner> @@ -69,6 +165,59 @@ <token key="ImportSource" variants="ImportSource"/> </histogram> +<histogram name="UserDataImporter.{ImportSource}.{ImportDataType}.Outcome" + enum="UserDataImportOutcome" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + Records the final outcome of attempting to import a given data type. + </summary> + <token key="ImportSource" variants="ImportSource"/> + <token key="ImportDataType" variants="ImportDataType"/> +</histogram> + +<histogram + name="UserDataImporter.{ImportSource}.{ImportDataType}.PreparedCount" + units="items" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + The number of items prepared for import for this data type. Note that in + certain cases (notably history, which is parsed in a streaming manner) this + may be an estimate, with actual parsing to occur later. + </summary> + <token key="ImportSource" variants="ImportSource"/> + <token key="ImportDataType" variants="ImportDataType"/> +</histogram> + +<histogram + name="UserDataImporter.{ImportSource}.{ImportDataType}.PrepareDuration" + units="ms" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + The time taken to prepare the data for import for this data type. Usually + this involves parsing, but note that in certain cases (notably history, + which is parsed in a streaming manner) this may not encompass all parsing + work that is done in the entire pipeline. + </summary> + <token key="ImportSource" variants="ImportSource"/> + <token key="ImportDataType" variants="ImportDataType"/> +</histogram> + +<histogram name="UserDataImporter.{ImportSource}.{ImportDataType}.SuccessRate" + units="%" expires_after="2026-01-28"> + <owner>tmartino@chromium.org</owner> + <owner>bling-transactions@google.com</owner> + <summary> + The percentage of prepared items that were successfully imported + (ImportedCount / PreparedCount) for this data type. Note that in some cases + PreparedCount is an estimate, which means we could get over 100%. + </summary> + <token key="ImportSource" variants="ImportSource"/> + <token key="ImportDataType" variants="ImportDataType"/> +</histogram> + </histograms> </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/variations/enums.xml b/tools/metrics/histograms/metadata/variations/enums.xml index 7cf4c8a..b3a9a9d 100644 --- a/tools/metrics/histograms/metadata/variations/enums.xml +++ b/tools/metrics/histograms/metadata/variations/enums.xml
@@ -154,6 +154,8 @@ <int value="12" label="Experiment has an invalid name"/> <int value="13" label="Feature has an invalid name"/> <int value="14" label="Forcing flag has an invalid name"/> + <int value="15" label="Unsupported study consistency"/> + <int value="16" label="Unsupported study activation type"/> </enum> <enum name="VariationsLimitedEntropySeedRejectionReason">
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml index 8c6a1c6..b33f84c 100644 --- a/tools/metrics/histograms/metadata/variations/histograms.xml +++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -621,7 +621,7 @@ </histogram> <histogram name="Variations.SeedFreshnessDiff" units="minutes" - expires_after="2025-09-18"> + expires_after="2026-08-04"> <owner>ntfschr@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index b32a44b..0b71180 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@ "full_remote_path": "perfetto-luci-artifacts/361808c959b026d558c9948602ea38bf25d8981e/linux-arm64/trace_processor_shell" }, "win": { - "hash": "1d8d5ba88b553967b061903a5bf55749cd151be7", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/39ae3a6839b334458b6cea6fd3783380e593bee0/trace_processor_shell.exe" + "hash": "9e4470bd95ec16b9d27d6803191f377d3aa5d985", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/b226f6147822d9c8f0c706f8ed2746ed9e5f1289/trace_processor_shell.exe" }, "linux_arm": { "hash": "ab1a0d9236a63649044414663b6ace711253648f", @@ -21,8 +21,8 @@ "full_remote_path": "perfetto-luci-artifacts/v51.2/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "6c5a4c88db75eaffcb49b6167413c5c174bce5c7", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/79987e4753ec3572794821544b5f00a1e1b08fa8/trace_processor_shell" + "hash": "59de59d714a1e3baea17f1bd2c33c0f8aa1a9a3c", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/27062b54dde5b49c79f4b85e0a21bde2345219a8/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 9fc4965..e1c7581 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -326,6 +326,9 @@ crbug.com/1452148 [ android-pixel-6-pro ] system_health.common_mobile/browse:social:twitter:2019 [ Skip ] crbug.com/1452148 [ android-pixel-6 ] system_health.common_mobile/load:tools:dropbox:2019 [ Skip ] crbug.com/1452148 [ android-pixel-6-pro ] system_health.common_mobile/load:tools:dropbox:2019 [ Skip ] +crbug.com/436580154 [ android-pixel-6 ] system_health.common_mobile/browse:media:youtube:2019 [ Skip ] +crbug.com/436580154 [ android-pixel-6 ] system_health.common_mobile/browse:news:nytimes:2019 [ Skip ] +crbug.com/436580154 [ android-pixel-6-pro ] system_health.common_mobile/browse:news:nytimes:2019 [ Skip ] crbug.com/332938899 [ android-wembley ] system_health.common_mobile/load:tools:dropbox:2019 [ Skip ] crbug.com/326463795 [ android-pixel-tablet ] system_health.common_mobile/browse:social:twitter:2019 [ Skip ] crbug.com/326463795 [ android-pixel-tablet ] system_health.common_mobile/browse:tools:maps:2019 [ Skip ] @@ -602,6 +605,10 @@ crbug.com/1452148 [ android-go ] v8.browsing_mobile-future/browse:media:tiktok_infinite_scroll:2021 [ Skip ] crbug.com/435172284 [ android-pixel-4 ] v8.browsing_mobile-future/browse:social:facebook_infinite_scroll:2018 [ Skip ] crbug.com/435172284 [ android-pixel-4 ] v8.browsing_mobile-future/browse:news:nytimes:2019 [ Skip ] +crbug.com/436580154 [ android-pixel-6 ] v8.browsing_mobile-future/browse:news:nytimes:2019 [ Skip ] +crbug.com/436580154 [ android-pixel-6-pro ] v8.browsing_mobile-future/browse:news:nytimes:2019 [ Skip ] +crbug.com/436580154 [ android-pixel-6 ] v8.browsing_mobile/browse:news:nytimes:2019 [ Skip ] +crbug.com/436580154 [ android-pixel-6-pro ] v8.browsing_mobile/browse:news:nytimes:2019 [ Skip ] # Fuchsia does not support new tab nor omnibox [ fuchsia-board-nelson ] v8.browsing_mobile/browse:chrome:newtab:2019 [ Skip ] [ fuchsia-board-nelson ] v8.browsing_mobile/browse:chrome:omnibox:2019 [ Skip ]
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc index a714b79..6da6d22d 100644 --- a/ui/accessibility/accessibility_features.cc +++ b/ui/accessibility/accessibility_features.cc
@@ -203,6 +203,10 @@ return base::FeatureList::IsEnabled(::features::kIChromeAccessible); } +BASE_FEATURE(kUiaDisconnectRootProviders, + "UiaDisconnectRootProviders", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kUiaProvider, "UiaProvider", base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kUiaEventOptimization,
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h index f7fc452..2cf20742a 100644 --- a/ui/accessibility/accessibility_features.h +++ b/ui/accessibility/accessibility_features.h
@@ -158,6 +158,10 @@ AX_BASE_EXPORT BASE_DECLARE_FEATURE(kIChromeAccessible); AX_BASE_EXPORT bool IsIChromeAccessibleEnabled(); +// Enables calls to UiaDisconnectProvider when destroying a AXFragmentRootWin's +// HWND. +AX_BASE_EXPORT BASE_DECLARE_FEATURE(kUiaDisconnectRootProviders); + // Use the browser's UIA provider when requested by // an accessibility client. AX_BASE_EXPORT BASE_DECLARE_FEATURE(kUiaProvider);
diff --git a/ui/accessibility/platform/ax_fragment_root_win.cc b/ui/accessibility/platform/ax_fragment_root_win.cc index 8323932..08034d9 100644 --- a/ui/accessibility/platform/ax_fragment_root_win.cc +++ b/ui/accessibility/platform/ax_fragment_root_win.cc
@@ -17,7 +17,6 @@ #include "base/trace_event/typed_macros.h" #include "base/win/scoped_safearray.h" #include "third_party/abseil-cpp/absl/container/flat_hash_map.h" -#include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/platform/ax_fragment_root_delegate_win.h" #include "ui/accessibility/platform/ax_platform.h" #include "ui/accessibility/platform/ax_platform_node_win.h" @@ -469,6 +468,10 @@ return base::Contains(property_listener_count_, property_id); } +IRawElementProviderSimple* AXFragmentRootWin::GetProvider() { + return static_cast<AXFragmentRootPlatformNodeWin*>(platform_node_.get()); +} + size_t AXFragmentRootWin::GetIndexInParentOfChild() const { AXPlatformNodeDelegate* parent = GetParentNodeDelegate();
diff --git a/ui/accessibility/platform/ax_fragment_root_win.h b/ui/accessibility/platform/ax_fragment_root_win.h index e7c5cc6..0148015 100644 --- a/ui/accessibility/platform/ax_fragment_root_win.h +++ b/ui/accessibility/platform/ax_fragment_root_win.h
@@ -12,6 +12,8 @@ #include "ui/accessibility/platform/ax_platform_node_delegate.h" #include "ui/accessibility/platform/ax_unique_id.h" +struct IRawElementProviderSimple; + namespace ui { class AXFragmentRootDelegateWin; @@ -64,6 +66,12 @@ bool HasEventListenerForEvent(int event_id); bool HasEventListenerForProperty(int property_id); + // Returns the fragment root's element provider. This provides direct access + // to the interface without increasing the instance's refcount. Prefer + // `GetNativeViewAccessible()` when returning the provider in response to a + // WM_GETOBJECT message, as that performs additional required bookkeeping. + IRawElementProviderSimple* GetProvider(); + private: // AXPlatformNodeDelegate overrides. gfx::NativeViewAccessible GetParent() const override;
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index a4c2d4e7..86d5ed075 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -509,6 +509,7 @@ "java/src/org/chromium/ui/text/DownloadableFontTextAppearanceSpan.java", "java/src/org/chromium/ui/text/EmptyTextWatcher.java", "java/src/org/chromium/ui/text/SpanApplier.java", + "java/src/org/chromium/ui/theme/ThemeResourceWrapper.java", "java/src/org/chromium/ui/util/AccessibilityUtil.java", "java/src/org/chromium/ui/util/AttrUtils.java", "java/src/org/chromium/ui/util/ClickWithMetaStateCallback.java", @@ -749,6 +750,7 @@ "junit/src/org/chromium/ui/shadows/ShadowAppCompatResourcesTest.java", "junit/src/org/chromium/ui/test/util/WindowInsetsTestUtilsUnitTest.java", "junit/src/org/chromium/ui/text/SpanApplierTest.java", + "junit/src/org/chromium/ui/theme/ThemeResourceWrapperUnitTest.java", "junit/src/org/chromium/ui/util/ColorBlendAnimationFactoryTest.java", "junit/src/org/chromium/ui/util/ColorUtilsTest.java", "junit/src/org/chromium/ui/util/RunnableTimerTest.java", @@ -764,6 +766,7 @@ "junit/src/org/chromium/ui/widget/ViewRectProviderTest.java", ] deps = [ + ":test_java_resources", ":ui_android_features_java", ":ui_java", ":ui_java_resources", @@ -778,6 +781,7 @@ "//base/test:test_support_java", "//build/android:build_java", "//third_party/android_deps:guava_android_java", + "//third_party/android_deps:material_design_java", "//third_party/androidx:androidx_activity_activity_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_appcompat_appcompat_resources_java", @@ -881,6 +885,7 @@ android_library("ui_unit_device_javatests") { testonly = true resources_package = "org.chromium.ui" + mergeable_android_manifests = [ "junit/AndroidManifest.xml" ] sources = [ "java/src/org/chromium/ui/UiUtilsTest.java", @@ -890,6 +895,7 @@ "javatests/src/org/chromium/ui/animation/ViewCurvedMotionAnimatorFactoryRenderTest.java", "javatests/src/org/chromium/ui/base/ClipboardAndroidTest.java", "javatests/src/org/chromium/ui/insets/WindowInsetsUtilsJavaUnitTest.java", + "javatests/src/org/chromium/ui/theme/ThemeResourceWrapperJavaUnitTest.java", "junit/src/org/chromium/ui/widget/TextViewWithLeadingTest.java", ] @@ -903,8 +909,11 @@ "//base:base_java_test_support", "//components/browser_ui/widget/android:java_resources", "//content/public/test/android:content_java_test_support", + "//third_party/androidx:androidx_activity_activity_java", "//third_party/androidx:androidx_annotation_annotation_java", + "//third_party/androidx:androidx_appcompat_appcompat_java", "//third_party/androidx:androidx_core_core_java", + "//third_party/androidx:androidx_fragment_fragment_java", "//third_party/androidx:androidx_test_core_java", "//third_party/androidx:androidx_test_runner_java", "//third_party/hamcrest:hamcrest_java",
diff --git a/ui/android/java/src/org/chromium/ui/base/DeviceInput.java b/ui/android/java/src/org/chromium/ui/base/DeviceInput.java index d4a7fab1..5bc997f 100644 --- a/ui/android/java/src/org/chromium/ui/base/DeviceInput.java +++ b/ui/android/java/src/org/chromium/ui/base/DeviceInput.java
@@ -40,6 +40,9 @@ /** See {@link #setSupportsAlphabeticKeyboardForTesting(boolean)}. */ private static @Nullable Boolean sSupportsAlphabeticKeyboardForTesting; + /** See {@link #setSupportsKeyboardForTesting(boolean)}. */ + private static @Nullable Boolean sSupportsKeyboardForTesting; + /** See {@link #setSupportsPrevisionPointerForTesting(boolean)}. */ private static @Nullable Boolean sSupportsPrecisionPointerForTesting; @@ -87,6 +90,13 @@ return getInstance().supportsAlphabeticKeyboardImpl(); } + /** Modifies the output of {@link #supportsKeyboard()} for testing. */ + public static void setSupportsKeyboardForTesting(Boolean supportsKeyboard) { + sSupportsKeyboardForTesting = supportsKeyboard; + // Register a callback to reset this value after every test method completes. + ResettersForTesting.register(() -> sSupportsKeyboardForTesting = null); + } + /** * @return Whether any currently connected {@link InputDevice} supports a keyboard. */ @@ -112,6 +122,10 @@ /** Implementation of {@link #supportsKeyboard()}. */ public boolean supportsKeyboardImpl() { ThreadUtils.assertOnUiThread(); + if (sSupportsKeyboardForTesting != null) { + return sSupportsKeyboardForTesting; + } + for (int i = 0; i < mDeviceSnapshotsById.size(); i++) { if (mDeviceSnapshotsById.valueAt(i).supportsKeyboard) { return true;
diff --git a/ui/android/java/src/org/chromium/ui/theme/OWNERS b/ui/android/java/src/org/chromium/ui/theme/OWNERS new file mode 100644 index 0000000..6925971 --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/theme/OWNERS
@@ -0,0 +1,2 @@ +wenyufu@chromium.org +sinansahin@google.com \ No newline at end of file
diff --git a/ui/android/java/src/org/chromium/ui/theme/ThemeResourceWrapper.java b/ui/android/java/src/org/chromium/ui/theme/ThemeResourceWrapper.java new file mode 100644 index 0000000..9b21dfb4 --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/theme/ThemeResourceWrapper.java
@@ -0,0 +1,168 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.theme; + +import android.content.Context; +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.content.res.Resources.Theme; +import android.view.ContextThemeWrapper; + +import androidx.annotation.StyleRes; + +import org.chromium.base.ObserverList; +import org.chromium.base.ThreadUtils; +import org.chromium.build.annotations.NullMarked; + +/** + * Delegate class that used to provide themes and resources based on state. This class internally + * holds a {@link android.view.ContextThemeWrapper}, and provide theme / resources based on current + * state whether the overlay is enabled. + * + * <p>This class is useful when the feature wants to provide different sets of themes / resources in + * different conditions, essentially allowing a ContextThemeWrapper to "unset" the applied theme + * overlay. See {@link ThemeResourceWrapperJavaUnitTest} for example usage. + * + * <p>This class should only be accessed on the UI thread. + */ +@NullMarked +public class ThemeResourceWrapper { + + /** Observe the theme resource changes provided by the wrapper. */ + public interface ThemeObserver { + + /** Called when the theme / resource is changed. */ + void onThemeResourceChanged(); + } + + private final Context mBaseContext; + private final @StyleRes int mResourceId; + private final ObserverList<ThemeObserver> mObservers = new ObserverList<>(); + private Context mThemedContext; + private boolean mIsUsingOverlay; + + // This is important so that we lock the call to mThemedContext. This is especially important + // to avoid unlimited recursion. + private boolean mIsBusy; + + /** + * Create the instance based on the base context. + * + * @param baseContext The base context to be wrapped + * @param resourceId The theme overlay resource to be used for the overlay. + */ + public ThemeResourceWrapper(Context baseContext, @StyleRes int resourceId) { + mBaseContext = baseContext; + mResourceId = resourceId; + mIsUsingOverlay = false; + + updateThemedContext(); + } + + /** Set whether we should enable the current theme overlay. */ + public void setIsUsingOverlay(boolean isUsingOverlay) { + if (mIsUsingOverlay == isUsingOverlay) return; + mIsUsingOverlay = isUsingOverlay; + updateThemedContext(); + } + + /** + * Return whether this class is reading resource from Themed context. This is a critical signal + * when the mBaseContext is a ContextWrapper which delegates the calls (e.g. {@link #getTheme} + * to a {@link ThemeResourceWrapper} instance. The delegating activity should reading this + * signal to prevent recursion calls that causes stackoverflow. + */ + public boolean isBusy() { + return mIsBusy; + } + + /** + * Forward the #getTheme call to the theme wrapper or base context based on state. + * + * @see Context#getTheme() + */ + public Theme getTheme() { + ThreadUtils.assertOnUiThread(); + assert !mIsBusy; + try { + mIsBusy = true; + return mThemedContext.getTheme(); + } finally { + mIsBusy = false; + } + } + + /** + * Forward the #getResources call to the theme wrapper or base context based on state. + * + * @see Context#getResources() + */ + public Resources getResources() { + ThreadUtils.assertOnUiThread(); + assert !mIsBusy; + try { + mIsBusy = true; + return mThemedContext.getResources(); + } finally { + mIsBusy = false; + } + } + + /** + * Forward the #getResources call to the theme wrapper or base context based on state. + * + * @see Context#getResources() + */ + public AssetManager getAssets() { + ThreadUtils.assertOnUiThread(); + assert !mIsBusy; + try { + mIsBusy = true; + return mThemedContext.getAssets(); + } finally { + mIsBusy = false; + } + } + + /** + * Forward the #getSystemService call to the theme wrapper or base context based on state. + * + * @see Context#getSystemService(String) + */ + public Object getSystemService(String name) { + ThreadUtils.assertOnUiThread(); + assert !mIsBusy; + try { + mIsBusy = true; + return mThemedContext.getSystemService(name); + } finally { + mIsBusy = false; + } + } + + public void addObserver(ThemeObserver observer) { + mObservers.addObserver(observer); + } + + public void removeObserver(ThemeObserver observer) { + mObservers.removeObserver(observer); + } + + public void destroy() { + mObservers.clear(); + } + + private void updateThemedContext() { + mThemedContext = + mIsUsingOverlay ? new ContextThemeWrapper(mBaseContext, mResourceId) : mBaseContext; + for (ThemeObserver observer : mObservers) { + observer.onThemeResourceChanged(); + } + } + + Context getThemedContextForTesting() { + return mThemedContext; + } +}
diff --git a/ui/android/javatests/src/org/chromium/ui/theme/OWNERS b/ui/android/javatests/src/org/chromium/ui/theme/OWNERS new file mode 100644 index 0000000..6b744cc --- /dev/null +++ b/ui/android/javatests/src/org/chromium/ui/theme/OWNERS
@@ -0,0 +1 @@ +file://ui/android/java/src/org/chromium/ui/theme/OWNERS
diff --git a/ui/android/javatests/src/org/chromium/ui/theme/ThemeResourceWrapperJavaUnitTest.java b/ui/android/javatests/src/org/chromium/ui/theme/ThemeResourceWrapperJavaUnitTest.java new file mode 100644 index 0000000..2888ae0 --- /dev/null +++ b/ui/android/javatests/src/org/chromium/ui/theme/ThemeResourceWrapperJavaUnitTest.java
@@ -0,0 +1,198 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.theme; + +import static org.junit.Assert.assertEquals; + +import android.content.res.AssetManager; +import android.content.res.Resources; +import android.content.res.Resources.Theme; +import android.graphics.Color; +import android.os.Bundle; +import android.util.TypedValue; + +import androidx.annotation.AttrRes; +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.appcompat.app.AppCompatActivity; +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.BaseActivityTestRule; +import org.chromium.base.test.BaseJUnit4ClassRunner; +import org.chromium.base.test.util.Batch; +import org.chromium.ui.R; + +/** Java test show case how to use the wrapper. */ +@Batch(Batch.PER_CLASS) +@RunWith(BaseJUnit4ClassRunner.class) +public class ThemeResourceWrapperJavaUnitTest { + + @Rule + public BaseActivityTestRule<ThemeResourceTestActivity> mActivityTestRule = + new BaseActivityTestRule<>(ThemeResourceTestActivity.class); + + private ThemeResourceTestActivity mActivity; + + @Before + public void setup() { + mActivityTestRule.launchActivity(null); + mActivity = mActivityTestRule.getActivity(); + ThreadUtils.runOnUiThreadBlocking( + () -> { + mActivity.getThemeResourceWrapper().setIsUsingOverlay(false); + }); + } + + @Test + @SmallTest + public void setThemeForOriginalActivity() { + ThreadUtils.runOnUiThreadBlocking( + () -> { + assertEquals( + "Color without overlay is blue.", + mActivity.getColor(android.R.color.holo_blue_light), + getPrimaryColor()); + + mActivity.setTheme(R.style.ThemeOverlay_WhitePrimary); + assertEquals( + "Color with new overlay will override the activity's default.", + Color.WHITE, + getPrimaryColor()); + }); + } + + @Test + @SmallTest + public void setThemeNoOpWithThemeResourceWrapper() { + ThreadUtils.runOnUiThreadBlocking( + () -> { + assertEquals( + "Color without overlay is blue.", + mActivity.getColor(android.R.color.holo_blue_light), + getPrimaryColor()); + + mActivity.getThemeResourceWrapper().setIsUsingOverlay(true); + assertEquals( + "Color using resource wrapper will be override into black.", + Color.BLACK, + getPrimaryColor()); + + mActivity.setTheme(R.style.ThemeOverlay_WhitePrimary); + assertEquals( + "While theme resource wrapper is in use, setTheme for activity is no" + + " op.", + Color.BLACK, + getPrimaryColor()); + }); + } + + @Test + @SmallTest + public void themeWrapperNoImpactOnOtherAttribute() { + ThreadUtils.runOnUiThreadBlocking( + () -> { + assertEquals( + "Text color highlight without overlay is blue.", + mActivity.getColor(android.R.color.holo_blue_light), + getTextColorHighlight()); + + mActivity.getThemeResourceWrapper().setIsUsingOverlay(true); + assertEquals( + "Text color highlight should remain no impacted by" + + " ThemeResourceWrapper.", + mActivity.getColor(android.R.color.holo_blue_light), + getTextColorHighlight()); + + // As theme resource is created by the time ThemeResourceWrapper is created, the + // new overlay applied to the base theme will not impact the overlay. + mActivity.setTheme(R.style.ThemeOverlay_WhitePrimary_WithTextColor); + assertEquals( + "Text color highlight should should remain no impacted.", + mActivity.getColor(android.R.color.holo_blue_light), + getTextColorHighlight()); + + // Turning off the overlay, the text color overlay that applied to the base + // activity will take effect. + mActivity.getThemeResourceWrapper().setIsUsingOverlay(false); + assertEquals( + "Text color highlight is override by #setTheme.", + Color.WHITE, + getTextColorHighlight()); + }); + } + + private @ColorInt int getPrimaryColor() { + return getColorFromAttr(R.attr.colorPrimary); + } + + private @ColorInt int getTextColorHighlight() { + return getColorFromAttr(android.R.attr.textColorHighlight); + } + + private @ColorInt int getColorFromAttr(@AttrRes int attrRes) { + TypedValue tv = new TypedValue(); + boolean success = mActivity.getTheme().resolveAttribute(attrRes, tv, true); + + return success ? mActivity.getColor(tv.resourceId) : Color.TRANSPARENT; + } + + /** + * Basic activity that delegates the resource call to a {@link ThemeResourceWrapper} instance. + */ + public static class ThemeResourceTestActivity extends AppCompatActivity { + + private ThemeResourceWrapper mThemeResourceWrapper; + + public ThemeResourceWrapper getThemeResourceWrapper() { + return mThemeResourceWrapper; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setTheme(R.style.ThemeOverlay_BluePrimary); + mThemeResourceWrapper = + new ThemeResourceWrapper(this, R.style.ThemeOverlay_BlackPrimary); + } + + @Override + public Resources getResources() { + if (mThemeResourceWrapper != null && !mThemeResourceWrapper.isBusy()) { + return mThemeResourceWrapper.getResources(); + } + return super.getResources(); + } + + @Override + public Theme getTheme() { + if (mThemeResourceWrapper != null && !mThemeResourceWrapper.isBusy()) { + return mThemeResourceWrapper.getTheme(); + } + return super.getTheme(); + } + + @Override + public AssetManager getAssets() { + if (mThemeResourceWrapper != null && !mThemeResourceWrapper.isBusy()) { + return mThemeResourceWrapper.getAssets(); + } + return super.getAssets(); + } + + @Override + public Object getSystemService(@NonNull String name) { + if (mThemeResourceWrapper != null && !mThemeResourceWrapper.isBusy()) { + return mThemeResourceWrapper.getSystemService(name); + } + return super.getSystemService(name); + } + } +}
diff --git a/ui/android/junit/AndroidManifest.xml b/ui/android/junit/AndroidManifest.xml index 1d592aa..8ae7f9e60 100644 --- a/ui/android/junit/AndroidManifest.xml +++ b/ui/android/junit/AndroidManifest.xml
@@ -16,5 +16,7 @@ <application android:theme="@style/Theme.AppCompat.Light"> <activity android:name="org.chromium.ui.base.TestActivity"/> + + <activity android:name="org.chromium.ui.theme.ThemeResourceWrapperJavaUnitTest$ThemeResourceTestActivity"/> </application> </manifest>
diff --git a/ui/android/junit/src/org/chromium/ui/theme/OWNERS b/ui/android/junit/src/org/chromium/ui/theme/OWNERS new file mode 100644 index 0000000..6b744cc --- /dev/null +++ b/ui/android/junit/src/org/chromium/ui/theme/OWNERS
@@ -0,0 +1 @@ +file://ui/android/java/src/org/chromium/ui/theme/OWNERS
diff --git a/ui/android/junit/src/org/chromium/ui/theme/ThemeResourceWrapperUnitTest.java b/ui/android/junit/src/org/chromium/ui/theme/ThemeResourceWrapperUnitTest.java new file mode 100644 index 0000000..dadb7ac --- /dev/null +++ b/ui/android/junit/src/org/chromium/ui/theme/ThemeResourceWrapperUnitTest.java
@@ -0,0 +1,82 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.theme; + +import static org.junit.Assert.assertEquals; + +import android.graphics.Color; + +import com.google.android.material.color.MaterialColors; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.ui.R; +import org.chromium.ui.base.TestActivity; + +@RunWith(BaseRobolectricTestRunner.class) +public class ThemeResourceWrapperUnitTest { + + @Rule public MockitoRule mMockitoJUnit = MockitoJUnit.rule(); + + private TestActivity mActivity; + private ThemeResourceWrapper mThemeWrapper; + + @Mock private ThemeResourceWrapper.ThemeObserver mThemeObserver; + + @Before + public void setUp() { + mActivity = Robolectric.buildActivity(TestActivity.class).create().get(); + mActivity.setTheme(R.style.ThemeOverlay_BlackPrimary); + + mThemeWrapper = new ThemeResourceWrapper(mActivity, R.style.ThemeOverlay_WhitePrimary); + mThemeWrapper.addObserver(mThemeObserver); + } + + @After + public void tearDown() { + mThemeWrapper.destroy(); + mActivity.finish(); + } + + @Test + public void testThemeWrapper() { + mThemeWrapper.setIsUsingOverlay(true); + Mockito.verify(mThemeObserver).onThemeResourceChanged(); + + int colorPrimary = MaterialColors.getColor(mActivity, R.attr.colorPrimary, "TAG"); + int wrapperColorPrimary = + MaterialColors.getColor( + mThemeWrapper.getThemedContextForTesting(), R.attr.colorPrimary, "TAG"); + + assertEquals("Primary expected to be black without overlay.", Color.BLACK, colorPrimary); + assertEquals( + "Themed context should have different color.", Color.WHITE, wrapperColorPrimary); + } + + @Test + public void testThemeWrapper_Disabled() { + mThemeWrapper.setIsUsingOverlay(false); + Mockito.verifyNoInteractions(mThemeObserver); + + int colorPrimary = MaterialColors.getColor(mActivity, R.attr.colorPrimary, "TAG"); + int wrapperColorPrimary = + MaterialColors.getColor( + mThemeWrapper.getThemedContextForTesting(), R.attr.colorPrimary, "TAG"); + + assertEquals("Primary expected to be black without overlay.", Color.BLACK, colorPrimary); + assertEquals( + "Themed context should have different color.", Color.BLACK, wrapperColorPrimary); + } +}
diff --git a/ui/android/test/java/res/values/attrs.xml b/ui/android/test/java/res/values/attrs.xml index 40c63b3..a93b430b 100644 --- a/ui/android/test/java/res/values/attrs.xml +++ b/ui/android/test/java/res/values/attrs.xml
@@ -6,4 +6,7 @@ --> <resources> <attr name="badAttr" format="reference"/> + + <!-- Work around in case AppCompat attributes cant be found. --> + <attr name="colorPrimary" format="color"/> </resources>
diff --git a/ui/android/test/java/res/values/styles.xml b/ui/android/test/java/res/values/styles.xml index 6dbe263..2395e76 100644 --- a/ui/android/test/java/res/values/styles.xml +++ b/ui/android/test/java/res/values/styles.xml
@@ -18,4 +18,21 @@ <style name="StyleIntoTextAppearance"> <item name="android:textAppearance">@style/StyleWithLeading</item> </style> + + <style name="ThemeOverlay.BlackPrimary" parent=""> + <item name="colorPrimary">@android:color/black</item> + </style> + + <style name="ThemeOverlay.WhitePrimary" parent=""> + <item name="colorPrimary">@android:color/white</item> + </style> + + <style name="ThemeOverlay.BluePrimary" parent=""> + <item name="colorPrimary">@android:color/holo_blue_light</item> + <item name="android:textColorHighlight">@android:color/holo_blue_light</item> + </style> + + <style name="ThemeOverlay.WhitePrimary.WithTextColor"> + <item name="android:textColorHighlight">@android:color/white</item> + </style> </resources>
diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc index ff71b4a..d92879b 100644 --- a/ui/aura/gestures/gesture_recognizer_unittest.cc +++ b/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -2993,7 +2993,7 @@ delegate.get(), -1234, bounds, root_window())); const int kSteps = 15; - const int kTouchPoints = 4; + const size_t kTouchPoints = 4; gfx::Point points[kTouchPoints] = { gfx::Point(10, 30), gfx::Point(30, 20), @@ -3006,39 +3006,39 @@ // The unified gesture recognizer assumes a finger has stopped if it hasn't // moved for too long. See ui/events/velocity_tracker/velocity_tracker.cc's // kAssumePointerStoppedTimeMs. - for (int count = 2; count <= kTouchPoints; ++count) { - generator.GestureMultiFingerScroll( - count, points, 10, kSteps, 0, -11 * kSteps); + for (size_t count = 2; count <= kTouchPoints; ++count) { + generator.GestureMultiFingerScroll(count, base::span(points).first(count), + 10, kSteps, 0, -11 * kSteps); EXPECT_TRUE(delegate->swipe_up()); delegate->Reset(); - generator.GestureMultiFingerScroll( - count, points, 10, kSteps, 0, 11 * kSteps); + generator.GestureMultiFingerScroll(count, base::span(points).first(count), + 10, kSteps, 0, 11 * kSteps); EXPECT_TRUE(delegate->swipe_down()); delegate->Reset(); - generator.GestureMultiFingerScroll( - count, points, 10, kSteps, -11 * kSteps, 0); + generator.GestureMultiFingerScroll(count, base::span(points).first(count), + 10, kSteps, -11 * kSteps, 0); EXPECT_TRUE(delegate->swipe_left()); delegate->Reset(); - generator.GestureMultiFingerScroll( - count, points, 10, kSteps, 11 * kSteps, 0); + generator.GestureMultiFingerScroll(count, base::span(points).first(count), + 10, kSteps, 11 * kSteps, 0); EXPECT_TRUE(delegate->swipe_right()); delegate->Reset(); - generator.GestureMultiFingerScroll( - count, points, 10, kSteps, 5 * kSteps, 12 * kSteps); + generator.GestureMultiFingerScroll(count, base::span(points).first(count), + 10, kSteps, 5 * kSteps, 12 * kSteps); EXPECT_FALSE(delegate->swipe_down()); delegate->Reset(); - generator.GestureMultiFingerScroll( - count, points, 10, kSteps, 4 * kSteps, 12 * kSteps); + generator.GestureMultiFingerScroll(count, base::span(points).first(count), + 10, kSteps, 4 * kSteps, 12 * kSteps); EXPECT_TRUE(delegate->swipe_down()); delegate->Reset(); - generator.GestureMultiFingerScroll( - count, points, 10, kSteps, 3 * kSteps, 12 * kSteps); + generator.GestureMultiFingerScroll(count, base::span(points).first(count), + 10, kSteps, 3 * kSteps, 12 * kSteps); EXPECT_TRUE(delegate->swipe_down()); delegate->Reset(); }
diff --git a/ui/aura/test/test_window_builder.cc b/ui/aura/test/test_window_builder.cc index d6f2b6c9..32a89e75 100644 --- a/ui/aura/test/test_window_builder.cc +++ b/ui/aura/test/test_window_builder.cc
@@ -97,11 +97,12 @@ std::unique_ptr<Window> TestWindowBuilder::Build() { auto window = CreateWindowInternal(); - if (parent()) { + auto* parent = release_parent(); + if (parent) { if (!params_.bounds.IsEmpty()) { window->SetBounds(params_.bounds); } - params_.parent->AddChild(window.get()); + parent->AddChild(window.get()); } else { // Parent window is not specified. A parent window will be picked from // the context.
diff --git a/ui/aura/test/test_window_builder.h b/ui/aura/test/test_window_builder.h index ecefc01..0eb59fd7 100644 --- a/ui/aura/test/test_window_builder.h +++ b/ui/aura/test/test_window_builder.h
@@ -86,8 +86,13 @@ const WindowBuilderParams& params() const { return params_; } bool built() const { return built_; } - // Subclass needs a write access to the parent_. - Window* parent() { return params_.parent; } + // Subclass needs a write access to parent. Reset it after it is returned to + // avoid dangling pointer. + Window* release_parent() { + auto* r = params_.parent.get(); + params_.parent = nullptr; + return r; + } private: WindowBuilderParams params_;
diff --git a/ui/events/devices/x11/device_data_manager_x11.cc b/ui/events/devices/x11/device_data_manager_x11.cc index e2f10d5..584add04 100644 --- a/ui/events/devices/x11/device_data_manager_x11.cc +++ b/ui/events/devices/x11/device_data_manager_x11.cc
@@ -351,12 +351,12 @@ if (sourceid >= kMaxDeviceNum || deviceid >= kMaxDeviceNum) return; data->clear(); - const x11::Input::Fp3232* valuators = xiev->axisvalues.data(); + auto valuators_iter = xiev->axisvalues.begin(); for (int i = 0; i <= valuator_count_[sourceid]; ++i) { if (IsXinputMaskSet(xiev->valuator_mask.data(), i)) { int type = data_type_lookup_[sourceid][i]; if (type != DT_LAST_ENTRY) { - double valuator = Fp3232ToDouble(*valuators); + double valuator = Fp3232ToDouble(*valuators_iter); (*data)[type] = valuator; if (IsTouchDataType(type)) { int slot = -1; @@ -364,7 +364,7 @@ last_seen_valuator_[sourceid][slot][type] = valuator; } } - valuators++; + ++valuators_iter; } } } @@ -400,12 +400,12 @@ int slot = 0; if (val_index >= 0) { if (IsXinputMaskSet(xiev->valuator_mask.data(), val_index)) { - const x11::Input::Fp3232* valuators = xiev->axisvalues.data(); + auto valuators_iter = xiev->axisvalues.begin(); while (val_index--) { if (IsXinputMaskSet(xiev->valuator_mask.data(), val_index)) - ++valuators; + ++valuators_iter; } - *value = Fp3232ToDouble(*valuators); + *value = Fp3232ToDouble(*valuators_iter); if (IsTouchDataType(type)) { if (GetSlotNumber(*xiev, &slot) && slot >= 0 && slot < kMaxSlotNum) last_seen_valuator_[sourceid][slot][type] = *value; @@ -578,7 +578,7 @@ auto deviceid = static_cast<uint16_t>(xiev->deviceid); if (sourceid >= kMaxDeviceNum || deviceid >= kMaxDeviceNum) return; - const x11::Input::Fp3232* valuators = xiev->axisvalues.data(); + auto valuators_iter = xiev->axisvalues.begin(); ScrollInfo* info = &scroll_data_[sourceid]; @@ -588,12 +588,12 @@ for (int i = 0; i <= valuator_count_[sourceid]; ++i) { if (!IsXinputMaskSet(xiev->valuator_mask.data(), i)) continue; - auto valuator = Fp3232ToDouble(*valuators); + auto valuator = Fp3232ToDouble(*valuators_iter); if (i == horizontal_number) *x_offset = ExtractAndUpdateScrollOffset(&info->horizontal, valuator); else if (i == vertical_number) *y_offset = ExtractAndUpdateScrollOffset(&info->vertical, valuator); - valuators++; + ++valuators_iter; } }
diff --git a/ui/events/event_dispatcher_unittest.cc b/ui/events/event_dispatcher_unittest.cc index 6de964b..88ac0ab 100644 --- a/ui/events/event_dispatcher_unittest.cc +++ b/ui/events/event_dispatcher_unittest.cc
@@ -8,7 +8,6 @@ #include <utility> #include "base/check.h" -#include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" #include "base/notreached.h" #include "testing/gtest/include/gtest/gtest.h" @@ -254,12 +253,7 @@ EXPECT_FALSE(mouse.stopped_propagation()); EXPECT_FALSE(mouse.handled()); - { - int expected[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - UNSAFE_TODO(EXPECT_EQ( - std::vector<int>(expected, expected + sizeof(expected) / sizeof(int)), - child.handler_list())); - } + EXPECT_EQ(std::vector<int>({1, 2, 3, 4, 5, 6, 7, 8}), child.handler_list()); child.Reset(); event_mod.set_phase(EP_PREDISPATCH); @@ -270,42 +264,32 @@ EXPECT_EQ(EP_POSTDISPATCH, mouse.phase()); EXPECT_FALSE(mouse.stopped_propagation()); EXPECT_TRUE(mouse.handled()); - { // |h1| marks the event as handled. So only the pre-target handlers should // receive the event. - int expected[] = { 1, 2, 3, 4 }; - UNSAFE_TODO(EXPECT_EQ( - std::vector<int>(expected, expected + sizeof(expected) / sizeof(int)), - child.handler_list())); - } + EXPECT_EQ(std::vector<int>({1, 2, 3, 4}), child.handler_list()); child.Reset(); event_mod.set_phase(EP_PREDISPATCH); event_mod.set_result(ER_UNHANDLED); - int nexpected[] = { 1, 2, 3, 4, 5 }; h1.set_event_result(ER_UNHANDLED); h5.set_event_result(ER_CONSUMED); dispatcher.ProcessEvent(&child, &mouse); EXPECT_EQ(EP_POSTDISPATCH, mouse.phase()); EXPECT_TRUE(mouse.stopped_propagation()); EXPECT_TRUE(mouse.handled()); - UNSAFE_TODO(EXPECT_EQ( - std::vector<int>(nexpected, nexpected + sizeof(nexpected) / sizeof(int)), - child.handler_list())); + EXPECT_EQ(std::vector<int>({1, 2, 3, 4, 5}), child.handler_list()); child.Reset(); event_mod.set_phase(EP_PREDISPATCH); event_mod.set_result(ER_UNHANDLED); - int exp[] = { 1 }; h1.set_event_result(ER_CONSUMED); dispatcher.ProcessEvent(&child, &mouse); EXPECT_EQ(EP_POSTDISPATCH, mouse.phase()); EXPECT_TRUE(mouse.stopped_propagation()); EXPECT_TRUE(mouse.handled()); - UNSAFE_TODO(EXPECT_EQ(std::vector<int>(exp, exp + sizeof(exp) / sizeof(int)), - child.handler_list())); + EXPECT_EQ(std::vector<int>({1}), child.handler_list()); parent.RemovePreTargetHandler(&h1); parent.RemovePreTargetHandler(&h2); @@ -332,10 +316,7 @@ dispatcher.ProcessEvent(&target, &mouse); EXPECT_EQ(ER_UNHANDLED, mouse.result()); - int handlers[] = { 11, 11 }; - UNSAFE_TODO(EXPECT_EQ( - std::vector<int>(handlers, handlers + sizeof(handlers) / sizeof(int)), - target.handler_list())); + EXPECT_EQ(std::vector<int>({11, 11}), target.handler_list()); target.RemovePreTargetHandler(&handler); }
diff --git a/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc b/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc index 3746af5..5914c270 100644 --- a/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc +++ b/ui/events/ozone/evdev/event_converter_evdev_impl_unittest.cc
@@ -1232,8 +1232,8 @@ ui::EvdevSetBit(key_bits.data(), key); } - devinfo.SetEventTypes(ev_bits.data(), ev_bits.size()); - devinfo.SetKeyEvents(key_bits.data(), key_bits.size()); + devinfo.SetEventTypes(ev_bits); + devinfo.SetKeyEvents(key_bits); std::string log = LogSubst(kDefaultDeviceLogDescription, "keyboard_type", "ui::KeyboardType::VALID_KEYBOARD"); @@ -1248,8 +1248,8 @@ ui::EvdevSetBit(ev_bits.data(), EV_LED); ui::EvdevSetBit(led_bits.data(), LED_CAPSL); - devinfo.SetEventTypes(ev_bits.data(), ev_bits.size()); - devinfo.SetLedEvents(led_bits.data(), led_bits.size()); + devinfo.SetEventTypes(ev_bits); + devinfo.SetLedEvents(led_bits); std::string log = LogSubst(kDefaultDeviceLogDescription, "has_caps_lock_led", "1");
diff --git a/ui/events/ozone/evdev/event_device_info.cc b/ui/events/ozone/evdev/event_device_info.cc index 76a14bb..a478509 100644 --- a/ui/events/ozone/evdev/event_device_info.cc +++ b/ui/events/ozone/evdev/event_device_info.cc
@@ -15,6 +15,7 @@ #include <cstring> #include "base/containers/fixed_flat_set.h" +#include "base/containers/span.h" #include "base/feature_list.h" #include "base/files/file_path.h" #include "base/logging.h" @@ -418,22 +419,20 @@ // |size| is num_slots + 1 (for code). void GetSlotValues(int fd, const base::FilePath& path, - int32_t* request, - unsigned int size) { - size_t data_size = size * sizeof(*request); - if (ioctl(fd, EVIOCGMTSLOTS(data_size), request) < 0) { + base::span<int32_t> request) { + size_t data_size = request.size() * sizeof(request[0]); + if (ioctl(fd, EVIOCGMTSLOTS(data_size), request.data()) < 0) { PLOG(ERROR) << "Failed EVIOCGMTSLOTS (code=" << request[0] << " path=" << path.value() << ")"; } } -void AssignBitset(const unsigned long* src, - size_t src_len, - unsigned long* dst, - size_t dst_len) { - memcpy(dst, src, std::min(src_len, dst_len) * sizeof(unsigned long)); - if (src_len < dst_len) - memset(&dst[src_len], 0, (dst_len - src_len) * sizeof(unsigned long)); +void AssignBitset(base::span<const unsigned long> src, + base::span<unsigned long> dst) { + dst.copy_prefix_from(src.first(std::min(src.size(), dst.size()))); + if (src.size() < dst.size()) { + std::ranges::fill(dst.last(dst.size() - src.size()), 0); + } } bool IsDenylistedAbsoluteMouseDevice(const input_id& id) { @@ -516,7 +515,7 @@ memset(request.data(), 0, request.memsize()); request_code = i; - GetSlotValues(fd, path, request.data(), max_num_slots + 1); + GetSlotValues(fd, path, request); std::vector<int32_t>* slots = &slot_values_[i - EVDEV_ABS_MT_FIRST]; slots->assign(request.begin() + 1, request.begin() + 1 + max_num_slots); @@ -537,40 +536,40 @@ return true; } -void EventDeviceInfo::SetEventTypes(const unsigned long* ev_bits, size_t len) { - AssignBitset(ev_bits, len, ev_bits_.data(), ev_bits_.size()); +void EventDeviceInfo::SetEventTypes(base::span<const unsigned long> ev_bits) { + AssignBitset(ev_bits, ev_bits_); } -void EventDeviceInfo::SetKeyEvents(const unsigned long* key_bits, size_t len) { - AssignBitset(key_bits, len, key_bits_.data(), key_bits_.size()); +void EventDeviceInfo::SetKeyEvents(base::span<const unsigned long> key_bits) { + AssignBitset(key_bits, key_bits_); } -void EventDeviceInfo::SetRelEvents(const unsigned long* rel_bits, size_t len) { - AssignBitset(rel_bits, len, rel_bits_.data(), rel_bits_.size()); +void EventDeviceInfo::SetRelEvents(base::span<const unsigned long> rel_bits) { + AssignBitset(rel_bits, rel_bits_); } -void EventDeviceInfo::SetAbsEvents(const unsigned long* abs_bits, size_t len) { - AssignBitset(abs_bits, len, abs_bits_.data(), abs_bits_.size()); +void EventDeviceInfo::SetAbsEvents(base::span<const unsigned long> abs_bits) { + AssignBitset(abs_bits, abs_bits_); } -void EventDeviceInfo::SetMscEvents(const unsigned long* msc_bits, size_t len) { - AssignBitset(msc_bits, len, msc_bits_.data(), msc_bits_.size()); +void EventDeviceInfo::SetMscEvents(base::span<const unsigned long> msc_bits) { + AssignBitset(msc_bits, msc_bits_); } -void EventDeviceInfo::SetSwEvents(const unsigned long* sw_bits, size_t len) { - AssignBitset(sw_bits, len, sw_bits_.data(), sw_bits_.size()); +void EventDeviceInfo::SetSwEvents(base::span<const unsigned long> sw_bits) { + AssignBitset(sw_bits, sw_bits_); } -void EventDeviceInfo::SetLedEvents(const unsigned long* led_bits, size_t len) { - AssignBitset(led_bits, len, led_bits_.data(), led_bits_.size()); +void EventDeviceInfo::SetLedEvents(base::span<const unsigned long> led_bits) { + AssignBitset(led_bits, led_bits_); } -void EventDeviceInfo::SetFfEvents(const unsigned long* ff_bits, size_t len) { - AssignBitset(ff_bits, len, ff_bits_.data(), ff_bits_.size()); +void EventDeviceInfo::SetFfEvents(base::span<const unsigned long> ff_bits) { + AssignBitset(ff_bits, ff_bits_); } -void EventDeviceInfo::SetProps(const unsigned long* prop_bits, size_t len) { - AssignBitset(prop_bits, len, prop_bits_.data(), prop_bits_.size()); +void EventDeviceInfo::SetProps(base::span<const unsigned long> prop_bits) { + AssignBitset(prop_bits, prop_bits_); } void EventDeviceInfo::SetAbsInfo(unsigned int code,
diff --git a/ui/events/ozone/evdev/event_device_info.h b/ui/events/ozone/evdev/event_device_info.h index ba0ac91..e4131d09 100644 --- a/ui/events/ozone/evdev/event_device_info.h +++ b/ui/events/ozone/evdev/event_device_info.h
@@ -15,6 +15,7 @@ #include <vector> #include "base/component_export.h" +#include "base/containers/span.h" #include "ui/events/devices/input_device.h" #include "ui/events/ozone/evdev/event_device_util.h" @@ -75,15 +76,15 @@ bool Initialize(int fd, const base::FilePath& path); // Manual initialization. - void SetEventTypes(const unsigned long* ev_bits, size_t len); - void SetKeyEvents(const unsigned long* key_bits, size_t len); - void SetRelEvents(const unsigned long* rel_bits, size_t len); - void SetAbsEvents(const unsigned long* abs_bits, size_t len); - void SetMscEvents(const unsigned long* msc_bits, size_t len); - void SetSwEvents(const unsigned long* sw_bits, size_t len); - void SetLedEvents(const unsigned long* led_bits, size_t len); - void SetFfEvents(const unsigned long* ff_bits, size_t len); - void SetProps(const unsigned long* prop_bits, size_t len); + void SetEventTypes(base::span<const unsigned long> ev_bits); + void SetKeyEvents(base::span<const unsigned long> key_bits); + void SetRelEvents(base::span<const unsigned long> rel_bits); + void SetAbsEvents(base::span<const unsigned long> abs_bits); + void SetMscEvents(base::span<const unsigned long> msc_bits); + void SetSwEvents(base::span<const unsigned long> sw_bits); + void SetLedEvents(base::span<const unsigned long> led_bits); + void SetFfEvents(base::span<const unsigned long> ff_bits); + void SetProps(base::span<const unsigned long> prop_bits); void SetAbsInfo(unsigned int code, const input_absinfo& absinfo); void SetAbsMtSlots(unsigned int code, const std::vector<int32_t>& values); void SetAbsMtSlot(unsigned int code, unsigned int slot, uint32_t value);
diff --git a/ui/events/ozone/evdev/event_device_test_util.cc b/ui/events/ozone/evdev/event_device_test_util.cc index aa6dfa7..e2ac711 100644 --- a/ui/events/ozone/evdev/event_device_test_util.cc +++ b/ui/events/ozone/evdev/event_device_test_util.cc
@@ -7,6 +7,7 @@ #include <stdint.h> #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/format_macros.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" @@ -25,12 +26,12 @@ #define EVDEV_BITS_TO_GROUPS(x) \ (((x) + kTestDataWordSize - 1) / kTestDataWordSize) -std::string SerializeBitfield(unsigned long* bitmap, int max) { +std::string SerializeBitfield(base::span<unsigned long> bitmap, int max) { std::string ret; for (int i = EVDEV_BITS_TO_GROUPS(max) - 1; i >= 0; i--) { - if (UNSAFE_TODO(bitmap[i]) || ret.size()) { - base::StringAppendF(&ret, "%lx", UNSAFE_TODO(bitmap[i])); + if (bitmap[i] || ret.size()) { + base::StringAppendF(&ret, "%lx", bitmap[i]); if (i > 0) ret += " "; @@ -71,8 +72,9 @@ } // Require canonically formatted input. - if (bitfield != SerializeBitfield(out->data(), max_bits)) + if (bitfield != SerializeBitfield(*out, max_bits)) { return false; + } return true; } @@ -1573,47 +1575,47 @@ std::vector<unsigned long> ev_bits; if (!ParseBitfield(capabilities.ev, EV_CNT, &ev_bits)) return false; - devinfo->SetEventTypes(&ev_bits[0], ev_bits.size()); + devinfo->SetEventTypes(ev_bits); std::vector<unsigned long> key_bits; if (!ParseBitfield(capabilities.key, KEY_CNT, &key_bits)) return false; - devinfo->SetKeyEvents(&key_bits[0], key_bits.size()); + devinfo->SetKeyEvents(key_bits); std::vector<unsigned long> rel_bits; if (!ParseBitfield(capabilities.rel, REL_CNT, &rel_bits)) return false; - devinfo->SetRelEvents(&rel_bits[0], rel_bits.size()); + devinfo->SetRelEvents(rel_bits); std::vector<unsigned long> abs_bits; if (!ParseBitfield(capabilities.abs, ABS_CNT, &abs_bits)) return false; - devinfo->SetAbsEvents(&abs_bits[0], abs_bits.size()); + devinfo->SetAbsEvents(abs_bits); std::vector<unsigned long> sw_bits; if (!ParseBitfield(capabilities.sw, SW_CNT, &sw_bits)) return false; - devinfo->SetSwEvents(&sw_bits[0], sw_bits.size()); + devinfo->SetSwEvents(sw_bits); std::vector<unsigned long> msc_bits; if (!ParseBitfield(capabilities.msc, MSC_CNT, &msc_bits)) return false; - devinfo->SetMscEvents(&msc_bits[0], msc_bits.size()); + devinfo->SetMscEvents(msc_bits); std::vector<unsigned long> led_bits; if (!ParseBitfield(capabilities.led, LED_CNT, &led_bits)) return false; - devinfo->SetLedEvents(&led_bits[0], led_bits.size()); + devinfo->SetLedEvents(led_bits); std::vector<unsigned long> ff_bits; if (!ParseBitfield(capabilities.ff, FF_CNT, &ff_bits)) return false; - devinfo->SetFfEvents(&ff_bits[0], ff_bits.size()); + devinfo->SetFfEvents(ff_bits); std::vector<unsigned long> prop_bits; if (!ParseBitfield(capabilities.prop, INPUT_PROP_CNT, &prop_bits)) return false; - devinfo->SetProps(&prop_bits[0], prop_bits.size()); + devinfo->SetProps(prop_bits); for (size_t i = 0; i < capabilities.abs_axis_count; ++i) { const DeviceAbsoluteAxis& axis = UNSAFE_TODO(capabilities.abs_axis[i]);
diff --git a/ui/events/ozone/evdev/stylus_button_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/stylus_button_event_converter_evdev_unittest.cc index cf3b899..a7e317c 100644 --- a/ui/events/ozone/evdev/stylus_button_event_converter_evdev_unittest.cc +++ b/ui/events/ozone/evdev/stylus_button_event_converter_evdev_unittest.cc
@@ -15,6 +15,7 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/functional/bind.h" @@ -73,9 +74,9 @@ ~MockStylusButtonEventConverterEvdev() override {} - void ConfigureReadMock(struct input_event* queue, - long read_this_many, - long queue_index); + void ConfigureReadMock(base::span<struct input_event> queue, + size_t read_this_many, + size_t queue_index); // Actually dispatch the event reader code. void ReadNow() { @@ -113,12 +114,13 @@ } void MockStylusButtonEventConverterEvdev::ConfigureReadMock( - struct input_event* queue, - long read_this_many, - long queue_index) { - int nwrite = UNSAFE_TODO( - HANDLE_EINTR(write(write_pipe_, queue + queue_index, - sizeof(struct input_event) * read_this_many))); + base::span<struct input_event> queue, + size_t read_this_many, + size_t queue_index) { + CHECK_GE(queue.size(), queue_index + read_this_many); + int nwrite = HANDLE_EINTR(write(write_pipe_, + queue.subspan(queue_index).data(), + sizeof(struct input_event) * read_this_many)); DPCHECK(nwrite == static_cast<int>(sizeof(struct input_event) * read_this_many)) << "write() failed";
diff --git a/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc index 4f5a787..e07f143 100644 --- a/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc +++ b/ui/events/ozone/evdev/tablet_event_converter_evdev_unittest.cc
@@ -19,6 +19,7 @@ #include <utility> #include <vector> +#include "base/containers/span.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/functional/bind.h" @@ -321,9 +322,9 @@ ~MockTabletEventConverterEvdev() override = default; - void ConfigureReadMock(struct input_event* queue, - long read_this_many, - long queue_index); + void ConfigureReadMock(base::span<struct input_event> queue, + size_t read_this_many, + size_t queue_index); // Actually dispatch the event reader code. void ReadNow() { @@ -392,10 +393,13 @@ write_pipe_ = fds[1]; } -void MockTabletEventConverterEvdev::ConfigureReadMock(struct input_event* queue, - long read_this_many, - long queue_index) { - int nwrite = HANDLE_EINTR(write(write_pipe_, queue + queue_index, +void MockTabletEventConverterEvdev::ConfigureReadMock( + base::span<struct input_event> queue, + size_t read_this_many, + size_t queue_index) { + CHECK_GE(queue.size(), queue_index + read_this_many); + int nwrite = HANDLE_EINTR(write(write_pipe_, + queue.subspan(queue_index).data(), sizeof(struct input_event) * read_this_many)); DPCHECK(nwrite == static_cast<int>(sizeof(struct input_event) * read_this_many)) @@ -465,10 +469,9 @@ return ev->AsKeyEvent(); } - void CheckEvents(struct ExpectedEvent expected_events[], - unsigned num_events) { - ASSERT_EQ(num_events, size()); - for (unsigned i = 0; i < num_events; ++i) { + void CheckEvents(base::span<const ExpectedEvent> expected_events) { + ASSERT_EQ(expected_events.size(), size()); + for (size_t i = 0; i < expected_events.size(); ++i) { ui::MouseEvent* event = dispatched_event(i); EXPECT_EQ(event->pointer_details().pointer_type, expected_events[i].pointer_type) @@ -930,7 +933,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, SideEraserAlwaysPressedKernel5) { @@ -976,7 +979,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, SideEraserAlwaysPressedKernel6) { @@ -1018,7 +1021,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, SideEraserReleasedWhileTouchingKernel5) { @@ -1073,7 +1076,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, SideEraserReleasedWhileTouchingKernel6) { @@ -1123,7 +1126,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, @@ -1182,7 +1185,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, TailEraserKernel5And6) { @@ -1232,7 +1235,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button1AlwaysPressedKernel5) { @@ -1283,7 +1286,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button1AlwaysPressedKernel6) { @@ -1336,7 +1339,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button1ReleasedWhileTouchingKernel5) { @@ -1407,7 +1410,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button1ReleasedWhileTouchingKernel6) { @@ -1482,7 +1485,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button1PressedWhileTouchingKernel5) { @@ -1539,7 +1542,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button1PressedWhileTouchingKernel6) { @@ -1615,7 +1618,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button2AlwaysPressedKernel5And6) { @@ -1676,7 +1679,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button2ReleasedWhileTouchingKernel5And6) { @@ -1738,7 +1741,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Button2PressedWhileTouchingKernel5And6) { @@ -1795,7 +1798,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, @@ -1860,7 +1863,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, @@ -1927,7 +1930,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, @@ -1990,7 +1993,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, @@ -2057,7 +2060,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, @@ -2125,7 +2128,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, @@ -2190,7 +2193,7 @@ }; dev->ProcessEvents(mock_kernel_queue, std::size(mock_kernel_queue)); - CheckEvents(expected_events, std::size(expected_events)); + CheckEvents(expected_events); } TEST_F(TabletEventConverterEvdevTest, Basic) {
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc index 0730bf62..f52d27c2 100644 --- a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc +++ b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -2416,8 +2416,8 @@ ui::EvdevSetBit(ev_bits.data(), EV_KEY); ui::EvdevSetBit(key_bits.data(), BTN_TOOL_PEN); - devinfo.SetEventTypes(ev_bits.data(), ev_bits.size()); - devinfo.SetKeyEvents(key_bits.data(), key_bits.size()); + devinfo.SetEventTypes(ev_bits); + devinfo.SetKeyEvents(key_bits); dev->Initialize(devinfo); @@ -2540,8 +2540,8 @@ ui::EvdevSetBit(ev_bits.data(), EV_KEY); ui::EvdevSetBit(key_bits.data(), BTN_LEFT); - devinfo.SetEventTypes(ev_bits.data(), ev_bits.size()); - devinfo.SetKeyEvents(key_bits.data(), key_bits.size()); + devinfo.SetEventTypes(ev_bits); + devinfo.SetKeyEvents(key_bits); dev->Initialize(devinfo);
diff --git a/ui/events/ozone/evdev/touch_filter/false_touch_finder_unittest.cc b/ui/events/ozone/evdev/touch_filter/false_touch_finder_unittest.cc index cbdee72..be6702c 100644 --- a/ui/events/ozone/evdev/touch_filter/false_touch_finder_unittest.cc +++ b/ui/events/ozone/evdev/touch_filter/false_touch_finder_unittest.cc
@@ -10,7 +10,7 @@ #include <memory> #include "base/command_line.h" -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/logging.h" #include "base/strings/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,12 +41,12 @@ ~FalseTouchFinderTest() override {} - bool FilterAndCheck(const TouchEntry entries[], size_t count) { + bool FilterAndCheck(base::span<const TouchEntry> entries) { std::vector<InProgressTouchEvdev> touches; size_t start_index = 0u; std::bitset<kNumTouchEvdevSlots> was_touching; - for (size_t i = 0; i < count; ++i) { - const TouchEntry& entry = UNSAFE_TODO(entries[i]); + for (size_t i = 0; i < entries.size(); ++i) { + const TouchEntry& entry = entries[i]; InProgressTouchEvdev touch; touch.x = entry.location.x(); @@ -58,14 +58,12 @@ touch.touching = entry.touching; touches.push_back(touch); - if (i == count - 1 || - entry.time_ms != UNSAFE_TODO(entries[i + 1]).time_ms) { + if (i == entries.size() - 1 || entry.time_ms != entries[i + 1].time_ms) { false_touch_finder_->HandleTouches( touches, base::TimeTicks() + base::Milliseconds(entry.time_ms)); for (size_t j = 0; j < touches.size(); ++j) { - bool expect_delay = - UNSAFE_TODO(entries[j + start_index]).expect_delay; + bool expect_delay = entries[j + start_index].expect_delay; size_t slot = touches[j].slot; if (false_touch_finder_->SlotShouldDelay(slot) != expect_delay) { LOG(ERROR) << base::StringPrintf( @@ -116,7 +114,7 @@ {100, 4, true, gfx::PointF(100, touchscreen_height - 1), 0.35, true}, {110, 4, true, gfx::PointF(100, touchscreen_height - 1), 0.35, true}, {120, 4, false, gfx::PointF(100, touchscreen_height - 1), 0.35, true}}; - EXPECT_TRUE(FilterAndCheck(kTestData, std::size(kTestData))); + EXPECT_TRUE(FilterAndCheck(kTestData)); } // Test that a touch on the edge which starts at an edge is delayed but released @@ -131,7 +129,7 @@ {60, 1, true, gfx::PointF(0, 100), 0.35, true}, {70, 1, true, gfx::PointF(0, 101), 0.35, false}, {80, 1, false, gfx::PointF(0, 101), 0.35, false}}; - EXPECT_TRUE(FilterAndCheck(kTestData, std::size(kTestData))); + EXPECT_TRUE(FilterAndCheck(kTestData)); } // Test that a touch on the edge which starts away from the edge is not @@ -142,7 +140,7 @@ {20, 1, true, gfx::PointF(100, 100), 0.35, false}, {30, 1, true, gfx::PointF(0, 100), 0.35, false}, {40, 1, false, gfx::PointF(0, 100), 0.35, false}}; - EXPECT_TRUE(FilterAndCheck(kTestData, std::size(kTestData))); + EXPECT_TRUE(FilterAndCheck(kTestData)); } // Test that a pinky finger lightly pressed is not filtered out. Based on real @@ -154,7 +152,7 @@ {30, 1, true, gfx::PointF(10, 10), 0.215686, false}, {40, 1, true, gfx::PointF(10, 10), 0.211765, false}, {50, 1, true, gfx::PointF(10, 10), 0.203922, false}}; - EXPECT_TRUE(FilterAndCheck(kTestData, std::size(kTestData))); + EXPECT_TRUE(FilterAndCheck(kTestData)); } } // namespace ui
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc index d82348a..5b79797 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.cc
@@ -19,6 +19,7 @@ #include <tuple> #include "base/containers/span.h" +#include "base/numerics/safe_conversions.h" #ifndef USE_EIGEN #define USE_EIGEN 0 @@ -120,7 +121,7 @@ #endif // OP_LIB_BENCHMARK // The size of a shape in terms of number of coefficients. -inline int32_t ShapeSize(const int32_t rank, const int32_t* shape) { +inline int32_t ShapeSize(const int32_t rank, base::span<const int32_t> shape) { int32_t size = 1; for (int32_t i = 0; i < rank; ++i) size *= shape[i]; @@ -129,10 +130,11 @@ // For convolutional operations, calculates the output size with VALID padding. // Returns (height, width). -inline std::tuple<int, int> GetConvOutputSizeVALID(const int32_t* input_shape, - const int32_t* kernel_shape, - int32_t stride_y, - int32_t stride_x) { +inline std::tuple<int, int> GetConvOutputSizeVALID( + base::span<const int32_t> input_shape, + base::span<const int32_t> kernel_shape, + int32_t stride_y, + int32_t stride_x) { return std::make_tuple( (input_shape[1] + stride_y - kernel_shape[0]) / stride_y, (input_shape[2] + stride_x - kernel_shape[1]) / stride_x); @@ -140,9 +142,10 @@ // For convolutional operations, calculates the output size with SAME padding. // Returns (height, width). -inline std::tuple<int, int> GetConvOutputSizeSAME(const int32_t* input_shape, - int32_t stride_y, - int32_t stride_x) { +inline std::tuple<int, int> GetConvOutputSizeSAME( + base::span<const int32_t> input_shape, + int32_t stride_y, + int32_t stride_x) { return std::make_tuple((input_shape[1] + stride_y - 1) / stride_y, (input_shape[2] + stride_x - 1) / stride_x); } @@ -151,10 +154,10 @@ // specify which axes are reduced. template <typename Tidx> int32_t GetReduceInnerSize(int32_t input_tensor_rank, - const int32_t* __restrict input_shape, + base::span<const int32_t> input_shape, int32_t index_tensor_rank, - const int32_t* __restrict index_shape, - const Tidx* __restrict index_values) { + base::span<const int32_t> index_shape, + base::span<const Tidx> index_values) { assert(index_tensor_rank <= 1); const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; int32_t inner_size = 1; @@ -170,47 +173,51 @@ template <typename T> void ConcatV2Args2(int32_t arg0_rank, - const int32_t* __restrict arg0_shape, - const T* __restrict arg0_values, + base::span<const int32_t> arg0_shape, + base::span<const T> arg0_values, int32_t arg1_rank, - const int32_t* __restrict arg1_shape, - const T* __restrict arg1_values, - const int32_t* __restrict axis_value, - T* __restrict output_values) { + base::span<const int32_t> arg1_shape, + base::span<const T> arg1_values, + base::span<const int32_t> axis_value, + base::span<T> output_values) { BENCHMARK_TIMER("ConcatV2Args2"); - const int32_t axis = axis_value[0]; + const size_t axis = base::checked_cast<size_t>(axis_value[0]); const int32_t num_lines = ShapeSize(axis, arg0_shape); - const int32_t arg0_line_size = ShapeSize(arg0_rank - axis, arg0_shape + axis); - const int32_t arg1_line_size = ShapeSize(arg1_rank - axis, arg1_shape + axis); + const size_t arg0_line_size = base::checked_cast<size_t>( + ShapeSize(arg0_rank - axis, arg0_shape.subspan(axis))); + const size_t arg1_line_size = base::checked_cast<size_t>( + ShapeSize(arg1_rank - axis, arg1_shape.subspan(axis))); for (int32_t line = 0; line < num_lines; ++line) { - std::copy(arg0_values, arg0_values + arg0_line_size, output_values); - arg0_values += arg0_line_size; - output_values += arg0_line_size; - std::copy(arg1_values, arg1_values + arg1_line_size, output_values); - arg1_values += arg1_line_size; - output_values += arg1_line_size; + output_values.copy_prefix_from(arg0_values.first(arg0_line_size)); + arg0_values = arg0_values.subspan(arg0_line_size); + output_values = output_values.subspan(arg0_line_size); + output_values.copy_prefix_from(arg1_values.first(arg1_line_size)); + arg1_values = arg1_values.subspan(arg1_line_size); + output_values = output_values.subspan(arg1_line_size); } } template <typename T> -void MatMul(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict weight_shape, - const T* __restrict weight_values, - T* __restrict output_values) { +void MatMul(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> weight_shape, + base::span<const T> weight_values, + base::span<T> output_values) { BENCHMARK_TIMER("MatMul"); #if USE_EIGEN const auto in = - ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]); + ConstMatrixMap<T>(input_values.data(), input_shape[1], input_shape[0]); const auto weight = - ConstMatrixMap<T>(weight_values, weight_shape[1], weight_shape[0]); - auto result = MatrixMap<T>(output_values, weight_shape[1], input_shape[0]); + ConstMatrixMap<T>(weight_values.data(), weight_shape[1], weight_shape[0]); + auto result = + MatrixMap<T>(output_values.data(), weight_shape[1], input_shape[0]); result.noalias() = weight * in; #else const int32_t batch_size = input_shape[0]; const int32_t num_inputs = weight_shape[0]; const int32_t num_outputs = weight_shape[1]; assert(input_shape[1] == num_inputs); + auto output_iter = output_values.begin(); for (int32_t batch = 0; batch < batch_size; ++batch) { for (int32_t out_i = 0; out_i < num_outputs; ++out_i) { T value = 0; @@ -218,22 +225,22 @@ value += input_values[batch * num_inputs + in_i] * weight_values[in_i * num_outputs + out_i]; } - *output_values++ = value; + *output_iter++ = value; } } #endif } template <typename T> -void DepthwiseConv2dNative(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, - const T* __restrict kernel_values, +void DepthwiseConv2dNative(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, + base::span<const T> kernel_values, int32_t stride_y, int32_t stride_x, int32_t out_height, int32_t out_width, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("DepthwiseConv2dNative"); // Give the shape values nicer names. assert(input_shape[3] == kernel_shape[2]); @@ -265,7 +272,7 @@ 1, // channel mult }; - T* out_write_ptr = output_values; + auto out_write_iter = output_values.begin(); for (int32_t batch = 0; batch < batch_size; ++batch) { for (int32_t out_y = 0; out_y < out_height; ++out_y) { for (int32_t out_x = 0; out_x < out_width; ++out_x) { @@ -285,7 +292,8 @@ std::min(kernel_width, in_width - in_x_origin); for (int32_t in_c = 0; in_c < in_depth; ++in_c) { - for (int32_t mul_c = 0; mul_c < depth_mul; ++mul_c, ++out_write_ptr) { + for (int32_t mul_c = 0; mul_c < depth_mul; + ++mul_c, ++out_write_iter) { // Convolve. T sum = 0; for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { @@ -307,7 +315,7 @@ sum += input_value * kernel_value; } } - *out_write_ptr = sum; + *out_write_iter = sum; } // mul_c } // in_c } // out_x @@ -316,13 +324,13 @@ } template <typename T> -void DepthwiseConv2dNativeVALID(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, - const T* __restrict kernel_values, +void DepthwiseConv2dNativeVALID(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, + base::span<const T> kernel_values, int32_t stride_y, int32_t stride_x, - T* __restrict output_values) { + base::span<T> output_values) { const auto out_size = GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x); DepthwiseConv2dNative<T>( @@ -331,13 +339,13 @@ } template <typename T> -void DepthwiseConv2dNativeSAME(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, - const T* __restrict kernel_values, +void DepthwiseConv2dNativeSAME(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, + base::span<const T> kernel_values, int32_t stride_y, int32_t stride_x, - T* __restrict output_values) { + base::span<T> output_values) { const auto out_size = GetConvOutputSizeSAME(input_shape, stride_y, stride_x); DepthwiseConv2dNative<T>( input_shape, input_values, kernel_shape, kernel_values, stride_y, @@ -345,13 +353,13 @@ } template <typename T> -void FullyConnected(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict weight_shape, - const T* __restrict weight_values, - const int32_t* __restrict bias_shape, - const T* __restrict bias_values, - T* __restrict output_values) { +void FullyConnected(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> weight_shape, + base::span<const T> weight_values, + base::span<const int32_t> bias_shape, + base::span<const T> bias_values, + base::span<T> output_values) { BENCHMARK_TIMER("FullyConnected"); #if USE_EIGEN const auto in = @@ -381,11 +389,11 @@ } template <typename T, typename TBlocks, typename TPaddings> -void SpaceToBatchNDRank4(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const TBlocks* __restrict block_shape_values, - const TPaddings* __restrict padding_values, - T* __restrict output_values) { +void SpaceToBatchNDRank4(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const TBlocks> block_shape_values, + base::span<const TPaddings> padding_values, + base::span<T> output_values) { BENCHMARK_TIMER("SpaceToBatchNDRank4"); const int32_t input_batch_size = input_shape[0]; const int32_t input_height = input_shape[1]; @@ -415,10 +423,10 @@ const int32_t shift_h = (out_b / input_batch_size) / block_shape_width; for (int32_t out_h = 0; out_h < output_height; ++out_h) { for (int32_t out_w = 0; out_w < output_width; ++out_w) { - T* out = output_values + - (((out_b * output_height + out_h) * output_width + out_w) * - output_depth + - 0); + base::span<T> out = output_values.subspan(base::checked_cast<size_t>( + (((out_b * output_height + out_h) * output_width + out_w) * + output_depth + + 0))); // Check if padding cell are being handled. if (out_h * block_shape_height + shift_h < padding_top || out_h * block_shape_height + shift_h >= @@ -427,9 +435,10 @@ out_w * block_shape_width + shift_w >= padding_left + input_width) { // This may not execute correctly when pad_value != 0 and T != uint8. #if USE_TYPED_MEMSETMEMCPY - std::fill(out, out + input_depth, pad_value); + std::ranges::fill(out.first(base::checked_cast<size_t>(input_depth)), + pad_value); #else - std::memset(out, pad_value, input_depth * sizeof(T)); + std::memset(out.data(), pad_value, input_depth * sizeof(T)); #endif } else { const int32_t i0 = input_batch; @@ -437,13 +446,15 @@ (out_h * block_shape_height + shift_h) - padding_top; const int32_t i2 = (out_w * block_shape_width + shift_w) - padding_left; - const T* in = - input_values + - (((i0 * input_height + i1) * input_width + i2) * input_depth + 0); + base::span<const T> in = + input_values.subspan(base::checked_cast<size_t>( + (((i0 * input_height + i1) * input_width + i2) * input_depth + + 0))); #if USE_TYPED_MEMSETMEMCPY - std::copy(in, in + input_depth, out); + out.copy_prefix_from( + in.first(base::checked_cast<size_t>(input_depth))); #else - std::memcpy(out, in, input_depth * sizeof(T)); + std::memcpy(out.data(), in.data(), input_depth * sizeof(T)); #endif } } @@ -452,11 +463,11 @@ } template <typename T, typename TBlocks, typename TCrops> -void BatchToSpaceNDRank4(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const TBlocks* __restrict block_shape_values, - const TCrops* __restrict crops_values, - T* __restrict output_values) { +void BatchToSpaceNDRank4(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const TBlocks> block_shape_values, + base::span<const TCrops> crops_values, + base::span<T> output_values) { BENCHMARK_TIMER("BatchToSpaceNDRank4"); const int32_t input_batch_size = input_shape[0]; const int32_t input_height = input_shape[1]; @@ -493,18 +504,19 @@ if (out_w < 0 || out_w >= output_width) { continue; } - T* out = output_values + - (((out_batch * output_height + out_h) * output_width + out_w) * - output_depth + - 0); - const T* in = input_values + - (((in_batch * input_height + in_h) * input_width + in_w) * - input_depth + - 0); + base::span<T> out = output_values.subspan(base::checked_cast<size_t>( + (((out_batch * output_height + out_h) * output_width + out_w) * + output_depth + + 0))); + base::span<const T> in = + input_values.subspan(base::checked_cast<size_t>( + (((in_batch * input_height + in_h) * input_width + in_w) * + input_depth + + 0))); #if USE_TYPED_MEMSETMEMCPY - std::copy(in, in + input_depth, out); + std::ranges::copy(in.first(input_depth), out); #else - std::memcpy(out, in, input_depth * sizeof(T)); + std::memcpy(out.data(), in.data(), input_depth * sizeof(T)); #endif } } @@ -513,80 +525,84 @@ #if USE_EIGEN template <typename T, typename Tidx> -void SparseDenseMatMulCSR(const int32_t* __restrict input_shape, - const T* __restrict input_values, +void SparseDenseMatMulCSR(base::span<const int32_t> input_shape, + base::span<const T> input_values, const int32_t num_rows, - const int32_t* __restrict nnz_shape, - const T* __restrict nnz_values, - const Tidx* __restrict outer_index, - const Tidx* __restrict cols, - T* __restrict output_values) { + base::span<const int32_t> nnz_shape, + base::span<const T> nnz_values, + base::span<const Tidx> outer_index, + base::span<const Tidx> cols, + base::span<T> output_values) { BENCHMARK_TIMER("SparseDenseMatMulCSR"); const int32_t num_cols = input_shape[1]; const auto in = - ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]); + ConstMatrixMap<T>(input_values.data(), input_shape[1], input_shape[0]); const Eigen::Map<const SparseMatrix<T, Tidx>> weight( - num_rows, num_cols, nnz_shape[0], outer_index, cols, nnz_values); - auto result = MatrixMap<T>(output_values, num_rows, input_shape[0]); + num_rows, num_cols, nnz_shape[0], outer_index.data(), cols.data(), + nnz_values.data()); + auto result = MatrixMap<T>(output_values.data(), num_rows, input_shape[0]); result.noalias() = weight * in; } template <typename T, typename Tidx> -void SparseFullyConnectedCSR(const int32_t* __restrict input_shape, - const T* __restrict input_values, +void SparseFullyConnectedCSR(base::span<const int32_t> input_shape, + base::span<const T> input_values, const int32_t num_rows, - const int32_t* __restrict nnz_shape, - const T* __restrict nnz_values, - const Tidx* __restrict outer_index, - const Tidx* __restrict cols, - const int32_t* __restrict bias_shape, - const T* __restrict bias_values, - T* __restrict output_values) { + base::span<const int32_t> nnz_shape, + base::span<const T> nnz_values, + base::span<const Tidx> outer_index, + base::span<const Tidx> cols, + base::span<const int32_t> bias_shape, + base::span<const T> bias_values, + base::span<T> output_values) { BENCHMARK_TIMER("SparseFullyConnectedCSR"); const int32_t num_cols = input_shape[1]; const auto in = - ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]); - const auto bias = ConstRowVectorMap<T>(bias_values, bias_shape[0]); + ConstMatrixMap<T>(input_values.data(), input_shape[1], input_shape[0]); + const auto bias = ConstRowVectorMap<T>(bias_values.data(), bias_shape[0]); const Eigen::Map<const SparseMatrix<T, Tidx>> weight( - num_rows, num_cols, nnz_shape[0], outer_index, cols, nnz_values); - auto result = MatrixMap<T>(output_values, num_rows, input_shape[0]); + num_rows, num_cols, nnz_shape[0], outer_index.data(), cols.data(), + nnz_values.data()); + auto result = MatrixMap<T>(output_values.data(), num_rows, input_shape[0]); result.noalias() = (weight * in).colwise() + bias; } #endif template <typename T, typename TIndex> void Gather(int32_t params_rank, - const int32_t* __restrict params_shape, - const T* __restrict params_values, + base::span<const int32_t> params_shape, + base::span<const T> params_values, int32_t indices_rank, - const int32_t* __restrict indices_shape, - const TIndex* __restrict indices_values, - T* __restrict output_values) { + base::span<const int32_t> indices_shape, + base::span<const TIndex> indices_values, + base::span<T> output_values) { BENCHMARK_TIMER("Gather"); const int32_t num_indices = ShapeSize(indices_rank, indices_shape); const int32_t num_params = params_shape[0]; - const int32_t slice_size = ShapeSize(params_rank - 1, params_shape + 1); + const size_t slice_size = base::checked_cast<size_t>( + ShapeSize(params_rank - 1, params_shape.subspan(1u))); for (int32_t i = 0; i < num_indices; ++i) { const int32_t index = indices_values[i]; if (index < 0 || index >= num_params) { - std::fill(output_values, output_values + slice_size, 0); + std::ranges::fill(output_values.first(slice_size), 0); } else { - std::copy(params_values + index * slice_size, - params_values + index * slice_size + slice_size, output_values); + // Index is >= 0 and is an int32_t so safe to cast to size_t. + output_values.copy_prefix_from(params_values.subspan( + static_cast<size_t>(index) * slice_size, slice_size)); } - output_values += slice_size; + output_values = output_values.subspan(slice_size); } } template <typename T> -void Im2Row(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, +void Im2Row(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, int32_t stride_y, int32_t stride_x, int32_t out_height, int32_t out_width, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("Im2Row"); // Give the shape values nicer names. assert(input_shape[3] == kernel_shape[2]); @@ -629,67 +645,71 @@ // Padding top. if (kernel_y_start != 0) { const int32_t num_lines = kernel_y_start; - const int32_t num_coeffs = num_lines * kernel_width * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(num_lines * kernel_width * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { // Padding left. if (kernel_x_start != 0) { - const int32_t num_coeffs = kernel_x_start * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(kernel_x_start * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } // Valid values. { const int32_t in_y = in_y_origin + k_y; const int32_t in_x = in_x_origin + kernel_x_start; - const int32_t num_coeffs = - (kernel_x_end - kernel_x_start) * in_depth; + const size_t num_coeffs = base::checked_cast<size_t>( + (kernel_x_end - kernel_x_start) * in_depth); #if USE_TYPED_MEMSETMEMCPY - const int32_t offset = - batch * batch_stride + in_y * y_stride + in_x * x_stride; - std::copy(input_values + offset, input_values + offset + num_coeffs, - output_values); + const size_t offset = base::checked_cast<size_t>( + batch * batch_stride + in_y * y_stride + in_x * x_stride); + output_values.copy_prefix_from( + input_values.subspan(offset, num_coeffs)); #else - std::memcpy(output_values, - input_values // Reusing the restricted pointer. + std::memcpy(output_values.data(), + input_values.data() // Reusing the restricted pointer. + batch * batch_stride // batch + in_y * y_stride // y + in_x * x_stride, // x num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } // Padding right. if (kernel_x_end != kernel_width) { - const int32_t num_coeffs = (kernel_width - kernel_x_end) * in_depth; + const size_t num_coeffs = base::checked_cast<size_t>( + (kernel_width - kernel_x_end) * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } } // Padding bottom. if (kernel_y_end != kernel_height) { const int32_t num_lines = kernel_height - kernel_y_end; - const int32_t num_coeffs = num_lines * kernel_width * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(num_lines * kernel_width * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } } } @@ -697,12 +717,12 @@ } template <typename T> -void Im2RowVALID(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, +void Im2RowVALID(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, int32_t stride_y, int32_t stride_x, - T* __restrict output_values) { + base::span<T> output_values) { const auto out_size = GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x); Im2Row<T>(input_shape, input_values, kernel_shape, stride_y, stride_x, @@ -710,12 +730,12 @@ } template <typename T> -void Im2RowSAME(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, +void Im2RowSAME(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, int32_t stride_y, int32_t stride_x, - T* __restrict output_values) { + base::span<T> output_values) { const auto out_size = GetConvOutputSizeSAME(input_shape, stride_y, stride_x); Im2Row<T>(input_shape, input_values, kernel_shape, stride_y, stride_x, std::get<0>(out_size), std::get<1>(out_size), output_values); @@ -725,11 +745,11 @@ // because it's a lot less verbose and easier for the compiler to optimize. #define POOL_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \ template <typename T> \ - void OP_NAME##Pool(const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t stride_y, \ + void OP_NAME##Pool(base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t stride_y, \ int32_t stride_x, int32_t kernel_height, \ int32_t kernel_width, int32_t out_height, \ - int32_t out_width, T* __restrict output_values) { \ + int32_t out_width, base::span<T> output_values) { \ BENCHMARK_TIMER(#OP_NAME, "Pool"); \ const int32_t batch_size = input_shape[0]; \ const int32_t in_height = input_shape[1]; \ @@ -748,7 +768,7 @@ 1, \ }; \ \ - T* out_write_ptr = output_values; \ + auto out_write_iter = output_values.begin(); \ for (int32_t batch = 0; batch < batch_size; ++batch) { \ for (int32_t out_y = 0; out_y < out_height; ++out_y) { \ for (int32_t out_x = 0; out_x < out_width; ++out_x) { \ @@ -766,7 +786,7 @@ (kernel_x_end - kernel_x_start); \ (void)sizeof(count); \ \ - for (int32_t chan = 0; chan < depth; ++chan, ++out_write_ptr) { \ + for (int32_t chan = 0; chan < depth; ++chan, ++out_write_iter) { \ T value = DEFAULT_VALUE; \ for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { \ const int32_t in_y = in_y_origin + k_y; \ @@ -780,7 +800,7 @@ value = UPDATE_EXPR; \ } \ } \ - *out_write_ptr = RESULT_EXPR; \ + *out_write_iter = RESULT_EXPR; \ } \ } \ } \ @@ -788,10 +808,10 @@ } \ \ template <typename T> \ - void OP_NAME##PoolVALID(const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t stride_y, \ + void OP_NAME##PoolVALID(base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t stride_y, \ int32_t stride_x, int32_t kernel_height, \ - int32_t kernel_width, T* __restrict output_values) { \ + int32_t kernel_width, base::span<T> output_values) { \ const int32_t kernel_shape[4] = {kernel_height, kernel_width, 1, 1}; \ const auto out_size = \ GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x); \ @@ -801,10 +821,10 @@ } \ \ template <typename T> \ - void OP_NAME##PoolSAME(const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t stride_y, \ + void OP_NAME##PoolSAME(base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t stride_y, \ int32_t stride_x, int32_t kernel_height, \ - int32_t kernel_width, T* __restrict output_values) { \ + int32_t kernel_width, base::span<T> output_values) { \ const auto out_size = \ GetConvOutputSizeSAME(input_shape, stride_y, stride_x); \ OP_NAME##Pool<T>(input_shape, input_values, stride_y, stride_x, \ @@ -817,9 +837,9 @@ template <typename T> void Memcpy(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - T* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<T> output_values) { BENCHMARK_TIMER("Memcpy"); const int32_t size = ShapeSize(rank, input_shape); for (int32_t i = 0; i < size; ++i) { @@ -829,11 +849,11 @@ template <typename T> void Softmax(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, + base::span<const int32_t> input_shape, + base::span<const T> input_values, const int32_t reduce_dim, - T* __restrict output_values, - T* __restrict scratch_values) { + base::span<T> output_values, + base::span<T> scratch_values) { BENCHMARK_TIMER("Softmax"); const int32_t size = ShapeSize(rank, input_shape); if (rank == 2 && reduce_dim == 1) { @@ -869,9 +889,9 @@ // Returns the start position for a slice in a single dimension. template <typename T> int32_t StridedSliceBegin(int32_t range_mask, - const T* __restrict range_values, - const T* __restrict strides, - const int32_t* __restrict input_shape, + base::span<const T> range_values, + base::span<const T> strides, + base::span<const int32_t> input_shape, int32_t dim) { const bool is_explicit = 0 == (range_mask & (1 << dim)); if (is_explicit) { @@ -886,9 +906,9 @@ // Returns the end position for a slice in a single dimension. template <typename T> int32_t StridedSliceEnd(int32_t range_mask, - const T* __restrict range_values, - const T* __restrict strides, - const int32_t* __restrict input_shape, + base::span<const T> range_values, + base::span<const T> strides, + base::span<const int32_t> input_shape, int32_t dim) { const bool is_explicit = 0 == (range_mask & (1 << dim)); if (is_explicit) { @@ -902,14 +922,14 @@ template <typename T, typename TIdx> void StridedSlice(const int32_t input_rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const TIdx* __restrict begin, - const TIdx* __restrict end, - const TIdx* __restrict strides, + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const TIdx> begin, + base::span<const TIdx> end, + base::span<const TIdx> strides, int32_t begin_mask, int32_t end_mask, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("StridedSlice"); const int32_t MAX_RANK = 8; assert(input_rank < MAX_RANK); @@ -970,13 +990,15 @@ } #if USE_TYPED_MEMSETMEMCPY - std::copy(input_values + read_offset, - input_values + read_offset + block_size, output_values); + output_values.copy_prefix_from( + input_values.subspan(base::checked_cast<size_t>(read_offset), + base::checked_cast<size_t>(block_size))); #else - std::memcpy(output_values, input_values + read_offset, + std::memcpy(output_values.data(), input_values.data() + read_offset, block_size * sizeof(T)); #endif - output_values += block_size; + output_values = + output_values.subspan(base::checked_cast<size_t>(block_size)); // Advance the read position. for (int32_t dim = last_sliced_dim; dim >= 0; --dim) { @@ -989,10 +1011,10 @@ } template <typename T> -void TransposeRank3(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict perm, - T* __restrict output_values) { +void TransposeRank3(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> perm, + base::span<T> output_values) { BENCHMARK_TIMER("TransposeRank3"); const std::array<int32_t, 3> in_strides = { input_shape[1] * input_shape[2], @@ -1018,10 +1040,10 @@ } template <typename T> -void TransposeRank4(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict perm, - T* __restrict output_values) { +void TransposeRank4(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> perm, + base::span<T> output_values) { BENCHMARK_TIMER("TransposeRank4"); const std::array<int32_t, 4> in_strides = { input_shape[1] * input_shape[2] * input_shape[3], @@ -1052,13 +1074,13 @@ template <typename T, typename TIdx, typename TDepth> void OneHot(const int32_t input_rank, - const int32_t* __restrict input_shape, - const TIdx* __restrict input_values, - const TDepth* __restrict depth, - const T* __restrict on_value, - const T* __restrict off_value, + base::span<const int32_t> input_shape, + base::span<const TIdx> input_values, + const TDepth* depth, + const T* on_value, + const T* off_value, const int32_t axis, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("OneHot"); const int32_t num_elements = ShapeSize(input_rank, input_shape); // We can assume axis >= 0 in this implementation. @@ -1079,12 +1101,12 @@ template <typename T, typename TIdx, typename TDepth> void OneHotLastDim(const int32_t input_rank, - const int32_t* __restrict input_shape, - const TIdx* __restrict input_values, + base::span<const int32_t> input_shape, + base::span<const TIdx> input_values, const TDepth* __restrict depth, const T* __restrict on_value, const T* __restrict off_value, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("OneHotLastDim"); const int32_t num_elements = ShapeSize(input_rank, input_shape); int32_t write_offset = 0; @@ -1105,25 +1127,25 @@ #if USE_EIGEN -#define SIMPLE_UNARY_OP(OP_NAME, _, EXPR_EIGEN) \ - template <typename T> \ - void OP_NAME(const int32_t rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, \ - T* __restrict output_values) { \ - BENCHMARK_TIMER(#OP_NAME); \ - const int32_t size = ShapeSize(rank, input_shape); \ - auto values = ConstRowVectorMap<T>(input_values, size).array(); \ - auto output = RowVectorMap<T>(output_values, size).array(); \ - output = EXPR_EIGEN; \ +#define SIMPLE_UNARY_OP(OP_NAME, _, EXPR_EIGEN) \ + template <typename T> \ + void OP_NAME(const int32_t rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, \ + base::span<T> output_values) { \ + BENCHMARK_TIMER(#OP_NAME); \ + const int32_t size = ShapeSize(rank, input_shape); \ + auto values = ConstRowVectorMap<T>(input_values.data(), size).array(); \ + auto output = RowVectorMap<T>(output_values.data(), size).array(); \ + output = EXPR_EIGEN; \ } #else #define SIMPLE_UNARY_OP(OP_NAME, EXPR, _) \ template <typename T> \ - void OP_NAME(const int32_t rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, \ - T* __restrict output_values) { \ + void OP_NAME(const int32_t rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, \ + base::span<T> output_values) { \ BENCHMARK_TIMER(#OP_NAME); \ const int32_t size = ShapeSize(rank, input_shape); \ for (int32_t i = 0; i < size; ++i) { \ @@ -1178,19 +1200,19 @@ template <typename T, typename OP> void OpNoBroadcast(const int32_t left_rank, - const int32_t* __restrict left_shape, - const T* __restrict left_values, + base::span<const int32_t> left_shape, + base::span<const T> left_values, const int32_t right_rank, - const int32_t* __restrict right_shape, - const T* __restrict right_values, - T* __restrict output_values, + base::span<const int32_t> right_shape, + base::span<const T> right_values, + base::span<T> output_values, OP op) { BENCHMARK_TIMER(op.name, "NoBroadcast"); const int32_t size = ShapeSize(left_rank, left_shape); #if USE_EIGEN - auto lhs = ConstRowVectorMap<T>(left_values, size).array(); - auto rhs = ConstRowVectorMap<T>(right_values, size).array(); - auto output = RowVectorMap<T>(output_values, size).array(); + auto lhs = ConstRowVectorMap<T>(left_values.data(), size).array(); + auto rhs = ConstRowVectorMap<T>(right_values.data(), size).array(); + auto output = RowVectorMap<T>(output_values.data(), size).array(); op.apply(lhs, rhs, output); #else for (int32_t i = 0; i < size; ++i) { @@ -1201,12 +1223,12 @@ template <typename T, typename OP> void OpInnerBroadcast(int32_t left_rank, - const int32_t* __restrict left_shape, - const T* __restrict left_values, + base::span<const int32_t> left_shape, + base::span<const T> left_values, int32_t right_rank, - const int32_t* __restrict right_shape, - const T* __restrict right_values, - T* __restrict output_values, + base::span<const int32_t> right_shape, + base::span<const T> right_values, + base::span<T> output_values, OP op) { BENCHMARK_TIMER(op.name, "InnerBroadcast"); const int32_t output_size = ShapeSize(left_rank, left_shape); @@ -1215,13 +1237,13 @@ #if USE_EIGEN if (inner_size == 1) { // Apply the same value to all elements. - auto left = ConstMatrixMap<T>(left_values, inner_size, outer_size); - auto output = MatrixMap<T>(output_values, inner_size, outer_size); + auto left = ConstMatrixMap<T>(left_values.data(), inner_size, outer_size); + auto output = MatrixMap<T>(output_values.data(), inner_size, outer_size); op.apply(left.array(), right_values[0], output.array()); } else { - auto left = ConstMatrixMap<T>(left_values, inner_size, outer_size); - auto right = ConstRowVectorMap<T>(right_values, inner_size); - auto output = MatrixMap<T>(output_values, inner_size, outer_size); + auto left = ConstMatrixMap<T>(left_values.data(), inner_size, outer_size); + auto right = ConstRowVectorMap<T>(right_values.data(), inner_size); + auto output = MatrixMap<T>(output_values.data(), inner_size, outer_size); for (int32_t col = 0; col < outer_size; col++) { op.apply(left.col(col).array(), right.array(), output.col(col).array()); } @@ -1244,7 +1266,7 @@ // 0]. inline bool IncrementIndices(int32_t rank, base::span<const int32_t> shape, - int32_t* indices) { + base::span<int32_t> indices) { int32_t i = rank - 1; while (i >= 0 && indices[i] == shape[i] - 1) { --i; @@ -1263,7 +1285,7 @@ // E.g. if the shape is (2, 3) and indices are [1, 2] the offset is 1*3 + 2. inline int32_t Offset(int32_t rank, base::span<const int32_t> shape, - const int32_t* indices) { + base::span<const int32_t> indices) { int32_t offset = 0; int32_t mul = 1; for (int32_t i = rank - 1; i >= 0; --i) { @@ -1280,9 +1302,9 @@ // indices_rank - input_rank indices are ignored. // E.g. if the input_shape is (4) and indices are [2, 3, 1] the offset is 1. inline int32_t BroadcastOffset(int32_t input_rank, - const int32_t* input_shape, + base::span<const int32_t> input_shape, int32_t indices_rank, - const int32_t* indices) { + base::span<const int32_t> indices) { int32_t offset = 0; int32_t mul = 1; for (int32_t i = input_rank - 1; i >= 0; --i) { @@ -1296,12 +1318,12 @@ template <typename T, typename OP> void OpGenericBroadcast(int32_t left_rank, - const int32_t* __restrict left_shape, - const T* __restrict left_values, + base::span<const int32_t> left_shape, + base::span<const T> left_values, int32_t right_rank, - const int32_t* __restrict right_shape, - const T* __restrict right_values, - T* __restrict output_values, + base::span<const int32_t> right_shape, + base::span<const T> right_values, + base::span<T> output_values, OP op) { BENCHMARK_TIMER(op.name, "GenericBroadcast"); const int32_t output_rank = std::max(left_rank, right_rank); @@ -1330,7 +1352,9 @@ template <typename T> \ struct Op##OP_NAME { \ const char* name = #OP_NAME; \ - T operator()(const T lhs, const T rhs) { return EXPR; } \ + T operator()(const T lhs, const T rhs) { \ + return EXPR; \ + } \ template <typename X, typename Y, typename Z> \ void apply(const X& lhs, const Y& rhs, Z out) { \ out = EXPR_EIGEN; \ @@ -1338,29 +1362,29 @@ }; \ template <typename T> \ void OP_NAME##NoBroadcast( \ - const int32_t left_rank, const int32_t* __restrict left_shape, \ - const T* __restrict left_values, const int32_t right_rank, \ - const int32_t* __restrict right_shape, const T* __restrict right_values, \ - T* __restrict output_values) { \ + const int32_t left_rank, base::span<const int32_t> left_shape, \ + base::span<const T> left_values, const int32_t right_rank, \ + base::span<const int32_t> right_shape, base::span<const T> right_values, \ + base::span<T> output_values) { \ OpNoBroadcast(left_rank, left_shape, left_values, right_rank, right_shape, \ right_values, output_values, Op##OP_NAME<T>()); \ } \ template <typename T> \ void OP_NAME##InnerBroadcast( \ - const int32_t left_rank, const int32_t* __restrict left_shape, \ - const T* __restrict left_values, const int32_t right_rank, \ - const int32_t* __restrict right_shape, const T* __restrict right_values, \ - T* __restrict output_values) { \ + const int32_t left_rank, base::span<const int32_t> left_shape, \ + base::span<const T> left_values, const int32_t right_rank, \ + base::span<const int32_t> right_shape, base::span<const T> right_values, \ + base::span<T> output_values) { \ OpInnerBroadcast(left_rank, left_shape, left_values, right_rank, \ right_shape, right_values, output_values, \ Op##OP_NAME<T>()); \ } \ template <typename T> \ - void OP_NAME(const int32_t left_rank, const int32_t* __restrict left_shape, \ - const T* __restrict left_values, const int32_t right_rank, \ - const int32_t* __restrict right_shape, \ - const T* __restrict right_values, \ - T* __restrict output_values) { \ + void OP_NAME(const int32_t left_rank, base::span<const int32_t> left_shape, \ + base::span<const T> left_values, const int32_t right_rank, \ + base::span<const int32_t> right_shape, \ + base::span<const T> right_values, \ + base::span<T> output_values) { \ OpGenericBroadcast(left_rank, left_shape, left_values, right_rank, \ right_shape, right_values, output_values, \ Op##OP_NAME<T>()); \ @@ -1383,212 +1407,218 @@ // We use macros instead of template functions with templated functors here // because it's a lot less verbose and easier for the compiler to optimize. -#define REDUCE_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \ - template <typename T, typename Tidx> \ - void OP_NAME##InnerReduce( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - BENCHMARK_TIMER(#OP_NAME, "InnerReduce"); \ - const int32_t inner_size = \ - GetReduceInnerSize(input_rank, input_shape, index_tensor_rank, \ - index_shape, index_values); \ - const int32_t input_size = ShapeSize(input_rank, input_shape); \ - const int32_t outer_size = input_size / inner_size; \ - for (int32_t idx_out = 0; idx_out < outer_size; ++idx_out) { \ - T value = DEFAULT_VALUE; \ - for (int32_t idx_in = 0; idx_in < inner_size; ++idx_in) { \ - const T prev = value; \ - const T next = input_values[idx_out * inner_size + idx_in]; \ - value = UPDATE_EXPR; \ - } \ - const T count = inner_size; \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - output_values[idx_out] = RESULT_EXPR; \ - } \ - } \ - template <typename T, typename Tidx> \ - void OP_NAME##GenericReduceRank2( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - assert(input_rank == 2); \ - assert(index_tensor_rank <= 1); \ - BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank2"); \ - const int32_t output_size = input_shape[1]; \ - std::fill_n(output_values, output_size, DEFAULT_VALUE); \ - for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ - for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1, ++input_values) { \ - T* out_ptr = output_values + dim1; \ - const T prev = *out_ptr; \ - const T next = *input_values; \ - *out_ptr = UPDATE_EXPR; \ - } \ - } \ - const T count = input_shape[0]; \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - for (int32_t i = 0; i < output_size; ++i) { \ - const T value = output_values[i]; \ - output_values[i] = RESULT_EXPR; \ - } \ - } \ - template <typename T, typename Tidx> \ - void OP_NAME##GenericReduceRank3( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - assert(input_rank == 3); \ - assert(index_tensor_rank <= 1); \ - BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank3"); \ - int32_t out_shape[3] = {input_shape[0], input_shape[1], input_shape[2]}; \ - bool reduce_mask[3] = {false, false, false}; \ - const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ - for (int32_t i = 0; i < num_indices; ++i) { \ - reduce_mask[index_values[i]] = true; \ - out_shape[index_values[i]] = 1; \ - } \ - const int32_t out_strides[3] = { \ - reduce_mask[0] ? 0 : out_shape[1] * out_shape[2], \ - reduce_mask[1] ? 0 : out_shape[2], \ - reduce_mask[2] ? 0 : 1, \ - }; \ - const int32_t output_size = ShapeSize(input_rank, out_shape); \ - std::fill_n(output_values, output_size, DEFAULT_VALUE); \ - for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ - for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ - for (int32_t dim2 = 0; dim2 < input_shape[2]; \ - ++dim2, ++input_values) { \ - T* out_ptr = output_values + out_strides[0] * dim0 + \ - out_strides[1] * dim1 + out_strides[2] * dim2; \ - const T prev = *out_ptr; \ - const T next = *input_values; \ - *out_ptr = UPDATE_EXPR; \ - } \ - } \ - } \ - const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ - (reduce_mask[1] ? input_shape[1] : 1) * \ - (reduce_mask[2] ? input_shape[2] : 1); \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - for (int32_t i = 0; i < output_size; ++i) { \ - const T value = output_values[i]; \ - output_values[i] = RESULT_EXPR; \ - } \ - } \ - template <typename T, typename Tidx> \ - void OP_NAME##GenericReduceRank4( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - assert(input_rank == 4); \ - assert(index_tensor_rank <= 1); \ - BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank4"); \ - int32_t out_shape[4] = {input_shape[0], input_shape[1], input_shape[2], \ - input_shape[3]}; \ - bool reduce_mask[4] = {false, false, false, false}; \ - const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ - for (int32_t i = 0; i < num_indices; ++i) { \ - reduce_mask[index_values[i]] = true; \ - out_shape[index_values[i]] = 1; \ - } \ - const int32_t out_strides[4] = { \ - reduce_mask[0] ? 0 : out_shape[1] * out_shape[2] * out_shape[3], \ - reduce_mask[1] ? 0 : out_shape[2] * out_shape[3], \ - reduce_mask[2] ? 0 : out_shape[3], \ - reduce_mask[3] ? 0 : 1, \ - }; \ - const int32_t output_size = ShapeSize(input_rank, out_shape); \ - std::fill_n(output_values, output_size, DEFAULT_VALUE); \ - for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ - for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ - for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \ - for (int32_t dim3 = 0; dim3 < input_shape[3]; \ - ++dim3, ++input_values) { \ - T* out_ptr = output_values + out_strides[0] * dim0 + \ - out_strides[1] * dim1 + out_strides[2] * dim2 + \ - out_strides[3] * dim3; \ - const T prev = *out_ptr; \ - const T next = *input_values; \ - *out_ptr = UPDATE_EXPR; \ - } \ - } \ - } \ - } \ - const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ - (reduce_mask[1] ? input_shape[1] : 1) * \ - (reduce_mask[2] ? input_shape[2] : 1) * \ - (reduce_mask[3] ? input_shape[3] : 1); \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - for (int32_t i = 0; i < output_size; ++i) { \ - const T value = output_values[i]; \ - output_values[i] = RESULT_EXPR; \ - } \ - } \ - template <typename T, typename Tidx> \ - void OP_NAME##GenericReduceRank5( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - assert(input_rank == 5); \ - assert(index_tensor_rank <= 1); \ - BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank5"); \ - int32_t out_shape[5] = {input_shape[0], input_shape[1], input_shape[2], \ - input_shape[3], input_shape[4]}; \ - /* If true, reduce the input across that dimension. */ \ - bool reduce_mask[5] = {false, false, false, false, false}; \ - const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ - for (int32_t i = 0; i < num_indices; ++i) { \ - reduce_mask[index_values[i]] = true; \ - out_shape[index_values[i]] = 1; \ - } \ - const int32_t out_strides[5] = { \ - reduce_mask[0] \ - ? 0 \ - : out_shape[1] * out_shape[2] * out_shape[3] * out_shape[4], \ - reduce_mask[1] ? 0 : out_shape[2] * out_shape[3] * out_shape[4], \ - reduce_mask[2] ? 0 : out_shape[3] * out_shape[4], \ - reduce_mask[3] ? 0 : out_shape[4], \ - reduce_mask[4] ? 0 : 1, \ - }; \ - const int32_t output_size = ShapeSize(input_rank, out_shape); \ - std::fill_n(output_values, output_size, DEFAULT_VALUE); \ - for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ - for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ - for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \ - for (int32_t dim3 = 0; dim3 < input_shape[3]; ++dim3) { \ - for (int32_t dim4 = 0; dim4 < input_shape[4]; \ - ++dim4, ++input_values) { \ - T* out_ptr = output_values + out_strides[0] * dim0 + \ - out_strides[1] * dim1 + out_strides[2] * dim2 + \ - out_strides[3] * dim3 + out_strides[4] * dim4; \ - const T prev = *out_ptr; \ - const T next = *input_values; \ - *out_ptr = UPDATE_EXPR; \ - } \ - } \ - } \ - } \ - } \ - const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ - (reduce_mask[1] ? input_shape[1] : 1) * \ - (reduce_mask[2] ? input_shape[2] : 1) * \ - (reduce_mask[3] ? input_shape[3] : 1) * \ - (reduce_mask[4] ? input_shape[4] : 1); \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - for (int32_t i = 0; i < output_size; ++i) { \ - const T value = output_values[i]; \ - output_values[i] = RESULT_EXPR; \ - } \ +#define REDUCE_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \ + template <typename T, typename Tidx> \ + void OP_NAME##InnerReduce( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + BENCHMARK_TIMER(#OP_NAME, "InnerReduce"); \ + const int32_t inner_size = \ + GetReduceInnerSize(input_rank, input_shape, index_tensor_rank, \ + index_shape, index_values); \ + const int32_t input_size = ShapeSize(input_rank, input_shape); \ + const int32_t outer_size = input_size / inner_size; \ + for (int32_t idx_out = 0; idx_out < outer_size; ++idx_out) { \ + T value = DEFAULT_VALUE; \ + for (int32_t idx_in = 0; idx_in < inner_size; ++idx_in) { \ + const T prev = value; \ + const T next = input_values[idx_out * inner_size + idx_in]; \ + value = UPDATE_EXPR; \ + } \ + const T count = inner_size; \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + output_values[idx_out] = RESULT_EXPR; \ + } \ + } \ + template <typename T, typename Tidx> \ + void OP_NAME##GenericReduceRank2( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + assert(input_rank == 2); \ + assert(index_tensor_rank <= 1); \ + BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank2"); \ + const int32_t output_size = input_shape[1]; \ + std::ranges::fill(output_values, DEFAULT_VALUE); \ + auto input_iter = input_values.begin(); \ + for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ + for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1, ++input_iter) { \ + T* out_ptr = &output_values[dim1]; \ + const T prev = *out_ptr; \ + const T next = *input_iter; \ + *out_ptr = UPDATE_EXPR; \ + } \ + } \ + const T count = input_shape[0]; \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + for (int32_t i = 0; i < output_size; ++i) { \ + const T value = output_values[i]; \ + output_values[i] = RESULT_EXPR; \ + } \ + } \ + template <typename T, typename Tidx> \ + void OP_NAME##GenericReduceRank3( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + assert(input_rank == 3); \ + assert(index_tensor_rank <= 1); \ + BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank3"); \ + int32_t out_shape[3] = {input_shape[0], input_shape[1], input_shape[2]}; \ + bool reduce_mask[3] = {false, false, false}; \ + const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ + for (int32_t i = 0; i < num_indices; ++i) { \ + reduce_mask[index_values[i]] = true; \ + out_shape[index_values[i]] = 1; \ + } \ + const int32_t out_strides[3] = { \ + reduce_mask[0] ? 0 : out_shape[1] * out_shape[2], \ + reduce_mask[1] ? 0 : out_shape[2], \ + reduce_mask[2] ? 0 : 1, \ + }; \ + const int32_t output_size = ShapeSize(input_rank, base::span(out_shape)); \ + std::ranges::fill(output_values, DEFAULT_VALUE); \ + auto input_iter = input_values.begin(); \ + for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ + for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ + for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2, ++input_iter) { \ + T* out_ptr = \ + &output_values[out_strides[0] * dim0 + out_strides[1] * dim1 + \ + out_strides[2] * dim2]; \ + const T prev = *out_ptr; \ + const T next = *input_iter; \ + *out_ptr = UPDATE_EXPR; \ + } \ + } \ + } \ + const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ + (reduce_mask[1] ? input_shape[1] : 1) * \ + (reduce_mask[2] ? input_shape[2] : 1); \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + for (int32_t i = 0; i < output_size; ++i) { \ + const T value = output_values[i]; \ + output_values[i] = RESULT_EXPR; \ + } \ + } \ + template <typename T, typename Tidx> \ + void OP_NAME##GenericReduceRank4( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + assert(input_rank == 4); \ + assert(index_tensor_rank <= 1); \ + BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank4"); \ + int32_t out_shape[4] = {input_shape[0], input_shape[1], input_shape[2], \ + input_shape[3]}; \ + bool reduce_mask[4] = {false, false, false, false}; \ + const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ + for (int32_t i = 0; i < num_indices; ++i) { \ + reduce_mask[index_values[i]] = true; \ + out_shape[index_values[i]] = 1; \ + } \ + const int32_t out_strides[4] = { \ + reduce_mask[0] ? 0 : out_shape[1] * out_shape[2] * out_shape[3], \ + reduce_mask[1] ? 0 : out_shape[2] * out_shape[3], \ + reduce_mask[2] ? 0 : out_shape[3], \ + reduce_mask[3] ? 0 : 1, \ + }; \ + const int32_t output_size = ShapeSize(input_rank, base::span(out_shape)); \ + std::ranges::fill(output_values, DEFAULT_VALUE); \ + auto input_iter = input_values.begin(); \ + for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ + for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ + for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \ + for (int32_t dim3 = 0; dim3 < input_shape[3]; \ + ++dim3, ++input_iter) { \ + T* out_ptr = \ + &output_values[out_strides[0] * dim0 + out_strides[1] * dim1 + \ + out_strides[2] * dim2 + out_strides[3] * dim3]; \ + const T prev = *out_ptr; \ + const T next = *input_iter; \ + *out_ptr = UPDATE_EXPR; \ + } \ + } \ + } \ + } \ + const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ + (reduce_mask[1] ? input_shape[1] : 1) * \ + (reduce_mask[2] ? input_shape[2] : 1) * \ + (reduce_mask[3] ? input_shape[3] : 1); \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + for (int32_t i = 0; i < output_size; ++i) { \ + const T value = output_values[i]; \ + output_values[i] = RESULT_EXPR; \ + } \ + } \ + template <typename T, typename Tidx> \ + void OP_NAME##GenericReduceRank5( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + assert(input_rank == 5); \ + assert(index_tensor_rank <= 1); \ + BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank5"); \ + int32_t out_shape[5] = {input_shape[0], input_shape[1], input_shape[2], \ + input_shape[3], input_shape[4]}; \ + /* If true, reduce the input across that dimension. */ \ + bool reduce_mask[5] = {false, false, false, false, false}; \ + const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ + for (int32_t i = 0; i < num_indices; ++i) { \ + reduce_mask[index_values[i]] = true; \ + out_shape[index_values[i]] = 1; \ + } \ + const int32_t out_strides[5] = { \ + reduce_mask[0] \ + ? 0 \ + : out_shape[1] * out_shape[2] * out_shape[3] * out_shape[4], \ + reduce_mask[1] ? 0 : out_shape[2] * out_shape[3] * out_shape[4], \ + reduce_mask[2] ? 0 : out_shape[3] * out_shape[4], \ + reduce_mask[3] ? 0 : out_shape[4], \ + reduce_mask[4] ? 0 : 1, \ + }; \ + const int32_t output_size = ShapeSize(input_rank, base::span(out_shape)); \ + std::ranges::fill(output_values, DEFAULT_VALUE); \ + auto input_iter = input_values.begin(); \ + for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ + for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ + for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \ + for (int32_t dim3 = 0; dim3 < input_shape[3]; ++dim3) { \ + for (int32_t dim4 = 0; dim4 < input_shape[4]; \ + ++dim4, ++input_iter) { \ + T* out_ptr = &output_values[out_strides[0] * dim0 + \ + out_strides[1] * dim1 + \ + out_strides[2] * dim2 + \ + out_strides[3] * dim3 + \ + out_strides[4] * dim4]; \ + const T prev = *out_ptr; \ + const T next = *input_iter; \ + *out_ptr = UPDATE_EXPR; \ + } \ + } \ + } \ + } \ + } \ + const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ + (reduce_mask[1] ? input_shape[1] : 1) * \ + (reduce_mask[2] ? input_shape[2] : 1) * \ + (reduce_mask[3] ? input_shape[3] : 1) * \ + (reduce_mask[4] ? input_shape[4] : 1); \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + for (int32_t i = 0; i < output_size; ++i) { \ + const T value = output_values[i]; \ + output_values[i] = RESULT_EXPR; \ + } \ } REDUCE_OP(Max, std::numeric_limits<T>::lowest(), std::max(prev, next), value) @@ -1602,11 +1632,11 @@ template <typename T> void DequantizeMinCombined(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const float* __restrict min_range, - const float* __restrict max_range, - float* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const float> min_range, + base::span<const float> max_range, + base::span<float> output_values) { BENCHMARK_TIMER("DequantizeMinCombined"); const int32_t size = ShapeSize(rank, input_shape); const float offset = @@ -1627,11 +1657,11 @@ template <typename T> void DequantizeMinFirst(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const float* __restrict min_range, - const float* __restrict max_range, - float* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const float> min_range, + base::span<const float> max_range, + base::span<float> output_values) { BENCHMARK_TIMER("DequantizeMinFirst"); const int32_t size = ShapeSize(rank, input_shape); const float range_scale = (max_range[0] - min_range[0]) / @@ -1655,21 +1685,21 @@ template <typename T> void AddN(const int32_t rank, - const int32_t* __restrict shape, - std::initializer_list<const T* __restrict> input_values, - T* __restrict output_values) { + base::span<const int32_t> shape, + std::initializer_list<base::span<const T>> input_values, + base::span<T> output_values) { BENCHMARK_TIMER("AddN"); const int32_t size = ShapeSize(rank, shape); #if USE_EIGEN - auto output = RowVectorMap<T>(output_values, size).array(); - std::fill_n(output_values, size, 0); - for (const auto input_value : input_values) { - output += ConstRowVectorMap<T>(input_value, size).array(); + auto output = RowVectorMap<T>(output_values.data(), size).array(); + std::ranges::fill(output_values, 0); + for (const auto& input_value : input_values) { + output += ConstRowVectorMap<T>(input_value.data(), size).array(); } #else for (int32_t i = 0; i < size; ++i) { T output_value = 0; - for (auto input_value : input_values) { + for (const auto& input_value : input_values) { output_value += input_value[i]; } output_values[i] = output_value; @@ -15358,10 +15388,11 @@ int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2] = {1, 1}; void Inference( - const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,173 */ + base::span<const float> + input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,173 */ , - float* __restrict logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: - 1,1 */ + base::span<float> + logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: 1,1 */ , FixedAllocations* __restrict fixed) { const int32_t input_from_feature_columns_input_layer_concat_concat0_shape[] =
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h index 3178e62..b84e7b4 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference.h
@@ -6,6 +6,8 @@ #define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_H_ #include <cstdint> +#include "base/containers/span.h" + namespace ui::internal_onedevice::alpha_model { struct alignas(16) FixedAllocations { float alloc0[117]; @@ -29,9 +31,10 @@ 1 void Inference( - const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,173 */ + base::span<const float> + input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,173 */ , - float* __restrict logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: + base::span<float> logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: 1,1 */ , FixedAllocations* __restrict fixed);
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc index 730f8099..26271183 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.cc
@@ -19,6 +19,7 @@ #include <tuple> #include "base/containers/span.h" +#include "base/numerics/safe_conversions.h" #ifndef USE_EIGEN #define USE_EIGEN 0 @@ -119,7 +120,7 @@ #endif // OP_LIB_BENCHMARK // The size of a shape in terms of number of coefficients. -inline int32_t ShapeSize(const int32_t rank, const int32_t* shape) { +inline int32_t ShapeSize(const int32_t rank, base::span<const int32_t> shape) { int32_t size = 1; for (int32_t i = 0; i < rank; ++i) size *= shape[i]; @@ -128,10 +129,11 @@ // For convolutional operations, calculates the output size with VALID padding. // Returns (height, width). -inline std::tuple<int, int> GetConvOutputSizeVALID(const int32_t* input_shape, - const int32_t* kernel_shape, - int32_t stride_y, - int32_t stride_x) { +inline std::tuple<int, int> GetConvOutputSizeVALID( + base::span<const int32_t> input_shape, + base::span<const int32_t> kernel_shape, + int32_t stride_y, + int32_t stride_x) { return std::make_tuple( (input_shape[1] + stride_y - kernel_shape[0]) / stride_y, (input_shape[2] + stride_x - kernel_shape[1]) / stride_x); @@ -139,9 +141,10 @@ // For convolutional operations, calculates the output size with SAME padding. // Returns (height, width). -inline std::tuple<int, int> GetConvOutputSizeSAME(const int32_t* input_shape, - int32_t stride_y, - int32_t stride_x) { +inline std::tuple<int, int> GetConvOutputSizeSAME( + base::span<const int32_t> input_shape, + int32_t stride_y, + int32_t stride_x) { return std::make_tuple((input_shape[1] + stride_y - 1) / stride_y, (input_shape[2] + stride_x - 1) / stride_x); } @@ -150,10 +153,10 @@ // specify which axes are reduced. template <typename Tidx> int32_t GetReduceInnerSize(int32_t input_tensor_rank, - const int32_t* __restrict input_shape, + base::span<const int32_t> input_shape, int32_t index_tensor_rank, - const int32_t* __restrict index_shape, - const Tidx* __restrict index_values) { + base::span<const int32_t> index_shape, + base::span<const Tidx> index_values) { assert(index_tensor_rank <= 1); const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; int32_t inner_size = 1; @@ -169,47 +172,51 @@ template <typename T> void ConcatV2Args2(int32_t arg0_rank, - const int32_t* __restrict arg0_shape, - const T* __restrict arg0_values, + base::span<const int32_t> arg0_shape, + base::span<const T> arg0_values, int32_t arg1_rank, - const int32_t* __restrict arg1_shape, - const T* __restrict arg1_values, - const int32_t* __restrict axis_value, - T* __restrict output_values) { + base::span<const int32_t> arg1_shape, + base::span<const T> arg1_values, + base::span<const int32_t> axis_value, + base::span<T> output_values) { BENCHMARK_TIMER("ConcatV2Args2"); - const int32_t axis = axis_value[0]; + const size_t axis = base::checked_cast<size_t>(axis_value[0]); const int32_t num_lines = ShapeSize(axis, arg0_shape); - const int32_t arg0_line_size = ShapeSize(arg0_rank - axis, arg0_shape + axis); - const int32_t arg1_line_size = ShapeSize(arg1_rank - axis, arg1_shape + axis); + const size_t arg0_line_size = base::checked_cast<size_t>( + ShapeSize(arg0_rank - axis, arg0_shape.subspan(axis))); + const size_t arg1_line_size = base::checked_cast<size_t>( + ShapeSize(arg1_rank - axis, arg1_shape.subspan(axis))); for (int32_t line = 0; line < num_lines; ++line) { - std::copy(arg0_values, arg0_values + arg0_line_size, output_values); - arg0_values += arg0_line_size; - output_values += arg0_line_size; - std::copy(arg1_values, arg1_values + arg1_line_size, output_values); - arg1_values += arg1_line_size; - output_values += arg1_line_size; + output_values.copy_prefix_from(arg0_values.first(arg0_line_size)); + arg0_values = arg0_values.subspan(arg0_line_size); + output_values = output_values.subspan(arg0_line_size); + output_values.copy_prefix_from(arg1_values.first(arg1_line_size)); + arg1_values = arg1_values.subspan(arg1_line_size); + output_values = output_values.subspan(arg1_line_size); } } template <typename T> -void MatMul(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict weight_shape, - const T* __restrict weight_values, - T* __restrict output_values) { +void MatMul(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> weight_shape, + base::span<const T> weight_values, + base::span<T> output_values) { BENCHMARK_TIMER("MatMul"); #if USE_EIGEN const auto in = - ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]); + ConstMatrixMap<T>(input_values.data(), input_shape[1], input_shape[0]); const auto weight = - ConstMatrixMap<T>(weight_values, weight_shape[1], weight_shape[0]); - auto result = MatrixMap<T>(output_values, weight_shape[1], input_shape[0]); + ConstMatrixMap<T>(weight_values.data(), weight_shape[1], weight_shape[0]); + auto result = + MatrixMap<T>(output_values.data(), weight_shape[1], input_shape[0]); result.noalias() = weight * in; #else const int32_t batch_size = input_shape[0]; const int32_t num_inputs = weight_shape[0]; const int32_t num_outputs = weight_shape[1]; assert(input_shape[1] == num_inputs); + auto output_iter = output_values.begin(); for (int32_t batch = 0; batch < batch_size; ++batch) { for (int32_t out_i = 0; out_i < num_outputs; ++out_i) { T value = 0; @@ -217,22 +224,22 @@ value += input_values[batch * num_inputs + in_i] * weight_values[in_i * num_outputs + out_i]; } - *output_values++ = value; + *output_iter++ = value; } } #endif } template <typename T> -void DepthwiseConv2dNative(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, - const T* __restrict kernel_values, +void DepthwiseConv2dNative(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, + base::span<const T> kernel_values, int32_t stride_y, int32_t stride_x, int32_t out_height, int32_t out_width, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("DepthwiseConv2dNative"); // Give the shape values nicer names. assert(input_shape[3] == kernel_shape[2]); @@ -264,7 +271,7 @@ 1, // channel mult }; - T* out_write_ptr = output_values; + auto out_write_iter = output_values.begin(); for (int32_t batch = 0; batch < batch_size; ++batch) { for (int32_t out_y = 0; out_y < out_height; ++out_y) { for (int32_t out_x = 0; out_x < out_width; ++out_x) { @@ -284,7 +291,8 @@ std::min(kernel_width, in_width - in_x_origin); for (int32_t in_c = 0; in_c < in_depth; ++in_c) { - for (int32_t mul_c = 0; mul_c < depth_mul; ++mul_c, ++out_write_ptr) { + for (int32_t mul_c = 0; mul_c < depth_mul; + ++mul_c, ++out_write_iter) { // Convolve. T sum = 0; for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { @@ -306,7 +314,7 @@ sum += input_value * kernel_value; } } - *out_write_ptr = sum; + *out_write_iter++ = sum; } // mul_c } // in_c } // out_x @@ -315,13 +323,13 @@ } template <typename T> -void DepthwiseConv2dNativeVALID(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, - const T* __restrict kernel_values, +void DepthwiseConv2dNativeVALID(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, + base::span<const T> kernel_values, int32_t stride_y, int32_t stride_x, - T* __restrict output_values) { + base::span<T> output_values) { const auto out_size = GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x); DepthwiseConv2dNative<T>( @@ -330,13 +338,13 @@ } template <typename T> -void DepthwiseConv2dNativeSAME(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, - const T* __restrict kernel_values, +void DepthwiseConv2dNativeSAME(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, + base::span<const T> kernel_values, int32_t stride_y, int32_t stride_x, - T* __restrict output_values) { + base::span<T> output_values) { const auto out_size = GetConvOutputSizeSAME(input_shape, stride_y, stride_x); DepthwiseConv2dNative<T>( input_shape, input_values, kernel_shape, kernel_values, stride_y, @@ -344,21 +352,22 @@ } template <typename T> -void FullyConnected(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict weight_shape, - const T* __restrict weight_values, - const int32_t* __restrict bias_shape, - const T* __restrict bias_values, - T* __restrict output_values) { +void FullyConnected(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> weight_shape, + base::span<const T> weight_values, + base::span<const int32_t> bias_shape, + base::span<const T> bias_values, + base::span<T> output_values) { BENCHMARK_TIMER("FullyConnected"); #if USE_EIGEN const auto in = - ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]); + ConstMatrixMap<T>(input_values.data(), input_shape[1], input_shape[0]); const auto weight = - ConstMatrixMap<T>(weight_values, weight_shape[1], weight_shape[0]); - const auto bias = ConstRowVectorMap<T>(bias_values, bias_shape[0]); - auto result = MatrixMap<T>(output_values, weight_shape[1], input_shape[0]); + ConstMatrixMap<T>(weight_values.data(), weight_shape[1], weight_shape[0]); + const auto bias = ConstRowVectorMap<T>(bias_values.data(), bias_shape[0]); + auto result = + MatrixMap<T>(output_values.data(), weight_shape[1], input_shape[0]); result.noalias() = (weight * in).colwise() + bias; #else const int32_t batch_size = input_shape[0]; @@ -380,11 +389,11 @@ } template <typename T, typename TBlocks, typename TPaddings> -void SpaceToBatchNDRank4(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const TBlocks* __restrict block_shape_values, - const TPaddings* __restrict padding_values, - T* __restrict output_values) { +void SpaceToBatchNDRank4(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const TBlocks> block_shape_values, + base::span<const TPaddings> padding_values, + base::span<T> output_values) { BENCHMARK_TIMER("SpaceToBatchNDRank4"); const int32_t input_batch_size = input_shape[0]; const int32_t input_height = input_shape[1]; @@ -414,10 +423,10 @@ const int32_t shift_h = (out_b / input_batch_size) / block_shape_width; for (int32_t out_h = 0; out_h < output_height; ++out_h) { for (int32_t out_w = 0; out_w < output_width; ++out_w) { - T* out = output_values + - (((out_b * output_height + out_h) * output_width + out_w) * - output_depth + - 0); + base::span<T> out = output_values.subspan(base::checked_cast<size_t>( + (((out_b * output_height + out_h) * output_width + out_w) * + output_depth + + 0))); // Check if padding cell are being handled. if (out_h * block_shape_height + shift_h < padding_top || out_h * block_shape_height + shift_h >= @@ -426,9 +435,10 @@ out_w * block_shape_width + shift_w >= padding_left + input_width) { // This may not execute correctly when pad_value != 0 and T != uint8. #if USE_TYPED_MEMSETMEMCPY - std::fill(out, out + input_depth, pad_value); + std::ranges::fill(out.first(base::checked_cast<size_t>(input_depth)), + pad_value); #else - std::memset(out, pad_value, input_depth * sizeof(T)); + std::memset(out.data(), pad_value, input_depth * sizeof(T)); #endif } else { const int32_t i0 = input_batch; @@ -436,13 +446,15 @@ (out_h * block_shape_height + shift_h) - padding_top; const int32_t i2 = (out_w * block_shape_width + shift_w) - padding_left; - const T* in = - input_values + - (((i0 * input_height + i1) * input_width + i2) * input_depth + 0); + base::span<const T> in = + input_values.subspan(base::checked_cast<size_t>( + (((i0 * input_height + i1) * input_width + i2) * input_depth + + 0))); #if USE_TYPED_MEMSETMEMCPY - std::copy(in, in + input_depth, out); + out.copy_prefix_from( + in.first(base::checked_cast<size_t>(input_depth))); #else - std::memcpy(out, in, input_depth * sizeof(T)); + std::memcpy(out.data(), in.data(), input_depth * sizeof(T)); #endif } } @@ -451,11 +463,11 @@ } template <typename T, typename TBlocks, typename TCrops> -void BatchToSpaceNDRank4(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const TBlocks* __restrict block_shape_values, - const TCrops* __restrict crops_values, - T* __restrict output_values) { +void BatchToSpaceNDRank4(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const TBlocks> block_shape_values, + base::span<const TCrops> crops_values, + base::span<T> output_values) { BENCHMARK_TIMER("BatchToSpaceNDRank4"); const int32_t input_batch_size = input_shape[0]; const int32_t input_height = input_shape[1]; @@ -492,18 +504,18 @@ if (out_w < 0 || out_w >= output_width) { continue; } - T* out = output_values + - (((out_batch * output_height + out_h) * output_width + out_w) * - output_depth + - 0); - const T* in = input_values + - (((in_batch * input_height + in_h) * input_width + in_w) * - input_depth + - 0); + base::span<T> out = output_values.subspan(base::checked_cast<size_t>( + (((out_batch * output_height + out_h) * output_width + out_w) * + output_depth))); + base::span<const T> in = + input_values.subspan(base::checked_cast<size_t>( + (((in_batch * input_height + in_h) * input_width + in_w) * + input_depth + + 0))); #if USE_TYPED_MEMSETMEMCPY - std::copy(in, in + input_depth, out); + out.copy_prefix_from(in.first(input_depth)); #else - std::memcpy(out, in, input_depth * sizeof(T)); + std::memcpy(out.data(), in.data(), input_depth * sizeof(T)); #endif } } @@ -512,80 +524,83 @@ #if USE_EIGEN template <typename T, typename Tidx> -void SparseDenseMatMulCSR(const int32_t* __restrict input_shape, - const T* __restrict input_values, +void SparseDenseMatMulCSR(base::span<const int32_t> input_shape, + base::span<const T> input_values, const int32_t num_rows, - const int32_t* __restrict nnz_shape, - const T* __restrict nnz_values, - const Tidx* __restrict outer_index, - const Tidx* __restrict cols, - T* __restrict output_values) { + base::span<const int32_t> nnz_shape, + base::span<const T> nnz_values, + base::span<const Tidx> outer_index, + base::span<const Tidx> cols, + base::span<T> output_values) { BENCHMARK_TIMER("SparseDenseMatMulCSR"); const int32_t num_cols = input_shape[1]; const auto in = - ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]); + ConstMatrixMap<T>(input_values.data(), input_shape[1], input_shape[0]); const Eigen::Map<const SparseMatrix<T, Tidx>> weight( - num_rows, num_cols, nnz_shape[0], outer_index, cols, nnz_values); - auto result = MatrixMap<T>(output_values, num_rows, input_shape[0]); + num_rows, num_cols, nnz_shape[0], outer_index.data(), cols.data(), + nnz_values.data()); + auto result = MatrixMap<T>(output_values.data(), num_rows, input_shape[0]); result.noalias() = weight * in; } template <typename T, typename Tidx> -void SparseFullyConnectedCSR(const int32_t* __restrict input_shape, - const T* __restrict input_values, +void SparseFullyConnectedCSR(base::span<const int32_t> input_shape, + base::span<const T> input_values, const int32_t num_rows, - const int32_t* __restrict nnz_shape, - const T* __restrict nnz_values, - const Tidx* __restrict outer_index, - const Tidx* __restrict cols, - const int32_t* __restrict bias_shape, - const T* __restrict bias_values, - T* __restrict output_values) { + base::span<const int32_t> nnz_shape, + base::span<const T> nnz_values, + base::span<const Tidx> outer_index, + base::span<const Tidx> cols, + base::span<const int32_t> bias_shape, + base::span<const T> bias_values, + base::span<T> output_values) { BENCHMARK_TIMER("SparseFullyConnectedCSR"); const int32_t num_cols = input_shape[1]; const auto in = - ConstMatrixMap<T>(input_values, input_shape[1], input_shape[0]); - const auto bias = ConstRowVectorMap<T>(bias_values, bias_shape[0]); + ConstMatrixMap<T>(input_values.data(), input_shape[1], input_shape[0]); + const auto bias = ConstRowVectorMap<T>(bias_values.data(), bias_shape[0]); const Eigen::Map<const SparseMatrix<T, Tidx>> weight( - num_rows, num_cols, nnz_shape[0], outer_index, cols, nnz_values); - auto result = MatrixMap<T>(output_values, num_rows, input_shape[0]); + num_rows, num_cols, nnz_shape[0], outer_index.data(), cols.data(), + nnz_values.data()); + auto result = MatrixMap<T>(output_values.data(), num_rows, input_shape[0]); result.noalias() = (weight * in).colwise() + bias; } #endif template <typename T, typename TIndex> void Gather(int32_t params_rank, - const int32_t* __restrict params_shape, - const T* __restrict params_values, + base::span<const int32_t> params_shape, + base::span<const T> params_values, int32_t indices_rank, - const int32_t* __restrict indices_shape, - const TIndex* __restrict indices_values, - T* __restrict output_values) { + base::span<const int32_t> indices_shape, + base::span<const TIndex> indices_values, + base::span<T> output_values) { BENCHMARK_TIMER("Gather"); const int32_t num_indices = ShapeSize(indices_rank, indices_shape); const int32_t num_params = params_shape[0]; - const int32_t slice_size = ShapeSize(params_rank - 1, params_shape + 1); + const size_t slice_size = base::checked_cast<size_t>( + ShapeSize(params_rank - 1, params_shape.subspan(1u))); for (int32_t i = 0; i < num_indices; ++i) { const int32_t index = indices_values[i]; if (index < 0 || index >= num_params) { - std::fill(output_values, output_values + slice_size, 0); + std::ranges::fill(output_values.first(slice_size), 0); } else { - std::copy(params_values + index * slice_size, - params_values + index * slice_size + slice_size, output_values); + output_values.copy_prefix_from(params_values.subspan( + base::checked_cast<size_t>(index) * slice_size, slice_size)); } - output_values += slice_size; + output_values = output_values.subspan(slice_size); } } template <typename T> -void Im2Row(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, +void Im2Row(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, int32_t stride_y, int32_t stride_x, int32_t out_height, int32_t out_width, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("Im2Row"); // Give the shape values nicer names. assert(input_shape[3] == kernel_shape[2]); @@ -628,36 +643,38 @@ // Padding top. if (kernel_y_start != 0) { const int32_t num_lines = kernel_y_start; - const int32_t num_coeffs = num_lines * kernel_width * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(num_lines * kernel_width * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { // Padding left. if (kernel_x_start != 0) { - const int32_t num_coeffs = kernel_x_start * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(kernel_x_start * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } // Valid values. { const int32_t in_y = in_y_origin + k_y; const int32_t in_x = in_x_origin + kernel_x_start; - const int32_t num_coeffs = - (kernel_x_end - kernel_x_start) * in_depth; + const size_t num_coeffs = base::checked_cast<size_t>( + (kernel_x_end - kernel_x_start) * in_depth); #if USE_TYPED_MEMSETMEMCPY const int32_t offset = batch * batch_stride + in_y * y_stride + in_x * x_stride; - std::copy(input_values + offset, input_values + offset + num_coeffs, - output_values); + output_values.copy_prefix_from(input_values.subspan( + base::checked_cast<size_t>(offset), num_coeffs)); #else std::memcpy(output_values, input_values // Reusing the restricted pointer. @@ -666,29 +683,31 @@ + in_x * x_stride, // x num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } // Padding right. if (kernel_x_end != kernel_width) { - const int32_t num_coeffs = (kernel_width - kernel_x_end) * in_depth; + const size_t num_coeffs = base::checked_cast<size_t>( + (kernel_width - kernel_x_end) * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else std::memset(output_values, 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } } // Padding bottom. if (kernel_y_end != kernel_height) { const int32_t num_lines = kernel_height - kernel_y_end; - const int32_t num_coeffs = num_lines * kernel_width * in_depth; + const size_t num_coeffs = + base::checked_cast<size_t>(num_lines * kernel_width * in_depth); #if USE_TYPED_MEMSETMEMCPY - std::fill(output_values, output_values + num_coeffs, 0); + std::ranges::fill(output_values.first(num_coeffs), 0); #else - std::memset(output_values, 0, num_coeffs * sizeof(T)); + std::memset(output_values.data(), 0, num_coeffs * sizeof(T)); #endif - output_values += num_coeffs; + output_values = output_values.subspan(num_coeffs); } } } @@ -696,12 +715,12 @@ } template <typename T> -void Im2RowVALID(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, +void Im2RowVALID(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, int32_t stride_y, int32_t stride_x, - T* __restrict output_values) { + base::span<T> output_values) { const auto out_size = GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x); Im2Row<T>(input_shape, input_values, kernel_shape, stride_y, stride_x, @@ -709,12 +728,12 @@ } template <typename T> -void Im2RowSAME(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict kernel_shape, +void Im2RowSAME(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> kernel_shape, int32_t stride_y, int32_t stride_x, - T* __restrict output_values) { + base::span<T> output_values) { const auto out_size = GetConvOutputSizeSAME(input_shape, stride_y, stride_x); Im2Row<T>(input_shape, input_values, kernel_shape, stride_y, stride_x, std::get<0>(out_size), std::get<1>(out_size), output_values); @@ -724,11 +743,11 @@ // because it's a lot less verbose and easier for the compiler to optimize. #define POOL_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \ template <typename T> \ - void OP_NAME##Pool(const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t stride_y, \ + void OP_NAME##Pool(base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t stride_y, \ int32_t stride_x, int32_t kernel_height, \ int32_t kernel_width, int32_t out_height, \ - int32_t out_width, T* __restrict output_values) { \ + int32_t out_width, base::span<T> output_values) { \ BENCHMARK_TIMER(#OP_NAME, "Pool"); \ const int32_t batch_size = input_shape[0]; \ const int32_t in_height = input_shape[1]; \ @@ -747,7 +766,7 @@ 1, \ }; \ \ - T* out_write_ptr = output_values; \ + auto out_write_iter = output_values.begin(); \ for (int32_t batch = 0; batch < batch_size; ++batch) { \ for (int32_t out_y = 0; out_y < out_height; ++out_y) { \ for (int32_t out_x = 0; out_x < out_width; ++out_x) { \ @@ -765,7 +784,7 @@ (kernel_x_end - kernel_x_start); \ (void)sizeof(count); \ \ - for (int32_t chan = 0; chan < depth; ++chan, ++out_write_ptr) { \ + for (int32_t chan = 0; chan < depth; ++chan, ++out_write_iter) { \ T value = DEFAULT_VALUE; \ for (int32_t k_y = kernel_y_start; k_y < kernel_y_end; ++k_y) { \ const int32_t in_y = in_y_origin + k_y; \ @@ -779,7 +798,7 @@ value = UPDATE_EXPR; \ } \ } \ - *out_write_ptr = RESULT_EXPR; \ + *out_write_iter = RESULT_EXPR; \ } \ } \ } \ @@ -787,10 +806,10 @@ } \ \ template <typename T> \ - void OP_NAME##PoolVALID(const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t stride_y, \ + void OP_NAME##PoolVALID(base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t stride_y, \ int32_t stride_x, int32_t kernel_height, \ - int32_t kernel_width, T* __restrict output_values) { \ + int32_t kernel_width, base::span<T> output_values) { \ const int32_t kernel_shape[4] = {kernel_height, kernel_width, 1, 1}; \ const auto out_size = \ GetConvOutputSizeVALID(input_shape, kernel_shape, stride_y, stride_x); \ @@ -800,10 +819,10 @@ } \ \ template <typename T> \ - void OP_NAME##PoolSAME(const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t stride_y, \ + void OP_NAME##PoolSAME(base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t stride_y, \ int32_t stride_x, int32_t kernel_height, \ - int32_t kernel_width, T* __restrict output_values) { \ + int32_t kernel_width, base::span<T> output_values) { \ const auto out_size = \ GetConvOutputSizeSAME(input_shape, stride_y, stride_x); \ OP_NAME##Pool<T>(input_shape, input_values, stride_y, stride_x, \ @@ -816,9 +835,9 @@ template <typename T> void Memcpy(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - T* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<T> output_values) { BENCHMARK_TIMER("Memcpy"); const int32_t size = ShapeSize(rank, input_shape); for (int32_t i = 0; i < size; ++i) { @@ -828,11 +847,11 @@ template <typename T> void Softmax(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, + base::span<const int32_t> input_shape, + base::span<const T> input_values, const int32_t reduce_dim, - T* __restrict output_values, - T* __restrict scratch_values) { + base::span<T> output_values, + base::span<T> scratch_values) { BENCHMARK_TIMER("Softmax"); const int32_t size = ShapeSize(rank, input_shape); if (rank == 2 && reduce_dim == 1) { @@ -868,9 +887,9 @@ // Returns the start position for a slice in a single dimension. template <typename T> int32_t StridedSliceBegin(int32_t range_mask, - const T* __restrict range_values, - const T* __restrict strides, - const int32_t* __restrict input_shape, + base::span<const T> range_values, + base::span<const T> strides, + base::span<const int32_t> input_shape, int32_t dim) { const bool is_explicit = 0 == (range_mask & (1 << dim)); if (is_explicit) { @@ -885,9 +904,9 @@ // Returns the end position for a slice in a single dimension. template <typename T> int32_t StridedSliceEnd(int32_t range_mask, - const T* __restrict range_values, - const T* __restrict strides, - const int32_t* __restrict input_shape, + base::span<const T> range_values, + base::span<const T> strides, + base::span<const int32_t> input_shape, int32_t dim) { const bool is_explicit = 0 == (range_mask & (1 << dim)); if (is_explicit) { @@ -901,14 +920,14 @@ template <typename T, typename TIdx> void StridedSlice(const int32_t input_rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const TIdx* __restrict begin, - const TIdx* __restrict end, - const TIdx* __restrict strides, + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const TIdx> begin, + base::span<const TIdx> end, + base::span<const TIdx> strides, int32_t begin_mask, int32_t end_mask, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("StridedSlice"); const int32_t MAX_RANK = 8; assert(input_rank < MAX_RANK); @@ -969,13 +988,15 @@ } #if USE_TYPED_MEMSETMEMCPY - std::copy(input_values + read_offset, - input_values + read_offset + block_size, output_values); + output_values.copy_prefix_from( + input_values.subspan(base::checked_cast<size_t>(read_offset), + base::checked_cast<size_t>(block_size))); #else - std::memcpy(output_values, input_values + read_offset, + std::memcpy(output_values.data(), input_values + read_offset, block_size * sizeof(T)); #endif - output_values += block_size; + output_values = + output_values.subspan(base::checked_cast<size_t>(block_size)); // Advance the read position. for (int32_t dim = last_sliced_dim; dim >= 0; --dim) { @@ -988,10 +1009,10 @@ } template <typename T> -void TransposeRank3(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict perm, - T* __restrict output_values) { +void TransposeRank3(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> perm, + base::span<T> output_values) { BENCHMARK_TIMER("TransposeRank3"); const std::array<int32_t, 3> in_strides = { input_shape[1] * input_shape[2], @@ -1017,10 +1038,10 @@ } template <typename T> -void TransposeRank4(const int32_t* __restrict input_shape, - const T* __restrict input_values, - const int32_t* __restrict perm, - T* __restrict output_values) { +void TransposeRank4(base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const int32_t> perm, + base::span<T> output_values) { BENCHMARK_TIMER("TransposeRank4"); const std::array<int32_t, 4> in_strides = { input_shape[1] * input_shape[2] * input_shape[3], @@ -1051,13 +1072,13 @@ template <typename T, typename TIdx, typename TDepth> void OneHot(const int32_t input_rank, - const int32_t* __restrict input_shape, - const TIdx* __restrict input_values, - const TDepth* __restrict depth, - const T* __restrict on_value, - const T* __restrict off_value, + base::span<const int32_t> input_shape, + base::span<const TIdx> input_values, + const TDepth* depth, + const T* on_value, + const T* off_value, const int32_t axis, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("OneHot"); const int32_t num_elements = ShapeSize(input_rank, input_shape); // We can assume axis >= 0 in this implementation. @@ -1078,12 +1099,12 @@ template <typename T, typename TIdx, typename TDepth> void OneHotLastDim(const int32_t input_rank, - const int32_t* __restrict input_shape, - const TIdx* __restrict input_values, + base::span<const int32_t> input_shape, + base::span<const TIdx> input_values, const TDepth* __restrict depth, const T* __restrict on_value, const T* __restrict off_value, - T* __restrict output_values) { + base::span<T> output_values) { BENCHMARK_TIMER("OneHotLastDim"); const int32_t num_elements = ShapeSize(input_rank, input_shape); int32_t write_offset = 0; @@ -1104,25 +1125,25 @@ #if USE_EIGEN -#define SIMPLE_UNARY_OP(OP_NAME, _, EXPR_EIGEN) \ - template <typename T> \ - void OP_NAME(const int32_t rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, \ - T* __restrict output_values) { \ - BENCHMARK_TIMER(#OP_NAME); \ - const int32_t size = ShapeSize(rank, input_shape); \ - auto values = ConstRowVectorMap<T>(input_values, size).array(); \ - auto output = RowVectorMap<T>(output_values, size).array(); \ - output = EXPR_EIGEN; \ +#define SIMPLE_UNARY_OP(OP_NAME, _, EXPR_EIGEN) \ + template <typename T> \ + void OP_NAME(const int32_t rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, \ + base::span<T> output_values) { \ + BENCHMARK_TIMER(#OP_NAME); \ + const int32_t size = ShapeSize(rank, input_shape); \ + auto values = ConstRowVectorMap<T>(input_values.data(), size).array(); \ + auto output = RowVectorMap<T>(output_values.data(), size).array(); \ + output = EXPR_EIGEN; \ } #else #define SIMPLE_UNARY_OP(OP_NAME, EXPR, _) \ template <typename T> \ - void OP_NAME(const int32_t rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, \ - T* __restrict output_values) { \ + void OP_NAME(const int32_t rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, \ + base::span<T> output_values) { \ BENCHMARK_TIMER(#OP_NAME); \ const int32_t size = ShapeSize(rank, input_shape); \ for (int32_t i = 0; i < size; ++i) { \ @@ -1177,19 +1198,19 @@ template <typename T, typename OP> void OpNoBroadcast(const int32_t left_rank, - const int32_t* __restrict left_shape, - const T* __restrict left_values, + base::span<const int32_t> left_shape, + base::span<const T> left_values, const int32_t right_rank, - const int32_t* __restrict right_shape, - const T* __restrict right_values, - T* __restrict output_values, + base::span<const int32_t> right_shape, + base::span<const T> right_values, + base::span<T> output_values, OP op) { BENCHMARK_TIMER(op.name, "NoBroadcast"); const int32_t size = ShapeSize(left_rank, left_shape); #if USE_EIGEN - auto lhs = ConstRowVectorMap<T>(left_values, size).array(); - auto rhs = ConstRowVectorMap<T>(right_values, size).array(); - auto output = RowVectorMap<T>(output_values, size).array(); + auto lhs = ConstRowVectorMap<T>(left_values.data(), size).array(); + auto rhs = ConstRowVectorMap<T>(right_values.data(), size).array(); + auto output = RowVectorMap<T>(output_values.data(), size).array(); op.apply(lhs, rhs, output); #else for (int32_t i = 0; i < size; ++i) { @@ -1200,12 +1221,12 @@ template <typename T, typename OP> void OpInnerBroadcast(int32_t left_rank, - const int32_t* __restrict left_shape, - const T* __restrict left_values, + base::span<const int32_t> left_shape, + base::span<const T> left_values, int32_t right_rank, - const int32_t* __restrict right_shape, - const T* __restrict right_values, - T* __restrict output_values, + base::span<const int32_t> right_shape, + base::span<const T> right_values, + base::span<T> output_values, OP op) { BENCHMARK_TIMER(op.name, "InnerBroadcast"); const int32_t output_size = ShapeSize(left_rank, left_shape); @@ -1214,13 +1235,13 @@ #if USE_EIGEN if (inner_size == 1) { // Apply the same value to all elements. - auto left = ConstMatrixMap<T>(left_values, inner_size, outer_size); - auto output = MatrixMap<T>(output_values, inner_size, outer_size); + auto left = ConstMatrixMap<T>(left_values.data(), inner_size, outer_size); + auto output = MatrixMap<T>(output_values.data(), inner_size, outer_size); op.apply(left.array(), right_values[0], output.array()); } else { - auto left = ConstMatrixMap<T>(left_values, inner_size, outer_size); - auto right = ConstRowVectorMap<T>(right_values, inner_size); - auto output = MatrixMap<T>(output_values, inner_size, outer_size); + auto left = ConstMatrixMap<T>(left_values.data(), inner_size, outer_size); + auto right = ConstRowVectorMap<T>(right_values.data(), inner_size); + auto output = MatrixMap<T>(output_values.data(), inner_size, outer_size); for (int32_t col = 0; col < outer_size; col++) { op.apply(left.col(col).array(), right.array(), output.col(col).array()); } @@ -1243,7 +1264,7 @@ // 0]. inline bool IncrementIndices(int32_t rank, base::span<const int32_t> shape, - int32_t* indices) { + base::span<int32_t> indices) { int32_t i = rank - 1; while (i >= 0 && indices[i] == shape[i] - 1) { --i; @@ -1262,7 +1283,7 @@ // E.g. if the shape is (2, 3) and indices are [1, 2] the offset is 1*3 + 2. inline int32_t Offset(int32_t rank, base::span<const int32_t> shape, - const int32_t* indices) { + base::span<const int32_t> indices) { int32_t offset = 0; int32_t mul = 1; for (int32_t i = rank - 1; i >= 0; --i) { @@ -1279,9 +1300,9 @@ // indices_rank - input_rank indices are ignored. // E.g. if the input_shape is (4) and indices are [2, 3, 1] the offset is 1. inline int32_t BroadcastOffset(int32_t input_rank, - const int32_t* input_shape, + base::span<const int32_t> input_shape, int32_t indices_rank, - const int32_t* indices) { + base::span<const int32_t> indices) { int32_t offset = 0; int32_t mul = 1; for (int32_t i = input_rank - 1; i >= 0; --i) { @@ -1295,12 +1316,12 @@ template <typename T, typename OP> void OpGenericBroadcast(int32_t left_rank, - const int32_t* __restrict left_shape, - const T* __restrict left_values, + base::span<const int32_t> left_shape, + base::span<const T> left_values, int32_t right_rank, - const int32_t* __restrict right_shape, - const T* __restrict right_values, - T* __restrict output_values, + base::span<const int32_t> right_shape, + base::span<const T> right_values, + base::span<T> output_values, OP op) { BENCHMARK_TIMER(op.name, "GenericBroadcast"); const int32_t output_rank = std::max(left_rank, right_rank); @@ -1329,7 +1350,9 @@ template <typename T> \ struct Op##OP_NAME { \ const char* name = #OP_NAME; \ - T operator()(const T lhs, const T rhs) { return EXPR; } \ + T operator()(const T lhs, const T rhs) { \ + return EXPR; \ + } \ template <typename X, typename Y, typename Z> \ void apply(const X& lhs, const Y& rhs, Z out) { \ out = EXPR_EIGEN; \ @@ -1337,29 +1360,29 @@ }; \ template <typename T> \ void OP_NAME##NoBroadcast( \ - const int32_t left_rank, const int32_t* __restrict left_shape, \ - const T* __restrict left_values, const int32_t right_rank, \ - const int32_t* __restrict right_shape, const T* __restrict right_values, \ - T* __restrict output_values) { \ + const int32_t left_rank, base::span<const int32_t> left_shape, \ + base::span<const T> left_values, const int32_t right_rank, \ + base::span<const int32_t> right_shape, base::span<const T> right_values, \ + base::span<T> output_values) { \ OpNoBroadcast(left_rank, left_shape, left_values, right_rank, right_shape, \ right_values, output_values, Op##OP_NAME<T>()); \ } \ template <typename T> \ void OP_NAME##InnerBroadcast( \ - const int32_t left_rank, const int32_t* __restrict left_shape, \ - const T* __restrict left_values, const int32_t right_rank, \ - const int32_t* __restrict right_shape, const T* __restrict right_values, \ - T* __restrict output_values) { \ + const int32_t left_rank, base::span<const int32_t> left_shape, \ + base::span<const T> left_values, const int32_t right_rank, \ + base::span<const int32_t> right_shape, base::span<const T> right_values, \ + base::span<T> output_values) { \ OpInnerBroadcast(left_rank, left_shape, left_values, right_rank, \ right_shape, right_values, output_values, \ Op##OP_NAME<T>()); \ } \ template <typename T> \ - void OP_NAME(const int32_t left_rank, const int32_t* __restrict left_shape, \ - const T* __restrict left_values, const int32_t right_rank, \ - const int32_t* __restrict right_shape, \ - const T* __restrict right_values, \ - T* __restrict output_values) { \ + void OP_NAME(const int32_t left_rank, base::span<const int32_t> left_shape, \ + base::span<const T> left_values, const int32_t right_rank, \ + base::span<const int32_t> right_shape, \ + base::span<const T> right_values, \ + base::span<T> output_values) { \ OpGenericBroadcast(left_rank, left_shape, left_values, right_rank, \ right_shape, right_values, output_values, \ Op##OP_NAME<T>()); \ @@ -1382,212 +1405,218 @@ // We use macros instead of template functions with templated functors here // because it's a lot less verbose and easier for the compiler to optimize. -#define REDUCE_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \ - template <typename T, typename Tidx> \ - void OP_NAME##InnerReduce( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - BENCHMARK_TIMER(#OP_NAME, "InnerReduce"); \ - const int32_t inner_size = \ - GetReduceInnerSize(input_rank, input_shape, index_tensor_rank, \ - index_shape, index_values); \ - const int32_t input_size = ShapeSize(input_rank, input_shape); \ - const int32_t outer_size = input_size / inner_size; \ - for (int32_t idx_out = 0; idx_out < outer_size; ++idx_out) { \ - T value = DEFAULT_VALUE; \ - for (int32_t idx_in = 0; idx_in < inner_size; ++idx_in) { \ - const T prev = value; \ - const T next = input_values[idx_out * inner_size + idx_in]; \ - value = UPDATE_EXPR; \ - } \ - const T count = inner_size; \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - output_values[idx_out] = RESULT_EXPR; \ - } \ - } \ - template <typename T, typename Tidx> \ - void OP_NAME##GenericReduceRank2( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - assert(input_rank == 2); \ - assert(index_tensor_rank <= 1); \ - BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank2"); \ - const int32_t output_size = input_shape[1]; \ - std::fill_n(output_values, output_size, DEFAULT_VALUE); \ - for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ - for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1, ++input_values) { \ - T* out_ptr = output_values + dim1; \ - const T prev = *out_ptr; \ - const T next = *input_values; \ - *out_ptr = UPDATE_EXPR; \ - } \ - } \ - const T count = input_shape[0]; \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - for (int32_t i = 0; i < output_size; ++i) { \ - const T value = output_values[i]; \ - output_values[i] = RESULT_EXPR; \ - } \ - } \ - template <typename T, typename Tidx> \ - void OP_NAME##GenericReduceRank3( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - assert(input_rank == 3); \ - assert(index_tensor_rank <= 1); \ - BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank3"); \ - int32_t out_shape[3] = {input_shape[0], input_shape[1], input_shape[2]}; \ - bool reduce_mask[3] = {false, false, false}; \ - const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ - for (int32_t i = 0; i < num_indices; ++i) { \ - reduce_mask[index_values[i]] = true; \ - out_shape[index_values[i]] = 1; \ - } \ - const int32_t out_strides[3] = { \ - reduce_mask[0] ? 0 : out_shape[1] * out_shape[2], \ - reduce_mask[1] ? 0 : out_shape[2], \ - reduce_mask[2] ? 0 : 1, \ - }; \ - const int32_t output_size = ShapeSize(input_rank, out_shape); \ - std::fill_n(output_values, output_size, DEFAULT_VALUE); \ - for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ - for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ - for (int32_t dim2 = 0; dim2 < input_shape[2]; \ - ++dim2, ++input_values) { \ - T* out_ptr = output_values + out_strides[0] * dim0 + \ - out_strides[1] * dim1 + out_strides[2] * dim2; \ - const T prev = *out_ptr; \ - const T next = *input_values; \ - *out_ptr = UPDATE_EXPR; \ - } \ - } \ - } \ - const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ - (reduce_mask[1] ? input_shape[1] : 1) * \ - (reduce_mask[2] ? input_shape[2] : 1); \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - for (int32_t i = 0; i < output_size; ++i) { \ - const T value = output_values[i]; \ - output_values[i] = RESULT_EXPR; \ - } \ - } \ - template <typename T, typename Tidx> \ - void OP_NAME##GenericReduceRank4( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - assert(input_rank == 4); \ - assert(index_tensor_rank <= 1); \ - BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank4"); \ - int32_t out_shape[4] = {input_shape[0], input_shape[1], input_shape[2], \ - input_shape[3]}; \ - bool reduce_mask[4] = {false, false, false, false}; \ - const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ - for (int32_t i = 0; i < num_indices; ++i) { \ - reduce_mask[index_values[i]] = true; \ - out_shape[index_values[i]] = 1; \ - } \ - const int32_t out_strides[4] = { \ - reduce_mask[0] ? 0 : out_shape[1] * out_shape[2] * out_shape[3], \ - reduce_mask[1] ? 0 : out_shape[2] * out_shape[3], \ - reduce_mask[2] ? 0 : out_shape[3], \ - reduce_mask[3] ? 0 : 1, \ - }; \ - const int32_t output_size = ShapeSize(input_rank, out_shape); \ - std::fill_n(output_values, output_size, DEFAULT_VALUE); \ - for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ - for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ - for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \ - for (int32_t dim3 = 0; dim3 < input_shape[3]; \ - ++dim3, ++input_values) { \ - T* out_ptr = output_values + out_strides[0] * dim0 + \ - out_strides[1] * dim1 + out_strides[2] * dim2 + \ - out_strides[3] * dim3; \ - const T prev = *out_ptr; \ - const T next = *input_values; \ - *out_ptr = UPDATE_EXPR; \ - } \ - } \ - } \ - } \ - const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ - (reduce_mask[1] ? input_shape[1] : 1) * \ - (reduce_mask[2] ? input_shape[2] : 1) * \ - (reduce_mask[3] ? input_shape[3] : 1); \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - for (int32_t i = 0; i < output_size; ++i) { \ - const T value = output_values[i]; \ - output_values[i] = RESULT_EXPR; \ - } \ - } \ - template <typename T, typename Tidx> \ - void OP_NAME##GenericReduceRank5( \ - int32_t input_rank, const int32_t* __restrict input_shape, \ - const T* __restrict input_values, int32_t index_tensor_rank, \ - const int32_t* __restrict index_shape, \ - const Tidx* __restrict index_values, T* __restrict output_values) { \ - assert(input_rank == 5); \ - assert(index_tensor_rank <= 1); \ - BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank5"); \ - int32_t out_shape[5] = {input_shape[0], input_shape[1], input_shape[2], \ - input_shape[3], input_shape[4]}; \ - /* If true, reduce the input across that dimension. */ \ - bool reduce_mask[5] = {false, false, false, false, false}; \ - const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ - for (int32_t i = 0; i < num_indices; ++i) { \ - reduce_mask[index_values[i]] = true; \ - out_shape[index_values[i]] = 1; \ - } \ - const int32_t out_strides[5] = { \ - reduce_mask[0] \ - ? 0 \ - : out_shape[1] * out_shape[2] * out_shape[3] * out_shape[4], \ - reduce_mask[1] ? 0 : out_shape[2] * out_shape[3] * out_shape[4], \ - reduce_mask[2] ? 0 : out_shape[3] * out_shape[4], \ - reduce_mask[3] ? 0 : out_shape[4], \ - reduce_mask[4] ? 0 : 1, \ - }; \ - const int32_t output_size = ShapeSize(input_rank, out_shape); \ - std::fill_n(output_values, output_size, DEFAULT_VALUE); \ - for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ - for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ - for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \ - for (int32_t dim3 = 0; dim3 < input_shape[3]; ++dim3) { \ - for (int32_t dim4 = 0; dim4 < input_shape[4]; \ - ++dim4, ++input_values) { \ - T* out_ptr = output_values + out_strides[0] * dim0 + \ - out_strides[1] * dim1 + out_strides[2] * dim2 + \ - out_strides[3] * dim3 + out_strides[4] * dim4; \ - const T prev = *out_ptr; \ - const T next = *input_values; \ - *out_ptr = UPDATE_EXPR; \ - } \ - } \ - } \ - } \ - } \ - const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ - (reduce_mask[1] ? input_shape[1] : 1) * \ - (reduce_mask[2] ? input_shape[2] : 1) * \ - (reduce_mask[3] ? input_shape[3] : 1) * \ - (reduce_mask[4] ? input_shape[4] : 1); \ - /* Used by mean reduce. */ \ - (void)sizeof(count); \ - for (int32_t i = 0; i < output_size; ++i) { \ - const T value = output_values[i]; \ - output_values[i] = RESULT_EXPR; \ - } \ +#define REDUCE_OP(OP_NAME, DEFAULT_VALUE, UPDATE_EXPR, RESULT_EXPR) \ + template <typename T, typename Tidx> \ + void OP_NAME##InnerReduce( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + BENCHMARK_TIMER(#OP_NAME, "InnerReduce"); \ + const int32_t inner_size = \ + GetReduceInnerSize(input_rank, input_shape, index_tensor_rank, \ + index_shape, index_values); \ + const int32_t input_size = ShapeSize(input_rank, input_shape); \ + const int32_t outer_size = input_size / inner_size; \ + for (int32_t idx_out = 0; idx_out < outer_size; ++idx_out) { \ + T value = DEFAULT_VALUE; \ + for (int32_t idx_in = 0; idx_in < inner_size; ++idx_in) { \ + const T prev = value; \ + const T next = input_values[idx_out * inner_size + idx_in]; \ + value = UPDATE_EXPR; \ + } \ + const T count = inner_size; \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + output_values[idx_out] = RESULT_EXPR; \ + } \ + } \ + template <typename T, typename Tidx> \ + void OP_NAME##GenericReduceRank2( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + assert(input_rank == 2); \ + assert(index_tensor_rank <= 1); \ + BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank2"); \ + const int32_t output_size = input_shape[1]; \ + std::ranges::fill(output_values, DEFAULT_VALUE); \ + auto input_iter = input_values.begin(); \ + for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ + for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1, ++input_iter) { \ + T* out_ptr = &output_values[dim1]; \ + const T prev = *out_ptr; \ + const T next = *input_iter; \ + *out_ptr = UPDATE_EXPR; \ + } \ + } \ + const T count = input_shape[0]; \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + for (int32_t i = 0; i < output_size; ++i) { \ + const T value = output_values[i]; \ + output_values[i] = RESULT_EXPR; \ + } \ + } \ + template <typename T, typename Tidx> \ + void OP_NAME##GenericReduceRank3( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + assert(input_rank == 3); \ + assert(index_tensor_rank <= 1); \ + BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank3"); \ + int32_t out_shape[3] = {input_shape[0], input_shape[1], input_shape[2]}; \ + bool reduce_mask[3] = {false, false, false}; \ + const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ + for (int32_t i = 0; i < num_indices; ++i) { \ + reduce_mask[index_values[i]] = true; \ + out_shape[index_values[i]] = 1; \ + } \ + const int32_t out_strides[3] = { \ + reduce_mask[0] ? 0 : out_shape[1] * out_shape[2], \ + reduce_mask[1] ? 0 : out_shape[2], \ + reduce_mask[2] ? 0 : 1, \ + }; \ + const int32_t output_size = ShapeSize(input_rank, base::span(out_shape)); \ + std::ranges::fill(output_values, DEFAULT_VALUE); \ + auto input_iter = input_values.begin(); \ + for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ + for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ + for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2, ++input_iter) { \ + T* out_ptr = \ + &output_values[out_strides[0] * dim0 + out_strides[1] * dim1 + \ + out_strides[2] * dim2]; \ + const T prev = *out_ptr; \ + const T next = *input_iter; \ + *out_ptr = UPDATE_EXPR; \ + } \ + } \ + } \ + const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ + (reduce_mask[1] ? input_shape[1] : 1) * \ + (reduce_mask[2] ? input_shape[2] : 1); \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + for (int32_t i = 0; i < output_size; ++i) { \ + const T value = output_values[i]; \ + output_values[i] = RESULT_EXPR; \ + } \ + } \ + template <typename T, typename Tidx> \ + void OP_NAME##GenericReduceRank4( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + assert(input_rank == 4); \ + assert(index_tensor_rank <= 1); \ + BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank4"); \ + int32_t out_shape[4] = {input_shape[0], input_shape[1], input_shape[2], \ + input_shape[3]}; \ + bool reduce_mask[4] = {false, false, false, false}; \ + const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ + for (int32_t i = 0; i < num_indices; ++i) { \ + reduce_mask[index_values[i]] = true; \ + out_shape[index_values[i]] = 1; \ + } \ + const int32_t out_strides[4] = { \ + reduce_mask[0] ? 0 : out_shape[1] * out_shape[2] * out_shape[3], \ + reduce_mask[1] ? 0 : out_shape[2] * out_shape[3], \ + reduce_mask[2] ? 0 : out_shape[3], \ + reduce_mask[3] ? 0 : 1, \ + }; \ + const int32_t output_size = ShapeSize(input_rank, base::span(out_shape)); \ + std::ranges::fill(output_values, DEFAULT_VALUE); \ + auto input_iter = input_values.begin(); \ + for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ + for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ + for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \ + for (int32_t dim3 = 0; dim3 < input_shape[3]; \ + ++dim3, ++input_iter) { \ + T* out_ptr = \ + &output_values[out_strides[0] * dim0 + out_strides[1] * dim1 + \ + out_strides[2] * dim2 + out_strides[3] * dim3]; \ + const T prev = *out_ptr; \ + const T next = *input_iter; \ + *out_ptr = UPDATE_EXPR; \ + } \ + } \ + } \ + } \ + const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ + (reduce_mask[1] ? input_shape[1] : 1) * \ + (reduce_mask[2] ? input_shape[2] : 1) * \ + (reduce_mask[3] ? input_shape[3] : 1); \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + for (int32_t i = 0; i < output_size; ++i) { \ + const T value = output_values[i]; \ + output_values[i] = RESULT_EXPR; \ + } \ + } \ + template <typename T, typename Tidx> \ + void OP_NAME##GenericReduceRank5( \ + int32_t input_rank, base::span<const int32_t> input_shape, \ + base::span<const T> input_values, int32_t index_tensor_rank, \ + base::span<const int32_t> index_shape, \ + base::span<const Tidx> index_values, base::span<T> output_values) { \ + assert(input_rank == 5); \ + assert(index_tensor_rank <= 1); \ + BENCHMARK_TIMER(#OP_NAME, "GenericReduceRank5"); \ + int32_t out_shape[5] = {input_shape[0], input_shape[1], input_shape[2], \ + input_shape[3], input_shape[4]}; \ + /* If true, reduce the input across that dimension. */ \ + bool reduce_mask[5] = {false, false, false, false, false}; \ + const int32_t num_indices = index_tensor_rank > 0 ? index_shape[0] : 1; \ + for (int32_t i = 0; i < num_indices; ++i) { \ + reduce_mask[index_values[i]] = true; \ + out_shape[index_values[i]] = 1; \ + } \ + const int32_t out_strides[5] = { \ + reduce_mask[0] \ + ? 0 \ + : out_shape[1] * out_shape[2] * out_shape[3] * out_shape[4], \ + reduce_mask[1] ? 0 : out_shape[2] * out_shape[3] * out_shape[4], \ + reduce_mask[2] ? 0 : out_shape[3] * out_shape[4], \ + reduce_mask[3] ? 0 : out_shape[4], \ + reduce_mask[4] ? 0 : 1, \ + }; \ + const int32_t output_size = ShapeSize(input_rank, base::span(out_shape)); \ + std::ranges::fill(output_values, DEFAULT_VALUE); \ + auto input_iter = input_values.begin(); \ + for (int32_t dim0 = 0; dim0 < input_shape[0]; ++dim0) { \ + for (int32_t dim1 = 0; dim1 < input_shape[1]; ++dim1) { \ + for (int32_t dim2 = 0; dim2 < input_shape[2]; ++dim2) { \ + for (int32_t dim3 = 0; dim3 < input_shape[3]; ++dim3) { \ + for (int32_t dim4 = 0; dim4 < input_shape[4]; \ + ++dim4, ++input_iter) { \ + T* out_ptr = &output_values[out_strides[0] * dim0 + \ + out_strides[1] * dim1 + \ + out_strides[2] * dim2 + \ + out_strides[3] * dim3 + \ + out_strides[4] * dim4]; \ + const T prev = *out_ptr; \ + const T next = *input_iter; \ + *out_ptr = UPDATE_EXPR; \ + } \ + } \ + } \ + } \ + } \ + const T count = (reduce_mask[0] ? input_shape[0] : 1) * \ + (reduce_mask[1] ? input_shape[1] : 1) * \ + (reduce_mask[2] ? input_shape[2] : 1) * \ + (reduce_mask[3] ? input_shape[3] : 1) * \ + (reduce_mask[4] ? input_shape[4] : 1); \ + /* Used by mean reduce. */ \ + (void)sizeof(count); \ + for (int32_t i = 0; i < output_size; ++i) { \ + const T value = output_values[i]; \ + output_values[i] = RESULT_EXPR; \ + } \ } REDUCE_OP(Max, std::numeric_limits<T>::lowest(), std::max(prev, next), value) @@ -1601,11 +1630,11 @@ template <typename T> void DequantizeMinCombined(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const float* __restrict min_range, - const float* __restrict max_range, - float* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const float> min_range, + base::span<const float> max_range, + base::span<float> output_values) { BENCHMARK_TIMER("DequantizeMinCombined"); const int32_t size = ShapeSize(rank, input_shape); const float offset = @@ -1626,11 +1655,11 @@ template <typename T> void DequantizeMinFirst(const int32_t rank, - const int32_t* __restrict input_shape, - const T* __restrict input_values, - const float* __restrict min_range, - const float* __restrict max_range, - float* __restrict output_values) { + base::span<const int32_t> input_shape, + base::span<const T> input_values, + base::span<const float> min_range, + base::span<const float> max_range, + base::span<float> output_values) { BENCHMARK_TIMER("DequantizeMinFirst"); const int32_t size = ShapeSize(rank, input_shape); const float range_scale = (max_range[0] - min_range[0]) / @@ -1654,21 +1683,21 @@ template <typename T> void AddN(const int32_t rank, - const int32_t* __restrict shape, - std::initializer_list<const T* __restrict> input_values, - T* __restrict output_values) { + base::span<const int32_t> shape, + std::initializer_list<base::span<const T>> input_values, + base::span<T> output_values) { BENCHMARK_TIMER("AddN"); const int32_t size = ShapeSize(rank, shape); #if USE_EIGEN - auto output = RowVectorMap<T>(output_values, size).array(); - std::fill_n(output_values, size, 0); - for (const auto input_value : input_values) { - output += ConstRowVectorMap<T>(input_value, size).array(); + auto output = RowVectorMap<T>(output_values.data(), size).array(); + std::ranges::fill(output_values, 0); + for (const auto& input_value : input_values) { + output += ConstRowVectorMap<T>(input_value.data(), size).array(); } #else for (int32_t i = 0; i < size; ++i) { T output_value = 0; - for (auto input_value : input_values) { + for (const auto& input_value : input_values) { output_value += input_value[i]; } output_values[i] = output_value; @@ -3902,10 +3931,11 @@ int32_t logits_MatMul_merged_with_dnn_logits_BiasAdd0Shape[2] = {1, 1}; void Inference( - const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,325 */ + base::span<const float> + input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,325 */ , - float* __restrict logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: - 1,1 */ + base::span<float> + logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: 1,1 */ , FixedAllocations* __restrict fixed) { const int32_t input_from_feature_columns_input_layer_concat_concat0_shape[] =
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h index d891976..a305ab6 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_inference_beta.h
@@ -6,6 +6,8 @@ #define UI_EVENTS_OZONE_EVDEV_TOUCH_FILTER_PALM_MODEL_ONEDEVICE_TRAIN_PALM_DETECTION_FILTER_INFERENCE_BETA_H_ #include <cstdint> +#include "base/containers/span.h" + namespace ui::internal_onedevice::beta_model { struct alignas(16) FixedAllocations { float alloc0[20]; @@ -29,9 +31,10 @@ 1 void Inference( - const float* __restrict input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,325 */ + base::span<const float> + input_from_feature_columns_input_layer_concat_concat0 /* shape: 1,325 */ , - float* __restrict logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: + base::span<float> logits_MatMul_merged_with_dnn_logits_BiasAdd0 /* shape: 1,1 */ , FixedAllocations* __restrict fixed);
diff --git a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc index bc17f87..c72ca5f9 100644 --- a/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc +++ b/ui/events/ozone/evdev/touch_filter/palm_model/onedevice_train_palm_detection_filter_model.cc
@@ -50,11 +50,13 @@ if (config_.model_version == kBetaVersion) { std::unique_ptr<beta::FixedAllocations> fixed_allocations( new beta::FixedAllocations()); - beta::Inference(&features[0], &output, fixed_allocations.get()); + beta::Inference(features, base::span_from_ref(output), + fixed_allocations.get()); } else { std::unique_ptr<alpha::FixedAllocations> fixed_allocations( new alpha::FixedAllocations()); - alpha::Inference(&features[0], &output, fixed_allocations.get()); + alpha::Inference(features, base::span_from_ref(output), + fixed_allocations.get()); } return output; }
diff --git a/ui/events/test/event_generator.cc b/ui/events/test/event_generator.cc index 64744b3..e9f18d1 100644 --- a/ui/events/test/event_generator.cc +++ b/ui/events/test/event_generator.cc
@@ -18,6 +18,7 @@ #include "base/check.h" #include "base/containers/adapters.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/task/single_thread_task_runner.h" @@ -507,20 +508,25 @@ } void EventGenerator::GestureMultiFingerScrollWithDelays( - int count, - const gfx::Point start[], - const gfx::Vector2d delta[], - const int delay_adding_finger_ms[], - const int delay_releasing_finger_ms[], + int spanification_suspected_redundant_count, + base::span<const gfx::Point> start, + base::span<const gfx::Vector2d> delta, + base::span<const int> delay_adding_finger_ms, + base::span<const int> delay_releasing_finger_ms, int event_separation_time_ms, int steps) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK( + spanification_suspected_redundant_count == static_cast<int>(start.size()), + base::NotFatalUntil::M143); const int kMaxTouchPoints = 10; - CHECK_LE(count, kMaxTouchPoints); + CHECK_LE(spanification_suspected_redundant_count, kMaxTouchPoints); CHECK_GT(steps, 0); std::array<gfx::Point, kMaxTouchPoints> points; std::array<gfx::Vector2d, kMaxTouchPoints> delta_per_step; - for (int i = 0; i < count; ++i) { + for (int i = 0; i < spanification_suspected_redundant_count; ++i) { points[i] = start[i]; delta_per_step[i].set_x(delta[i].x() / steps); delta_per_step[i].set_y(delta[i].y() / steps); @@ -530,7 +536,7 @@ std::array<base::TimeTicks, kMaxTouchPoints> press_time; std::array<base::TimeTicks, kMaxTouchPoints> release_time; std::array<bool, kMaxTouchPoints> pressed; - for (int i = 0; i < count; ++i) { + for (int i = 0; i < spanification_suspected_redundant_count; ++i) { pressed[i] = false; press_time[i] = press_time_first + base::Milliseconds(delay_adding_finger_ms[i]); @@ -543,7 +549,7 @@ base::TimeTicks move_time = press_time_first + base::Milliseconds(event_separation_time_ms * step); - for (int i = 0; i < count; ++i) { + for (int i = 0; i < spanification_suspected_redundant_count; ++i) { if (!pressed[i] && move_time >= press_time[i]) { ui::TouchEvent press( ui::EventType::kTouchPressed, points[i], press_time[i], @@ -555,7 +561,9 @@ // All touch release events should occur at the end if // |event_separation_time_ms| is 0. - for (int i = 0; i < count && event_separation_time_ms > 0; ++i) { + for (int i = 0; i < spanification_suspected_redundant_count && + event_separation_time_ms > 0; + ++i) { if (pressed[i] && move_time >= release_time[i]) { ui::TouchEvent release( ui::EventType::kTouchReleased, points[i], release_time[i], @@ -565,7 +573,7 @@ } } - for (int i = 0; i < count; ++i) { + for (int i = 0; i < spanification_suspected_redundant_count; ++i) { points[i] += delta_per_step[i]; if (pressed[i]) { ui::TouchEvent move( @@ -579,7 +587,7 @@ base::TimeTicks default_release_time = press_time_first + base::Milliseconds(event_separation_time_ms * steps); // Ensures that all pressed fingers are released in the end. - for (int i = 0; i < count; ++i) { + for (int i = 0; i < spanification_suspected_redundant_count; ++i) { if (pressed[i]) { ui::TouchEvent release( ui::EventType::kTouchReleased, points[i], default_release_time, @@ -591,36 +599,49 @@ } void EventGenerator::GestureMultiFingerScrollWithDelays( - int count, - const gfx::Point start[], - const int delay_adding_finger_ms[], + int spanification_suspected_redundant_count, + base::span<const gfx::Point> start, + base::span<const int> delay_adding_finger_ms, int event_separation_time_ms, int steps, int move_x, int move_y) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK( + spanification_suspected_redundant_count == static_cast<int>(start.size()), + base::NotFatalUntil::M143); const int kMaxTouchPoints = 10; - int delay_releasing_finger_ms[kMaxTouchPoints]; - gfx::Vector2d delta[kMaxTouchPoints]; + std::array<int, kMaxTouchPoints> delay_releasing_finger_ms; + std::array<gfx::Vector2d, kMaxTouchPoints> delta; for (int i = 0; i < kMaxTouchPoints; ++i) { delay_releasing_finger_ms[i] = event_separation_time_ms * steps; delta[i].set_x(move_x); delta[i].set_y(move_y); } - GestureMultiFingerScrollWithDelays( - count, start, delta, delay_adding_finger_ms, delay_releasing_finger_ms, - event_separation_time_ms, steps); + GestureMultiFingerScrollWithDelays(spanification_suspected_redundant_count, + start, delta, delay_adding_finger_ms, + delay_releasing_finger_ms, + event_separation_time_ms, steps); } -void EventGenerator::GestureMultiFingerScroll(int count, - const gfx::Point start[], - int event_separation_time_ms, - int steps, - int move_x, - int move_y) { +void EventGenerator::GestureMultiFingerScroll( + int spanification_suspected_redundant_count, + base::span<const gfx::Point> start, + int event_separation_time_ms, + int steps, + int move_x, + int move_y) { + // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be + // redundant in M143. + CHECK( + spanification_suspected_redundant_count == static_cast<int>(start.size()), + base::NotFatalUntil::M143); const int kMaxTouchPoints = 10; int delays[kMaxTouchPoints] = {}; - GestureMultiFingerScrollWithDelays( - count, start, delays, event_separation_time_ms, steps, move_x, move_y); + GestureMultiFingerScrollWithDelays(spanification_suspected_redundant_count, + start, delays, event_separation_time_ms, + steps, move_x, move_y); } void EventGenerator::ScrollSequence(const gfx::Point& start,
diff --git a/ui/events/test/event_generator.h b/ui/events/test/event_generator.h index 00ddab5..a8491d6 100644 --- a/ui/events/test/event_generator.h +++ b/ui/events/test/event_generator.h
@@ -9,6 +9,7 @@ #include <optional> #include <vector> +#include "base/containers/span.h" #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/time/time.h" @@ -423,33 +424,35 @@ // fingers and add fingers with a delay. |steps| and // |event_separation_time_ms| are relevant when testing velocity/fling/swipe, // otherwise these can be any non-zero value. - void GestureMultiFingerScrollWithDelays(int count, - const gfx::Point start[], - const gfx::Vector2d delta[], - const int delay_adding_finger_ms[], - const int delay_releasing_finger_ms[], - int event_separation_time_ms, - int steps); + void GestureMultiFingerScrollWithDelays( + int spanification_suspected_redundant_count, + base::span<const gfx::Point> start, + base::span<const gfx::Vector2d> delta, + base::span<const int> delay_adding_finger_ms, + base::span<const int> delay_releasing_finger_ms, + int event_separation_time_ms, + int steps); // Similar to GestureMultiFingerScrollWithDelays() above. Generates press, // move, release touch-events to generate a sequence of multi-finger scroll // events. All fingers are released at the end of scrolling together. All // fingers move the same amount specified by |move_x| and |move_y|. - void GestureMultiFingerScrollWithDelays(int count, - const gfx::Point start[], - const int delay_adding_finger_ms[], - int event_separation_time_ms, - int steps, - int move_x, - int move_y); + void GestureMultiFingerScrollWithDelays( + int spanification_suspected_redundant_count, + base::span<const gfx::Point> start, + base::span<const int> delay_adding_finger_ms, + int event_separation_time_ms, + int steps, + int move_x, + int move_y); // Similar to GestureMultiFingerScrollWithDelays(). Generates press, move, // release touch-events to generate a sequence of multi-finger scroll events. // All fingers are pressed at the beginning together and are released at the // end of scrolling together. All fingers move move the same amount specified // by |move_x| and |move_y|. - void GestureMultiFingerScroll(int count, - const gfx::Point start[], + void GestureMultiFingerScroll(int spanification_suspected_redundant_count, + base::span<const gfx::Point> start, int event_separation_time_ms, int steps, int move_x,
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc index 127ad25d..da863c4 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc
@@ -7074,15 +7074,22 @@ TEST_F(RenderTextTest, HarfBuzz_SplitRunsWithMissingGlyphSmallCaps) { RenderTextHarfBuzz* render_text = GetRenderText(); + + // "ꟺ" and "M" are in the same script, but all OS's split them between + // different fonts. This test ensures that each glyph is not in its own + // run, but rather that the final rendered runs place adjacent runs with the + // same final fallback font in the same run. render_text->SetText(u"ꟺM"); -#if BUILDFLAG(IS_ANDROID) - // Android doesn't support either glyph, so they are both missing glyphs in - // the same run. - EXPECT_EQ(std::vector<std::u16string>({u"ꟺM"}), GetRunListStrings()); - EXPECT_EQ("[0->1]", GetRunListStructureString()); -#else + // Must snapshot histograms before checking for missing glyphs. base::HistogramTester histograms; + + // This test requires both glyphs to render for merging to occur. If there + // are still missing glyphs (this happens on some versions of Android), + // return early. + if (GetHarfBuzzRunList()->HasMissingGlyphs()) { + return; + } EXPECT_EQ(std::vector<std::u16string>({u"ꟺ", u"M"}), GetRunListStrings()); EXPECT_EQ("[0][1]", GetRunListStructureString()); @@ -7090,7 +7097,6 @@ histograms.ExpectTotalCount("RenderTextHarfBuzz.ShapeRunsFallback", 1); EXPECT_EQ(histograms.GetTotalSum("RenderTextHarfBuzz.ShapeRunsFallback"), 2); -#endif // BUILDFLAG(IS_ANDROID) CheckBoundsForCursorPositions(); }
diff --git a/ui/gl/dc_layer_tree.cc b/ui/gl/dc_layer_tree.cc index 0936692..60881d0 100644 --- a/ui/gl/dc_layer_tree.cc +++ b/ui/gl/dc_layer_tree.cc
@@ -1295,53 +1295,37 @@ this, d3d11_device_, dcomp_device_); } } - gfx::Transform transform; - gfx::Rect clip_rect; - if (!video_swap_chain->PresentToSwapChain(overlay, &transform, - &clip_rect)) { + + std::optional<SwapChainPresenter::OverlayPositionAdjustment> + overlay_position_adjustment; + if (std::optional<DCLayerOverlayImage> video_image = + video_swap_chain->PresentToSwapChain( + overlay, overlay_position_adjustment)) { + overlay.overlay_image = std::move(video_image); + overlay.content_rect = gfx::RectF(overlay.overlay_image->size()); + + if (overlay_position_adjustment) { + overlay.transform = overlay_position_adjustment->transform; + overlay.quad_rect = overlay_position_adjustment->quad_rect; + if (overlay.clip_rect) { + overlay.clip_rect = overlay_position_adjustment->clip_rect; + } + } + + if (overlay.video_params.is_full_screen_video && + !overlay_position_adjustment && + base::FeatureList::IsEnabled( + features::kEarlyFullScreenVideoOptimization)) { + // If we failed to disable the desktop plane, we need to manually add + // a solid color layer to act as the video background mat. + need_background_layer = true; + } + } else { DLOG(ERROR) << "PresentToSwapChain failed"; return base::unexpected( CommitError{CommitError::Reason::kPresentToSwapChain}); } - gfx::Size content_size = video_swap_chain->content_size(); - - if (base::FeatureList::IsEnabled( - features::kEarlyFullScreenVideoOptimization)) { - if (overlay.video_params.is_full_screen_video) { - const gfx::Size monitor_size = GetMonitorSizeForWindow(window()); - if (video_swap_chain->TryDisablePrimaryPlane(monitor_size, overlay)) { - // If we successfully disable the primary plane, it means DWM's - // internal swap chain is now the size of the monitor. In this case - // we want to just treat it as an unscaled image that completely - // fills the screen. - overlay.transform = gfx::Transform(); - overlay.quad_rect = gfx::Rect(monitor_size); - if (overlay.clip_rect.has_value()) { - overlay.clip_rect = gfx::Rect(monitor_size); - } - content_size = monitor_size; - } else { - need_background_layer = true; - } - } - } else { - CHECK(!overlay.video_params.is_full_screen_video); - - // |SwapChainPresenter| may have changed the size of the overlay's quad - // rect, e.g. to present to a swap chain exactly the size of the display - // rect when the source video is larger. - overlay.transform = transform; - overlay.quad_rect.set_size(video_swap_chain->content_size()); - if (overlay.clip_rect.has_value()) { - overlay.clip_rect = clip_rect; - } - } - - overlay.overlay_image = DCLayerOverlayImage( - content_size, video_swap_chain->FinishPresentToSwapChain()); - overlay.content_rect = gfx::RectF(content_size); - if (tint_video_layer_) { SkColor4f tint_color; switch (video_swap_chain->GetLastPresentationMode()) { @@ -1408,8 +1392,6 @@ } if (need_background_layer) { - // If we failed to disable the desktop plane, we need to manually - // add a solid color layer to act as the video background mat. DCLayerOverlayParams background_mat; background_mat.quad_rect = gfx::Rect(GetMonitorSizeForWindow(window())); background_mat.z_order = INT_MIN;
diff --git a/ui/gl/dcomp_presenter_unittest.cc b/ui/gl/dcomp_presenter_unittest.cc index cb1c18f..0835e7e 100644 --- a/ui/gl/dcomp_presenter_unittest.cc +++ b/ui/gl/dcomp_presenter_unittest.cc
@@ -33,6 +33,7 @@ #include "ui/gfx/frame_data.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/test/geometry_util.h" #include "ui/gfx/geometry/transform.h" #include "ui/gfx/geometry/vector2d_conversions.h" #include "ui/gfx/geometry/vector2d_f.h" @@ -1235,25 +1236,26 @@ DCompPresenterTest::GetValues(), &DCompPresenterTest::GetParamName); -class DCompPresenterPixelTestBase : public DCompPresenterTestBase<> { +template <class Param = std::monostate> +class DCompPresenterPixelTestBase : public DCompPresenterTestBase<Param> { public: DCompPresenterPixelTestBase() : window_(&platform_delegate_, gfx::Rect(100, 100)) { - parent_window_ = window_.hwnd(); + this->parent_window_ = window_.hwnd(); } protected: void SetUp() override { static_cast<ui::PlatformWindow*>(&window_)->Show(); - DCompPresenterTestBase::SetUp(); + DCompPresenterTestBase<Param>::SetUp(); } void TearDown() override { // Test harness times out without DestroyWindow() here. - if (IsWindow(parent_window_)) { - DestroyWindow(parent_window_); + if (IsWindow(this->parent_window_)) { + DestroyWindow(this->parent_window_); } - DCompPresenterTestBase::TearDown(); + DCompPresenterTestBase<Param>::TearDown(); } void InitializeForPixelTest(const gfx::Size& window_size, @@ -1261,9 +1263,10 @@ const gfx::Rect& content_rect, const gfx::Rect& quad_rect, const bool is_p010) { - EXPECT_TRUE(presenter_->Resize(window_size, 1.0, gfx::ColorSpace(), true)); + EXPECT_TRUE( + this->presenter_->Resize(window_size, 1.0, gfx::ColorSpace(), true)); - InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack); + this->InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack); Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = GetDirectCompositionD3D11Device(); @@ -1280,9 +1283,9 @@ params.layer_id = gfx::OverlayLayerId::MakeForTesting(0); params.video_params.color_space = gfx::ColorSpace::CreateREC709(); params.video_params.is_p010_content = is_p010; - ScheduleOverlay(std::move(params)); + this->ScheduleOverlay(std::move(params)); - ASSERT_EQ(PresentAndGetSwapResult(), gfx::SwapResult::SWAP_ACK); + ASSERT_EQ(this->PresentAndGetSwapResult(), gfx::SwapResult::SWAP_ACK); Sleep(1000); } @@ -1292,9 +1295,10 @@ void RunNearestNeighborTest(bool scale_via_buffer) { const gfx::Size window_size(100, 100); - EXPECT_TRUE(presenter_->Resize(window_size, 1.0, gfx::ColorSpace(), true)); + EXPECT_TRUE( + this->presenter_->Resize(window_size, 1.0, gfx::ColorSpace(), true)); - InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack); + this->InitializeRootAndScheduleRootSurface(window_size, SkColors::kBlack); auto dc_layer_params = CreateParamsFromImage( CreateDCompSurface(gfx::Size(2, 2), SkColors::kBlack, @@ -1319,8 +1323,8 @@ window_size.height() / dc_layer_params.quad_rect.height()); } - ScheduleOverlay(std::move(dc_layer_params)); - ASSERT_EQ(PresentAndGetSwapResult(), gfx::SwapResult::SWAP_ACK); + this->ScheduleOverlay(std::move(dc_layer_params)); + ASSERT_EQ(this->PresentAndGetSwapResult(), gfx::SwapResult::SWAP_ACK); SkBitmap pixels = GLTestHelper::ReadBackWindow(window_.hwnd(), window_size); @@ -1367,19 +1371,20 @@ DCLayerOverlayParams fit_in_hole_overlay) { EXPECT_TRUE(gfx::Rect(window_size).Contains(root_surface_hole)); - EXPECT_TRUE(presenter_->Resize(window_size, 1.0, gfx::ColorSpace(), true)); + EXPECT_TRUE( + this->presenter_->Resize(window_size, 1.0, gfx::ColorSpace(), true)); auto root_surface = CreateParamsFromImage( CreateDCompSurface(window_size, kRootSurfaceInitialColor, {{root_surface_hole, kRootSurfaceHiddenColor}})); root_surface.quad_rect = gfx::Rect(window_size); root_surface.z_order = 0; - root_surface.layer_id = GetRootSurfaceId(); - ScheduleOverlay(std::move(root_surface)); + root_surface.layer_id = this->GetRootSurfaceId(); + this->ScheduleOverlay(std::move(root_surface)); - ScheduleOverlay(std::move(fit_in_hole_overlay)); + this->ScheduleOverlay(std::move(fit_in_hole_overlay)); - ASSERT_EQ(PresentAndGetSwapResult(), gfx::SwapResult::SWAP_ACK); + ASSERT_EQ(this->PresentAndGetSwapResult(), gfx::SwapResult::SWAP_ACK); auto pixels = GLTestHelper::ReadBackWindow(window_.hwnd(), window_size); @@ -1479,15 +1484,7 @@ ui::WinWindow window_; }; -class DCompPresenterPixelTest : public DCompPresenterPixelTestBase { - protected: - void SetUp() override { - static_cast<ui::PlatformWindow*>(&window_)->Show(); - DCompPresenterPixelTestBase::SetUp(); - } -}; - -class DCompPresenterVideoPixelTest : public DCompPresenterPixelTestBase { +class DCompPresenterVideoPixelTest : public DCompPresenterPixelTestBase<> { protected: void TestVideo(const gfx::ColorSpace& color_space, SkColor expected_color, @@ -1571,6 +1568,8 @@ TestVideo(gfx::ColorSpace(), SkColorSetRGB(0xe1, 0x90, 0xeb), true); } +class DCompPresenterPixelTest : public DCompPresenterPixelTestBase<> {}; + INSTANTIATE_TEST_SUITE_P(, DCompPresenterPixelTest, DCompPresenterPixelTest::GetValues(), @@ -2286,6 +2285,222 @@ } } +struct EarlyFullScreenVideoOptimizationParam { + bool use_early_full_screen_video_optimization = false; +}; + +void PrintTo(const EarlyFullScreenVideoOptimizationParam& param, + std::ostream* os) { + if (param.use_early_full_screen_video_optimization) { + *os << "EarlyFullScreenOptOn"; + } else { + *os << "EarlyFullScreenOptOff"; + } +} + +class DCompPresenterFullScreenOptimizationPixelTest + : public DCompPresenterPixelTestBase< + EarlyFullScreenVideoOptimizationParam> { + public: + void SetUp() override { + static_cast<ui::PlatformWindow*>(&window_)->Show(); + EnableFeature(features::kDirectCompositionLetterboxVideoOptimization); + if (GetTestParam().use_early_full_screen_video_optimization) { + EnableFeature(features::kEarlyFullScreenVideoOptimization); + } else { + DisableFeature(features::kEarlyFullScreenVideoOptimization); + } + DCompPresenterPixelTestBase::SetUp(); + } + + void SetMonitorSize(const gfx::Size& monitor_size) { + SetDirectCompositionScaledOverlaysSupportedForTesting(true); + SetDirectCompositionMonitorInfoForTesting(1, monitor_size); + EXPECT_TRUE( + this->presenter_->Resize(monitor_size, 1.0, gfx::ColorSpace(), true)); + static_cast<ui::PlatformWindow*>(&window_)->SetBoundsInPixels( + gfx::Rect(monitor_size)); + } + + void DoOneFrame(const gfx::Size& monitor_size, + Microsoft::WRL::ComPtr<ID3D11Texture2D> texture, + bool is_full_screen) { + ASSERT_NE(texture, nullptr); + + // Use red for full screen because we expect the root surface to be fully + // occluded by the "full screen"-ed swap chain. We can use the presence of + // red as an indication that the full screening failed. + // + // We don't expect the video to be either of these background colors. + const SkColor4f expected_background_color = SkColors::kBlack; + const SkColor4f unexpected_background_color = SkColors::kRed; + const SkColor4f root_surface_color = is_full_screen + ? unexpected_background_color + : expected_background_color; + InitializeRootAndScheduleRootSurface(monitor_size, root_surface_color); + + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + const gfx::Size texture_size = gfx::Size(desc.Width, desc.Height); + auto params = + CreateParamsFromImage(DCLayerOverlayImage(texture_size, texture)); + params.layer_id = gfx::OverlayLayerId::MakeForTesting(0); + if (is_full_screen) { + const float scale_factor = + std::min(static_cast<float>(monitor_size.width()) / + static_cast<float>(texture_size.width()), + static_cast<float>(monitor_size.height()) / + static_cast<float>(texture_size.height())); + params.quad_rect = + gfx::ScaleToEnclosingRect(gfx::Rect(texture_size), scale_factor); + params.transform = gfx::Transform::MakeTranslation( + (monitor_size.width() - params.quad_rect.width()) / 2.0, + (monitor_size.height() - params.quad_rect.height()) / 2.0); + if (GetTestParam().use_early_full_screen_video_optimization) { + params.video_params.is_full_screen_video = true; + } else { + params.video_params.possible_video_fullscreen_letterboxing = true; + } + } else { + // An arbitrary rect that is not the full screen. + params.quad_rect = gfx::Rect(gfx::ScaleToCeiledSize(monitor_size, 0.5)); + } + const gfx::Rect expected_target_rect = + params.transform.MapRect(params.quad_rect); + params.clip_rect = expected_target_rect; + params.video_params.color_space = gfx::ColorSpace::CreateREC709(); + ScheduleOverlay(std::move(params)); + + ASSERT_EQ(this->PresentAndGetSwapResult(), gfx::SwapResult::SWAP_ACK); + + const SkBitmap actual_pixels = + GLTestHelper::ReadBackWindow(window_.hwnd(), monitor_size); + gfx::Rect actual_video_bounds; + bool already_asserted_wrong_background_color = false; + for (int y = 0; y < actual_pixels.height(); y++) { + for (int x = 0; x < actual_pixels.width(); x++) { + const SkColor4f actual_color = actual_pixels.getColor4f(x, y); + if (actual_color == expected_background_color) { + // If the color matches the background mat color, no action. + } else if (actual_color == unexpected_background_color) { + // If `actual_color` is `root_surface_color`, then we are missing + // the video background mat. + if (!already_asserted_wrong_background_color) { + EXPECT_SKCOLOR_EQ(actual_color.toSkColor(), + expected_background_color.toSkColor()) + << "background mat is the wrong color!"; + // Avoid spamming the log output for every pixel. + already_asserted_wrong_background_color = true; + } + } else { + // Any other color will be conservatively called "part of the video". + actual_video_bounds.Union(gfx::Rect(x, y, 1, 1)); + } + } + } + + // Check that the video appears in the center of the window. If something + // went wrong, the video may be stretched across the whole window or may + // appear un-centered at the top left. + EXPECT_EQ(actual_video_bounds, expected_target_rect); + } +}; + +// Check that the first frame of a full screen optimized swap chain appears in +// the correct place. +TEST_P(DCompPresenterFullScreenOptimizationPixelTest, FirstFrame) { + // Test a fraction of a 1920x1200 monitor to speed up the pixel readback. + const float scale_factor = 0.25; + const gfx::Size monitor_size(1920 * scale_factor, 1200 * scale_factor); + const gfx::Size texture_size(2, 2); + + SetMonitorSize(monitor_size); + + auto texture = + CreateNV12Texture(GetDirectCompositionD3D11Device(), texture_size); + + DoOneFrame(monitor_size, texture, /*is_full_screen=*/true); +} + +// Check that two contiguous frames that share a `SwapChainPresenter` but do not +// update the video texture will maintain the full screen optimization. +TEST_P(DCompPresenterFullScreenOptimizationPixelTest, KeepFullScreenSameImage) { + // Test a fraction of a 1920x1200 monitor to speed up the pixel readback. + const float scale_factor = 0.25; + const gfx::Size monitor_size(1920 * scale_factor, 1200 * scale_factor); + const gfx::Size texture_size(2, 2); + + SetMonitorSize(monitor_size); + + auto texture = + CreateNV12Texture(GetDirectCompositionD3D11Device(), texture_size); + + DoOneFrame(monitor_size, texture, /*is_full_screen=*/true); + DoOneFrame(monitor_size, texture, /*is_full_screen=*/true); +} + +// Check that two contiguous frames that share a `SwapChainPresenter` that +// changes the video texture will maintain the full screen optimization. +TEST_P(DCompPresenterFullScreenOptimizationPixelTest, + KeepFullScreenDifferentImage) { + // Test a fraction of a 1920x1200 monitor to speed up the pixel readback. + const float scale_factor = 0.25; + const gfx::Size monitor_size(1920 * scale_factor, 1200 * scale_factor); + const gfx::Size texture_size(2, 2); + + SetMonitorSize(monitor_size); + + DoOneFrame(monitor_size, + CreateNV12Texture(GetDirectCompositionD3D11Device(), texture_size), + /*is_full_screen=*/true); + + DoOneFrame(monitor_size, + CreateNV12Texture(GetDirectCompositionD3D11Device(), texture_size), + /*is_full_screen=*/true); +} + +// Check entering full screen mode succeeds when we do not change the video +// texture. +TEST_P(DCompPresenterFullScreenOptimizationPixelTest, + EnterFullScreenSameImage) { + // Test a fraction of a 1920x1200 monitor to speed up the pixel readback. + const float scale_factor = 0.25; + const gfx::Size monitor_size(1920 * scale_factor, 1200 * scale_factor); + const gfx::Size texture_size(2, 2); + + SetMonitorSize(monitor_size); + + auto texture = + CreateNV12Texture(GetDirectCompositionD3D11Device(), texture_size); + + DoOneFrame(monitor_size, texture, /*is_full_screen=*/false); + DoOneFrame(monitor_size, texture, /*is_full_screen=*/true); +} + +// Check exiting full screen mode succeeds when we do not change the video +// texture. +TEST_P(DCompPresenterFullScreenOptimizationPixelTest, ExitFullScreenSameImage) { + // Test a fraction of a 1920x1200 monitor to speed up the pixel readback. + const float scale_factor = 0.25; + const gfx::Size monitor_size(1920 * scale_factor, 1200 * scale_factor); + const gfx::Size texture_size(2, 2); + + SetMonitorSize(monitor_size); + + auto texture = + CreateNV12Texture(GetDirectCompositionD3D11Device(), texture_size); + + DoOneFrame(monitor_size, texture, /*is_full_screen=*/true); + DoOneFrame(monitor_size, texture, /*is_full_screen=*/false); +} + +INSTANTIATE_TEST_SUITE_P( + , + DCompPresenterFullScreenOptimizationPixelTest, + DCompPresenterFullScreenOptimizationPixelTest::GetValues( + testing::ConvertGenerator(testing::Bool())), + &DCompPresenterFullScreenOptimizationPixelTest::GetParamName); + class DCompPresenterSkiaGoldTest : public DCompPresenterPixelTest { protected: void SetUp() override {
diff --git a/ui/gl/gl_display.cc b/ui/gl/gl_display.cc index 5ee06d9..da18121 100644 --- a/ui/gl/gl_display.cc +++ b/ui/gl/gl_display.cc
@@ -749,6 +749,8 @@ base::SysInfo::GetAndroidHardwareEGL() != "emulation") { egl_android_native_fence_sync_supported_ = true; } + UMA_HISTOGRAM_BOOLEAN("GPU.Android.HasEGLDupNativeFenceFunction", + !!g_driver_egl.fn.eglDupNativeFenceFDANDROIDFn); if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableAndroidNativeFenceSyncForTesting)) {
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc index 42a064d..312eed5 100644 --- a/ui/gl/gl_switches.cc +++ b/ui/gl/gl_switches.cc
@@ -231,7 +231,7 @@ // Detect and mark a single full screen video during overlay processing. BASE_FEATURE(kEarlyFullScreenVideoOptimization, "EarlyFullScreenVideoOptimization", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Adjust the letterbox video size and position to the center of the screen so // that DWM power optimization can be turned on.
diff --git a/ui/gl/swap_chain_presenter.cc b/ui/gl/swap_chain_presenter.cc index dd295ee..7358319 100644 --- a/ui/gl/swap_chain_presenter.cc +++ b/ui/gl/swap_chain_presenter.cc
@@ -11,6 +11,7 @@ #include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" #include "base/feature_list.h" +#include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -1493,25 +1494,64 @@ return false; } - UINT present_flags = DXGI_PRESENT_USE_DURATION; - hr = decode_swap_chain_->PresentBuffer(array_slice, 1, present_flags); - // Ignore DXGI_STATUS_OCCLUDED since that's not an error but only indicates - // that the window is occluded and we can stop rendering. - if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) { - DLOG(ERROR) << "PresentBuffer failed with error 0x" << std::hex << hr; - return false; - } + pending_swap_buffer_ = array_slice; swap_chain_size_ = swap_chain_size; content_size_ = swap_chain_size; swap_chain_format_ = DXGI_FORMAT_NV12; - RecordPresentationStatistics(); return true; } -bool SwapChainPresenter::PresentToSwapChain(DCLayerOverlayParams& params, - gfx::Transform* visual_transform, - gfx::Rect* visual_clip_rect) { +std::optional<DCLayerOverlayImage> SwapChainPresenter::PresentToSwapChain( + DCLayerOverlayParams& overlay, + std::optional<OverlayPositionAdjustment>& overlay_position_adjustment) { + gfx::Transform transform; + gfx::Rect clip_rect; + if (!SetupPresentToSwapChain(overlay, &transform, &clip_rect)) { + return std::nullopt; + } + + if (base::FeatureList::IsEnabled( + features::kEarlyFullScreenVideoOptimization)) { + if (overlay.video_params.is_full_screen_video) { + const gfx::Size monitor_size = + GetMonitorSizeForWindow(layer_tree_->window()); + if (TryDisablePrimaryPlane(monitor_size, overlay)) { + // If we successfully disable the primary plane, it means DWM's + // internal swap chain is now the size of the monitor. In this case + // we want to just treat it as an unscaled image that completely + // fills the screen. + overlay_position_adjustment = OverlayPositionAdjustment{ + .transform = gfx::Transform(), + .quad_rect = gfx::Rect(monitor_size), + .clip_rect = gfx::Rect(monitor_size), + }; + } + } + } else { + CHECK(!overlay.video_params.is_full_screen_video); + + // |SwapChainPresenter| may have changed the size of the overlay's quad + // rect, e.g. to present to a swap chain exactly the size of the display + // rect when the source video is larger. + overlay_position_adjustment = OverlayPositionAdjustment{ + .transform = transform, + .quad_rect = gfx::Rect(overlay.quad_rect.origin(), content_size_), + .clip_rect = clip_rect, + }; + } + + if (!FinishPresentToSwapChain()) { + return std::nullopt; + } + + return DCLayerOverlayImage(content_size_, content_); +} + +bool SwapChainPresenter::SetupPresentToSwapChain( + DCLayerOverlayParams& params, + gfx::Transform* visual_transform, + gfx::Rect* visual_clip_rect) { DCHECK(params.overlay_image); DCHECK_NE(params.overlay_image->type(), DCLayerOverlayType::kDCompVisualContent); @@ -1738,16 +1778,6 @@ } } - UINT flags = DXGI_PRESENT_USE_DURATION; - UINT interval = 1; - if (DirectCompositionSwapChainTearingEnabled()) { - flags |= DXGI_PRESENT_ALLOW_TEARING; - interval = 0; - } else if (base::FeatureList::IsEnabled( - features::kDXGISwapChainPresentInterval0)) { - interval = 0; - } - // DWM can turn off the desktop plane if this is a YUV swap chain and the // overlay candidate covers the whole screen with letterboxing. bool is_letterboxing_overlay_ready = false; @@ -1780,13 +1810,7 @@ } } - // Ignore DXGI_STATUS_OCCLUDED since that's not an error but only indicates - // that the window is occluded and we can stop rendering. - hr = swap_chain_->Present(interval, flags); - if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) { - DLOG(ERROR) << "Present failed with error 0x" << std::hex << hr; - return false; - } + pending_swap_buffer_ = 0; // Update |visual_transform| and |visual_clip_rect| for the full screen // letterboxing overlay presentation. @@ -1797,7 +1821,6 @@ } last_overlay_image_ = std::move(params.overlay_image); - RecordPresentationStatistics(); return true; } @@ -1815,8 +1838,11 @@ if (Microsoft::WRL::ComPtr<IDXGIDecodeSwapChain> decode_swap_chain; SUCCEEDED( swap_chain_->QueryInterface(IID_PPV_ARGS(&decode_swap_chain)))) { - return TryDisableDesktopPlane(decode_swap_chain.Get(), monitor_size, - gfx::ToRoundedRect(target_rect)); + if (TryDisableDesktopPlane(decode_swap_chain.Get(), monitor_size, + gfx::ToRoundedRect(target_rect))) { + content_size_ = monitor_size; + return true; + } } return false; } @@ -1840,6 +1866,7 @@ if (target_rect.ApproximatelyEqual(ideal_full_screen_rect, tolerance, tolerance)) { pending_dcomp_surface_rect_in_window_ = gfx::Rect(monitor_size); + content_size_ = monitor_size; return true; } @@ -1849,17 +1876,50 @@ return false; } -Microsoft::WRL::ComPtr<IUnknown> -SwapChainPresenter::FinishPresentToSwapChain() { +bool SwapChainPresenter::FinishPresentToSwapChain() { if (IsMediaFoundationSurfaceProxy()) { CHECK(last_overlay_image_->dcomp_surface_proxy()); CHECK(pending_dcomp_surface_rect_in_window_); last_overlay_image_->dcomp_surface_proxy()->SetRect( pending_dcomp_surface_rect_in_window_.value()); pending_dcomp_surface_rect_in_window_.reset(); + } else if (pending_swap_buffer_) { + if (decode_swap_chain_) { + constexpr UINT kPresentFlags = DXGI_PRESENT_USE_DURATION; + HRESULT hr = decode_swap_chain_->PresentBuffer( + pending_swap_buffer_.value(), 1, kPresentFlags); + // Ignore DXGI_STATUS_OCCLUDED since that's not an error but only + // indicates that the window is occluded and we can stop rendering. + if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) { + DLOG(ERROR) << "PresentBuffer failed: " + << logging::SystemErrorCodeToString(hr); + return false; + } + } else { + CHECK_EQ(pending_swap_buffer_.value(), 0u); + UINT flags = DXGI_PRESENT_USE_DURATION; + UINT interval = 1; + if (DirectCompositionSwapChainTearingEnabled()) { + flags |= DXGI_PRESENT_ALLOW_TEARING; + interval = 0; + } else if (base::FeatureList::IsEnabled( + features::kDXGISwapChainPresentInterval0)) { + interval = 0; + } + // Ignore DXGI_STATUS_OCCLUDED since that's not an error but only + // indicates that the window is occluded and we can stop rendering. + HRESULT hr = swap_chain_->Present(interval, flags); + if (FAILED(hr) && hr != DXGI_STATUS_OCCLUDED) { + DLOG(ERROR) << "Present failed: " + << logging::SystemErrorCodeToString(hr); + return false; + } + } + pending_swap_buffer_.reset(); + RecordPresentationStatistics(); } - return content_; + return true; } // static bool SwapChainPresenter::CreateSurfaceHandleHelperForTesting(HANDLE* handle) {
diff --git a/ui/gl/swap_chain_presenter.h b/ui/gl/swap_chain_presenter.h index 4d8596d6..6b3a7172 100644 --- a/ui/gl/swap_chain_presenter.h +++ b/ui/gl/swap_chain_presenter.h
@@ -19,6 +19,7 @@ #include "base/time/time.h" #include "base/win/scoped_handle.h" #include "ui/gfx/color_space.h" +#include "ui/gl/dc_layer_overlay_image.h" #include "ui/gl/dc_layer_overlay_params.h" #include "ui/gl/dc_layer_tree.h" #include "ui/gl/gl_export.h" @@ -42,24 +43,26 @@ ~SwapChainPresenter() override; - // Present the given overlay to swap chain. The backing content may not match - // |overlay.quad_rect| (e.g. in the case of full screen) so this method - // returns a modified |visual_transform| and |visual_clip_rect| that should be - // used instead of the ones on |overlay|. - // Returns true on success. - bool PresentToSwapChain(DCLayerOverlayParams& overlay, - gfx::Transform* visual_transform, - gfx::Rect* visual_clip_rect); + // Indicates the modification overlay position required to display the swap + // chain image. + // + // Note this can be removed once we migrate fully to + // `EarlyFullScreenVideoOptimization` since we will only need adjustment in + // the full screen optimization case and we know the intended on-screen rect + // in this case (i.e. the monitor rect). + struct OverlayPositionAdjustment { + gfx::Transform transform; + gfx::Rect quad_rect; + gfx::Rect clip_rect; + }; - // Attempt to disable the desktop primary plane by expanding the video swap - // chain to fill `monitor_size`, fully occluding any content behind it with - // solid black. - bool TryDisablePrimaryPlane(const gfx::Size& monitor_size, - const DCLayerOverlayParams& overlay); - - // Finalize the presentation and return the DComp visual content representing - // the swap chain. - Microsoft::WRL::ComPtr<IUnknown> FinishPresentToSwapChain(); + // Take and present `overlay.overlay_image` to this swap chain and return a + // new overlay image representing the video. Also returns + // `overlay_position_adjustment` if the overlay position needs to be adjusted, + // e.g. the handle the swap chain being resized in the full screen case. + std::optional<DCLayerOverlayImage> PresentToSwapChain( + DCLayerOverlayParams& overlay, + std::optional<OverlayPositionAdjustment>& overlay_position_adjustment); const Microsoft::WRL::ComPtr<IDXGISwapChain1>& swap_chain() const { return swap_chain_; @@ -121,6 +124,26 @@ int composed_count_ = 0; }; + // Ensure the swap chain is allocated and take `overlay.overlay_image` and + // prepare the swap chain to present it. + // + // The backing content may not match `overlay.quad_rect` (e.g. in the case of + // full screen) so this method returns a modified `visual_transform` and + // `visual_clip_rect` that should be used instead of the ones on `overlay`. + // + // Returns true on success. + bool SetupPresentToSwapChain(DCLayerOverlayParams& overlay, + gfx::Transform* visual_transform, + gfx::Rect* visual_clip_rect); + + // Attempt to disable the desktop primary plane by expanding the video swap + // chain to fill `monitor_size`, fully occluding any content behind it with + // solid black. + bool TryDisablePrimaryPlane(const gfx::Size& monitor_size, + const DCLayerOverlayParams& overlay); + + bool FinishPresentToSwapChain(); + // Upload given YUV buffers to an NV12 texture that can be used to create // video processor input view. Returns nullptr on failure. UNSAFE_BUFFER_USAGE Microsoft::WRL::ComPtr<ID3D11Texture2D> UploadVideoImage( @@ -369,6 +392,8 @@ Microsoft::WRL::ComPtr<IDXGIDecodeSwapChain> decode_swap_chain_; Microsoft::WRL::ComPtr<IUnknown> decode_surface_; + std::optional<uint32_t> pending_swap_buffer_; + bool is_on_battery_power_; bool enable_vp_auto_hdr_ = false;
diff --git a/ui/message_center/views/notification_control_buttons_unittest.cc b/ui/message_center/views/notification_control_buttons_unittest.cc index 5588dcd..970e20b 100644 --- a/ui/message_center/views/notification_control_buttons_unittest.cc +++ b/ui/message_center/views/notification_control_buttons_unittest.cc
@@ -6,6 +6,7 @@ #include "base/memory/raw_ptr.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/color_utils.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_unittest_util.h"
diff --git a/ui/message_center/views/notification_view_base_unittest.cc b/ui/message_center/views/notification_view_base_unittest.cc index d7e1993..ed02988 100644 --- a/ui/message_center/views/notification_view_base_unittest.cc +++ b/ui/message_center/views/notification_view_base_unittest.cc
@@ -13,6 +13,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/color/color_id.h" #include "ui/color/color_provider.h"
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.h b/ui/views/bubble/bubble_dialog_delegate_view.h index e275d978..a6e9774 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view.h +++ b/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -94,7 +94,6 @@ class ArcSplashScreenDialogView; class BaseDialogDelegateView; class ResizeConfirmationDialogView; -class RoundedCornerBubbleDialogDelegateView; namespace input_overlay { class DeleteEditShortcut; @@ -811,7 +810,6 @@ friend class ::arc::ArcSplashScreenDialogView; friend class ::arc::BaseDialogDelegateView; friend class ::arc::ResizeConfirmationDialogView; - friend class ::arc::RoundedCornerBubbleDialogDelegateView; friend class ::arc::input_overlay::DeleteEditShortcut; friend class ::arc::input_overlay::RichNudge; friend class ::ash::AnchoredNudge;
diff --git a/ui/views/controls/button/button.h b/ui/views/controls/button/button.h index 6e95b6d..82b3224 100644 --- a/ui/views/controls/button/button.h +++ b/ui/views/controls/button/button.h
@@ -16,6 +16,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "build/build_config.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "ui/actions/actions.h" #include "ui/base/metadata/metadata_types.h" #include "ui/base/mojom/menu_source_type.mojom-forward.h"
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc index 9286f69..85a94bd 100644 --- a/ui/views/controls/table/table_view_unittest.cc +++ b/ui/views/controls/table/table_view_unittest.cc
@@ -20,6 +20,7 @@ #include "base/test/bind.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h"
diff --git a/ui/views/view.h b/ui/views/view.h index b3fa15b..08ec59e 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -29,11 +29,10 @@ #include "base/types/pass_key.h" #include "build/build_config.h" #include "third_party/skia/include/core/SkPath.h" -#include "ui/accessibility/ax_enums.mojom.h" +#include "ui/accessibility/ax_enums.mojom-forward.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/class_property.h" #include "ui/base/clipboard/clipboard_format_type.h" -#include "ui/base/cursor/cursor.h" #include "ui/base/dragdrop/drop_target_event.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-forward.h" #include "ui/base/dragdrop/os_exchange_data.h" @@ -99,6 +98,7 @@ struct AXNodeData; class ColorProvider; class Compositor; +class Cursor; class InputMethod; class Layer; class LayerTreeOwner;
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc index 7c2fee8..ad09821 100644 --- a/ui/views/widget/widget_unittest.cc +++ b/ui/views/widget/widget_unittest.cc
@@ -24,6 +24,7 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/ax_node_data.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h" #include "ui/base/hit_test.h" #include "ui/base/metadata/metadata_header_macros.h"
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 6c7e129..df17e97 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -40,6 +40,7 @@ #include "services/tracing/public/cpp/perfetto/macros.h" #include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_window_handle_event_info.pbzero.h" #include "third_party/skia/include/core/SkPath.h" +#include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/platform/ax_fragment_root_win.h" #include "ui/accessibility/platform/ax_platform.h" #include "ui/accessibility/platform/ax_platform_node_win.h" @@ -1897,11 +1898,21 @@ map.erase(i); } - // If we have ever returned a UIA object via WM_GETOBJECT, signal that all - // objects associated with this HWND can be discarded. See: - // https://docs.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiareturnrawelementprovider#remarks + if (ax_fragment_root_ && + base::FeatureList::IsEnabled(features::kUiaDisconnectRootProviders)) { + // Note that the fragment root's element provider is being disconnected so + // that re-entrant WM_GETOBJECT messages are not serviced. + disconnecting_fragment_root_ = true; + + // Clean up UIA resources associated with this window's fragment root; see + // https://learn.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiadisconnectprovider. + ::UiaDisconnectProvider(ax_fragment_root_->GetProvider()); + } + if (did_return_uia_object_) { - UiaReturnRawElementProvider(hwnd(), 0, 0, nullptr); + // Disassociate this window from MSAA clients that are observing events; see + // https://docs.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiareturnrawelementprovider#remarks + ::UiaReturnRawElementProvider(hwnd(), 0, 0, nullptr); } } @@ -2075,6 +2086,14 @@ is_uia_request && ::ui::AXPlatform::GetInstance().IsUiaProviderEnabled(); const bool is_msaa_request = static_cast<DWORD>(OBJID_CLIENT) == obj_id; + if (is_uia_active && disconnecting_fragment_root_) { + // An application that calls UiaDisconnectProvider should not respond to a + // re-entrant WM_GETOBJECT message by returning a pointer to the provider + // that it is trying to disconnect. + // https://learn.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiadisconnectprovider + return 0; + } + if (is_uia_request) { ::ui::AXPlatform::GetInstance().OnUiaProviderRequested(is_uia_active); }
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h index fc583188..c8aff1d0 100644 --- a/ui/views/win/hwnd_message_handler.h +++ b/ui/views/win/hwnd_message_handler.h
@@ -803,6 +803,11 @@ // cause re-entrancy during teardown. https://crbug.com/1087553 bool did_return_uia_object_; + // Set to true immediately before disconnecting the fragment root's element + // provider. From that point onward, any request for UiaRootObjectId via + // WM_GET_OBJECT will be ignored. + bool disconnecting_fragment_root_ = false; + // The location where the user clicked on the caption. We cache this when we // receive the WM_NCLBUTTONDOWN message. We use this in the subsequent // WM_NCMOUSEMOVE message to see if the mouse actually moved.
diff --git a/ui/webui/resources/cr_components/composebox/composebox.ts b/ui/webui/resources/cr_components/composebox/composebox.ts index 7c1fbbb..9cb59f3 100644 --- a/ui/webui/resources/cr_components/composebox/composebox.ts +++ b/ui/webui/resources/cr_components/composebox/composebox.ts
@@ -179,6 +179,8 @@ this.errorMessage_ = this.i18n('composeboxFileUploadExpired'); break; + default: + break; } this.showErrorScrim_ = true; } else {
diff --git a/ui/wm/core/shadow_controller.cc b/ui/wm/core/shadow_controller.cc index 815ffd5f..d54544d 100644 --- a/ui/wm/core/shadow_controller.cc +++ b/ui/wm/core/shadow_controller.cc
@@ -100,7 +100,6 @@ const gfx::Rect& new_bounds, ui::PropertyChangeReason reason) override; void OnWindowDestroyed(aura::Window* window) override; - void OnWindowOcclusionChanged(aura::Window* window) override; private: friend class base::RefCounted<Impl>; @@ -266,10 +265,6 @@ bool ShadowController::Impl::ShouldShowShadowForWindow( aura::Window* window) const { - if (window->GetOcclusionState() == aura::Window::OcclusionState::OCCLUDED) { - return false; - } - if (delegate_) { const bool should_show = delegate_->ShouldShowShadowForWindow(window); if (should_show) @@ -287,14 +282,6 @@ return GetShadowElevationConvertDefault(window) > 0; } -void ShadowController::Impl::OnWindowOcclusionChanged(aura::Window* window) { - ui::Shadow* shadow = GetShadowForWindow(window); - if (!shadow) { - return; - } - HandlePossibleShadowVisibilityChange(window); -} - void ShadowController::Impl::MaybeSetShadowRadiusForWindow( aura::Window* window) const { ui::Shadow* shadow = GetShadowForWindow(window); @@ -344,8 +331,6 @@ window->layer()->Add(shadow->layer()); window->layer()->StackAtBottom(shadow->layer()); - window->TrackOcclusionState(); - if (delegate_) { delegate_->ApplyColorThemeToWindowShadow(window); }
diff --git a/v8 b/v8 index 4ec2f43..22b4de0 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 4ec2f43a229069d6124c88527ee7bb9cc642edc3 +Subproject commit 22b4de0c06965bfc5c40c617132760db7bc0bd41