diff --git a/DEPS b/DEPS index 0e2d1e8..12f6c891 100644 --- a/DEPS +++ b/DEPS
@@ -273,7 +273,7 @@ 'screen_ai_windows_386': 'version:138.00', # siso CIPD package version. - 'siso_version': 'git_revision:70e1167e0e6dad10c8388cace8fd9d9376c43316', + 'siso_version': 'git_revision:17b491ae74e86312a96239ff88e852acee83c135', # download libaom test data 'download_libaom_testdata': False, @@ -295,19 +295,19 @@ # 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': '23319755d0789a1e63cc4c1dfb6f38403c9bfa63', + 'src_internal_revision': '20b9f62811d76f8f5de0eba491b161f8bb948c6e', # 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': '32591be9cd3bea8c9e1ad39c64bc8230a4c4d499', + 'skia_revision': 'c8f54c1bc565b8a7eced0a77088b228efdc70c2c', # 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': '8b2e5e57af618aadee7b3b9f967348c87da61591', + 'v8_revision': '3005b00df2a95266a853252e20e78f637adc5c2f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '1c7fa5f847f236cc758f58838a9f5f958c1de0de', + 'angle_revision': '8357b6a24cae20d24058cfef3277066c4993a1ae', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -371,11 +371,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '4a839855c5e79d91689784e2c7284f3f6288123b', + 'catapult_revision': '52ad7cf544050f01f47c070716b9dae8eb9fab2b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. - 'crossbench_revision': '6f0c3181a39f6fdfbaea35689d8126e0361da071', + 'crossbench_revision': '47e5e3d994ddcc2319cec110ce670ccc1baa3223', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -391,7 +391,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': '682af1f84e33247088b8ca38e189f734ff9923ef', + 'devtools_frontend_revision': '28fbee169c8a26c6c2ed2ec2550465fe3d697a34', # 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. @@ -415,7 +415,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '0f24b334d63efffa544d1c2fc6d779576a3aa5e9', + 'dawn_revision': '968646ae6a99b1751d5a7a4298e3bf6976123326', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -519,7 +519,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. - 'llvm_libc_revision': 'c8248a038fe70b7495d1d52fde500cf2dd6fae82', + 'llvm_libc_revision': 'd7bdad4ef86b827a96469b1dfdfcfa1218930e59', # 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. @@ -527,7 +527,7 @@ # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': 'a01c02c9d4acbdae3b7e8a2f3ee58579a9c29f96', + 'libcxx_revision': 'a9cc573e7c591795d11b72d8323ba0e573b55bd6', # GN CIPD package version. 'gn_version': 'git_revision:487f8353f15456474437df32bb186187b0940b45', @@ -837,143 +837,143 @@ 'objects': [ { # The Android libclang_rt.builtins libraries are currently only included in the Linux clang package. - 'object_name': 'Linux_x64/clang-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '557ae6a59be1eb465d0e726766b757132f0ff5f1a13bda0a871887421a59497d', - 'size_bytes': 55589384, - 'generation': 1746143871500001, + 'object_name': 'Linux_x64/clang-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': 'ecd163a9ba1a622fd761ff426c73b6ff95b3697cb18baa9183a4b414072d8633', + 'size_bytes': 55589720, + 'generation': 1746525620539676, 'condition': '(host_os == "linux" or checkout_android) and non_git_source', }, { - 'object_name': 'Linux_x64/clang-tidy-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': 'd940c80b7c1358e99759b90fd3ec3bee4099ee5bdc7858132dfb9474504b5baf', - 'size_bytes': 13553540, - 'generation': 1746143871510594, + 'object_name': 'Linux_x64/clang-tidy-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '2cb4311b17b400ae969d691e90576d1e110d555cb366e0a007b01272f2231e4e', + 'size_bytes': 13570756, + 'generation': 1746525620814582, 'condition': 'host_os == "linux" and checkout_clang_tidy and non_git_source', }, { - 'object_name': 'Linux_x64/clangd-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': 'b138ec884298dd0601232dd98f92d2697e64eefe2ac5b4eee383eefa8909ed15', - 'size_bytes': 13783716, - 'generation': 1746143871533160, + 'object_name': 'Linux_x64/clangd-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '4758d370c079cb70da49ba510e434871c2f4f2cb96ad5e4eeb523d669ccd016b', + 'size_bytes': 13824764, + 'generation': 1746525620948078, 'condition': 'host_os == "linux" and checkout_clangd and non_git_source', }, { - 'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '98c252d7459a0645fb2daacb95b996fab9325072b29f5ef752e5864d7cea44d2', - 'size_bytes': 2292976, - 'generation': 1746143871601054, + 'object_name': 'Linux_x64/llvm-code-coverage-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '97d1fe6e3081f938c0bd691197f1326e804c5859644a3550259fef223c856138', + 'size_bytes': 2295328, + 'generation': 1746525621371092, 'condition': 'host_os == "linux" and checkout_clang_coverage_tools and non_git_source', }, { - 'object_name': 'Linux_x64/llvmobjdump-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '0bf6b769345d7234e16ce57e839732d3be94ab1043a55d0aae2cb3f20399f7bd', - 'size_bytes': 5697144, - 'generation': 1746143871548416, + 'object_name': 'Linux_x64/llvmobjdump-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': 'df8518b635e60716b430321800cbbb083dde39a3fa856b0a865aefd7dd915a81', + 'size_bytes': 5699744, + 'generation': 1746525621090221, 'condition': '((checkout_linux or checkout_mac or checkout_android) and host_os == "linux") and non_git_source', }, { - 'object_name': 'Mac/clang-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '29482bbf5baff85fe278d12a7456d517e10497a888f3082b49043a1f73c0def4', - 'size_bytes': 52061888, - 'generation': 1746143873509655, + 'object_name': 'Mac/clang-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '220dfa6acb4468dfa83f353215ff741ca2b30738f028dc2f8a7b3b9c5f45bb14', + 'size_bytes': 52096988, + 'generation': 1746525623855538, 'condition': 'host_os == "mac" and host_cpu == "x64"', }, { - 'object_name': 'Mac/clang-mac-runtime-library-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '167dcfa307f1a6e0d5ac26701be84b6a0acc2dc9ebf48d2601c37f89579fac90', - 'size_bytes': 992296, - 'generation': 1746143880809968, + 'object_name': 'Mac/clang-mac-runtime-library-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '41f00c834c5f4f81dfa07477d79a64fff17531759d6df7256a72111590645ae8', + 'size_bytes': 993908, + 'generation': 1746525645453067, 'condition': 'checkout_mac and not host_os == "mac"', }, { - 'object_name': 'Mac/clang-tidy-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '2503c1f5c1d304aaf30da2ccc6ffb0834a409429d5754780f1b80afbffc9bd5d', - 'size_bytes': 13636716, - 'generation': 1746143873535744, + 'object_name': 'Mac/clang-tidy-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '4160f7a53e99c7c6fe4e589d20874b12a068625d92209bafdf3ccb1edeec37cf', + 'size_bytes': 13670156, + 'generation': 1746525624439549, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_tidy', }, { - 'object_name': 'Mac/clangd-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '04a7e47676d58e10fc5ca28f87035a452c5b6d959c5f965a2d7efae7d72d2424', - 'size_bytes': 15070916, - 'generation': 1746143873533731, + 'object_name': 'Mac/clangd-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '04a3d9cb8e8742c5807d302b6f46e1dcfcdd36ad55ae8f9894c558f28db93f08', + 'size_bytes': 15092288, + 'generation': 1746525624237513, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clangd', }, { - 'object_name': 'Mac/llvm-code-coverage-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '97680b6f03a575050b941ead3ee816bf697b159c0b3304d29af7d0fee6cbfdd3', - 'size_bytes': 2266332, - 'generation': 1746143873609231, + 'object_name': 'Mac/llvm-code-coverage-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': 'effe34835ea45e43b21d9aab0790f21b0291966614ddda23ab37eeea26a188ff', + 'size_bytes': 2270324, + 'generation': 1746525624667951, 'condition': 'host_os == "mac" and host_cpu == "x64" and checkout_clang_coverage_tools', }, { - 'object_name': 'Mac_arm64/clang-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '8ab032725c51a542f7e54b8795952039b0b910f3f5315bca13ae669febaa425f', - 'size_bytes': 44082720, - 'generation': 1746143882532819, + 'object_name': 'Mac_arm64/clang-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': 'f0c7db116dd1dc93f8935baf3ee130f4f2eb72c4953d0e132dea473a030194ba', + 'size_bytes': 44103784, + 'generation': 1746525647078692, 'condition': 'host_os == "mac" and host_cpu == "arm64"', }, { - 'object_name': 'Mac_arm64/clang-tidy-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '35679319e006d4fdc27aa5e62e1637db33026ef06c2cfa36abe14aa4113f34ab', - 'size_bytes': 11794244, - 'generation': 1746143882559932, + 'object_name': 'Mac_arm64/clang-tidy-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '32e49f6d1339be7c0387e404930aafb25c460b9396f1f5801a6fdd107fcbacb0', + 'size_bytes': 11823236, + 'generation': 1746525647324075, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_tidy', }, { - 'object_name': 'Mac_arm64/clangd-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '6ecfc7eee127d298d55757d405bc29d3197d60b8316d51355eca218442c55b90', - 'size_bytes': 12067876, - 'generation': 1746143882556967, + 'object_name': 'Mac_arm64/clangd-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '7f77dbff038c35c2a688b4c8d05fa2b22cecc7d175659dbe88c88f952fa63fbd', + 'size_bytes': 12089948, + 'generation': 1746525647467078, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clangd', }, { - 'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '09f89d979a09cad96b4d81090bec5cc3e7c12c7b5431ab21842d47b67b93122a', - 'size_bytes': 1975672, - 'generation': 1746143882686932, + 'object_name': 'Mac_arm64/llvm-code-coverage-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '71c858f90180069f7ef0b16f8e7869ed319bae00c984179cbdd25956fa6c73ff', + 'size_bytes': 1979552, + 'generation': 1746525647890816, 'condition': 'host_os == "mac" and host_cpu == "arm64" and checkout_clang_coverage_tools', }, { - 'object_name': 'Win/clang-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': 'e9b3c67428ee5fff61ab2e229da2ecd807cceb5e48983baa2aa31ae675059931', - 'size_bytes': 47070352, - 'generation': 1746143892525539, + 'object_name': 'Win/clang-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': 'd04ead6c2da3e38558d6bb19e06b05aa6dfa6b4b82b678c25295c803bb378c86', + 'size_bytes': 47099456, + 'generation': 1746525671111178, 'condition': 'host_os == "win"', }, { - 'object_name': 'Win/clang-tidy-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': 'b7ff1c51e8f91ffe5bab9db99529f802114ce62ec588d0953d3a548424520836', - 'size_bytes': 13437572, - 'generation': 1746143892543580, + 'object_name': 'Win/clang-tidy-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '3b026fb8d3363b04a7434d0df710c2ebf8074e9aca7a236447cc0efb0718ec82', + 'size_bytes': 13470524, + 'generation': 1746525671342028, 'condition': 'host_os == "win" and checkout_clang_tidy', }, { - 'object_name': 'Win/clang-win-runtime-library-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '1ed7bf852f8255bf35335c14110c959743e17903e0020c776be3b8d80a564ae9', - 'size_bytes': 2484344, - 'generation': 1746143899795872, + 'object_name': 'Win/clang-win-runtime-library-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': 'b6a49e302e5c9d562e575e1c1431777d90d4950dc7e6bba9b1c21d0ceba93c29', + 'size_bytes': 2484356, + 'generation': 1746525692368377, 'condition': 'checkout_win and not host_os == "win"', }, { - 'object_name': 'Win/clangd-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '90f9035116a665e8a620b259d299c845be42b68c7dce8a6439ba189d550bd6ca', - 'size_bytes': 13855648, - 'generation': 1746143892528921, + 'object_name': 'Win/clangd-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': '51953564440fd82547a27b1fe0cd76d9a0c200162ee7530fe14d805511613be7', + 'size_bytes': 13886984, + 'generation': 1746525671497511, 'condition': 'host_os == "win" and checkout_clangd', }, { - 'object_name': 'Win/llvm-code-coverage-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '100dc0773b81d1a65b40356038d2c85e5aabd613b2e5830846d60c9fa2ca04bf', - 'size_bytes': 2374764, - 'generation': 1746143892621367, + 'object_name': 'Win/llvm-code-coverage-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': 'e5e5a685fde6a4ddd211913ccf6f8e62ac7e6567fec26d68d5bff3aeac42c330', + 'size_bytes': 2376076, + 'generation': 1746525671928280, 'condition': 'host_os == "win" and checkout_clang_coverage_tools', }, { - 'object_name': 'Win/llvmobjdump-llvmorg-21-init-10502-gb2e2ae87-1.tar.xz', - 'sha256sum': '104ef589d1d1d9a7f1acd38e25c418b12de8b685c4f55f45f626cc64f3f1cc98', - 'size_bytes': 5685804, - 'generation': 1746143892549487, + 'object_name': 'Win/llvmobjdump-llvmorg-21-init-10851-gcd6c4b61-1.tar.xz', + 'sha256sum': 'd02d624d3ecfe5dbaa2e93b2da5a6443e4f25b9fe2fab43b8b540fccc91e4770', + 'size_bytes': 5687508, + 'generation': 1746525671637063, 'condition': '(checkout_linux or checkout_mac or checkout_android) and host_os == "win"', }, ] @@ -984,31 +984,31 @@ 'bucket': 'chromium-browser-clang', 'objects': [ { - 'object_name': 'Linux_x64/rust-toolchain-3350c1eb3fd8fe1bee1ed4c76944d707bd256876-1-llvmorg-21-init-10502-gb2e2ae87.tar.xz', - 'sha256sum': 'b7b13f2fbd22c5415abec739570acd74066361ce3c82313660be65ab67f1a075', - 'size_bytes': 118912744, - 'generation': 1746143864066683, + 'object_name': 'Linux_x64/rust-toolchain-4a0969e06dbeaaa43914d2d00b2e843d49aa3886-1-llvmorg-21-init-10851-gcd6c4b61.tar.xz', + 'sha256sum': '2d8498b5dcab2954c8212564798252c3edc9c0181ea8b05d3d6ae42b7b6adf7d', + 'size_bytes': 118439104, + 'generation': 1746525613682798, 'condition': 'host_os == "linux" and non_git_source', }, { - 'object_name': 'Mac/rust-toolchain-3350c1eb3fd8fe1bee1ed4c76944d707bd256876-1-llvmorg-21-init-10502-gb2e2ae87.tar.xz', - 'sha256sum': '322dc36f74871d746545a1bb75470968315bce5ed4b385f43033e376f4c12a9b', - 'size_bytes': 112193460, - 'generation': 1746143865768180, + 'object_name': 'Mac/rust-toolchain-4a0969e06dbeaaa43914d2d00b2e843d49aa3886-1-llvmorg-21-init-10851-gcd6c4b61.tar.xz', + 'sha256sum': '93e57858344a978ce2df2d9926c541d8e25cd9def0054328dba4ac13ff633d34', + 'size_bytes': 111691112, + 'generation': 1746525615270255, 'condition': 'host_os == "mac" and host_cpu == "x64"', }, { - 'object_name': 'Mac_arm64/rust-toolchain-3350c1eb3fd8fe1bee1ed4c76944d707bd256876-1-llvmorg-21-init-10502-gb2e2ae87.tar.xz', - 'sha256sum': '2a95ec6fe7623c43e87f06829bae17c45f1c94c19db4c8f085d77cb948c0ee3f', - 'size_bytes': 101896012, - 'generation': 1746143867490688, + 'object_name': 'Mac_arm64/rust-toolchain-4a0969e06dbeaaa43914d2d00b2e843d49aa3886-1-llvmorg-21-init-10851-gcd6c4b61.tar.xz', + 'sha256sum': '4c1f9d7ff8c1febdb755ad971b0ae8d9b3c5bed5b30b96ea00caa784dfb86427', + 'size_bytes': 101778572, + 'generation': 1746525616855514, 'condition': 'host_os == "mac" and host_cpu == "arm64"', }, { - 'object_name': 'Win/rust-toolchain-3350c1eb3fd8fe1bee1ed4c76944d707bd256876-1-llvmorg-21-init-10502-gb2e2ae87.tar.xz', - 'sha256sum': 'da814703ae38af456eeeb63985198cb7ec48740b0a143249830fc880d633f80b', - 'size_bytes': 193736940, - 'generation': 1746143869370201, + 'object_name': 'Win/rust-toolchain-4a0969e06dbeaaa43914d2d00b2e843d49aa3886-1-llvmorg-21-init-10851-gcd6c4b61.tar.xz', + 'sha256sum': '7d2484e229f4015d3711f1294d11048764ec22ebaf8266701abf350cd51c897b', + 'size_bytes': 193318196, + 'generation': 1746525618539172, 'condition': 'host_os == "win"', }, ], @@ -1475,7 +1475,7 @@ 'packages': [ { 'package': 'chromium/chrome/test/data/variations/cipd', - 'version': 'VHYCX9xYCTReHB7RcGQeEqjdvegilaW1svSJscjtDX4C', + 'version': 'ReWAdAhFsmTN1Z6g09iwNFqpNxVIeGzINfzDf4EumCUC', }, ], 'dep_type': 'cipd', @@ -1486,12 +1486,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - 'a85f502de34463769977268999f0dbce0321efa6', + '11c3547fd4f0706067ad840ff190038861085741', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'e157e12d99cfc729a970b474344673c44e2d2c9c', + 'url': Var('chromium_git') + '/website.git' + '@' + 'b2558d301fc88f8e4671024c47960ff1ee82cf34', }, 'src/ios/third_party/earl_grey2/src': { @@ -1716,7 +1716,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/error_prone', - 'version': '2t_u1XEjof609BQE4czlCQzEqRliKS_qY35FOu_VckgC', + 'version': 'FLtgIzcLepAc87BaSXIELZIJPT4yxnr8K3MmFaEHrK8C', }, ], 'condition': 'checkout_android and non_git_source', @@ -1738,7 +1738,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/lint', - 'version': '0xqmMJ1qdP4NPN5s9VmWiNhchvNz_RLBrjXN4jUKN3gC', + 'version': '2fKjMen4v_UU1CDYJqhwJCr6uh-L5w25n9lAKx6SlP0C', }, ], 'condition': 'checkout_android and non_git_source', @@ -1749,7 +1749,7 @@ 'packages': [ { 'package': 'chromium/third_party/android_build_tools/manifest_merger', - 'version': '7lstFdOjh1bFmfSZ8le-aZ1a1COQtwirGzuEWa43tnUC', + 'version': 'GnPGgBK8kiq32GuJB3iI20yJbFjgt2dqHsmwoPShJ-4C', }, ], 'condition': 'checkout_android and non_git_source', @@ -1978,7 +1978,7 @@ 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '30d9438e7baf0c045f973de2f517b51554d14d7d', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '18580cf9c407a3c23aa072b9d745832516de699e', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -2229,7 +2229,7 @@ 'packages': [ { 'package': 'chromium/third_party/kotlin_stdlib', - 'version': '74gAxjfyJIVJGIA4z0V-jCmMW6A6dDJSoWMh7qhlzp4C', + 'version': 'aHCAN6w_ZZCJL7MOPlDbEieRsiUs6ftT33fCI4bbwVwC', }, ], 'condition': 'checkout_android and non_git_source', @@ -2894,7 +2894,7 @@ Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'), 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '626c9f19118aac2e0faf45db73e9101d4502190c', + Var('webrtc_git') + '/src.git' + '@' + 'd69d0808c37b4ea338e59a58837ef180023316a6', # 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. @@ -3071,7 +3071,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'Gji5w3Fe9lCNNUKPYZBBjSkEtcijgDLpAH48woRMNU8C', + 'version': '6XoJDL99IbFbTSQxQLQaQODFYghbzVxlKzfDpAbi65EC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4591,7 +4591,7 @@ 'src/components/autofill/core/browser/form_parsing/internal_resources': { 'url': Var('chrome_git') + '/chrome/components/autofill_regex_patterns.git' + '@' + - '8f3290e53c07fe9527fc48952edde535c3cfa13a', + 'ee4b7f29de55d7867a004208580a994e5da35ed0', 'condition': 'checkout_src_internal', }, @@ -4650,7 +4650,7 @@ 'src/components/test/data/autofill/heuristics-json/internal': { 'url': Var('chrome_git') + '/chrome/test/autofill/structured_forms.git' + '@' + - 'dbd13cb361518dac753112204eacd1ce9e1fab84', + 'cdb496540ac02f8d98cfc04097e3e10a197f18f4', 'condition': 'checkout_chromium_autofill_test_dependencies', }, @@ -4680,7 +4680,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '56c2b01d07aad9c323ad655a8cb07b849923ac99', + 'c32f19290092f9592d3be32943becfab3f52a9cd', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 574fe38a..1e7b7fe0 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -967,6 +967,7 @@ r'android_webview/browser/ip_protection/.*', r'chrome/browser/ip_protection/.*', r'components/ip_protection/.*', + r'net/quic/dedicated_web_transport_http3_client\.cc', # Needed to use MediaPipe API. r'components/media_effects/.*\.cc',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 559c17c..cab4c11f 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -662,8 +662,7 @@ (delegate) ? delegate->isModalContextMenu() : false; } -std::vector<std::unique_ptr<content::NavigationThrottle>> -AwContentBrowserClient::CreateThrottlesForNavigation( +void AwContentBrowserClient::CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) { // We allow intercepting only navigations within main frames. This // is used to post onPageStarted. We handle shouldOverrideUrlLoading @@ -711,8 +710,6 @@ &navigation_handle, urlClassifier)); } } - - return {}; } std::unique_ptr<content::PrefetchServiceDelegate>
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h index 13fb940..d2ed3814 100644 --- a/android_webview/browser/aw_content_browser_client.h +++ b/android_webview/browser/aw_content_browser_client.h
@@ -149,8 +149,7 @@ content::WebContents* web_contents, content::SiteInstance& main_frame_site, blink::web_pref::WebPreferences* web_prefs) override; - std::vector<std::unique_ptr<content::NavigationThrottle>> - CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override; std::unique_ptr<content::PrefetchServiceDelegate> CreatePrefetchServiceDelegate(
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java index 81135bf..d367f6a 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java +++ b/android_webview/glue/java/src/com/android/webview/chromium/SharedWebViewChromium.java
@@ -18,6 +18,8 @@ import org.chromium.content_public.browser.MessagePayload; import org.chromium.content_public.browser.MessagePort; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.Callable; /** @@ -227,4 +229,29 @@ } public void configureBaseline(int baseline) {} + + public List<String> addJavascriptInterfaces( + List<Object> objects, List<String> names, List<List<String>> sitePatterns) { + // This is called specifically from the WebViewBuilder API which always builds + // and configures on the UI thread specifically. If we are not on the UI thread, + // this is an issue and should be reported back. + // Executing on the UI thread means we can return our validation results + // synchronously. + if (checkNeedsPost()) { + throw new IllegalStateException("WebView must not be configured outside of UI Thread"); + } + assert objects.size() == names.size() && names.size() == sitePatterns.size(); + + // TODO: Add support to JS injection code in content to handle bulk push of + // patterns. JNIZero currently doesn't support multi dimensional arrays so + // List<List<String>> is a problem. + List<String> badPatterns = new ArrayList<>(); + + for (int i = 0; i < objects.size(); i++) { + badPatterns.addAll( + mAwContents.addJavascriptInterface( + objects.get(i), names.get(i), sitePatterns.get(i))); + } + return badPatterns; + } }
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 27ffd8c..babba53a 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
@@ -236,6 +236,9 @@ AndroidAutofillFeatures.ANDROID_AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID_IN_CCT_NAME, "Disables checking AutofilManager#isEnabled too early. Mainly affects CCTs."), Flag.baseFeature( + AndroidAutofillFeatures.ANDROID_AUTOFILL_LAZY_FRAMEWORK_WRAPPER_NAME, + "Enable lazily initializing framework Autofill wrapper."), + Flag.baseFeature( AutofillFeatures.AUTOFILL_ACCEPT_DOM_MUTATION_AFTER_AUTOFILL_SUBMISSION, "Accepts DOM_MUTATION_AFTER_AUTOFILL submissions detected on password forms."), Flag.baseFeature(
diff --git a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewBuilderBoundaryInterface.java b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewBuilderBoundaryInterface.java index a2ae6f92..459ac03 100644 --- a/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewBuilderBoundaryInterface.java +++ b/android_webview/support_library/boundary_interfaces/src/org/chromium/support_lib_boundary/WebViewBuilderBoundaryInterface.java
@@ -15,6 +15,8 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.util.ArrayList; +import java.util.List; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -35,20 +37,38 @@ @Target(ElementType.TYPE_USE) @IntDef({ ConfigField.BASELINE, + ConfigField.JAVASCRIPT_INTERFACE, }) @Retention(RetentionPolicy.SOURCE) @interface ConfigField { int BASELINE = 0; + int JAVASCRIPT_INTERFACE = 1; } class Config implements Consumer<BiConsumer<@ConfigField Integer, Object>> { public int baseline = Baseline.DEFAULT; + List<Object> mJavascriptInterfaceObjects = new ArrayList<>(); + List<String> mJavascriptInterfaceNames = new ArrayList<>(); + List<List<String>> mJavascriptInterfaceSitePatterns = new ArrayList<>(); + + public void addJavascriptInterface(Object object, String name, List<String> sitePatterns) { + mJavascriptInterfaceObjects.add(object); + mJavascriptInterfaceNames.add(name); + mJavascriptInterfaceSitePatterns.add(sitePatterns); + } // This method handles reading all config in AndroidX to transfer over to Chromium. // It's job is to essentially "serialize" the fields into known keys. @Override public void accept(BiConsumer<@ConfigField Integer, Object> chromiumConfig) { chromiumConfig.accept(ConfigField.BASELINE, baseline); + chromiumConfig.accept( + ConfigField.JAVASCRIPT_INTERFACE, + new Object[] { + mJavascriptInterfaceObjects, + mJavascriptInterfaceNames, + mJavascriptInterfaceSitePatterns + }); } }
diff --git a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewBuilderAdapter.java b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewBuilderAdapter.java index fdfea93..5818f7a 100644 --- a/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewBuilderAdapter.java +++ b/android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewBuilderAdapter.java
@@ -7,12 +7,15 @@ import android.content.Context; import android.webkit.WebView; +import androidx.annotation.Nullable; + import com.android.webview.chromium.SharedWebViewChromium; import com.android.webview.chromium.WebkitToSharedGlueConverter; import org.chromium.support_lib_boundary.WebViewBuilderBoundaryInterface; import org.chromium.support_lib_boundary.WebViewBuilderBoundaryInterface.ConfigField; +import java.util.List; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -36,6 +39,9 @@ static class Builder implements BiConsumer<@ConfigField Integer, Object> { private Integer mBaseline; + private @Nullable List<Object> mJavascriptInterfaceObjects; + private @Nullable List<String> mJavascriptInterfaceNames; + private @Nullable List<List<String>> mJavascriptInterfaceSitePatterns; @Override public void accept(@ConfigField Integer key, Object value) { @@ -46,6 +52,15 @@ mBaseline = (Integer) value; break; } + case ConfigField.JAVASCRIPT_INTERFACE: + { + Object[] interfaceParams = (Object[]) value; + mJavascriptInterfaceObjects = (List<Object>) interfaceParams[0]; + mJavascriptInterfaceNames = (List<String>) interfaceParams[1]; + mJavascriptInterfaceSitePatterns = + (List<List<String>>) interfaceParams[2]; + break; + } } } catch (ClassCastException e) { throw new InternalApiMismatchException(key + " was not configured correctly", e); @@ -64,6 +79,15 @@ sharedWebViewChromium.configureBaseline(mBaseline); } + if (mJavascriptInterfaceObjects != null + && mJavascriptInterfaceNames != null + && mJavascriptInterfaceSitePatterns != null) { + sharedWebViewChromium.addJavascriptInterfaces( + mJavascriptInterfaceObjects, + mJavascriptInterfaceNames, + mJavascriptInterfaceSitePatterns); + } + return webview; } }
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 882fcda..c8e9897 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
@@ -5049,6 +5049,14 @@ getter isComposing method constructor method getTargetRanges +interface IntegrityViolationReportBody : ReportBody + attribute @@toStringTag + getter blockedURL + getter destination + getter documentURL + getter reportOnly + method constructor + method toJSON interface IntersectionObserver attribute @@toStringTag getter delay
diff --git a/android_webview/tools/run_cts.pydeps b/android_webview/tools/run_cts.pydeps index 9f26c3bf..a80607f7 100644 --- a/android_webview/tools/run_cts.pydeps +++ b/android_webview/tools/run_cts.pydeps
@@ -74,6 +74,7 @@ //third_party/catapult/devil/devil/devil_env.py //third_party/catapult/devil/devil/utils/__init__.py //third_party/catapult/devil/devil/utils/cmd_helper.py +//third_party/catapult/devil/devil/utils/host_utils.py //third_party/catapult/devil/devil/utils/lazy/__init__.py //third_party/catapult/devil/devil/utils/lazy/weak_constant.py //third_party/catapult/devil/devil/utils/logging_common.py
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 40ecc18..fa001839 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -3800,7 +3800,6 @@ "app_menu/notification_overflow_view_unittest.cc", "assistant/assistant_alarm_timer_controller_unittest.cc", "assistant/assistant_controller_impl_unittest.cc", - "assistant/assistant_interaction_controller_impl_unittest.cc", "assistant/assistant_notification_controller_impl_unittest.cc", "assistant/assistant_setup_controller_unittest.cc", "assistant/assistant_state_controller_unittest.cc", @@ -5516,7 +5515,6 @@ "//components/desks_storage:test_support", "//components/drive", "//components/drive:test_support", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", "//components/manta/proto", "//components/prefs:test_support",
diff --git a/ash/accelerators/accelerator_table_unittest.cc b/ash/accelerators/accelerator_table_unittest.cc index 05757eb..43c64dff 100644 --- a/ash/accelerators/accelerator_table_unittest.cc +++ b/ash/accelerators/accelerator_table_unittest.cc
@@ -8,7 +8,7 @@ #include <tuple> #include "ash/public/cpp/accelerators.h" -#include "base/hash/md5.h" +#include "ash/test/ash_test_util.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,9 +19,9 @@ // The number of non-Search-based accelerators. constexpr int kNonSearchAcceleratorsNum = 113; -// The hash of non-Search-based accelerators. See HashAcceleratorData(). +// The hash of non-Search-based accelerators. constexpr char kNonSearchAcceleratorsHash[] = - "d8d437fd800f34f648c5bc4bb47926b0"; + "911675569c0f8f713f08027577f21eb620e16996f21f3aa172a6c805b9124ad8"; struct Cmp { bool operator()(const AcceleratorData& lhs, @@ -42,18 +42,6 @@ (accelerator.modifiers & ui::EF_COMMAND_DOWN) ? "true" : "false"); } -std::string HashAcceleratorData( - const std::vector<AcceleratorData>& accelerators) { - base::MD5Context context; - base::MD5Init(&context); - for (const AcceleratorData& accelerator : accelerators) { - base::MD5Update(&context, AcceleratorDataToString(accelerator)); - } - base::MD5Digest digest; - base::MD5Final(&digest, &context); - return MD5DigestToBase16(digest); -} - } // namespace TEST(AcceleratorTableTest, CheckDuplicatedAccelerators) { @@ -155,8 +143,8 @@ std::stable_sort(non_search_accelerators.begin(), non_search_accelerators.end(), Cmp()); - const std::string non_search_accelerators_hash = - HashAcceleratorData(non_search_accelerators); + const std::string non_search_accelerators_hash = ash::StableHashOfCollection( + non_search_accelerators, AcceleratorDataToString); EXPECT_EQ(non_search_accelerators_hash, kNonSearchAcceleratorsHash) << "New accelerators must use the Search key. Please talk to the UX "
diff --git a/ash/app_list/model/app_list_model_export.h b/ash/app_list/model/app_list_model_export.h index d3ee4be..c377831 100644 --- a/ash/app_list/model/app_list_model_export.h +++ b/ash/app_list/model/app_list_model_export.h
@@ -10,11 +10,7 @@ #if defined(COMPONENT_BUILD) -#if defined(APP_LIST_MODEL_IMPLEMENTATION) #define APP_LIST_MODEL_EXPORT __attribute__((visibility("default"))) -#else -#define APP_LIST_MODEL_EXPORT -#endif #else // defined(COMPONENT_BUILD) #define APP_LIST_MODEL_EXPORT
diff --git a/ash/app_list/views/search_box_view_unittest.cc b/ash/app_list/views/search_box_view_unittest.cc index 27453c42..273f998 100644 --- a/ash/app_list/views/search_box_view_unittest.cc +++ b/ash/app_list/views/search_box_view_unittest.cc
@@ -772,40 +772,6 @@ EXPECT_EQ(ax::mojom::DefaultActionVerb::kClick, data.GetDefaultActionVerb()); } -class SearchBoxViewAssistantButtonTest : public SearchBoxViewTest { - public: - SearchBoxViewAssistantButtonTest() = default; - SearchBoxViewAssistantButtonTest(const SearchBoxViewAssistantButtonTest&) = - delete; - SearchBoxViewAssistantButtonTest& operator=( - const SearchBoxViewAssistantButtonTest&) = delete; - ~SearchBoxViewAssistantButtonTest() override = default; - - // Overridden from testing::Test - void SetUp() override { - SearchBoxViewTest::SetUp(); - GetSearchModel()->search_box()->SetShowAssistantButton(true); - } -}; - -// Tests that the assistant button is visible by default. -TEST_F(SearchBoxViewAssistantButtonTest, AssistantButtonVisibleByDefault) { - EXPECT_TRUE(view()->edge_button_container()->GetVisible()); - EXPECT_TRUE(view()->assistant_button()->GetVisible()); -} - -// Tests that the assistant button is invisible after typing in the search box, -// and comes back when search box is empty. -TEST_F(SearchBoxViewAssistantButtonTest, - AssistantButtonChangeVisibilityWithTyping) { - KeyPress(ui::VKEY_A); - EXPECT_FALSE(view()->edge_button_container()->GetVisible()); - - KeyPress(ui::VKEY_BACK); - EXPECT_TRUE(view()->edge_button_container()->GetVisible()); - EXPECT_TRUE(view()->assistant_button()->GetVisible()); -} - class SearchBoxViewFilterButtonTest : public SearchBoxViewTest { public: SearchBoxViewFilterButtonTest() { @@ -1206,7 +1172,6 @@ non_zero_duration_mode_ = std::make_unique<ui::ScopedAnimationDurationScaleMode>( ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); - GetSearchModel()->search_box()->SetShowAssistantButton(true); } std::unique_ptr<ui::ScopedAnimationDurationScaleMode> non_zero_duration_mode_; @@ -1221,7 +1186,6 @@ // hidden. EXPECT_FALSE(search_box->filter_and_close_button_container()->GetVisible()); EXPECT_TRUE(search_box->edge_button_container()->GetVisible()); - EXPECT_TRUE(search_box->assistant_button()->GetVisible()); // Set search box to active state. search_box->SetSearchBoxActive(true, ui::EventType::kMousePressed); @@ -1235,15 +1199,6 @@ ui::LayerAnimationElement::AnimatableProperty::OPACITY)); EXPECT_EQ(close_animator->GetTargetOpacity(), 1.0f); - // Assistant button should be fading out. - EXPECT_TRUE(search_box->edge_button_container()->GetVisible()); - EXPECT_TRUE(search_box->assistant_button()->GetVisible()); - auto* assistant_animator = - search_box->edge_button_container()->layer()->GetAnimator(); - EXPECT_TRUE(assistant_animator->IsAnimatingProperty( - ui::LayerAnimationElement::AnimatableProperty::OPACITY)); - EXPECT_EQ(assistant_animator->GetTargetOpacity(), 0.0f); - // Set search box to inactive state, hiding the close button. search_box->SetSearchBoxActive(false, ui::EventType::kMousePressed); @@ -1252,14 +1207,6 @@ EXPECT_TRUE(close_animator->IsAnimatingProperty( ui::LayerAnimationElement::AnimatableProperty::OPACITY)); EXPECT_EQ(close_animator->GetTargetOpacity(), 0.0f); - - // Assistant button should be fading in. - EXPECT_TRUE(search_box->edge_button_container()->GetVisible()); - EXPECT_TRUE(search_box->assistant_button()->GetVisible()); - ASSERT_TRUE(assistant_animator); - EXPECT_TRUE(assistant_animator->IsAnimatingProperty( - ui::LayerAnimationElement::AnimatableProperty::OPACITY)); - EXPECT_EQ(assistant_animator->GetTargetOpacity(), 1.0f); } // Test that activating and deactivating the search box causes the search icon
diff --git a/ash/app_menu/app_menu_export.h b/ash/app_menu/app_menu_export.h index 3ba9e92..3065e2a 100644 --- a/ash/app_menu/app_menu_export.h +++ b/ash/app_menu/app_menu_export.h
@@ -10,11 +10,7 @@ #if defined(COMPONENT_BUILD) -#if defined(APP_MENU_IMPLEMENTATION) #define APP_MENU_EXPORT __attribute__((visibility("default"))) -#else -#define APP_MENU_EXPORT -#endif #else // defined(COMPONENT_BUILD) #define APP_MENU_EXPORT
diff --git a/ash/ash_export.h b/ash/ash_export.h index 8e3cd9c4..bc2e7be 100644 --- a/ash/ash_export.h +++ b/ash/ash_export.h
@@ -10,11 +10,7 @@ #if defined(COMPONENT_BUILD) -#if defined(ASH_IMPLEMENTATION) #define ASH_EXPORT __attribute__((visibility("default"))) -#else -#define ASH_EXPORT -#endif #else // defined(COMPONENT_BUILD) #define ASH_EXPORT
diff --git a/ash/assistant/assistant_interaction_controller_impl_unittest.cc b/ash/assistant/assistant_interaction_controller_impl_unittest.cc deleted file mode 100644 index e5636d33..0000000 --- a/ash/assistant/assistant_interaction_controller_impl_unittest.cc +++ /dev/null
@@ -1,353 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ash/assistant/assistant_interaction_controller_impl.h" - -#include <algorithm> -#include <map> - -#include "ash/assistant/assistant_suggestions_controller_impl.h" -#include "ash/assistant/model/assistant_interaction_model.h" -#include "ash/assistant/model/assistant_interaction_model_observer.h" -#include "ash/assistant/model/assistant_response.h" -#include "ash/assistant/model/assistant_response_observer.h" -#include "ash/assistant/model/ui/assistant_card_element.h" -#include "ash/assistant/model/ui/assistant_error_element.h" -#include "ash/assistant/model/ui/assistant_ui_element.h" -#include "ash/assistant/test/assistant_ash_test_base.h" -#include "ash/assistant/ui/assistant_view_ids.h" -#include "ash/assistant/ui/main_stage/assistant_error_element_view.h" -#include "ash/constants/ash_features.h" -#include "ash/public/cpp/app_list/app_list_features.h" -#include "ash/public/cpp/ash_web_view.h" -#include "ash/public/cpp/assistant/controller/assistant_interaction_controller.h" -#include "ash/public/cpp/assistant/controller/assistant_suggestions_controller.h" -#include "ash/test/fake_android_intent_helper.h" -#include "ash/test/test_ash_web_view.h" -#include "base/functional/bind.h" -#include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" -#include "base/time/time.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace ash { - -namespace { - -using assistant::AndroidAppInfo; -using assistant::Assistant; -using assistant::AssistantInteractionMetadata; -using assistant::AssistantInteractionSubscriber; -using assistant::AssistantInteractionType; -using assistant::AssistantQuerySource; -using assistant::AssistantSuggestion; -using assistant::AssistantSuggestionType; -using assistant::MockAssistantInteractionSubscriber; -using assistant::ScopedAssistantInteractionSubscriber; - -using ::testing::Invoke; -using ::testing::Mock; -using ::testing::Return; -using ::testing::StrictMock; - -// Mocks ----------------------------------------------------------------------- - -class AssistantInteractionSubscriberMock - : public AssistantInteractionSubscriber { - public: - explicit AssistantInteractionSubscriberMock(Assistant* service) { - scoped_subscriber_.Observe(service); - } - - ~AssistantInteractionSubscriberMock() override = default; - - MOCK_METHOD(void, - OnInteractionStarted, - (const AssistantInteractionMetadata&), - (override)); - - private: - ScopedAssistantInteractionSubscriber scoped_subscriber_{this}; -}; - -// AssistantInteractionControllerImplTest -------------------------------------- - -class AssistantInteractionControllerImplTest : public AssistantAshTestBase { - public: - AssistantInteractionControllerImplTest() = default; - - AssistantInteractionControllerImpl* interaction_controller() { - return static_cast<AssistantInteractionControllerImpl*>( - AssistantInteractionController::Get()); - } - - AssistantSuggestionsControllerImpl* suggestion_controller() { - return static_cast<AssistantSuggestionsControllerImpl*>( - AssistantSuggestionsController::Get()); - } - - const AssistantInteractionModel* interaction_model() { - return interaction_controller()->GetModel(); - } - - void StartInteraction() { - interaction_controller()->OnInteractionStarted( - AssistantInteractionMetadata()); - } - - AndroidAppInfo CreateAndroidAppInfo(const std::string& app_name = "unknown") { - AndroidAppInfo result; - result.localized_app_name = app_name; - return result; - } -}; - -AssistantCardElement* GetAssistantCardElement( - const std::vector<std::unique_ptr<AssistantUiElement>>& ui_elements) { - if (ui_elements.size() != 1lu || - ui_elements.front()->type() != AssistantUiElementType::kCard) { - return nullptr; - } - - return static_cast<AssistantCardElement*>(ui_elements.front().get()); -} - -} // namespace - -TEST_F(AssistantInteractionControllerImplTest, - ShouldBecomeActiveWhenInteractionStarts) { - EXPECT_EQ(interaction_model()->interaction_state(), - InteractionState::kInactive); - - interaction_controller()->OnInteractionStarted( - AssistantInteractionMetadata()); - - EXPECT_EQ(interaction_model()->interaction_state(), - InteractionState::kActive); -} - -TEST_F(AssistantInteractionControllerImplTest, - ShouldBeNoOpWhenOpenAppIsCalledWhileInactive) { - EXPECT_EQ(interaction_model()->interaction_state(), - InteractionState::kInactive); - - FakeAndroidIntentHelper fake_helper; - fake_helper.AddApp("app-name", "app-intent"); - interaction_controller()->OnOpenAppResponse(CreateAndroidAppInfo("app-name")); - - EXPECT_FALSE(fake_helper.last_launched_android_intent().has_value()); -} - -TEST_F(AssistantInteractionControllerImplTest, - ShouldBeNoOpWhenOpenAppIsCalledForUnknownAndroidApp) { - StartInteraction(); - FakeAndroidIntentHelper fake_helper; - interaction_controller()->OnOpenAppResponse( - CreateAndroidAppInfo("unknown-app-name")); - - EXPECT_FALSE(fake_helper.last_launched_android_intent().has_value()); -} - -TEST_F(AssistantInteractionControllerImplTest, - ShouldLaunchAppAndReturnSuccessWhenOpenAppIsCalled) { - const std::string app_name = "AppName"; - const std::string intent = "intent://AppName"; - - StartInteraction(); - FakeAndroidIntentHelper fake_helper; - fake_helper.AddApp(app_name, intent); - - interaction_controller()->OnOpenAppResponse(CreateAndroidAppInfo(app_name)); - - EXPECT_EQ(intent, fake_helper.last_launched_android_intent()); -} - -TEST_F(AssistantInteractionControllerImplTest, - ShouldAddSchemeToIntentWhenLaunchingAndroidApp) { - const std::string app_name = "AppName"; - const std::string intent = "#Intent-without-a-scheme"; - const std::string intent_with_scheme = "intent://" + intent; - - StartInteraction(); - FakeAndroidIntentHelper fake_helper; - fake_helper.AddApp(app_name, intent); - - interaction_controller()->OnOpenAppResponse(CreateAndroidAppInfo(app_name)); - - EXPECT_EQ(intent_with_scheme, fake_helper.last_launched_android_intent()); -} - -TEST_F(AssistantInteractionControllerImplTest, - ShouldCorrectlyMapSuggestionTypeToQuerySource) { - // Mock Assistant interaction subscriber. - StrictMock<AssistantInteractionSubscriberMock> mock(assistant_service()); - - // Configure the expected mappings between suggestion type and query source. - const std::map<AssistantSuggestionType, AssistantQuerySource> - types_to_sources = {{AssistantSuggestionType::kConversationStarter, - AssistantQuerySource::kConversationStarter}, - {AssistantSuggestionType::kBetterOnboarding, - AssistantQuerySource::kBetterOnboarding}, - {AssistantSuggestionType::kUnspecified, - AssistantQuerySource::kSuggestionChip}}; - - // Iterate over all expected mappings. - for (const auto& type_to_source : types_to_sources) { - base::RunLoop run_loop; - - // Confirm subscribers are delivered the expected query source... - EXPECT_CALL(mock, OnInteractionStarted) - .WillOnce(Invoke([&](const AssistantInteractionMetadata& metadata) { - EXPECT_EQ(type_to_source.second, metadata.source); - run_loop.QuitClosure().Run(); - })); - - AssistantSuggestion suggestion{/*id=*/base::UnguessableToken::Create(), - /*type=*/type_to_source.first, - /*text=*/""}; - const_cast<AssistantSuggestionsModel*>(suggestion_controller()->GetModel()) - ->SetConversationStarters({suggestion}); - - // ...when an Assistant suggestion of a given type is pressed. - interaction_controller()->OnSuggestionPressed(suggestion.id); - - run_loop.Run(); - } -} - -TEST_F(AssistantInteractionControllerImplTest, ShouldDisplayGenericErrorOnce) { - StartInteraction(); - - // Call OnTtsStarted twice to mimic the behavior of libassistant when network - // is disconnected. - interaction_controller()->OnTtsStarted(/*due_to_error=*/true); - interaction_controller()->OnTtsStarted(/*due_to_error=*/true); - - base::RunLoop().RunUntilIdle(); - - auto& ui_elements = - interaction_controller()->GetModel()->response()->GetUiElements(); - - EXPECT_EQ(ui_elements.size(), 1ul); - EXPECT_EQ(ui_elements.front()->type(), AssistantUiElementType::kError); - - base::RunLoop().RunUntilIdle(); - - interaction_controller()->OnInteractionFinished( - assistant::AssistantInteractionResolution::kError); - - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(ui_elements.size(), 1ul); - EXPECT_EQ(ui_elements.front()->type(), AssistantUiElementType::kError); -} - -TEST_F(AssistantInteractionControllerImplTest, - ShouldUpdateTimeOfLastInteraction) { - MockAssistantInteractionSubscriber mock_subscriber; - ScopedAssistantInteractionSubscriber scoped_subscriber{&mock_subscriber}; - scoped_subscriber.Observe(assistant_service()); - - base::RunLoop run_loop; - base::Time actual_time_of_last_interaction; - EXPECT_CALL(mock_subscriber, OnInteractionStarted) - .WillOnce(Invoke([&](const AssistantInteractionMetadata& metadata) { - actual_time_of_last_interaction = base::Time::Now(); - run_loop.QuitClosure().Run(); - })); - - ShowAssistantUi(); - MockTextInteraction().WithTextResponse("<Any-Text-Response>"); - run_loop.Run(); - - auto actual = interaction_controller()->GetTimeDeltaSinceLastInteraction(); - auto expected = base::Time::Now() - actual_time_of_last_interaction; - - EXPECT_NEAR(actual.InSeconds(), expected.InSeconds(), 1); -} - -TEST_F(AssistantInteractionControllerImplTest, CompactBubbleLauncher) { - static constexpr int kStandardLayoutAshWebViewWidth = 592; - static constexpr int kNarrowLayoutAshWebViewWidth = 496; - - UpdateDisplay("1200x800"); - ShowAssistantUi(); - StartInteraction(); - - interaction_controller()->OnHtmlResponse("<html></html>", "fallback"); - - base::RunLoop().RunUntilIdle(); - - AssistantCardElement* card_element = GetAssistantCardElement( - interaction_controller()->GetModel()->response()->GetUiElements()); - ASSERT_TRUE(card_element); - EXPECT_EQ(card_element->viewport_width(), 638); - EXPECT_EQ( - page_view()->GetViewByID(AssistantViewID::kAshWebView)->size().width(), - kStandardLayoutAshWebViewWidth); - - ASSERT_TRUE(page_view()->GetViewByID(AssistantViewID::kAshWebView) != - nullptr); - TestAshWebView* ash_web_view = static_cast<TestAshWebView*>( - page_view()->GetViewByID(AssistantViewID::kAshWebView)); - // max_size and min_size in AshWebView::InitParams are different from the view - // size. min_size affects to the size of rendered content, i.e. renderer will - // try to render the content to the size. But View::Size() doesn't. - ASSERT_TRUE(ash_web_view->init_params_for_testing().max_size); - ASSERT_TRUE(ash_web_view->init_params_for_testing().min_size); - EXPECT_EQ(ash_web_view->init_params_for_testing().max_size.value().width(), - kStandardLayoutAshWebViewWidth); - EXPECT_EQ(ash_web_view->init_params_for_testing().min_size.value().width(), - kStandardLayoutAshWebViewWidth); - - CloseAssistantUi(); - - // Change work area width < 1200 and confirm that the viewport width gets - // updated to narrow layout one. - UpdateDisplay("1199x800"); - ShowAssistantUi(); - StartInteraction(); - - interaction_controller()->OnHtmlResponse("<html></html>", "fallback"); - - base::RunLoop().RunUntilIdle(); - - card_element = GetAssistantCardElement( - interaction_controller()->GetModel()->response()->GetUiElements()); - ASSERT_TRUE(card_element); - ASSERT_TRUE(page_view()->GetViewByID(AssistantViewID::kAshWebView) != - nullptr); - EXPECT_EQ(card_element->viewport_width(), 542); - EXPECT_EQ( - page_view()->GetViewByID(AssistantViewID::kAshWebView)->size().width(), - kNarrowLayoutAshWebViewWidth); - - ASSERT_TRUE(page_view()->GetViewByID(AssistantViewID::kAshWebView) != - nullptr); - ash_web_view = static_cast<TestAshWebView*>( - page_view()->GetViewByID(AssistantViewID::kAshWebView)); - ASSERT_TRUE(ash_web_view->init_params_for_testing().max_size); - ASSERT_TRUE(ash_web_view->init_params_for_testing().min_size); - EXPECT_EQ(ash_web_view->init_params_for_testing().max_size.value().width(), - kNarrowLayoutAshWebViewWidth); - EXPECT_EQ(ash_web_view->init_params_for_testing().min_size.value().width(), - kNarrowLayoutAshWebViewWidth); -} - -TEST_F(AssistantInteractionControllerImplTest, FixedZoomLevel) { - ShowAssistantUi(); - StartInteraction(); - - interaction_controller()->OnHtmlResponse("<html></html>", "fallback"); - - base::RunLoop().RunUntilIdle(); - - TestAshWebView* ash_web_view = static_cast<TestAshWebView*>( - page_view()->GetViewByID(AssistantViewID::kAshWebView)); - EXPECT_TRUE(ash_web_view->init_params_for_testing().fix_zoom_level_to_one); -} -} // namespace ash
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 6a5a0639..50a5918 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -1429,6 +1429,11 @@ "HealthdInternalsTabs", base::FEATURE_ENABLED_BY_DEFAULT); +// Enables Kiosk session for the Helium android app. +BASE_FEATURE(kHeliumArcvmKiosk, + "HeliumArcvmKiosk", + base::FEATURE_DISABLED_BY_DEFAULT); + // If enabled, the Help app will render the App Detail Page and entry point. BASE_FEATURE(kHelpAppAppDetailPage, "HelpAppAppDetailPage", @@ -3928,6 +3933,10 @@ return base::FeatureList::IsEnabled(kHealthdInternalsTabs); } +bool IsHeliumArcvmKioskEnabled() { + return base::FeatureList::IsEnabled(kHeliumArcvmKiosk); +} + bool IsHibernateEnabled() { return base::FeatureList::IsEnabled(kHibernate); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 15fe4bb..8e7c59d 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -508,6 +508,8 @@ COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kHealthdInternalsTabs); COMPONENT_EXPORT(ASH_CONSTANTS) +BASE_DECLARE_FEATURE(kHeliumArcvmKiosk); +COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kHelpAppAppDetailPage); COMPONENT_EXPORT(ASH_CONSTANTS) BASE_DECLARE_FEATURE(kHelpAppAppsList); @@ -1246,6 +1248,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool AreAnyGlanceablesTimeManagementViewsEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool AreHealthdInternalsTabsEnabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool IsHeliumArcvmKioskEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsHibernateEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsHideShelfControlsInTabletModeEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsHoldingSpaceSuggestionsEnabled();
diff --git a/ash/keyboard/ui/keyboard_export.h b/ash/keyboard/ui/keyboard_export.h index cedeeec..a0e455c8 100644 --- a/ash/keyboard/ui/keyboard_export.h +++ b/ash/keyboard/ui/keyboard_export.h
@@ -18,11 +18,7 @@ #endif // defined(KEYBOARD_IMPLEMENTATION) #else // defined(WIN32) -#if defined(KEYBOARD_IMPLEMENTATION) #define KEYBOARD_EXPORT __attribute__((visibility("default"))) -#else -#define KEYBOARD_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ash/public/cpp/accelerator_actions_unittest.cc b/ash/public/cpp/accelerator_actions_unittest.cc index 389344718..c8418d9 100644 --- a/ash/public/cpp/accelerator_actions_unittest.cc +++ b/ash/public/cpp/accelerator_actions_unittest.cc
@@ -6,10 +6,9 @@ #include "ash/constants/ash_switches.h" #include "ash/test/ash_test_base.h" +#include "ash/test/ash_test_util.h" #include "base/command_line.h" #include "base/containers/fixed_flat_map.h" -#include "base/hash/md5.h" -#include "base/hash/md5_boringssl.h" #include "base/test/metrics/histogram_enum_reader.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,18 +17,19 @@ namespace { // The total number of accelerator actions. -constexpr int kAcceleratorActionsTotalNum = 171; +constexpr size_t kAcceleratorActionsTotalNum = 171; // The toal number of debug accelerators, these will not be used for hashing. -constexpr int kDebugAcceleratorActionsNum = 28; +constexpr size_t kDebugAcceleratorActionsNum = 28; // The hash of accelerator actions. Please update this when adding a new // accelerator action. -constexpr char kAcceleratorActionsHash[] = "58afc0af7632d35b39039ab49c1359bd"; +constexpr char kAcceleratorActionsHash[] = + "0827c8b3db8a74c4c8f080814060465fdf54f0f9bc2cc913cb549b8df6f67bb3"; // Define the mapping between an AcceleratorAction and its string name. // Example: // AcceleratorAction::kDevToggleUnifiedDesktop -> "DevToggleUnifiedDesktop". constexpr static auto kAcceleratorActionToName = - base::MakeFixedFlatMap<AcceleratorAction, const char*>({ + base::MakeFixedFlatMap<AcceleratorAction, std::string_view>({ #define ACCELERATOR_ACTION_ENTRY(action) \ {AcceleratorAction::k##action, #action}, #define ACCELERATOR_ACTION_ENTRY_FIXED_VALUE(action, value) \ @@ -100,29 +100,16 @@ "`kDebugAcceleratorActionsNum` (if applicable)."; // First check that the size of the enum is correct. - const int current_actions_size = kAcceleratorActionToName.size(); - EXPECT_EQ(current_actions_size, kAcceleratorActionsTotalNum) - << kCommonMessage; + ASSERT_EQ(kAcceleratorActionToName.size(), kAcceleratorActionsTotalNum); + const size_t kAcceleratorsToHashNum = + kAcceleratorActionsTotalNum - kDebugAcceleratorActionsNum; + const std::string hash = ash::StableHashOfCollection( + base::span(kAcceleratorActionToName).first<kAcceleratorsToHashNum>(), + [](const auto& item) { return item.second; }); - // Then check that the hash is correct. - base::MD5Context context; - base::MD5Init(&context); - int iter_count = 0; - for (const auto iter : kAcceleratorActionToName) { - base::MD5Update(&context, iter.second); - // Only hash up non-debug accelerator actions. - if (++iter_count >= current_actions_size - kDebugAcceleratorActionsNum) { - break; - } - } - - base::MD5Digest digest; - base::MD5Final(&digest, &context); - const std::string current_hash = MD5DigestToBase16(digest); - - EXPECT_EQ(current_hash, kAcceleratorActionsHash) + EXPECT_EQ(hash, kAcceleratorActionsHash) << kCommonMessage << " Please update kAcceleratorActionsHash to: \n" - << current_hash << "\n"; + << hash << "\n"; } INSTANTIATE_TEST_SUITE_P(
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc index 861494e..0e2fed7e 100644 --- a/ash/shelf/shelf_widget.cc +++ b/ash/shelf/shelf_widget.cc
@@ -504,16 +504,12 @@ -shelf->SelectValueForShelfAlignment(0, 0, safety_margin))); opaque_back_ground_layer->SetBounds(opaque_background_bounds); - const bool is_vertical_alignment_in_overview = - in_overview_mode && !shelf->IsHorizontalAlignment(); - - // Show rounded corners except in maximized (which includes split view) mode, - // or whenever we are "in app", or the shelf is on the vertical alignment in - // overview mode. + // Do not show rounded corners when the background is in maximized mode (app + // window covers entire background, including splitscreen), whenever we are + // "in app", or in overview mode (vertical or horizontal). if (background_type == ShelfBackgroundType::kMaximized || background_type == ShelfBackgroundType::kInApp || - (tablet_mode && (in_app || split_view)) || - is_vertical_alignment_in_overview) { + background_type == ShelfBackgroundType::kOverview) { opaque_background_.SetRoundedCornerRadius(0); } else { opaque_background_.SetRoundedCornerRadius(radius);
diff --git a/ash/test/ash_test_util.h b/ash/test/ash_test_util.h index 407ecdd4..b0ced26b5 100644 --- a/ash/test/ash_test_util.h +++ b/ash/test/ash_test_util.h
@@ -5,12 +5,21 @@ #ifndef ASH_TEST_ASH_TEST_UTIL_H_ #define ASH_TEST_ASH_TEST_UTIL_H_ +#include <array> #include <cstddef> +#include <iterator> +#include <ranges> +#include <string> #include <string_view> +#include <utility> #include <variant> +#include "base/containers/span.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "chromeos/ui/frame/caption_buttons/frame_size_button.h" #include "chromeos/ui/frame/multitask_menu/multitask_menu_metrics.h" +#include "crypto/hash.h" #include "services/data_decoder/public/mojom/image_decoder.mojom-shared.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/aura/window.h" @@ -123,6 +132,36 @@ // NOTE: This function causes an infinite loop if the target widget never shows. views::Widget* FindWidgetWithNameAndWaitIfNeeded(const std::string& name); +// Given a range r with elements r0, r1, ..., rn and an optional projection p +// (which defaults to the identity), return a stable hash of the concatenation +// of p(r0), p(r1), ..., p(rn). This is used in some tests to ensure that global +// data tables are not changed without consulting the owners of those tables or +// that other invariants are not violated. +// +// For example, use this like: +// std::vector<MyType> things; +// std::string hash = StableHashOfCollection(things, [](const MyType& thing) { +// return thing.ToString(); +// }; +// +// The projection must return something that base::as_byte_span() accepts - a +// string, vector of bytes, or many other range-like types are acceptable. +// +// This hash is guaranteed stable: the same values, supplied in the same order, +// will hash to the same value between test runs. +template <typename Range, typename Proj = std::identity> + requires std::ranges::range<Range> && + std::indirectly_unary_invocable<Proj, std::ranges::iterator_t<Range>> +std::string StableHashOfCollection(const Range& range, Proj proj = {}) { + crypto::hash::Hasher hasher(crypto::hash::HashKind::kSha256); + for (const auto& element : range) { + hasher.Update(base::as_byte_span(proj(element))); + } + std::array<uint8_t, crypto::hash::kSha256Size> hash; + hasher.Finish(hash); + return base::ToLowerASCII(base::HexEncode(base::as_string_view(hash))); +} + } // namespace ash #endif // ASH_TEST_ASH_TEST_UTIL_H_
diff --git a/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table_unittest.cc b/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table_unittest.cc index 230bfef..132f8f8 100644 --- a/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table_unittest.cc +++ b/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table_unittest.cc
@@ -9,9 +9,8 @@ #include "ash/public/cpp/accelerator_actions.h" #include "ash/public/cpp/accelerators.h" #include "ash/public/mojom/accelerator_info.mojom-shared.h" +#include "ash/test/ash_test_util.h" #include "base/containers/contains.h" -#include "base/hash/md5.h" -#include "base/hash/md5_boringssl.h" #include "base/strings/strcat.h" #include "base/strings/stringprintf.h" #include "chromeos/ash/services/assistant/public/cpp/features.h" @@ -25,7 +24,8 @@ // The total number of Ash accelerators. constexpr int kAshAcceleratorsTotalNum = 160; // The hash of Ash accelerators. -constexpr char kAshAcceleratorsHash[] = "864aa0f17421e1ce783c85780a7cf357"; +constexpr char kAshAcceleratorsHash[] = + "7c9f5d090e6be1c01bcfca53b67a79956737dbba149b4e683b44c6ace07e509d"; std::string ToActionName(ash::AcceleratorAction action) { return base::StrCat( @@ -60,19 +60,6 @@ } }; -std::string HashAshAcceleratorData( - const std::vector<ash::AcceleratorData>& accelerators) { - base::MD5Context context; - base::MD5Init(&context); - for (const auto& accelerator : accelerators) { - base::MD5Update(&context, AshAcceleratorDataToString(accelerator)); - } - - base::MD5Digest digest; - base::MD5Final(&digest, &context); - return MD5DigestToBase16(digest); -} - class AcceleratorLayoutMetadataTest : public testing::Test { public: AcceleratorLayoutMetadataTest() = default; @@ -182,7 +169,7 @@ std::stable_sort(ash_accelerators.begin(), ash_accelerators.end(), AshAcceleratorDataCmp()); const std::string ash_accelerators_hash = - HashAshAcceleratorData(ash_accelerators); + ash::StableHashOfCollection(ash_accelerators, AshAcceleratorDataToString); EXPECT_EQ(ash_accelerators_hash, kAshAcceleratorsHash) << kCommonMessage << "kAshAcceleratorsHash=\"" << ash_accelerators_hash << "\"\n";
diff --git a/base/BUILD.gn b/base/BUILD.gn index 02ac517..3b5e3da6 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -4573,7 +4573,7 @@ "android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionDelegate.java", "android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionFactory.java", "android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java", - "android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java", + "android/java/src/org/chromium/base/process_launcher/RebindServiceConnection.java", ] } @@ -4596,6 +4596,7 @@ # do no append to this list. sources = [ "android/java/src/org/chromium/base/ApkAssets.java", + "android/java/src/org/chromium/base/BaseFeatureList.java", "android/java/src/org/chromium/base/BaseFeatureMap.java", "android/java/src/org/chromium/base/BinderCallsListener.java", "android/java/src/org/chromium/base/CallbackController.java", @@ -5302,7 +5303,9 @@ android_aidl("process_launcher_aidl") { import_include = [ "android/java/src" ] sources = [ + "android/java/src/org/chromium/base/process_launcher/IChildProcessArgs.aidl", "android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl", + "android/java/src/org/chromium/base/process_launcher/IFileDescriptorInfo.aidl", "android/java/src/org/chromium/base/process_launcher/IParentProcess.aidl", ] }
diff --git a/base/allocator/partition_allocator/buckets.md b/base/allocator/partition_allocator/buckets.md index ae3536b..97ce6f11 100644 --- a/base/allocator/partition_allocator/buckets.md +++ b/base/allocator/partition_allocator/buckets.md
@@ -77,6 +77,12 @@ manner up to nearly 256 bytes. This pattern then repeats for sizes above 256 bytes, then 512 bytes, and so forth. +||Order-Index 0|Order-Index 1|Order-Index 2|Order-Index 3|Order-Index 4|Order-Index 5|Order-Index 6|Order-Index 7| +|-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| +|Order 8 (2⁷)|121-128|129-144|145-160|161-176|177-192|193-208|209-224|225-240| +|Order 9 (2⁸)|241-256|257-288|289-320|321-352|353-384|385-416|417-448|449-480| +|Order 10 (2⁹)|481-512|513-576|577-640|641-704|705-768|769-832|833-896|897-960| + ## Neutral Bucket Distribution The Neutral Bucket Distribution offers a sparser alternative, derived from the @@ -97,7 +103,7 @@ ### 8 Bytes Alignment (Typically 32-bit Systems) -| Index | Size | Bucket Distribution | Note | +| Index | Size | Bucket Distribution | Originating Formula | | -: | -: | :- | :- | | 0 | 8 | `kNeutral` and `kDenser` | linear [8 x 1] | | 1 | 16 | `kNeutral` and `kDenser` | linear [8 x 2] | @@ -217,11 +223,11 @@ | 115 | 786432 | `kNeutral` and `kDenser` | exponential [2¹⁹ x (1 + ½)] | | 116 | 851968 | `kDenser` only | exponential [2¹⁹ x (1 + ⅝)] | | 117 | 917504 | `kNeutral` and `kDenser` | exponential [2¹⁹ x (1 + ¾)] | -| 118 | 983040 | `kDenser` only | exponential [2¹⁹ x (1 + ⅞)] | +| 118 | 983040 | `kNeutral` and `kDenser` | exponential [2¹⁹ x (1 + ⅞)] | -### 8 Bytes Alignment (Typically 64-bit Systems) +### 16 Bytes Alignment (Typically 64-bit Systems) -| Index | Size | Bucket Distribution | Note | +| Index | Size | Bucket Distribution | Originating Formula | | -: | -: | :- | :- | | 0 | 16 | `kNeutral` and `kDenser` | linear [16 x 1] | | 1 | 32 | `kNeutral` and `kDenser` | linear [16 x 2] |
diff --git a/base/allocator/partition_allocator/src/partition_alloc/page_allocator_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/page_allocator_unittest.cc index c136658..5c5bc31 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/page_allocator_unittest.cc +++ b/base/allocator/partition_allocator/src/partition_alloc/page_allocator_unittest.cc
@@ -561,7 +561,13 @@ FreePages(buffer, size); } -TEST(PartitionAllocPageAllocatorTest, DecommitAndZero) { +// TODO(crbug.com/416151077): Enabled the test on UBSan. +#if defined(UNDEFINED_SANITIZER) +#define MAYBE_DecommitAndZero DISABLED_DecommitAndZero +#else +#define MAYBE_DecommitAndZero DecommitAndZero +#endif +TEST(PartitionAllocPageAllocatorTest, MAYBE_DecommitAndZero) { size_t size = PageAllocationGranularity(); uintptr_t buffer = AllocPages(size, PageAllocationGranularity(), PageAccessibilityConfiguration(
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h index 36c74fa..94a565b 100644 --- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h +++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/component_export.h
@@ -39,7 +39,7 @@ #define PA_COMPONENT_IMPORT_ANNOTATION __declspec(dllimport) #else // defined(WIN32) #define PA_COMPONENT_EXPORT_ANNOTATION __attribute__((visibility("default"))) -#define PA_COMPONENT_IMPORT_ANNOTATION +#define PA_COMPONENT_IMPORT_ANNOTATION __attribute__((visibility("default"))) #endif // defined(WIN32) #else // defined(COMPONENT_BUILD) #define PA_COMPONENT_EXPORT_ANNOTATION
diff --git a/base/android/base_feature_map.cc b/base/android/base_feature_map.cc index 48c27157..c1cfeb15 100644 --- a/base/android/base_feature_map.cc +++ b/base/android/base_feature_map.cc
@@ -19,6 +19,7 @@ &features::kBackgroundNotPerceptibleBinding, &features::kPostPowerMonitorBroadcastReceiverInitToBackground, &features::kPostGetMyMemoryStateToBackground, + &features::kUseSharedRebindServiceConnection, }; // static
diff --git a/base/android/content_uri_utils.cc b/base/android/content_uri_utils.cc index be84f86..59bc6cc 100644 --- a/base/android/content_uri_utils.cc +++ b/base/android/content_uri_utils.cc
@@ -54,13 +54,28 @@ } } -int OpenContentUri(const FilePath& content_uri, uint32_t open_flags) { - JNIEnv* env = base::android::AttachCurrentThread(); +ScopedJavaLocalRef<jobject> OpenContentUri(const FilePath& content_uri, + uint32_t open_flags) { + JNIEnv* env = android::AttachCurrentThread(); auto mode = TranslateOpenFlagsToJavaMode(open_flags); CHECK(mode.has_value()) << "Unsupported flags=0x" << std::hex << open_flags; return Java_ContentUriUtils_openContentUri(env, content_uri.value(), *mode); } +int ContentUriGetFd(const JavaRef<jobject>& java_parcel_file_descriptor) { + if (!java_parcel_file_descriptor) { + return -1; + } + JNIEnv* env = android::AttachCurrentThread(); + int fd = Java_ContentUriUtils_getFd(env, java_parcel_file_descriptor); + return dup(fd); +} + +void ContentUriClose(const JavaRef<jobject>& java_parcel_file_descriptor) { + JNIEnv* env = android::AttachCurrentThread(); + Java_ContentUriUtils_close(env, java_parcel_file_descriptor); +} + bool ContentUriGetFileInfo(const FilePath& content_uri, FileEnumerator::FileInfo* info) { JNIEnv* env = android::AttachCurrentThread();
diff --git a/base/android/content_uri_utils.h b/base/android/content_uri_utils.h index 9663cd4..d0f8b58 100644 --- a/base/android/content_uri_utils.h +++ b/base/android/content_uri_utils.h
@@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/android/scoped_java_ref.h" #include "base/base_export.h" #include "base/files/file.h" #include "base/files/file_enumerator.h" @@ -28,10 +29,22 @@ BASE_EXPORT std::optional<std::string> TranslateOpenFlagsToJavaMode( uint32_t open_flags); -// Opens a content URI and returns the file descriptor to the caller. +// Opens a content URI and returns the Java ParcelFileDescriptor to the caller +// which will own the object. Callers should call ContentUriGetFd() to get the +// platform file descriptor, and call ContentUriClose() when the file is closed. // `open_flags` is a bitmap of File::FLAG_* values. -// Returns -1 if the URI is invalid. -int OpenContentUri(const FilePath& content_uri, uint32_t open_flags); +// Returns null if the URI is invalid. +base::android::ScopedJavaLocalRef<jobject> OpenContentUri( + const FilePath& content_uri, + uint32_t open_flags); + +// Returns the platform FD or -1 if `java_parcel_file_descriptor` is invalid. +int ContentUriGetFd( + const base::android::JavaRef<jobject>& java_parcel_file_descriptor); + +// Closes `java_parcel_file_descriptor`. +void ContentUriClose( + const base::android::JavaRef<jobject>& java_parcel_file_descriptor); // Returns true if file exists and results are populated, else returns false. bool ContentUriGetFileInfo(const FilePath& content_uri,
diff --git a/base/android/java/src/org/chromium/base/BaseFeatureList.java b/base/android/java/src/org/chromium/base/BaseFeatureList.java new file mode 100644 index 0000000..e1750dbbb --- /dev/null +++ b/base/android/java/src/org/chromium/base/BaseFeatureList.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.base; + +import org.chromium.build.annotations.NullMarked; + +/** Convenience static methods to access {@link BaseFeatureMap}. */ +@NullMarked +public class BaseFeatureList { + private BaseFeatureList() {} + + public static final MutableFlagWithSafeDefault sUseSharedRebindServiceConnection = + new MutableFlagWithSafeDefault( + BaseFeatureMap.getInstance(), + BaseFeatures.USE_SHARED_REBIND_SERVICE_CONNECTION, + false); + + public static final MutableIntParamWithSafeDefault sMaxDeferredSharedRebindServiceConnection = + sUseSharedRebindServiceConnection.newIntParam("max-deferred-bindings", 0); +}
diff --git a/base/android/java/src/org/chromium/base/ContentUriUtils.java b/base/android/java/src/org/chromium/base/ContentUriUtils.java index ed630ed..630a4b42 100644 --- a/base/android/java/src/org/chromium/base/ContentUriUtils.java +++ b/base/android/java/src/org/chromium/base/ContentUriUtils.java
@@ -12,6 +12,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build; +import android.os.ParcelFileDescriptor; import android.provider.DocumentsContract; import android.provider.MediaStore; import android.text.TextUtils; @@ -55,13 +56,20 @@ * @return file descriptor upon success, or -1 otherwise. */ @CalledByNative - public static int openContentUri( + public static @Nullable ParcelFileDescriptor openContentUri( @JniType("std::string") String uriString, @JniType("std::string") String mode) { AssetFileDescriptor afd = getAssetFileDescriptor(uriString, mode); - if (afd != null) { - return afd.getParcelFileDescriptor().detachFd(); - } - return -1; + return afd != null ? afd.getParcelFileDescriptor() : null; + } + + @CalledByNative + private static int getFd(ParcelFileDescriptor parcelFileDescriptor) { + return parcelFileDescriptor.getFd(); + } + + @CalledByNative + private static void close(ParcelFileDescriptor parcelFileDescriptor) { + StreamUtil.closeQuietly(parcelFileDescriptor); } /**
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index af32e358f..a8f0dd8 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -364,13 +364,15 @@ /** * Optionally puts the RELRO section information so that it can be memory-mapped in another * process reading the bundle. + * * @param bundle Where to serialize. */ - public void putSharedRelrosToBundle(Bundle bundle) { + public @Nullable Bundle getSharedRelrosBundle() { assert mInitDone; if (useChromiumLinker()) { - getLinker().putSharedRelrosToBundle(bundle); + return getLinker().getSharedRelrosBundle(); } + return null; } private String creationAsString() {
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java index 7be4710b..076ba81 100644 --- a/base/android/java/src/org/chromium/base/library_loader/Linker.java +++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -67,7 +67,7 @@ * initialization runs implicitly as part of loading the library. In this case the behaviour is of * a producer. * - * - After loading the native library as a RELRO producer, the putSharedRelrosToBundle() becomes + * - After loading the native library as a RELRO producer, the getSharedRelroBundle() becomes * available to then send the Bundle to Linkers in other processes, consumed * by takeSharedRelrosFromBundle(). */ @@ -81,10 +81,6 @@ // Constant guarding debug logging. private static final boolean DEBUG = LibraryLoader.DEBUG; - // Constants used to pass the shared RELRO Bundle through Binder. - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - static final String SHARED_RELROS = "org.chromium.base.android.linker.shared_relros"; - private static final String BASE_LOAD_ADDRESS = "org.chromium.base.android.linker.base_load_address"; @@ -405,39 +401,40 @@ /** * Serializes information about the RELRO region to be passed to a Linker in another process. - * @param bundle The Bundle to serialize to. + * + * @param args The IChildProcessArgs to serialize to. */ - void putSharedRelrosToBundle(Bundle bundle) { + @Nullable Bundle getSharedRelrosBundle() { Bundle relros = null; synchronized (mLock) { - if (DEBUG) Log.i(TAG, "putSharedRelrosToBundle: state=%d", mState); + if (DEBUG) Log.i(TAG, "getSharedRelrosBundle: state=%d", mState); if (mState == State.DONE_PROVIDE_RELRO) { assert mRelroProducer; relros = assumeNonNull(mLocalLibInfo).toBundle(); } - bundle.putBundle(SHARED_RELROS, relros); if (DEBUG && relros != null) { assert mLocalLibInfo != null; Log.i( TAG, - "putSharedRelrosToBundle() puts mLoadAddress=0x%x, mLoadSize=%d, " + "getSharedRelrosBundle() puts mLoadAddress=0x%x, mLoadSize=%d, " + "mRelroFd=%d", mLocalLibInfo.mLoadAddress, mLocalLibInfo.mLoadSize, mLocalLibInfo.mRelroFd); } } + return relros; } /** - * Deserializes the RELRO region information that was marshalled by - * {@link #putLoadAddressToBundle(Bundle)} and wakes up the threads waiting for it to replace - * the RELRO section in this process with shared memory. + * Deserializes the RELRO region information that was marshalled by {@link + * #putLoadAddressToBundle(Bundle)} and wakes up the threads waiting for it to replace the RELRO + * section in this process with shared memory. + * * @param bundle The Bundle to extract the information from. */ - void takeSharedRelrosFromBundle(Bundle bundle) { - if (DEBUG) Log.i(TAG, "called takeSharedRelrosFromBundle(%s)", bundle); - Bundle relros = bundle.getBundle(SHARED_RELROS); + void takeSharedRelrosFromBundle(Bundle relros) { + if (DEBUG) Log.i(TAG, "called takeSharedRelrosFromBundle(%s)", relros); if (relros == null) return; LibInfo newRemote = LibInfo.fromBundle(relros); if (newRemote == null) return;
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java index 0c29acd5..a1f07e5 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
@@ -21,6 +21,7 @@ import androidx.annotation.IntDef; import androidx.annotation.VisibleForTesting; +import org.chromium.base.BaseFeatureList; import org.chromium.base.BaseFeatureMap; import org.chromium.base.BaseFeatures; import org.chromium.base.BuildInfo; @@ -185,6 +186,7 @@ // Cache BackgroundNotPerceptibleBinding feature flag value. private static @Nullable Boolean sUseBackgroundNotPerceptibleBinding; + private static @Nullable RebindServiceConnection sRebindServiceConnection; // Lock to protect all the fields that can be accessed outside launcher thread. private final Object mBindingStateLock = new Object(); @@ -192,6 +194,7 @@ private final Executor mLauncherExecutor; private ComponentName mServiceName; private final @Nullable ComponentName mFallbackServiceName; + private @Nullable Intent mBindIntent; // Parameters passed to the child process through the service binding intent. // If the service gets recreated by the framework the intent will be reused, so these parameters @@ -203,15 +206,15 @@ private final boolean mBindToCaller; private static class ConnectionParams { - final Bundle mConnectionBundle; + final IChildProcessArgs mChildProcessArgs; final @Nullable List<IBinder> mClientInterfaces; final @Nullable IBinder mBinderBox; ConnectionParams( - Bundle connectionBundle, + IChildProcessArgs childProcessArgs, @Nullable List<IBinder> clientInterfaces, @Nullable IBinder binderBox) { - mConnectionBundle = connectionBundle; + mChildProcessArgs = childProcessArgs; mClientInterfaces = clientInterfaces; mBinderBox = binderBox; } @@ -281,8 +284,8 @@ // inconvenient to log some histogram where this information is available. private final boolean mIsSandboxedForHistograms; - // Use Context.BIND_EXTERNAL_SERVICE flag for this service. - private final boolean mBindAsExternalService; + // The service binding flags for the default binding (i.e. visible binding). + private final int mDefaultBindFlags; // Strong binding will make the service priority equal to the priority of the activity. private ChildServiceConnection mStrongBinding; @@ -389,7 +392,11 @@ mIsSandboxedForHistograms = isSandboxedForHistograms; // Incremental install does not work with isolatedProcess, and externalService requires // isolatedProcess, so both need to be turned off for incremental install. - mBindAsExternalService = bindAsExternalService && !BuildConfig.IS_INCREMENTAL_INSTALL; + mDefaultBindFlags = + Context.BIND_AUTO_CREATE + | ((bindAsExternalService && !BuildConfig.IS_INCREMENTAL_INSTALL) + ? Context.BIND_EXTERNAL_SERVICE + : 0); if (connectionFactory == null) { mConnectionFactory = new ChildServiceConnectionFactory() { @@ -443,39 +450,35 @@ } private void createBindings(ComponentName serviceName) { - Intent intent = new Intent(); - intent.setComponent(serviceName); + mBindIntent = new Intent(); + mBindIntent.setComponent(serviceName); if (mServiceBundle != null) { - intent.putExtras(mServiceBundle); + mBindIntent.putExtras(mServiceBundle); } - int defaultFlags = - Context.BIND_AUTO_CREATE - | (mBindAsExternalService ? Context.BIND_EXTERNAL_SERVICE : 0); - mVisibleBinding = mConnectionFactory.createConnection( - intent, defaultFlags, mConnectionDelegate, mInstanceName); + mBindIntent, mDefaultBindFlags, mConnectionDelegate, mInstanceName); if (supportNotPerceptibleBinding()) { - int flags = defaultFlags | Context.BIND_NOT_PERCEPTIBLE; + int flags = mDefaultBindFlags | Context.BIND_NOT_PERCEPTIBLE; if (useBackgroundNotPerceptibleBinding()) { flags |= Context.BIND_NOT_FOREGROUND; } mNotPerceptibleBinding = mConnectionFactory.createConnection( - intent, flags, mConnectionDelegate, mInstanceName); + mBindIntent, flags, mConnectionDelegate, mInstanceName); } mStrongBinding = mConnectionFactory.createConnection( - intent, - defaultFlags | Context.BIND_IMPORTANT, + mBindIntent, + mDefaultBindFlags | Context.BIND_IMPORTANT, mConnectionDelegate, mInstanceName); mWaivedBinding = mConnectionFactory.createConnection( - intent, - defaultFlags | Context.BIND_WAIVE_PRIORITY, + mBindIntent, + mDefaultBindFlags | Context.BIND_WAIVE_PRIORITY, mConnectionDelegate, mInstanceName); } @@ -569,14 +572,26 @@ assert isRunningOnLauncherThread(); if (!isConnected()) return; assert mWaivedBinding.isBound(); - mWaivedBinding.bindServiceConnection(); + if (BaseFeatureList.sUseSharedRebindServiceConnection.isEnabled()) { + if (sRebindServiceConnection == null) { + sRebindServiceConnection = + new RebindServiceConnection( + BaseFeatureList.sMaxDeferredSharedRebindServiceConnection + .getValue()); + } + assert mBindIntent != null; + sRebindServiceConnection.rebind( + mBindIntent, mDefaultBindFlags | Context.BIND_WAIVE_PRIORITY, mInstanceName); + } else { + mWaivedBinding.bindServiceConnection(); + } } /** * Sets-up the connection after it was started with start(). * - * @param connectionBundle a bundle passed to the service that can be used to pass various - * parameters to the service + * @param childProcessArgs an aidl interface with all miscellaneous parameters for the child + * process connection. * @param clientInterfaces optional client specified interfaces that the child can use to * communicate with the parent process * @param binderBox optional binder box the child can use to unpack additional binders @@ -585,7 +600,7 @@ * @param zygoteInfoCallback will be called exactly once after the connection is set up */ public void setupConnection( - Bundle connectionBundle, + IChildProcessArgs childProcessArgs, @Nullable List<IBinder> clientInterfaces, @Nullable IBinder binderBox, ConnectionCallback connectionCallback, @@ -600,7 +615,7 @@ try (TraceEvent te = TraceEvent.scoped("ChildProcessConnection.setupConnection")) { mConnectionCallback = connectionCallback; mZygoteInfoCallback = zygoteInfoCallback; - mConnectionParams = new ConnectionParams(connectionBundle, clientInterfaces, binderBox); + mConnectionParams = new ConnectionParams(childProcessArgs, clientInterfaces, binderBox); // Run the setup if the service is already connected. If not, doConnectionSetup() will // be called from onServiceConnected(). if (mServiceConnectComplete) { @@ -882,7 +897,7 @@ }; try { mService.setupConnection( - mConnectionParams.mConnectionBundle, + mConnectionParams.mChildProcessArgs, parentProcess, mConnectionParams.mClientInterfaces, mConnectionParams.mBinderBox); @@ -1015,6 +1030,8 @@ if (mNotPerceptibleBinding != null) { mNotPerceptibleBinding.retire(); } + // We must clear shared waived binding when we unbind a waived binding. + clearSharedWaivedBinding(); mWaivedBinding.retire(); createBindings(mFallbackServiceName); } @@ -1026,6 +1043,8 @@ mConnectionParams = null; mUnbound = true; mStrongBinding.unbindServiceConnection(); + // We must clear shared waived binding when we unbind a waived binding. + clearSharedWaivedBinding(); mWaivedBinding.unbindServiceConnection(); if (mNotPerceptibleBinding != null) { mNotPerceptibleBinding.unbindServiceConnection(); @@ -1046,16 +1065,22 @@ } } - public void updateGroupImportance(int group, int importanceInGroup) { + private void clearSharedWaivedBinding() { + assert isRunningOnLauncherThread(); + if (sRebindServiceConnection != null) { + sRebindServiceConnection.unbind(); + } + } + + public boolean updateGroupImportance(int group, int importanceInGroup) { assert isRunningOnLauncherThread(); assert group != 0 || importanceInGroup == 0; if (mGroup != group || mImportanceInGroup != importanceInGroup) { mGroup = group; mImportanceInGroup = importanceInGroup; - if (isConnected()) { - mWaivedBinding.updateGroupImportance(group, importanceInGroup); - } + return isConnected() && mWaivedBinding.updateGroupImportance(group, importanceInGroup); } + return false; } public int getGroup() {
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java index 8cc6e3c..7f150e0 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java
@@ -16,16 +16,6 @@ public static final String EXTRA_BIND_TO_CALLER = "org.chromium.base.process_launcher.extra.bind_to_caller"; - // Below are the names for the items placed in the Bundle passed in the - // IChildProcessService.setupConnection call, once the connection has been established. - - // Key for the command line. - public static final String EXTRA_COMMAND_LINE = - "org.chromium.base.process_launcher.extra.command_line"; - - // Key for the file descriptors that should be mapped in the child process. - public static final String EXTRA_FILES = "org.chromium.base.process_launcher.extra.extraFiles"; - // Key for the browser package name. public static final String EXTRA_BROWSER_PACKAGE_NAME = "org.chromium.base.process_launcher.extra.browser_package_name";
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java index 6327a9c..73c889e 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java
@@ -57,14 +57,16 @@ /** * Called before setup is called on the connection. - * @param connectionBundle the bundle passed to the {@link ChildProcessService} in the - * setup call. Clients can add their own extras to the bundle. + * + * @param childProcessArgs the aidl parcelable passed to the {@link ChildProcessService} in + * the setup call. */ - public void onBeforeConnectionSetup(Bundle connectionBundle) {} + public void onBeforeConnectionSetup(IChildProcessArgs childProcessArgs) {} /** * Called when the connection was successfully established, meaning the setup call on the * service was successful. + * * @param connection the connection over which the setup call was made. */ public void onConnectionEstablished(ChildProcessConnection connection) {} @@ -95,7 +97,7 @@ private final Delegate mDelegate; private final String[] mCommandLine; - private final FileDescriptorInfo[] mFilesToBeMapped; + private final IFileDescriptorInfo[] mFilesToBeMapped; // The allocator used to create the connection. private final ChildConnectionAllocator mConnectionAllocator; @@ -126,7 +128,7 @@ Handler launcherHandler, Delegate delegate, String[] commandLine, - FileDescriptorInfo[] filesToBeMapped, + IFileDescriptorInfo[] filesToBeMapped, ChildConnectionAllocator connectionAllocator, @Nullable List<IBinder> clientInterfaces, @Nullable IBinder binderBox) { @@ -258,10 +260,10 @@ onServiceConnected(connection); } }; - Bundle connectionBundle = createConnectionBundle(); - mDelegate.onBeforeConnectionSetup(connectionBundle); + IChildProcessArgs connectionArgs = createConnectionArgs(); + mDelegate.onBeforeConnectionSetup(connectionArgs); mConnection.setupConnection( - connectionBundle, + connectionArgs, getClientInterfaces(), getBinderBox(), connectionCallback, @@ -280,7 +282,7 @@ // Proactively close the FDs rather than waiting for the GC to do it. try { - for (FileDescriptorInfo fileInfo : mFilesToBeMapped) { + for (IFileDescriptorInfo fileInfo : mFilesToBeMapped) { fileInfo.fd.close(); } } catch (IOException ioe) { @@ -306,11 +308,11 @@ return mLauncherHandler.getLooper() == Looper.myLooper(); } - private Bundle createConnectionBundle() { - Bundle bundle = new Bundle(); - bundle.putStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE, mCommandLine); - bundle.putParcelableArray(ChildProcessConstants.EXTRA_FILES, mFilesToBeMapped); - return bundle; + private IChildProcessArgs createConnectionArgs() { + IChildProcessArgs args = new IChildProcessArgs(); + args.commandLine = mCommandLine; + args.fileDescriptorInfos = mFilesToBeMapped; + return args; } private void onChildProcessDied() {
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java index 1862aed..d4c5f63 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java
@@ -16,7 +16,6 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; -import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; @@ -102,7 +101,7 @@ private String @Nullable [] mCommandLineParams; // File descriptors that should be registered natively. - private FileDescriptorInfo @Nullable [] mFdInfos; + private IFileDescriptorInfo @Nullable [] mFdInfos; @GuardedBy("mLibraryInitializedLock") private boolean mLibraryInitialized; @@ -160,7 +159,7 @@ @Override public void setupConnection( - Bundle args, + IChildProcessArgs args, IParentProcess parentProcess, List<IBinder> callbacks, IBinder binderBox) @@ -186,8 +185,7 @@ m.initInChildProcess(); // In a number of cases the app zygote decides not to produce a RELRO FD. // The bundle will tell the receiver to silently ignore it. - relroBundle = new Bundle(); - m.putSharedRelrosToBundle(relroBundle); + relroBundle = m.getSharedRelrosBundle(); } // After finishSetupConnection() the parent process will stop accepting // |relroBundle| from this process to ensure that another FD to shared memory @@ -332,7 +330,7 @@ long[] regionOffsets = new long[mFdInfos.length]; long[] regionSizes = new long[mFdInfos.length]; for (int i = 0; i < mFdInfos.length; i++) { - FileDescriptorInfo fdInfo = mFdInfos[i]; + IFileDescriptorInfo fdInfo = mFdInfos[i]; String key = idsToKeys != null ? idsToKeys.get(fdInfo.id) : null; if (key != null) { keys[i] = key; @@ -426,27 +424,19 @@ } private void processConnectionBundle( - Bundle bundle, List<IBinder> clientInterfaces, IBinder binderBox) { - // Required to unparcel FileDescriptorInfo. - ClassLoader classLoader = getApplicationContext().getClassLoader(); - bundle.setClassLoader(classLoader); + IChildProcessArgs args, List<IBinder> clientInterfaces, IBinder binderBox) { synchronized (mMainThread) { if (mCommandLineParams == null) { - mCommandLineParams = - bundle.getStringArray(ChildProcessConstants.EXTRA_COMMAND_LINE); + mCommandLineParams = args.commandLine; mMainThread.notifyAll(); } // We must have received the command line by now assert mCommandLineParams != null; - Parcelable[] fdInfosAsParcelable = - bundle.getParcelableArray(ChildProcessConstants.EXTRA_FILES); - if (fdInfosAsParcelable != null) { - // For why this arraycopy is necessary: - // http://stackoverflow.com/questions/8745893/i-dont-get-why-this-classcastexception-occurs - mFdInfos = new FileDescriptorInfo[fdInfosAsParcelable.length]; - System.arraycopy(fdInfosAsParcelable, 0, mFdInfos, 0, fdInfosAsParcelable.length); + IFileDescriptorInfo[] fdInfos = args.fileDescriptorInfos; + if (fdInfos != null) { + mFdInfos = fdInfos; } - mDelegate.onConnectionSetup(bundle, clientInterfaces, binderBox); + mDelegate.onConnectionSetup(args, clientInterfaces, binderBox); mMainThread.notifyAll(); } }
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java index 2bb8eed6..00069eba 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java
@@ -34,7 +34,7 @@ * @param binderBox an optional binder box which may contain other binders to be unpacked */ void onConnectionSetup( - Bundle connectionBundle, List<IBinder> clientInterfaces, IBinder binderBox); + IChildProcessArgs connectionArgs, List<IBinder> clientInterfaces, IBinder binderBox); /** * Called when the delegate should load the native library.
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java index 0b4a281..aca11232 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java
@@ -15,7 +15,14 @@ boolean isBound(); - void updateGroupImportance(int group, int importanceInGroup); + /** + * Calls `Context.updateServiceGroup()` if possible. + * + * <p>Returns `true` if the call succeeds. + * + * <p>Note that we need to rebind a service binding for the process to apply the change of this. + */ + boolean updateGroupImportance(int group, int importanceInGroup); void retire(); }
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java index a3576825..73375d08 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java +++ b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java
@@ -83,7 +83,7 @@ } @Override - public void updateGroupImportance(int group, int importanceInGroup) { + public boolean updateGroupImportance(int group, int importanceInGroup) { // ChildProcessConnection checks there is a real connection to the service before calling // this, and this `isBound` check should in theory be unnecessary. However this is still // tripped on some devices where another service connection bound successfully but this @@ -91,20 +91,19 @@ // behavior and is not handled. However, avoid crashing in `updateServiceGroup` by doing // this check here. if (!isBound()) { - return; + return false; } if (BindService.supportVariableConnections()) { try { mContext.updateServiceGroup(this, group, importanceInGroup); + return true; } catch (IllegalArgumentException e) { // There is an unavoidable race here binding might be removed for example due to a // crash, which has not been processed on the launcher thread. // Ignore these. See crbug.com/1026626 and crbug.com/1026626 for context. - return; } - BindService.doBindService( - mContext, mBindIntent, this, mBindFlags, mHandler, mExecutor, mInstanceName); } + return false; } @Override
diff --git a/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.aidl b/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.aidl deleted file mode 100644 index 033b792..0000000 --- a/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.aidl +++ /dev/null
@@ -1,7 +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. - -package org.chromium.base.process_launcher; - -parcelable FileDescriptorInfo;
diff --git a/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java b/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java deleted file mode 100644 index 5ecf70c..0000000 --- a/base/android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java +++ /dev/null
@@ -1,70 +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. - -package org.chromium.base.process_launcher; - -import android.os.Parcel; -import android.os.ParcelFileDescriptor; -import android.os.Parcelable; - -import org.chromium.build.annotations.NullMarked; -import org.chromium.build.annotations.UsedByReflection; - -import javax.annotation.concurrent.Immutable; - -/** - * Parcelable class that contains file descriptor and file region information to be passed to child - * processes. - */ -@Immutable -@UsedByReflection("child_process_launcher_helper_android.cc") -@NullMarked -public final class FileDescriptorInfo implements Parcelable { - public final int id; - public final ParcelFileDescriptor fd; - public final long offset; - public final long size; - - public FileDescriptorInfo(int id, ParcelFileDescriptor fd, long offset, long size) { - this.id = id; - this.fd = fd; - this.offset = offset; - this.size = size; - } - - FileDescriptorInfo(Parcel in) { - id = in.readInt(); - ParcelFileDescriptor gotFd = in.readParcelable(ParcelFileDescriptor.class.getClassLoader()); - assert gotFd != null; - fd = gotFd; - offset = in.readLong(); - size = in.readLong(); - } - - @Override - public int describeContents() { - return CONTENTS_FILE_DESCRIPTOR; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(id); - dest.writeParcelable(fd, CONTENTS_FILE_DESCRIPTOR); - dest.writeLong(offset); - dest.writeLong(size); - } - - public static final Parcelable.Creator<FileDescriptorInfo> CREATOR = - new Parcelable.Creator<FileDescriptorInfo>() { - @Override - public FileDescriptorInfo createFromParcel(Parcel in) { - return new FileDescriptorInfo(in); - } - - @Override - public FileDescriptorInfo[] newArray(int size) { - return new FileDescriptorInfo[size]; - } - }; -}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/IChildProcessArgs.aidl b/base/android/java/src/org/chromium/base/process_launcher/IChildProcessArgs.aidl new file mode 100644 index 0000000..0e56472 --- /dev/null +++ b/base/android/java/src/org/chromium/base/process_launcher/IChildProcessArgs.aidl
@@ -0,0 +1,16 @@ +// 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.base.process_launcher; + +import org.chromium.base.process_launcher.IFileDescriptorInfo; + +parcelable IChildProcessArgs { + int cpuCount; + long cpuFeatures; + String[] commandLine; + IFileDescriptorInfo[] fileDescriptorInfos; + // TODO(crbug.com/414609682): Convert this to something which is compatible with NDK aidl. + Bundle relroBundle; +}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl b/base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl index 02dddd10..b57f7e28 100644 --- a/base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl +++ b/base/android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl
@@ -4,9 +4,9 @@ package org.chromium.base.process_launcher; -import android.content.pm.ApplicationInfo; -import android.os.Bundle; +import android.os.PersistableBundle; +import org.chromium.base.process_launcher.IChildProcessArgs; import org.chromium.base.process_launcher.IParentProcess; interface IChildProcessService { @@ -22,8 +22,8 @@ ApplicationInfo getAppInfo(); // Sets up the initial IPC channel. - oneway void setupConnection(in Bundle args, IParentProcess parentProcess, - in List<IBinder> clientInterfaces, in IBinder binderBox); + oneway void setupConnection(in IChildProcessArgs args, in IParentProcess parentProcess, + in @nullable List<IBinder> clientInterfaces, in @nullable IBinder binderBox); // Forcefully kills the child process. oneway void forceKill();
diff --git a/base/android/java/src/org/chromium/base/process_launcher/IFileDescriptorInfo.aidl b/base/android/java/src/org/chromium/base/process_launcher/IFileDescriptorInfo.aidl new file mode 100644 index 0000000..19b62999 --- /dev/null +++ b/base/android/java/src/org/chromium/base/process_launcher/IFileDescriptorInfo.aidl
@@ -0,0 +1,12 @@ +// 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.base.process_launcher; + +parcelable IFileDescriptorInfo { + int id; + ParcelFileDescriptor fd; + long offset; + long size; +}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/RebindServiceConnection.java b/base/android/java/src/org/chromium/base/process_launcher/RebindServiceConnection.java new file mode 100644 index 0000000..71b21fa --- /dev/null +++ b/base/android/java/src/org/chromium/base/process_launcher/RebindServiceConnection.java
@@ -0,0 +1,111 @@ +// 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.base.process_launcher; + +import android.content.ComponentName; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Handler; +import android.os.IBinder; + +import org.chromium.base.ContextUtils; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + +import java.util.concurrent.Executor; + +/** + * RebindServiceConnection is to update a bound process in the LRU of the ProcessList of + * OomAdjuster. + * + * <p>`Context.updateServiceGroup()` requires application to rebind the process to apply the change. + * Also rebinding a process moves the process to the more recent position in the ProcessList even + * without `Context.updateServiceGroup()`. + * + * <p>This RebindServiceConnection is a workaround for 2 issues of rebinding ServiceConnection. + * + * <p>* Poorly differentiated concepts of a binding and a connection. + * + * <p>In the public API, a `ServiceConnection` uniquely identifies a binding. However, AMS has an + * additional `ConnectionRecord` concept, where for a given `ServiceConnection`, each + * `Context.bindService()` call creates is a new `ConnectionRecord`. This means that repeatedly + * re-binding with a given `ServiceConnection` will cause `ConnectionRecord` objects to accumulate + * in AMS, and there is a hard limit how many `ConnectionRecord`s a process can have. Unfortunately, + * the only way to free `ConnectionRecord` objects is to unbind the entire connection. This means + * it's necessary to use a dedicated `ServiceConnection` to trigger re-binding for + * `Context.updateServiceGroup()`, as the unbindings necessary to free `ConnectionRecord`s would + * interfere with the lifecycle management of a normal binding. + * + * <p>* Accumulation of un-GC'ed Binder proxies + * + * <p>`LoadedApk$ServiceDispatcher$InnerConnection` is created per new `Context` and + * `ServiceConnection` combination on `Context.bindService()` in the Android SDK. The inner + * connection represents a binder proxy and is GC-ed when GC happened on AMS. Though Binder Proxy is + * GC-ed eventually, if there are too many calls of pairs of `Context.bindService()` and + * `Context.unbindService()` in a short term even with the same `ServiceConnection`, Chrome can be + * killed due to too many Binder Proxy remaining. + * + * <p>To prevent the first issue, `ChildProcessConnection` uses this short living service connection + * `RebindServiceConnection` and `RebindServiceConnection.rebind()` unbinds itself just after + * binding it if maxDeferredConnections is zero. + * + * <p>If the second issue is problematic, RebindServiceConnection supports deferring unbinding so + * that it can be reused for multiple processes without increasing the Binder Proxy by setting + * maxDeferredConnections as non-zero. The `ConnectionRecord`s in AMS are cleared when the number of + * deferred connections reaches to maxDeferredConnections. + * + * <p>When `ChildProcessConnection` wants to kill the process (e.g. `unbind()`), keeping the + * deferred connections prevents the process from being freed by AMS. `ChildProcessConnection` have + * to call `RebindServiceConnection.unbind()` to clear all deferred connections when + * `ChildProcessConnection` unbinds the waived binding to avoid the leak. + */ +@NullMarked +/* package */ final class RebindServiceConnection implements ServiceConnection { + private final int mMaxDeferredConnections; + private int mDeferredConnections; + private final Handler mHandler; + private final Executor mExecutor; + + RebindServiceConnection(int maxDeferredConnections) { + mMaxDeferredConnections = maxDeferredConnections; + mHandler = new Handler(); + mExecutor = + (Runnable runnable) -> { + // We don't mind if the callback is executed on any thread because + // RebindServiceConnection does nothing on its callbacks. + runnable.run(); + }; + } + + void rebind(Intent bindIntent, int bindFlags, @Nullable String instanceName) { + BindService.doBindService( + ContextUtils.getApplicationContext(), + bindIntent, + this, + bindFlags, + mHandler, + mExecutor, + instanceName); + if (mDeferredConnections >= mMaxDeferredConnections) { + ContextUtils.getApplicationContext().unbindService(this); + mDeferredConnections = 0; + } else { + mDeferredConnections += 1; + } + } + + void unbind() { + if (mDeferredConnections > 0) { + ContextUtils.getApplicationContext().unbindService(this); + mDeferredConnections = 0; + } + } + + @Override + public void onServiceConnected(ComponentName name, IBinder service) {} + + @Override + public void onServiceDisconnected(ComponentName name) {} +}
diff --git a/base/android/junit/src/org/chromium/base/library_loader/LinkerTest.java b/base/android/junit/src/org/chromium/base/library_loader/LinkerTest.java index 92a21ea..f610302 100644 --- a/base/android/junit/src/org/chromium/base/library_loader/LinkerTest.java +++ b/base/android/junit/src/org/chromium/base/library_loader/LinkerTest.java
@@ -164,14 +164,12 @@ // Create the bundle following the _internal_ format of the Linker. Not great, but shorter // than factoring out this logic from the Linker only for testing. Bundle relros = libInfo.toBundle(); - Bundle b = new Bundle(); - b.putBundle(Linker.SHARED_RELROS, relros); // Exercise. linker.ensureInitialized( /* asRelroProducer= */ false, PreferAddress.RESERVE_HINT, someAddress); linker.pretendLibraryIsLoadedForTesting(); - linker.takeSharedRelrosFromBundle(b); + linker.takeSharedRelrosFromBundle(relros); // Verify. Assert.assertEquals(
diff --git a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java index 7b23aca4..614fe7f 100644 --- a/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java +++ b/base/android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java
@@ -82,9 +82,10 @@ } @Override - public void updateGroupImportance(int group, int importanceInGroup) { + public boolean updateGroupImportance(int group, int importanceInGroup) { mGroup = group; mImportanceInGroup = importanceInGroup; + return true; } @Override @@ -173,7 +174,7 @@ }) .when(mIChildProcessService) .setupConnection( - or(isNull(), any(Bundle.class)), + or(isNull(), any()), or(isNull(), any()), or(isNull(), any()), or(isNull(), any())); @@ -380,7 +381,7 @@ assertNotNull(mFirstServiceConnection); connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -399,7 +400,7 @@ assertNotNull(mFirstServiceConnection); connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -421,7 +422,7 @@ assertNotNull(mFirstServiceConnection); connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -448,7 +449,7 @@ assertNotNull(mFirstServiceConnection); connection1.start(/* useStrongBinding= */ true, /* serviceCallback= */ null); connection1.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -472,7 +473,7 @@ assertNotNull(mFirstServiceConnection); connection2.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); connection2.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -498,7 +499,7 @@ assertNotNull(mFirstServiceConnection); connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -529,7 +530,7 @@ assertNotNull(mFirstServiceConnection); connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -558,7 +559,7 @@ connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder); connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -577,7 +578,7 @@ connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder); connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -631,7 +632,7 @@ connection.start(/* useStrongBinding= */ false, /* serviceCallback= */ null); mFirstServiceConnection.notifyServiceConnected(mChildProcessServiceBinder); connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback, @@ -682,7 +683,7 @@ } connection.setupConnection( - /* connectionBundle= */ null, + /* childProcessArgs= */ null, /* clientInterfaces= */ null, /* binderBox= */ null, mConnectionCallback,
diff --git a/base/base_export.h b/base/base_export.h index 1df5354..dd4c591 100644 --- a/base/base_export.h +++ b/base/base_export.h
@@ -15,11 +15,7 @@ #endif // defined(BASE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(BASE_IMPLEMENTATION) #define BASE_EXPORT __attribute__((visibility("default"))) -#else -#define BASE_EXPORT -#endif // defined(BASE_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/base/component_export.h b/base/component_export.h index 0c70e8d..649cf45 100644 --- a/base/component_export.h +++ b/base/component_export.h
@@ -39,7 +39,7 @@ #define COMPONENT_IMPORT_ANNOTATION __declspec(dllimport) #else // defined(WIN32) #define COMPONENT_EXPORT_ANNOTATION __attribute__((visibility("default"))) -#define COMPONENT_IMPORT_ANNOTATION +#define COMPONENT_IMPORT_ANNOTATION __attribute__((visibility("default"))) #endif // defined(WIN32) #else // defined(COMPONENT_BUILD) #define COMPONENT_EXPORT_ANNOTATION
diff --git a/base/features.cc b/base/features.cc index 79791ac..97ca3bd 100644 --- a/base/features.cc +++ b/base/features.cc
@@ -118,6 +118,12 @@ BASE_FEATURE(kPostGetMyMemoryStateToBackground, "PostGetMyMemoryStateToBackground", FEATURE_ENABLED_BY_DEFAULT); + +// Use shared service connection to rebind a service binding to update the LRU +// in the ProcessList of OomAdjuster. +BASE_FEATURE(kUseSharedRebindServiceConnection, + "UseSharedRebindServiceConnection", + FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_ANDROID) void Init(EmitThreadControllerProfilerMetadata
diff --git a/base/features.h b/base/features.h index 0e4c48d..eb3fd68 100644 --- a/base/features.h +++ b/base/features.h
@@ -37,6 +37,7 @@ BASE_EXPORT BASE_DECLARE_FEATURE( kPostPowerMonitorBroadcastReceiverInitToBackground); BASE_EXPORT BASE_DECLARE_FEATURE(kPostGetMyMemoryStateToBackground); +BASE_EXPORT BASE_DECLARE_FEATURE(kUseSharedRebindServiceConnection); #endif #if BUILDFLAG(ENABLE_MUTEX_PRIORITY_INHERITANCE)
diff --git a/base/files/file.cc b/base/files/file.cc index 3847acd..e62d6d40 100644 --- a/base/files/file.cc +++ b/base/files/file.cc
@@ -57,10 +57,15 @@ File::File(File&& other) : file_(other.TakePlatformFile()), +#if BUILDFLAG(IS_ANDROID) + java_parcel_file_descriptor_( + std::move(other.java_parcel_file_descriptor_)), +#endif path_(other.path_), error_details_(other.error_details()), created_(other.created()), - async_(other.async_) {} + async_(other.async_) { +} File::~File() { // Go through the AssertIOAllowed logic. @@ -70,6 +75,9 @@ File& File::operator=(File&& other) { Close(); SetPlatformFile(other.TakePlatformFile()); +#if BUILDFLAG(IS_ANDROID) + java_parcel_file_descriptor_ = std::move(other.java_parcel_file_descriptor_); +#endif path_ = other.path_; error_details_ = other.error_details(); created_ = other.created();
diff --git a/base/files/file.h b/base/files/file.h index e666c56..9ca6817 100644 --- a/base/files/file.h +++ b/base/files/file.h
@@ -20,6 +20,10 @@ #include "base/trace_event/base_tracing_forward.h" #include "build/build_config.h" +#if BUILDFLAG(IS_ANDROID) +#include "base/android/scoped_java_ref.h" +#endif + struct stat; namespace base { @@ -426,6 +430,13 @@ ScopedPlatformFile file_; +#if BUILDFLAG(IS_ANDROID) + // Keeps the Java ParcelFileDescriptor alive when `this` wraps a file from an + // Android content provider (i.e. a content URI). Close() is called on the + // object when the file is closed. + base::android::ScopedJavaGlobalRef<jobject> java_parcel_file_descriptor_; +#endif + // Platform path to `file_`. Set if `this` wraps a file from an Android // content provider (i.e. a content URI) or if tracing is enabled in // `Initialize()`.
diff --git a/base/files/file_posix.cc b/base/files/file_posix.cc index ba5e066..aa4fbd4 100644 --- a/base/files/file_posix.cc +++ b/base/files/file_posix.cc
@@ -258,6 +258,11 @@ SCOPED_FILE_TRACE("Close"); ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK); +#if BUILDFLAG(IS_ANDROID) + if (java_parcel_file_descriptor_) { + internal::ContentUriClose(java_parcel_file_descriptor_); + } +#endif file_.reset(); } @@ -633,7 +638,8 @@ #if BUILDFLAG(IS_ANDROID) if (path.IsContentUri()) { - int fd = internal::OpenContentUri(path, flags); + java_parcel_file_descriptor_ = internal::OpenContentUri(path, flags); + int fd = internal::ContentUriGetFd(java_parcel_file_descriptor_); if (fd < 0) { error_details_ = FILE_ERROR_FAILED; return;
diff --git a/base/i18n/base_i18n_export.h b/base/i18n/base_i18n_export.h index 72afb46c..ced66202 100644 --- a/base/i18n/base_i18n_export.h +++ b/base/i18n/base_i18n_export.h
@@ -15,11 +15,7 @@ #endif // defined(BASE_I18N_IMPLEMENTATION) #else // defined(WIN32) -#if defined(BASE_I18N_IMPLEMENTATION) #define BASE_I18N_EXPORT __attribute__((visibility("default"))) -#else -#define BASE_I18N_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/base/test/android/java/src/org/chromium/base/ITestCallback.aidl b/base/test/android/java/src/org/chromium/base/ITestCallback.aidl index e7936d1..a64c999 100644 --- a/base/test/android/java/src/org/chromium/base/ITestCallback.aidl +++ b/base/test/android/java/src/org/chromium/base/ITestCallback.aidl
@@ -5,7 +5,6 @@ package org.chromium.base; import org.chromium.base.ITestController; -import org.chromium.base.process_launcher.FileDescriptorInfo; /** * This interface is called by the child process to pass its controller to its parent.
diff --git a/base/test/android/java/src/org/chromium/base/ITestController.aidl b/base/test/android/java/src/org/chromium/base/ITestController.aidl index bdcae2e..3cb964f 100644 --- a/base/test/android/java/src/org/chromium/base/ITestController.aidl +++ b/base/test/android/java/src/org/chromium/base/ITestController.aidl
@@ -4,8 +4,6 @@ package org.chromium.base; -import org.chromium.base.process_launcher.FileDescriptorInfo; - /** * This interface is used to control child processes. */
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java index 146efeb1..37d69ac 100644 --- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java +++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java
@@ -18,8 +18,8 @@ import org.chromium.base.process_launcher.ChildConnectionAllocator; import org.chromium.base.process_launcher.ChildProcessConnection; import org.chromium.base.process_launcher.ChildProcessLauncher; -import org.chromium.base.process_launcher.FileDescriptorInfo; import org.chromium.base.process_launcher.IChildProcessService; +import org.chromium.base.process_launcher.IFileDescriptorInfo; import java.io.IOException; import java.util.Arrays; @@ -135,7 +135,7 @@ private Integer mMainReturnCode; private MultiprocessTestClientLauncher( - String[] commandLine, FileDescriptorInfo[] filesToMap, IBinder binderBox) { + String[] commandLine, IFileDescriptorInfo[] filesToMap, IBinder binderBox) { assert isRunningOnLauncherThread(); if (sConnectionAllocator == null) { @@ -218,7 +218,7 @@ @CalledByNative private static int launchClient( final String[] commandLine, - final FileDescriptorInfo[] filesToMap, + final IFileDescriptorInfo[] filesToMap, final IBinder binderBox) { assert Looper.myLooper() != Looper.getMainLooper(); @@ -247,7 +247,7 @@ } private static MultiprocessTestClientLauncher createAndStartLauncherOnLauncherThread( - String[] commandLine, FileDescriptorInfo[] filesToMap, final IBinder binderBox) { + String[] commandLine, IFileDescriptorInfo[] filesToMap, final IBinder binderBox) { assert isRunningOnLauncherThread(); MultiprocessTestClientLauncher launcher = @@ -351,10 +351,10 @@ /** Does not take ownership of of fds. */ @CalledByNative - private static FileDescriptorInfo[] makeFdInfoArray(int[] keys, int[] fds) { - FileDescriptorInfo[] fdInfos = new FileDescriptorInfo[keys.length]; + private static IFileDescriptorInfo[] makeFdInfoArray(int[] keys, int[] fds) { + IFileDescriptorInfo[] fdInfos = new IFileDescriptorInfo[keys.length]; for (int i = 0; i < keys.length; i++) { - FileDescriptorInfo fdInfo = makeFdInfo(keys[i], fds[i]); + IFileDescriptorInfo fdInfo = makeFdInfo(keys[i], fds[i]); if (fdInfo == null) { Log.e(TAG, "Failed to make file descriptor (" + keys[i] + ", " + fds[i] + ")."); return null; @@ -364,7 +364,7 @@ return fdInfos; } - private static FileDescriptorInfo makeFdInfo(int id, int fd) { + private static IFileDescriptorInfo makeFdInfo(int id, int fd) { ParcelFileDescriptor parcelableFd = null; try { parcelableFd = ParcelFileDescriptor.fromFd(fd); @@ -372,7 +372,10 @@ Log.e(TAG, "Invalid FD provided for process connection, aborting connection.", e); return null; } - return new FileDescriptorInfo(id, parcelableFd, /* offset= */ 0, /* size= */ 0); + IFileDescriptorInfo fdInfo = new IFileDescriptorInfo(); + fdInfo.id = id; + fdInfo.fd = parcelableFd; + return fdInfo; } private static boolean isRunningOnLauncherThread() {
diff --git a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java index cf902ec..554841ce0 100644 --- a/base/test/android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java +++ b/base/test/android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java
@@ -13,6 +13,7 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.process_launcher.ChildProcessServiceDelegate; +import org.chromium.base.process_launcher.IChildProcessArgs; import org.chromium.native_test.MainRunner; import java.util.List; @@ -49,7 +50,7 @@ @Override public void onConnectionSetup( - Bundle connectionBundle, List<IBinder> callbacks, IBinder binderBox) { + IChildProcessArgs args, List<IBinder> callbacks, IBinder binderBox) { mTestCallback = ITestCallback.Stub.asInterface(callbacks.get(0)); mBinderBox = binderBox; }
diff --git a/base/test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java b/base/test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java index 376ff6f..9fe0b962 100644 --- a/base/test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java +++ b/base/test/android/javatests/src/org/chromium/base/process_launcher/TestChildProcessConnection.java
@@ -30,7 +30,9 @@ } @Override - public void updateGroupImportance(int group, int importanceInGroup) {} + public boolean updateGroupImportance(int group, int importanceInGroup) { + return true; + } @Override public void retire() {}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/ActivityElement.java b/base/test/android/javatests/src/org/chromium/base/test/transit/ActivityElement.java index 52f3af6..60154a5 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/ActivityElement.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/ActivityElement.java
@@ -11,7 +11,9 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * Represents an {@link Activity} that needs to exist to consider the Station active. @@ -31,7 +33,8 @@ @Override public @Nullable ConditionWithResult<ActivityT> createEnterCondition() { - return new ActivityExistsCondition(); + // Can be overridden with requireToBeInSameTask() or requireToBeInNewTask(). + return new ActivityExistsInNewTaskCondition(); } @Override @@ -39,47 +42,154 @@ return null; } - private class ActivityExistsCondition extends ConditionWithResult<ActivityT> { + void requireToBeInSameTask(Activity activity) { + replaceEnterCondition(new ActivityExistsInSameTaskCondition(activity)); + } - public ActivityExistsCondition() { + void requireToBeInNewTask() { + replaceEnterCondition(new ActivityExistsInNewTaskCondition()); + } + + void requireNoParticularTask() { + replaceEnterCondition(new ActivityExistsInAnyTaskCondition()); + } + + private abstract class ActivityExistsCondition extends ConditionWithResult<ActivityT> { + private ActivityExistsCondition() { super(/* isRunOnUiThread= */ false); } @Override protected ConditionStatusWithResult<ActivityT> resolveWithSuppliers() { - ActivityT candidate = null; + ActivityT candidateMatchingClass = null; + ActivityT candidateMatchingClassAndTask = null; + String reasonForTaskIdDifference = ""; List<Activity> allActivities = ApplicationStatus.getRunningActivities(); for (Activity activity : allActivities) { if (mActivityClass.equals(activity.getClass())) { ActivityT matched = mActivityClass.cast(activity); - if (candidate != null) { - return error("%s matched two Activities: %s, %s", this, candidate, matched) + candidateMatchingClass = matched; + reasonForTaskIdDifference = getReasonForTaskIdDifference(matched); + if (reasonForTaskIdDifference != null) { + continue; + } + if (candidateMatchingClassAndTask != null) { + return error( + "%s matched two Activities: %s, %s", + this, candidateMatchingClassAndTask, matched) .withoutResult(); } - candidate = matched; + candidateMatchingClassAndTask = matched; } } - if (candidate == null) { + if (candidateMatchingClass == null) { return awaiting("No Activity with expected class").withoutResult(); } + if (candidateMatchingClassAndTask == null) { + return awaiting("Activity not in expected task: " + reasonForTaskIdDifference) + .withoutResult(); + } - @ActivityState int state = ApplicationStatus.getStateForActivity(candidate); + @ActivityState + int state = ApplicationStatus.getStateForActivity(candidateMatchingClassAndTask); String statusString = String.format( - "matched: %s (state=%s)", candidate, activityStateDescription(state)); + "matched: %s (state=%s)", + candidateMatchingClassAndTask, activityStateDescription(state)); if (state == ActivityState.RESUMED) { - return fulfilled(statusString).withResult(candidate); + return fulfilled(statusString).withResult(candidateMatchingClassAndTask); } else { return awaiting(statusString).withoutResult(); } } + /** + * Return null if |activity| is in the expected task according to the Condition's specific + * criteria, or the reason for the difference otherwise. + */ + protected abstract @Nullable String getReasonForTaskIdDifference(ActivityT activity); + @Override public String buildDescription() { return "Activity exists and is RESUMED: " + mActivityClass.getSimpleName(); } } + private class ActivityExistsInAnyTaskCondition extends ActivityExistsCondition { + @Override + protected @Nullable String getReasonForTaskIdDifference(ActivityT activity) { + return null; + } + + @Override + public String buildDescription() { + return super.buildDescription() + " in any task"; + } + } + + private class ActivityExistsInSameTaskCondition extends ActivityExistsCondition { + private final int mOriginTaskId; + + private ActivityExistsInSameTaskCondition(Activity originActivity) { + super(); + mOriginTaskId = originActivity.getTaskId(); + assert mOriginTaskId != -1 : "The origin activity was not in any task"; + } + + @Override + protected @Nullable String getReasonForTaskIdDifference(ActivityT activity) { + // Ignore Activities in different tasks + int activityTaskId = activity.getTaskId(); + if (activityTaskId == mOriginTaskId) { + return null; + } else { + return String.format( + "Origin's task id: %d, candidate's was different: %d", + mOriginTaskId, activityTaskId); + } + } + + @Override + public String buildDescription() { + return super.buildDescription() + " in the same task as previous Station"; + } + } + + private class ActivityExistsInNewTaskCondition extends ActivityExistsCondition { + private final Map<Integer, Station<?>> mExistingTaskIds; + + private ActivityExistsInNewTaskCondition() { + super(); + + // Store all task ids of Activities known to Public Transit. + mExistingTaskIds = new HashMap<>(); + for (Station<?> activeStation : TrafficControl.getActiveStations()) { + ActivityElement<?> knownActivityElement = activeStation.getActivityElement(); + if (knownActivityElement != null) { + mExistingTaskIds.put(knownActivityElement.get().getTaskId(), activeStation); + } + } + } + + @Override + protected @Nullable String getReasonForTaskIdDifference(ActivityT activity) { + // Ignore Activities in known tasks + int candidateTaskId = activity.getTaskId(); + Station<?> stationInSameTask = mExistingTaskIds.get(candidateTaskId); + if (stationInSameTask != null) { + return String.format( + "%s's Activity was in same task: %d", + stationInSameTask.getName(), candidateTaskId); + } + return null; + } + + @Override + public String buildDescription() { + return super.buildDescription() + " in a new task"; + } + } + private static String activityStateDescription(@ActivityState int state) { return switch (state) { case ActivityState.CREATED -> "CREATED";
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/BatchedPublicTransitRule.java b/base/test/android/javatests/src/org/chromium/base/test/transit/BatchedPublicTransitRule.java index 9cef123c..76ea584 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/BatchedPublicTransitRule.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/BatchedPublicTransitRule.java
@@ -13,6 +13,8 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; +import java.util.List; + /** * Test rule for batched Public Transit tests. * @@ -73,6 +75,11 @@ public @Nullable T getHomeStation() { TransitAsserts.assertCurrentStationType( mHomeStationType, "getting base station", /* allowNull= */ true); - return (T) TrafficControl.getActiveStation(); + List<Station<?>> activeStations = TrafficControl.getActiveStations(); + if (activeStations.isEmpty()) { + return null; + } else { + return (T) activeStations.get(0); + } } }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/FacilitySwap.java b/base/test/android/javatests/src/org/chromium/base/test/transit/FacilitySwap.java index bd9add67f..b75a78c 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/FacilitySwap.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/FacilitySwap.java
@@ -36,18 +36,8 @@ @Override public String toDebugString() { - String facilitiesToExitString; - String facilitiesToEnterString; - if (mFacilitiesToExit.size() > 1) { - facilitiesToExitString = mFacilitiesToExit.toString(); - } else { - facilitiesToExitString = mFacilitiesToExit.get(0).toString(); - } - if (mFacilitiesToEnter.size() > 1) { - facilitiesToEnterString = mFacilitiesToEnter.toString(); - } else { - facilitiesToEnterString = mFacilitiesToEnter.get(0).toString(); - } + String facilitiesToExitString = getStateListString(mFacilitiesToExit); + String facilitiesToEnterString = getStateListString(mFacilitiesToEnter); return String.format( "FacilitySwap %d (from %s to %s)", mId, facilitiesToExitString, facilitiesToEnterString);
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/Station.java b/base/test/android/javatests/src/org/chromium/base/test/transit/Station.java index ac6d401..6be79b0 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/Station.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/Station.java
@@ -100,6 +100,26 @@ return mId; } + void requireToBeInSameTask(Station<?> originStation) { + assertInPhase(Phase.NEW); + if (mActivityElement != null) { + originStation.assertInPhase(Phase.ACTIVE); + ActivityElement<?> originActivityElement = originStation.getActivityElement(); + if (originActivityElement != null) { + mActivityElement.requireToBeInSameTask(originActivityElement.get()); + } else { + mActivityElement.requireNoParticularTask(); + } + } + } + + void requireToBeInNewTask() { + assertInPhase(Phase.NEW); + if (mActivityElement != null) { + mActivityElement.requireToBeInNewTask(); + } + } + /** * Starts a transition from this origin {@link Station} to another destination {@link Station}. * Runs the transition |trigger|, and blocks until the destination {@link Station} is considered @@ -112,7 +132,9 @@ * @param <T> the type of the destination {@link Station}. */ public final <T extends Station<?>> T travelToSync(T destination, @Nullable Trigger trigger) { - Trip trip = new Trip(this, destination, TransitionOptions.DEFAULT, trigger); + destination.requireToBeInSameTask(this); + Trip trip = + new Trip(List.of(this), List.of(destination), TransitionOptions.DEFAULT, trigger); trip.transitionSync(); return destination; } @@ -120,7 +142,8 @@ /** Version of #travelToSync() with extra TransitionOptions. */ public final <T extends Station<?>> T travelToSync( T destination, TransitionOptions options, @Nullable Trigger trigger) { - Trip trip = new Trip(this, destination, options, trigger); + destination.requireToBeInSameTask(this); + Trip trip = new Trip(List.of(this), List.of(destination), options, trigger); trip.transitionSync(); return destination; } @@ -298,6 +321,33 @@ } /** + * Starts a transition into a {@link Station} without leaving the current one. + * + * <p>Useful for opening a new window. + * + * <p>Runs the transition |trigger|, and blocks until the destination {@link Station} is + * considered ACTIVE (enter Conditions are fulfilled) and the {@link Trip}'s transition + * conditions are fulfilled. + * + * @param destination the {@link Facility} to arrive at. + * @param trigger the trigger to start the transition (e.g. clicking a view). + * @return the destination {@link Station}, now ACTIVE. + * @param <T> the type of the destination {@link Station}. + */ + public static <T extends Station<?>> T spawnSync(T destination, @Nullable Trigger trigger) { + return spawnSync(destination, TransitionOptions.DEFAULT, trigger); + } + + /** Version of {@link #spawnSync(T, Trigger)} with extra TransitionOptions. */ + public static <T extends Station<?>> T spawnSync( + T destination, TransitionOptions options, @Nullable Trigger trigger) { + destination.requireToBeInNewTask(); + Trip trip = new Trip(List.of(), List.of(destination), options, trigger); + trip.transitionSync(); + return destination; + } + + /** * Add a Facility which will be entered together with this Station. Both will become ACTIVE in * the same Trip. */ @@ -317,9 +367,7 @@ } /** Get the activity element associate with this station, if there's any. */ - public ActivityElement<HostActivity> getActivityElement() { - assert mActivityElement != null - : "Requesting an ActivityElement for a station with no host activity."; + public @Nullable ActivityElement<HostActivity> getActivityElement() { return mActivityElement; }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/TrafficControl.java b/base/test/android/javatests/src/org/chromium/base/test/transit/TrafficControl.java index d5f67f5..6f90792 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/TrafficControl.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/TrafficControl.java
@@ -23,48 +23,52 @@ private static final List<Pair<String, String>> sAllStationNames = new ArrayList<>(); private static @Nullable String sCurrentTestCase; - private static @Nullable Station<?> sActiveStation; + private static List<Station<?>> sActiveStations = new ArrayList<>(); static void notifyCreatedStation(Station<?> station) { sAllStationNames.add(Pair.create(sCurrentTestCase, station.getName())); } static void notifyEntryPointSentinelStationCreated(EntryPointSentinelStation sentinelStation) { - if (sActiveStation != null) { + for (Station<?> station : sActiveStations) { // Happens when test is batched, but the Activity is not kept between tests; Public // Transit's Station/Facility state need to reflect that and start from a new // {@link EntryPointSentinelStation}. - sActiveStation.setStateTransitioningFrom(); - sActiveStation.setStateFinished(); + station.setStateTransitioningFrom(); + station.setStateFinished(); } - sActiveStation = sentinelStation; + sActiveStations.clear(); } - static void notifyActiveStationChanged(Station<?> newActiveStation) { - assert newActiveStation.getPhase() == Phase.ACTIVE : "New active Station must be ACTIVE"; - if (sActiveStation != null) { - assert sActiveStation.getPhase() != Phase.ACTIVE + static void notifyActiveStationsChanged( + List<Station<?>> exitedStations, List<Station<?>> enteredStations) { + for (Station<?> enteredStation : enteredStations) { + assert enteredStation.getPhase() == Phase.ACTIVE : "New active Station must be ACTIVE"; + } + for (Station<?> exitedStation : exitedStations) { + assert exitedStation.getPhase() != Phase.ACTIVE : "Previously active station was not ACTIVE"; } - sActiveStation = newActiveStation; + sActiveStations.removeAll(exitedStations); + sActiveStations.addAll(enteredStations); } /** - * Hop off Public Transit - set the active station to null so that a subsequent test can go - * through an entry point again on the same process. + * Hop off Public Transit - clear the active stations so that a subsequent test can go through + * an entry point again on the same process. * * <p>Useful in Robolectric tests. */ public static void hopOffPublicTransit() { - sActiveStation = null; + sActiveStations.clear(); } public static List<Pair<String, String>> getAllStationsNames() { return sAllStationNames; } - public static @Nullable Station<?> getActiveStation() { - return sActiveStation; + public static List<Station<?>> getActiveStations() { + return sActiveStations; } static void onTestStarted(String testName) {
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/TransitAsserts.java b/base/test/android/javatests/src/org/chromium/base/test/transit/TransitAsserts.java index 21036cd90..f2cdc07 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/TransitAsserts.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/TransitAsserts.java
@@ -29,8 +29,15 @@ * {@link Facility} was not active. */ public static void assertFinalDestination( - Station expectedStation, Facility... expectedFacilities) { - Station activeStation = TrafficControl.getActiveStation(); + Station<?> expectedStation, Facility<?>... expectedFacilities) { + List<Station<?>> activeStations = TrafficControl.getActiveStations(); + if (activeStations.size() != 1) { + raiseAssertion( + String.format( + "Expected exactly one active station, but found %d", + activeStations.size())); + } + Station<?> activeStation = activeStations.get(0); if (activeStation != expectedStation) { raiseAssertion( String.format( @@ -45,7 +52,7 @@ expectedStation, ConditionalState.phaseToString(phase))); } - for (Facility facility : expectedFacilities) { + for (Facility<?> facility : expectedFacilities) { phase = facility.getPhase(); if (phase != Phase.ACTIVE) { raiseAssertion( @@ -57,6 +64,29 @@ } /** + * Asserts that the given stations are the final ones in a test method and no further + * transitions happened. + * + * <p>Version of {@link #assertFinalDestination(Station, Facility...)} when ending with multiple + * windows. + */ + public static void assertFinalDestinations(Station<?>... expectedStations) { + List<Station<?>> activeStations = TrafficControl.getActiveStations(); + for (Station<?> expectedStation : expectedStations) { + if (!activeStations.contains(expectedStation)) { + raiseAssertion( + String.format( + "Expected %s to be one of the final destinations, but it was not" + + " active", + expectedStation)); + } + } + if (activeStations.size() > expectedStations.length) { + raiseAssertion("Too many stations were active"); + } + } + + /** * Asserts the current station is of a given expected type. * * @param stationType the expected type of {@link Station} @@ -65,16 +95,30 @@ */ public static void assertCurrentStationType( Class<? extends Station<?>> stationType, String situation, boolean allowNull) { - Station activeStation = TrafficControl.getActiveStation(); - if ((activeStation == null && !allowNull) - || (activeStation != null && !stationType.isInstance(activeStation))) { + List<Station<?>> activeStations = TrafficControl.getActiveStations(); + if (activeStations.size() == 0) { + if (!allowNull) { + raiseAssertion( + String.format( + "Expected exactly one active station, but found %d", + activeStations.size())); + } + } else if (activeStations.size() == 1) { + Station<?> activeStation = activeStations.get(0); + if (!stationType.isInstance(activeStation)) { + raiseAssertion( + String.format( + "Expected current station to be of type <%s> at <%s>, but was" + + " actually of type <%s>", + stationType, + situation, + activeStation != null ? activeStation.getClass() : "null")); + } + } else { // if (activeStations.size() > 1) raiseAssertion( String.format( - "Expected current station to be of type <%s> at <%s>, but was actually" - + " of type <%s>", - stationType, - situation, - activeStation != null ? activeStation.getClass() : "null")); + "Expected exactly one active station, but found %d", + activeStations.size())); } }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/Transition.java b/base/test/android/javatests/src/org/chromium/base/test/transit/Transition.java index 07172931..85a83dff 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/Transition.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/Transition.java
@@ -288,4 +288,14 @@ } } } + + protected String getStateListString(List<? extends ConditionalState> states) { + if (states.isEmpty()) { + return "<none>"; + } else if (states.size() == 1) { + return states.get(0).toString(); + } else { + return states.toString(); + } + } }
diff --git a/base/test/android/javatests/src/org/chromium/base/test/transit/Trip.java b/base/test/android/javatests/src/org/chromium/base/test/transit/Trip.java index d2cd3093..9c62a0e 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/transit/Trip.java +++ b/base/test/android/javatests/src/org/chromium/base/test/transit/Trip.java
@@ -17,47 +17,57 @@ */ @NullMarked class Trip extends Transition { - private final Station mOrigin; - private final Station mDestination; + private final List<Station<?>> mOrigins; + private final List<Station<?>> mDestinations; /** - * Constructor. Trip is instantiated to move from one {@link Station} into another. + * Constructor. Trip is instantiated to move between {@link Station}s. * - * @param origin the {@link Station} to depart from. - * @param destination the {@link Station} to travel to. + * <p>The initial Transition is entering a single station. + * + * <p>Besides this, usually trips are triggered from one {@link Station} to another. With + * multiwindow, there can be any number of stations being exited and any number of stations + * being entered. + * + * @param origins the {@link Station}s to depart from. + * @param destinations the {@link Station}s to travel to. * @param options the {@link TransitionOptions}. * @param trigger the action that triggers the transition. e.g. clicking a View. */ Trip( - Station origin, - Station destination, + List<Station<?>> origins, + List<Station<?>> destinations, TransitionOptions options, @Nullable Trigger trigger) { super( options, - getStationPlusFacilitiesWithPhase(origin, Phase.ACTIVE), - getStationPlusFacilitiesWithPhase(destination, Phase.NEW), + getStationsPlusFacilitiesWithPhase(origins, Phase.ACTIVE), + getStationsPlusFacilitiesWithPhase(destinations, Phase.NEW), trigger); - mOrigin = origin; - mDestination = destination; + mOrigins = origins; + mDestinations = destinations; } - private static List<? extends ConditionalState> getStationPlusFacilitiesWithPhase( - Station station, @Phase int phase) { + private static List<? extends ConditionalState> getStationsPlusFacilitiesWithPhase( + List<Station<?>> stations, @Phase int phase) { List<ConditionalState> allConditionalStates = new ArrayList<>(); - allConditionalStates.add(station); - allConditionalStates.addAll(station.getFacilitiesWithPhase(phase)); + for (Station<?> station : stations) { + allConditionalStates.add(station); + allConditionalStates.addAll(station.getFacilitiesWithPhase(phase)); + } return allConditionalStates; } @Override protected void onAfterTransition() { super.onAfterTransition(); - TrafficControl.notifyActiveStationChanged(mDestination); + TrafficControl.notifyActiveStationsChanged(mOrigins, mDestinations); } @Override public String toDebugString() { - return String.format("Trip %d (%s to %s)", mId, mOrigin, mDestination); + return String.format( + "Trip %d (%s to %s)", + mId, getStateListString(mOrigins), getStateListString(mDestinations)); } }
diff --git a/base/test/test_proto_loader.h b/base/test/test_proto_loader.h index 0cc7a9ed..671464d 100644 --- a/base/test/test_proto_loader.h +++ b/base/test/test_proto_loader.h
@@ -23,11 +23,7 @@ #endif // defined(PROTO_TEST_IMPLEMENTATION) #else // defined(WIN32) -#if defined(PROTO_TEST_IMPLEMENTATION) #define PROTO_TEST_EXPORT __attribute__((visibility("default"))) -#else -#define PROTO_TEST_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD) #define PROTO_TEST_EXPORT
diff --git a/base/test/test_trace_processor_export.h b/base/test/test_trace_processor_export.h index f5191b80..94b5a2a 100644 --- a/base/test/test_trace_processor_export.h +++ b/base/test/test_trace_processor_export.h
@@ -14,13 +14,7 @@ #endif // defined(TEST_TRACE_PROCESSOR_IMPL) #else // defined(WIN32) - -#if defined(TEST_TRACE_PROCESSOR_IMPL) #define TEST_TRACE_PROCESSOR_EXPORT __attribute__((visibility("default"))) -#else -#define TEST_TRACE_PROCESSOR_EXPORT -#endif // defined(TEST_TRACE_PROCESSOR_IMPL) - #endif // defined(WIN32) #endif // BASE_TEST_TEST_TRACE_PROCESSOR_EXPORT_H_
diff --git a/build/android/apk_operations.pydeps b/build/android/apk_operations.pydeps index 5455106a..cde63ff 100644 --- a/build/android/apk_operations.pydeps +++ b/build/android/apk_operations.pydeps
@@ -48,6 +48,7 @@ ../../third_party/catapult/devil/devil/devil_env.py ../../third_party/catapult/devil/devil/utils/__init__.py ../../third_party/catapult/devil/devil/utils/cmd_helper.py +../../third_party/catapult/devil/devil/utils/host_utils.py ../../third_party/catapult/devil/devil/utils/lazy/__init__.py ../../third_party/catapult/devil/devil/utils/lazy/weak_constant.py ../../third_party/catapult/devil/devil/utils/logging_common.py
diff --git a/build/android/test_runner.pydeps b/build/android/test_runner.pydeps index f87ec1b..523ae642 100644 --- a/build/android/test_runner.pydeps +++ b/build/android/test_runner.pydeps
@@ -78,6 +78,7 @@ ../../third_party/catapult/devil/devil/utils/__init__.py ../../third_party/catapult/devil/devil/utils/cmd_helper.py ../../third_party/catapult/devil/devil/utils/file_utils.py +../../third_party/catapult/devil/devil/utils/host_utils.py ../../third_party/catapult/devil/devil/utils/lazy/__init__.py ../../third_party/catapult/devil/devil/utils/lazy/weak_constant.py ../../third_party/catapult/devil/devil/utils/logging_common.py
diff --git a/build/config/aix/BUILD.gn b/build/config/aix/BUILD.gn index 6e55c83..975f82e 100644 --- a/build/config/aix/BUILD.gn +++ b/build/config/aix/BUILD.gn
@@ -29,6 +29,7 @@ "-fdata-sections", "-ffunction-sections", "-fno-extern-tls-init", + "-fno-reorder-functions", "-O3", # "-Werror"
diff --git a/build/config/compiler/pgo/BUILD.gn b/build/config/compiler/pgo/BUILD.gn index b5b7703..52c6ced 100644 --- a/build/config/compiler/pgo/BUILD.gn +++ b/build/config/compiler/pgo/BUILD.gn
@@ -101,12 +101,26 @@ } if (_pgo_target != "" && pgo_data_path == "") { + common_args = [ + "--target", + _pgo_target, + ] + if (pgo_override_filename != "") { + common_args += [ + "--override-filename", + pgo_override_filename, + ] + + # This is slow but it is only expected to be run on the orderfile bots + # that require this special step. + exec_script("//tools/update_pgo_profiles.py", + common_args + [ + "update", + "--gs-url-base=$pgo_gs_bucket/$pgo_gs_bucket_path", + ]) + } pgo_data_path = exec_script("//tools/update_pgo_profiles.py", - [ - "--target", - _pgo_target, - "get_profile_path", - ], + common_args + [ "get_profile_path" ], "value") } assert(pgo_data_path != "",
diff --git a/build/config/compiler/pgo/pgo.gni b/build/config/compiler/pgo/pgo.gni index cdb0bbbd..646a0027 100644 --- a/build/config/compiler/pgo/pgo.gni +++ b/build/config/compiler/pgo/pgo.gni
@@ -39,6 +39,12 @@ # Whether to enable temporal pgo or not (experimental). temporal_pgo_profile = false + + # Flags to override the pgo profile with a freshly created one (newer than + # the sha1 in the repo). + pgo_override_filename = "" + pgo_gs_bucket = "" + pgo_gs_bucket_path = "" } # TODO(crbug.com/409738601): Remove assert once clang no
diff --git a/build/config/siso/clang_exception.star b/build/config/siso/clang_exception.star index 0379fae..e265bf9 100644 --- a/build/config/siso/clang_exception.star +++ b/build/config/siso/clang_exception.star
@@ -52,7 +52,6 @@ "action_outs": [ # keep-sorted start "./obj/content/test/content_unittests/auction_runner_unittest.o", - "./obj/v8/v8_compiler/csa-optimize-phase.o", # keep-sorted end ], "timeout": "4m",
diff --git a/build/config/win/manifest.gni b/build/config/win/manifest.gni index 805c24d0..2feb96c 100644 --- a/build/config/win/manifest.gni +++ b/build/config/win/manifest.gni
@@ -90,6 +90,7 @@ # We handle UAC by adding explicit .manifest files instead. "/manifestuac:no", ] + manifests + inputs = invoker.sources } # This group only exists to add a dep on the invoker's deps and to @@ -100,7 +101,7 @@ # Apply any dependencies from the invoker to this target, since those # dependencies may have created the input manifest files. - forward_variables_from(invoker, [ "deps" ]) + forward_variables_from(invoker, [ "public_deps" ]) } } } else {
diff --git a/build/rust/rust_bindgen_generator.gni b/build/rust/rust_bindgen_generator.gni index c91916b..796d593c 100644 --- a/build/rust/rust_bindgen_generator.gni +++ b/build/rust/rust_bindgen_generator.gni
@@ -223,21 +223,6 @@ clang_resource_dir, ] - # The `--sysroot` flag is not working as expected and gets ignored (we don't - # fully understand why, see b/328510249). But we add `-isystem` to point at - # the headers in the sysroot which are otherwise not found. - if (sysroot != "") { - if (is_win) { - args += - [ "-I" + rebase_path(sysroot + "/usr/include/", root_build_dir) ] - } else { - args += [ - "-isystem", - rebase_path(sysroot + "/usr/include/", root_build_dir), - ] - } - } - if (is_win) { # On Windows we fall back to using system headers from a sysroot from # depot_tools. This is negotiated by python scripts and the result is
diff --git a/build/rust/std/rules/BUILD.gn b/build/rust/std/rules/BUILD.gn index 7beac98..38957e8 100644 --- a/build/rust/std/rules/BUILD.gn +++ b/build/rust/std/rules/BUILD.gn
@@ -288,221 +288,225 @@ } cargo_crate("compiler_builtins") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/aarch64_linux.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/arm.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/arm_linux.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/avr.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/add.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/cmp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/conv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/div.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/extend.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/mul.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/pow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/sub.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/float/trunc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/hexagon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/addsub.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/big.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/bswap.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/leading_zeros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/mul.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/sdiv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/shift.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/specialized_div_rem/asymmetric.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/specialized_div_rem/binary_long.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/specialized_div_rem/delegate.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/specialized_div_rem/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/specialized_div_rem/norm_shift.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/specialized_div_rem/trifecta.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/trailing_zeros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/int/udiv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/lib.miri.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/acos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/acosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/acosh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/acoshf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/arch/aarch64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/arch/i586.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/arch/i686.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/arch/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/arch/wasm32.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/asin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/asinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/asinh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/asinhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/atan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/atan2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/atan2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/atanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/atanh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/atanhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/cbrt.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/cbrtf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/ceil.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/copysign.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/copysignf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/copysignf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/copysignf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/cos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/cosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/cosh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/coshf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/erf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/erff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/exp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/exp10.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/exp10f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/exp2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/exp2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/expf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/expm1.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/expm1f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/expo2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fabs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fabsf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fabsf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fabsf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fdim.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fdimf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fdimf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fdimf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/floor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/floorf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/floorf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/floorf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fma_wide.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fmin_fmax.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fminimum_fmaximum.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fminimum_fmaximum_num.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fmod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fmodf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fmodf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/fmodf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/frexp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/frexpf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/ceil.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/copysign.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fabs.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fdim.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/floor.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fmax.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fmaximum.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fmaximum_num.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fmin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fminimum.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fminimum_num.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/fmod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/rint.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/round.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/scalbn.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/sqrt.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/generic/trunc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/hypot.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/hypotf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/ilogb.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/ilogbf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/j0.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/j0f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/j1.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/j1f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/jn.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/jnf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/k_cos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/k_cosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/k_expo2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/k_expo2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/k_sin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/k_sinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/k_tan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/k_tanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/ldexp.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/ldexpf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/ldexpf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/ldexpf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/lgamma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/lgamma_r.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/lgammaf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/lgammaf_r.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/log.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/log10.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/log10f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/log1p.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/log1pf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/log2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/log2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/logf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/modf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/modff.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/nextafter.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/nextafterf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/pow.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/powf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/rem_pio2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/rem_pio2_large.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/rem_pio2f.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/remainder.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/remainderf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/remquo.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/remquof.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/rint.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/round.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/roundeven.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/roundf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/roundf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/roundf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/scalbn.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/scalbnf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/scalbnf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/scalbnf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sin.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sincos.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sincosf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sinf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sinh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sinhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sqrt.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sqrtf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sqrtf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/sqrtf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/support/big.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/support/big/tests.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/support/env.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/support/float_traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/support/hex_float.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/support/int_traits.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/support/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/support/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/tan.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/tanf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/tanh.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/tanhf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/tgamma.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/tgammaf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/trunc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/truncf.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/truncf128.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/libm_math/truncf16.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/math/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/mem/impls.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/mem/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/mem/x86_64.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/probestack.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/riscv.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/x86.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/aarch64_linux.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/arm.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/arm_linux.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/avr.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/add.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/cmp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/conv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/div.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/extend.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/mul.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/pow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/sub.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/float/trunc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/hexagon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/addsub.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/big.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/bswap.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/leading_zeros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/mul.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/sdiv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/shift.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/asymmetric.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/binary_long.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/delegate.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/norm_shift.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/specialized_div_rem/trifecta.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/trailing_zeros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/int/udiv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/lib.miri.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/acos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/acosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/acosh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/acoshf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/aarch64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/i586.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/wasm32.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/x86/detect.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/arch/x86/fma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/asin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/asinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/asinh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/asinhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atan2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atan2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atanh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/atanhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cbrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cbrtf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ceil.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/copysign.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/copysignf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/copysignf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/copysignf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/cosh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/coshf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/erf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/erff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp10.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp10f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/exp2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/expf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/expm1.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/expm1f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/expo2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fabs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fabsf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fabsf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fabsf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fdim.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fdimf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fdimf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fdimf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/floor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/floorf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/floorf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/floorf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmin_fmax.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fminimum_fmaximum.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fminimum_fmaximum_num.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmodf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmodf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/fmodf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/frexp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/frexpf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/ceil.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/copysign.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fabs.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fdim.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/floor.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fma_wide.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmax.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmaximum.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmaximum_num.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fminimum.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fminimum_num.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/fmod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/rint.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/round.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/scalbn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/sqrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/generic/trunc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/hypot.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/hypotf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ilogb.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ilogbf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/j0.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/j0f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/j1.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/j1f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/jn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/jnf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_cos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_cosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_expo2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_expo2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_sin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_sinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_tan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/k_tanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ldexp.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ldexpf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ldexpf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/ldexpf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/lgamma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/lgamma_r.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/lgammaf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/lgammaf_r.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log10.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log10f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log1p.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log1pf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/log2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/logf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/modf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/modff.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/nextafter.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/nextafterf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/pow.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/powf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/rem_pio2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/rem_pio2_large.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/rem_pio2f.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/remainder.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/remainderf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/remquo.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/remquof.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/rint.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/round.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/roundeven.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/roundf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/roundf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/roundf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/scalbn.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/scalbnf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/scalbnf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/scalbnf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sin.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sincos.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sincosf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sinf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sinh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sinhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sqrt.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sqrtf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sqrtf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/sqrtf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/big.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/big/tests.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/env.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/feature_detect.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/float_traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/hex_float.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/int_traits.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/support/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tan.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tanf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tanh.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tanhf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tgamma.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/tgammaf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/trunc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/truncf.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/truncf128.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/libm_math/truncf16.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/math/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/mem/impls.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/mem/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/mem/x86_64.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/probestack.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/riscv.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/x86.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/x86_64.rs", ] inputs = [] no_std = true @@ -510,7 +514,7 @@ # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.1.156" + cargo_pkg_version = "0.1.157" cargo_pkg_authors = "Jorge Aparicio <japaricious@gmail.com>" cargo_pkg_name = "compiler_builtins" cargo_pkg_description = "Compiler intrinsics used by the Rust compiler." @@ -537,9 +541,9 @@ "default", "rustc-dep-of-std", ] - build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/build.rs" - build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/build.rs" ] - build_script_inputs = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.156/src/../configure.rs" ] + build_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/build.rs" + build_sources = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/build.rs" ] + build_script_inputs = [ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/compiler_builtins-0.1.157/src/../configure.rs" ] rustenv = [ "CFG_DISABLE_UNSTABLE_FEATURES=0", "STD_ENV_ARCH=$rust_target_arch", @@ -1242,34 +1246,35 @@ } cargo_crate("hashbrown") { crate_type = "rlib" - crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/lib.rs" + crate_root = "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/lib.rs" sources = [ - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/control/bitmask.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/control/group/generic.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/control/group/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/control/group/neon.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/control/group/sse2.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/control/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/control/tag.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/external_trait_impls/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/external_trait_impls/rayon/helpers.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/external_trait_impls/rayon/map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/external_trait_impls/rayon/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/external_trait_impls/rayon/raw.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/external_trait_impls/rayon/set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/external_trait_impls/rayon/table.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/external_trait_impls/serde.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/lib.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/macros.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/map.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/raw/alloc.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/raw/mod.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/raw_entry.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/rustc_entry.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/scopeguard.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/set.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/table.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.2/src/util.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/bitmask.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/generic.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/lsx.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/neon.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/group/sse2.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/control/tag.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/helpers.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/raw.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/rayon/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/external_trait_impls/serde.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/lib.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/macros.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/map.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/raw/alloc.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/raw/mod.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/raw_entry.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/rustc_entry.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/scopeguard.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/set.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/table.rs", + "//third_party/rust-toolchain/lib/rustlib/src/rust/library/vendor/hashbrown-0.15.3/src/util.rs", ] inputs = [] no_std = true @@ -1277,7 +1282,7 @@ # Unit tests skipped. Generate with --with-tests to include them. build_native_rust_unit_tests = false edition = "2021" - cargo_pkg_version = "0.15.2" + cargo_pkg_version = "0.15.3" cargo_pkg_authors = "Amanieu d'Antras <amanieu@gmail.com>" cargo_pkg_name = "hashbrown" cargo_pkg_description = "A Rust port of Google's SwissTable hash map" @@ -1307,7 +1312,6 @@ "compiler_builtins", "core", "nightly", - "raw-entry", "rustc-dep-of-std", "rustc-internal-api", ] @@ -3041,7 +3045,6 @@ "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/aarch64.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/arm.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/auxvec.rs", - "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/cpuinfo.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/loongarch.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/mips.rs", "//third_party/rust-toolchain/lib/rustlib/src/rust/library/stdarch/crates/std_detect/src/detect/os/linux/mod.rs",
diff --git a/build/rust/tests/bindgen_static_fns_test/lib.h b/build/rust/tests/bindgen_static_fns_test/lib.h index eb070af..bb1abdd 100644 --- a/build/rust/tests/bindgen_static_fns_test/lib.h +++ b/build/rust/tests/bindgen_static_fns_test/lib.h
@@ -19,11 +19,7 @@ #endif // defined(COMPONENT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(COMPONENT_IMPLEMENTATION) #define COMPONENT_EXPORT __attribute__((visibility("default"))) -#else -#define COMPONENT_EXPORT -#endif // defined(COMPONENT_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD) @@ -46,4 +42,4 @@ } #endif -#endif // BUILD_RUST_TESTS_BINDGEN_STATIC_FNS_TEST_LIB_H_ +#endif // BUILD_RUST_TESTS_BINDGEN_STATIC_FNS_TEST_LIB_H_
diff --git a/build/rust/tests/bindgen_test/lib.h b/build/rust/tests/bindgen_test/lib.h index a6d686e..835f659 100644 --- a/build/rust/tests/bindgen_test/lib.h +++ b/build/rust/tests/bindgen_test/lib.h
@@ -21,11 +21,7 @@ #endif // defined(COMPONENT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(COMPONENT_IMPLEMENTATION) #define COMPONENT_EXPORT __attribute__((visibility("default"))) -#else -#define COMPONENT_EXPORT -#endif // defined(COMPONENT_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD) @@ -42,4 +38,4 @@ } #endif -#endif // BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_ +#endif // BUILD_RUST_TESTS_BINDGEN_TEST_LIB_H_
diff --git a/build/toolchain/apple/linker_driver.py b/build/toolchain/apple/linker_driver.py index 4bef15b..e502500 100755 --- a/build/toolchain/apple/linker_driver.py +++ b/build/toolchain/apple/linker_driver.py
@@ -135,6 +135,8 @@ # may not need to reexport unless LC_REEXPORT_DYLIB is used. self._reexport_in_old_module = False + # temp directory for lto cache. + self._object_path_lto = None def run(self): """Runs the linker driver, separating out the main compiler driver's @@ -274,9 +276,9 @@ # through the clang driver. See https://crbug.com/1324104 # The temporary directory for intermediate LTO object files. If it # exists, it will clean itself up on script exit. - object_path_lto = tempfile.TemporaryDirectory(dir=os.getcwd()) + self._object_path_lto = tempfile.TemporaryDirectory(dir=os.getcwd()) self._compiler_driver_args.append('-Wl,-object_path_lto,{}'.format( - os.path.relpath(object_path_lto.name))) + os.path.relpath(self._object_path_lto.name))) def check_reexport_in_old_module(self, tocname): """Linker driver pre-action for -Wcrl,tocname,<path>.
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index ab4de6f..72dff7b 100644 --- a/buildtools/deps_revisions.gni +++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision var in //DEPS. - libcxx_revision = "a01c02c9d4acbdae3b7e8a2f3ee58579a9c29f96" + libcxx_revision = "a9cc573e7c591795d11b72d8323ba0e573b55bd6" }
diff --git a/cc/animation/animation_export.h b/cc/animation/animation_export.h index 4ae15541..d249518 100644 --- a/cc/animation/animation_export.h +++ b/cc/animation/animation_export.h
@@ -15,11 +15,7 @@ #endif // defined(CC_ANIMATION_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CC_ANIMATION_IMPLEMENTATION) #define CC_ANIMATION_EXPORT __attribute__((visibility("default"))) -#else -#define CC_ANIMATION_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/cc/base/base_export.h b/cc/base/base_export.h index cd4a3e912..87e41f0 100644 --- a/cc/base/base_export.h +++ b/cc/base/base_export.h
@@ -15,11 +15,7 @@ #endif // defined(CC_BASE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CC_BASE_IMPLEMENTATION) #define CC_BASE_EXPORT __attribute__((visibility("default"))) -#else -#define CC_BASE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/cc/cc_export.h b/cc/cc_export.h index 9600c19..0c321a92 100644 --- a/cc/cc_export.h +++ b/cc/cc_export.h
@@ -15,11 +15,7 @@ #endif // defined(CC_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CC_IMPLEMENTATION) #define CC_EXPORT __attribute__((visibility("default"))) -#else -#define CC_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/cc/debug/debug_export.h b/cc/debug/debug_export.h index 04792aa..7c3bea1a 100644 --- a/cc/debug/debug_export.h +++ b/cc/debug/debug_export.h
@@ -15,11 +15,7 @@ #endif // defined(CC_DEBUG_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CC_DEBUG_IMPLEMENTATION) #define CC_DEBUG_EXPORT __attribute__((visibility("default"))) -#else -#define CC_DEBUG_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/cc/mojo_embedder/mojo_embedder_export.h b/cc/mojo_embedder/mojo_embedder_export.h index c6eca8a..825d2439 100644 --- a/cc/mojo_embedder/mojo_embedder_export.h +++ b/cc/mojo_embedder/mojo_embedder_export.h
@@ -15,11 +15,7 @@ #endif // defined(CC_MOJO_EMBEDDER_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CC_MOJO_EMBEDDER_IMPLEMENTATION) #define CC_MOJO_EMBEDDER_EXPORT __attribute__((visibility("default"))) -#else -#define CC_MOJO_EMBEDDER_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/cc/paint/paint_export.h b/cc/paint/paint_export.h index 0b14d85..7a935c96 100644 --- a/cc/paint/paint_export.h +++ b/cc/paint/paint_export.h
@@ -15,11 +15,7 @@ #endif // defined(CC_PAINT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CC_PAINT_IMPLEMENTATION) #define CC_PAINT_EXPORT __attribute__((visibility("default"))) -#else -#define CC_PAINT_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 97f843f..f4727068 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -182,10 +182,7 @@ if (build_mojo_proxy) { data_deps += [ "//mojo/proxy:mojo_proxy" ] } - deps += [ - "//components/exo/wayland:test_controller_stub", - "//components/exo/wayland:ui_controls_protocol_stub", - ] + deps += [ "//components/exo/wayland:ui_controls_protocol_stub" ] } if (is_win) {
diff --git a/chrome/VERSION b/chrome/VERSION index c38e913a..7e2c030 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=138 MINOR=0 -BUILD=7166 +BUILD=7167 PATCH=0
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsHelper.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsHelper.java index 332674e..e560574 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsHelper.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsHelper.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.tasks.tab_management; import org.chromium.chrome.browser.app.tabmodel.ArchivedTabModelOrchestrator; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabArchiver; @@ -31,21 +30,18 @@ TabClosureParams.closeAllTabs().hideTabGroups(true).build(), /* allowDialog= */ false); - Runnable undoRunnable = () -> {}; - if (ChromeFeatureList.sAndroidTabDeclutter.isEnabled()) { - final Profile profile = - tabModelSelector.getCurrentModel().getProfile().getOriginalProfile(); - List<Integer> previouslyArchivedTabIds = - unarchiveTabsForTabClosure(profile, regularTabCreator); - undoRunnable = - () -> - archiveTabsAfterTabClosureUndo( - profile, - tabModelSelector - .getTabGroupModelFilterProvider() - .getTabGroupModelFilter(/* isIncognito= */ false), - previouslyArchivedTabIds); - } + final Profile profile = + tabModelSelector.getCurrentModel().getProfile().getOriginalProfile(); + List<Integer> previouslyArchivedTabIds = + unarchiveTabsForTabClosure(profile, regularTabCreator); + Runnable undoRunnable = + () -> + archiveTabsAfterTabClosureUndo( + profile, + tabModelSelector + .getTabGroupModelFilterProvider() + .getTabGroupModelFilter(/* isIncognito= */ false), + previouslyArchivedTabIds); tabModelSelector .getModel(/* incognito= */ false) .getTabRemover()
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMessageManager.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMessageManager.java index 05f5fa1..7a2c4501 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMessageManager.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMessageManager.java
@@ -20,7 +20,6 @@ import org.chromium.chrome.browser.back_press.BackPressManager; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.hub.PaneManager; import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; @@ -303,33 +302,29 @@ assert profile != null; mProfile = profile; - if (ChromeFeatureList.sAndroidTabDeclutter.isEnabled()) { - mArchivedTabsMessageService = - new ArchivedTabsMessageService( - mActivity, - ArchivedTabModelOrchestrator.getForProfile(mProfile), - mBrowserControlsStateProvider, - mTabContentManager, - mTabListMode, - mRootView, - mSnackbarManager, - mRegularTabCreator, - mBackPressManager, - mModalDialogManager, - TrackerFactory.getTrackerForProfile(profile), - () -> - appendNextMessage( - MessageService.MessageType.ARCHIVED_TABS_MESSAGE), - mTabListCoordinatorSupplier, - mDesktopWindowStateManager, - mEdgeToEdgeSupplier, - TabGroupSyncServiceFactory.getForProfile(mProfile), - mPaneManagerSupplier, - mTabGroupUiActionHandlerSupplier, - mCurrentTabGroupModelFilterSupplier); - addObserver(mArchivedTabsMessageService); - mMessageCardProviderCoordinator.subscribeMessageService(mArchivedTabsMessageService); - } + mArchivedTabsMessageService = + new ArchivedTabsMessageService( + mActivity, + ArchivedTabModelOrchestrator.getForProfile(mProfile), + mBrowserControlsStateProvider, + mTabContentManager, + mTabListMode, + mRootView, + mSnackbarManager, + mRegularTabCreator, + mBackPressManager, + mModalDialogManager, + TrackerFactory.getTrackerForProfile(profile), + () -> appendNextMessage(MessageService.MessageType.ARCHIVED_TABS_MESSAGE), + mTabListCoordinatorSupplier, + mDesktopWindowStateManager, + mEdgeToEdgeSupplier, + TabGroupSyncServiceFactory.getForProfile(mProfile), + mPaneManagerSupplier, + mTabGroupUiActionHandlerSupplier, + mCurrentTabGroupModelFilterSupplier); + addObserver(mArchivedTabsMessageService); + mMessageCardProviderCoordinator.subscribeMessageService(mArchivedTabsMessageService); IphMessageService iphMessageService = new IphMessageService(profile, mTabGridIphDialogCoordinator);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettings.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettings.java index ca18375..e6bfa5f 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettings.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettings.java
@@ -102,10 +102,6 @@ private void configureTabArchiveSettings() { Preference tabArchiveSettingsPref = findPreference(PREF_TAB_ARCHIVE_SETTINGS); - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_TAB_DECLUTTER)) { - tabArchiveSettingsPref.setVisible(false); - return; - } TabArchiveSettings archiveSettings = new TabArchiveSettings(ChromeSharedPreferences.getInstance());
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettingsUnitTest.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettingsUnitTest.java index 335ba54e..ce839a7 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettingsUnitTest.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettingsUnitTest.java
@@ -66,7 +66,6 @@ ChromeFeatureList.TAB_GROUP_SYNC_ANDROID, ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH }) -@DisableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) public class TabsSettingsUnitTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); @@ -184,16 +183,6 @@ } @Test - @DisableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) - public void testArchiveSettingsHiddenWhenFeatureOff() { - TabsSettings tabsSettings = launchFragment(); - Preference archiveSettinsEntryPoint = - tabsSettings.findPreference(TabsSettings.PREF_TAB_ARCHIVE_SETTINGS); - assertFalse(archiveSettinsEntryPoint.isVisible()); - } - - @Test - @EnableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) public void testArchiveSettingsTitleAndSummary() { TabArchiveSettings archiveSettings = new TabArchiveSettings(ChromeSharedPreferences.getInstance());
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsDialogCoordinatorTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsDialogCoordinatorTest.java index a08bb71e..dcad9dbe 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsDialogCoordinatorTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsDialogCoordinatorTest.java
@@ -49,14 +49,12 @@ import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.UserActionTester; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.app.tabmodel.ArchivedTabModelOrchestrator; import org.chromium.chrome.browser.app.tabmodel.ArchivedTabModelOrchestrator.Observer; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.layouts.LayoutTestUtils; import org.chromium.chrome.browser.layouts.LayoutType; @@ -81,7 +79,6 @@ @RunWith(ChromeJUnit4ClassRunner.class) @DoNotBatch(reason = "TODO(crbug.com/348068134): Batch this test suite.") @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -@EnableFeatures({ChromeFeatureList.ANDROID_TAB_DECLUTTER}) @DisabledTest(message = "crbug.com/397759336") public class ArchivedTabsDialogCoordinatorTest { @Rule
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutPTTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutPTTest.java index 36fc74a..a5ed56a3 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutPTTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayoutPTTest.java
@@ -115,7 +115,9 @@ PageStation currentStation) { RegularTabSwitcherStation tabSwitcherStation = currentStation.openRegularTabSwitcher(); CarryOn.pickUp( - new TabThumbnailsCapturedCarryOn(/* isIncognito= */ false), /* trigger= */ null); + new TabThumbnailsCapturedCarryOn( + tabSwitcherStation.tabModelSelectorElement.get(), /* isIncognito= */ false), + /* trigger= */ null); return tabSwitcherStation; } @@ -124,7 +126,9 @@ PageStation currentStation) { IncognitoTabSwitcherStation tabSwitcherStation = currentStation.openIncognitoTabSwitcher(); CarryOn.pickUp( - new TabThumbnailsCapturedCarryOn(/* isIncognito= */ true), /* trigger= */ null); + new TabThumbnailsCapturedCarryOn( + tabSwitcherStation.tabModelSelectorElement.get(), /* isIncognito= */ true), + /* trigger= */ null); return tabSwitcherStation; }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java index 0d9c00a..4c2f7c4f 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
@@ -190,7 +190,7 @@ */ private class FeedSigninPromo { private final SigninPromoCoordinator mSigninPromoCoordinator; - private final View mPromoView; + @Nullable private View mPromoView; private boolean mCanShowPersonalizedSuggestions; private boolean mCanShowPromo; @@ -208,14 +208,18 @@ mCanShowPromo = mSigninPromoCoordinator.canShowPromo() && mCanShowPersonalizedSuggestions; - mPromoView = mSigninPromoCoordinator.buildPromoView((ViewGroup) mCoordinator.getView()); - mSigninPromoCoordinator.setView(mPromoView); + if (mCanShowPromo) { + // The view is created lazily to avoid increasing the browser memory footprint by + // keeping the view in memory even when it's never shown to the user. + initializePromoView(); + } } boolean canShowPromo() { return mCanShowPromo; } + @Nullable View getPromoView() { return mPromoView; } @@ -238,8 +242,16 @@ } mCanShowPromo = canShowPromo; + if (mPromoView == null && mCanShowPromo) { + initializePromoView(); + } mCoordinator.updateHeaderViews(mCanShowPromo ? mPromoView : null); } + + private void initializePromoView() { + mPromoView = mSigninPromoCoordinator.buildPromoView((ViewGroup) mCoordinator.getView()); + mSigninPromoCoordinator.setView(mPromoView); + } } /** Internal implementation of Stream.StreamsMediator. */
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 1125b67..9ee2359 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -2358,7 +2358,7 @@ if (!TabUiFeatureUtilities.isTabDragToCreateInstanceSupported()) return false; @Nullable TabGroupMetadata tabGroupMetadata = IntentHandler.getTabGroupMetadata(intent); return tabGroupMetadata != null - ? maybeLaunchDraggedTabGroupInWindow(tabGroupMetadata) + ? maybeLaunchDraggedTabGroupInWindow(intent, tabGroupMetadata) : maybeLaunchDraggedTabInWindow(intent); } @@ -2381,18 +2381,24 @@ } mMultiInstanceManager.moveTabToWindow(this, tab, /* atIndex= */ 0); RecordHistogram.recordBooleanHistogram(HISTOGRAM_DRAGGED_TAB_OPENED_NEW_WINDOW, true); - DragDropMetricUtils.recordTabDragDropType( + DragDropMetricUtils.recordDragDropType( ChromeDragDropUtils.getDragDropTypeFromIntent(intent), AppHeaderUtils.isAppInDesktopWindow( - mRootUiCoordinator.getDesktopWindowStateManager())); + mRootUiCoordinator.getDesktopWindowStateManager()), + /* isTabGroup= */ false); return true; } - // TODO(crbug.com/384979079): record metrics for tab group drop. - private boolean maybeLaunchDraggedTabGroupInWindow(@NonNull TabGroupMetadata tabGroupMetadata) { + private boolean maybeLaunchDraggedTabGroupInWindow( + Intent intent, @NonNull TabGroupMetadata tabGroupMetadata) { if (mMultiInstanceManager == null) return false; mMultiInstanceManager.moveTabGroupToWindow(this, tabGroupMetadata, /* atIndex= */ 0); + DragDropMetricUtils.recordDragDropType( + ChromeDragDropUtils.getDragDropTypeFromIntent(intent), + AppHeaderUtils.isAppInDesktopWindow( + mRootUiCoordinator.getDesktopWindowStateManager()), + /* isTabGroup= */ true); return true; } @@ -3391,7 +3397,15 @@ new NtpCustomizationCoordinator( this, mRootUiCoordinator.getBottomSheetController(), - getProfileProviderSupplier()) + () -> { + OneshotSupplier<ProfileProvider> profileProviderSupplier = + getProfileProviderSupplier(); + if (profileProviderSupplier.hasValue()) { + return getProfileProviderSupplier().get().getOriginalProfile(); + } + + return null; + }) .showBottomSheet(); NtpCustomizationMetricsUtils.recordOpenBottomSheetEntry( NtpCustomizationCoordinator.EntryPointType.MAIN_MENU);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabModelOrchestrator.java b/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabModelOrchestrator.java index bf6d1d8a..e1cb8522 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabModelOrchestrator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabModelOrchestrator.java
@@ -274,8 +274,7 @@ */ public void registerTabModelOrchestrator(TabbedModeTabModelOrchestrator orchestrator) { mActivityTabModelOrchestrators.add(orchestrator); - if (ChromeFeatureList.sAndroidTabDeclutter.isEnabled() - && mTabArchiveSettings.getArchiveEnabled()) { + if (mTabArchiveSettings.getArchiveEnabled()) { // To account for the local tab group sync database synchronizing with the sync service // on startup, a delay must be included when initiating a declutter pass that involves // archiving tab groups. Unfortunately, there is no particular synchronization step that @@ -431,7 +430,6 @@ private void doDeclutterPassImpl(TabbedModeTabModelOrchestrator orchestrator) { if (!mTabArchiveSettings.getArchiveEnabled()) return; - assert ChromeFeatureList.sAndroidTabDeclutter.isEnabled(); pauseSaveTabList(orchestrator); int archiveTimeHours = mTabArchiveSettings.getArchiveTimeDeltaHours();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java index 8313a16..24120459 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManager.java
@@ -10,7 +10,6 @@ import org.chromium.blink.mojom.DisplayMode; import org.chromium.cc.input.BrowserControlsState; import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; -import org.chromium.chrome.browser.browserservices.intents.WebappExtras; import org.chromium.chrome.browser.customtabs.CloseButtonVisibilityManager; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider; import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar; @@ -92,10 +91,7 @@ } private boolean shouldShowWebAppControls() { - WebappExtras webappExtras = mIntentDataProvider.getWebappExtras(); - return mInAppMode - && webappExtras != null - && webappExtras.displayMode == DisplayMode.MINIMAL_UI; + return mInAppMode && mIntentDataProvider.getResolvedDisplayMode() == DisplayMode.MINIMAL_UI; } /** Should be called when the browser enters and exits TWA mode. */ @@ -150,8 +146,10 @@ return BrowserControlsState.SHOWN; } - // Fallback to browser controls in fullscreen mode. - if (shouldShowWebAppControls() && !mIsInDesktopWindow) { + // Fallback to browser controls in fullscreen mode when running WebAPK or shortcut web app. + if (mIntentDataProvider.isWebappOrWebApkActivity() + && shouldShowWebAppControls() + && !mIsInDesktopWindow) { return BrowserControlsState.BOTH; }
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 0ed216fe..1855552 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
@@ -2067,20 +2067,19 @@ showContextMenu(stripView); } - /** - * Returns {@code true} if a context menu triggered from long-pressing a view is showing. Does - * not include the context menu from long-pressing the - */ + /** Returns {@code true} if a context menu triggered from long-pressing a view is showing. */ private boolean isViewContextMenuShowing() { return (mTabGroupContextMenuCoordinator != null && mTabGroupContextMenuCoordinator.isMenuShowing()) || (mTabContextMenuCoordinator != null - && mTabContextMenuCoordinator.isMenuShowing()); + && mTabContextMenuCoordinator.isMenuShowing()) + || (mCloseButtonMenu != null && mCloseButtonMenu.isShowing()); } private void dismissContextMenu() { if (mTabGroupContextMenuCoordinator != null) mTabGroupContextMenuCoordinator.dismiss(); if (mTabContextMenuCoordinator != null) mTabContextMenuCoordinator.dismiss(); + if (mCloseButtonMenu != null) mCloseButtonMenu.dismiss(); } /** @@ -2595,6 +2594,9 @@ return; } + // Don't allow the hovercard to show when any context menu is already showing. + if (isViewContextMenuShowing()) return; + int hoveredTabIndex = findIndexForTab(mLastHoveredTab.getTabId()); mTabHoverCardView.show( mModel.getTabAt(hoveredTabIndex),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabDragSource.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabDragSource.java index 9cb632d0..7dd910c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabDragSource.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabDragSource.java
@@ -58,7 +58,7 @@ import org.chromium.ui.dragdrop.DragDropGlobalState; import org.chromium.ui.dragdrop.DragDropGlobalState.TrackerToken; import org.chromium.ui.dragdrop.DragDropMetricUtils; -import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropTabResult; +import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropResult; import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropType; import org.chromium.ui.util.XrUtils; import org.chromium.ui.widget.Toast; @@ -387,9 +387,10 @@ if (didOccurInTabStrip(dragEvent.getY())) { res = onDrop(dragEvent); } else { - DragDropMetricUtils.recordTabDragDropResult( - DragDropTabResult.IGNORED_TOOLBAR, - AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager)); + DragDropMetricUtils.recordDragDropResult( + DragDropResult.IGNORED_TOOLBAR, + AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager), + isTabGroupDrop()); res = false; } break; @@ -484,7 +485,8 @@ StripLayoutHelper helper = mStripLayoutHelperSupplier.get(); helper.stopReorderMode(); if (isDragSource()) { - DragDropMetricUtils.recordTabReorderStripWithDragDrop(mUmaState.mDragEverLeftStrip); + DragDropMetricUtils.recordReorderStripWithDragDrop( + mUmaState.mDragEverLeftStrip, isTabGroupDrop()); return true; } @@ -530,14 +532,14 @@ tabIndex, /* isCollapsed= */ false); } - DragDropMetricUtils.recordTabDragDropType( + DragDropMetricUtils.recordDragDropType( DragDropType.TAB_STRIP_TO_TAB_STRIP, - AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager)); + AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager), + /* isTabGroup= */ false); mUmaState.mTabLeavingDestStripSystemElapsedTime = SystemClock.elapsedRealtime(); return true; } - // TODO(crbug.com/384979079): record metrics for tab group drop. private boolean handleGroupDrop(DragEvent dropEvent, StripLayoutHelper helper) { @Nullable TabGroupMetadata tabGroupMetadata = @@ -567,6 +569,11 @@ int tabIndex = helper.getTabIndexForTabDrop(dropEvent.getX() * mPxToDp); mMultiInstanceManager.moveTabGroupToWindow(getActivity(), tabGroupMetadata, tabIndex); } + DragDropMetricUtils.recordDragDropType( + DragDropType.TAB_STRIP_TO_TAB_STRIP, + AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager), + /* isTabGroup= */ true); + mUmaState.mTabLeavingDestStripSystemElapsedTime = SystemClock.elapsedRealtime(); return true; } @@ -583,7 +590,7 @@ - mUmaState.mTabEnteringDestStripSystemElapsedTime; assert duration >= 0 : "Duration when the drag is within the destination strip is invalid"; - DragDropMetricUtils.recordTabDurationWithinDestStrip(duration); + DragDropMetricUtils.recordDurationWithinDestStrip(duration, isTabGroupDrop()); } return false; } @@ -607,6 +614,7 @@ int sourceInstanceId = DragDropGlobalState.getState(sDragTrackerToken).getDragSourceInstance(); + boolean isTabGroupDrop = isTabGroupDrop(); mStripLayoutHelperSupplier.get().stopReorderMode(); mHandler.removeCallbacks(mOnDragExitRunnable); if (mShadowView != null) { @@ -622,22 +630,23 @@ // Only record for source strip to avoid duplicate. if (dropHandled) { - DragDropMetricUtils.recordTabDragDropResult( - DragDropTabResult.SUCCESS, - AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager)); - DragDropMetricUtils.recordTabDragDropClosedWindow(didCloseWindow); + DragDropMetricUtils.recordDragDropResult( + DragDropResult.SUCCESS, + AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager), + isTabGroupDrop); + DragDropMetricUtils.recordDragDropClosedWindow(didCloseWindow, isTabGroupDrop); } else if (MultiWindowUtils.getInstanceCount() == MultiWindowUtils.getMaxInstances()) { Toast.makeText( mWindowAndroid.getContext().get(), R.string.max_number_of_windows, Toast.LENGTH_LONG) .show(); - ChromeDragDropUtils.recordTabDragToCreateInstanceFailureCount(); - DragDropMetricUtils.recordTabDragDropResult( - DragDropTabResult.IGNORED_MAX_INSTANCES, - AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager)); + ChromeDragDropUtils.recordTabOrGroupDragToCreateInstanceFailureCount(); + DragDropMetricUtils.recordDragDropResult( + DragDropResult.IGNORED_MAX_INSTANCES, + AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager), + isTabGroupDrop); } - return true; } @@ -713,6 +722,12 @@ return tab != null; } + private boolean isTabGroupDrop() { + return ChromeDragDropUtils.getTabGroupMetadataFromGlobalState( + getDragDropGlobalState(/* dragEvent= */ null)) + != null; + } + public static void setDragTrackerTokenForTesting(TrackerToken token) { sDragTrackerToken = token; ResettersForTesting.register(() -> sDragTrackerToken = null); @@ -735,11 +750,14 @@ * @param tabTitle The title of the tab that cannot be moved. If null, no toast is shown. * @return {@code true} if the toast was shown, {@code false} otherwise. */ - // TODO(crbug.com/384979079): Record metrics. private boolean disallowDragWithMhtmlTab(Context context, @Nullable String tabTitle) { if (tabTitle == null) return false; String text = context.getString(R.string.tab_cannot_be_moved, tabTitle); Toast.makeText(context, text, Toast.LENGTH_LONG).show(); + DragDropMetricUtils.recordDragDropResult( + DragDropResult.IGNORED_MHTML_TAB, + AppHeaderUtils.isAppInDesktopWindow(mDesktopWindowStateManager), + /* isTabGroup= */ true); return true; } @@ -841,6 +859,10 @@ return tabModelSelector != null && tabModelSelector.getTotalTabCount() > 1; } + void createUmaStateForTesting() { + mUmaState = new DragLocalUmaState(); + } + View getShadowViewForTesting() { return mShadowView; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java index b6b4011..043a7f9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java
@@ -321,11 +321,7 @@ try { ParcelFileDescriptor fd = null; if (isContentUri) { - int fileDescriptor = - ContentUriUtils.openContentUri(mDownloadInfo.getFilePath(), "r"); - if (fileDescriptor > 0) { - fd = ParcelFileDescriptor.fromFd(fileDescriptor); - } + fd = ContentUriUtils.openContentUri(mDownloadInfo.getFilePath(), "r"); } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { fd = manager.openDownloadedFile(mDownloadId); } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeDragDropUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeDragDropUtils.java index 8fcdd64..ed51300e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeDragDropUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeDragDropUtils.java
@@ -27,37 +27,43 @@ /** Utility class for Chrome drag and drop implementations. */ public class ChromeDragDropUtils { - private static final int MAX_TAB_TEARING_FAILURE_COUNT_PER_DAY = 10; + private static final int MAX_TAB_OR_GROUP_TEARING_FAILURE_COUNT_PER_DAY = 10; /** - * Records linear histogram Android.DragDrop.Tab.MaxInstanceFailureCount and saves related - * SharedPreferences values. + * Records linear histogram Android.DragDrop.TabOrGroup.MaxInstanceFailureCount and saves + * related SharedPreferences values. */ - public static void recordTabDragToCreateInstanceFailureCount() { + public static void recordTabOrGroupDragToCreateInstanceFailureCount() { var prefs = ChromeSharedPreferences.getInstance(); - // Check the failure count in a day for every unhandled dragged tab drop when max instances + // Check the failure count in a day for every unhandled dragged tab or group drop when max + // instances // are open. long timestamp = prefs.readLong( - ChromePreferenceKeys.TAB_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, 0); + ChromePreferenceKeys + .TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, + 0); int failureCount = - prefs.readInt(ChromePreferenceKeys.TAB_TEARING_MAX_INSTANCES_FAILURE_COUNT, 0); + prefs.readInt( + ChromePreferenceKeys.TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_COUNT, 0); long current = System.currentTimeMillis(); boolean isNewDay = timestamp == 0 || current - timestamp > DateUtils.DAY_IN_MILLIS; if (isNewDay) { prefs.writeLong( - ChromePreferenceKeys.TAB_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, current); + ChromePreferenceKeys.TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, + current); // Reset the count to 0 if it is the start of the next 24-hour period. failureCount = 0; } RecordHistogram.recordExactLinearHistogram( - "Android.DragDrop.Tab.MaxInstanceFailureCount", + "Android.DragDrop.TabOrGroup.MaxInstanceFailureCount", failureCount + 1, - MAX_TAB_TEARING_FAILURE_COUNT_PER_DAY + 1); + MAX_TAB_OR_GROUP_TEARING_FAILURE_COUNT_PER_DAY + 1); prefs.writeInt( - ChromePreferenceKeys.TAB_TEARING_MAX_INSTANCES_FAILURE_COUNT, failureCount + 1); + ChromePreferenceKeys.TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_COUNT, + failureCount + 1); } /** @@ -71,7 +77,8 @@ return switch (intent.getIntExtra( IntentHandler.EXTRA_URL_DRAG_SOURCE, UrlIntentSource.UNKNOWN)) { case UrlIntentSource.LINK -> DragDropType.LINK_TO_NEW_INSTANCE; - case UrlIntentSource.TAB_IN_STRIP -> DragDropType.TAB_STRIP_TO_NEW_INSTANCE; + case UrlIntentSource.TAB_IN_STRIP, UrlIntentSource.TAB_GROUP_IN_STRIP -> DragDropType + .TAB_STRIP_TO_NEW_INSTANCE; default -> DragDropType.UNKNOWN_TO_NEW_INSTANCE; }; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListener.java b/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListener.java index da86b96c..afcb83a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListener.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListener.java
@@ -25,7 +25,7 @@ import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.dragdrop.DragDropGlobalState; import org.chromium.ui.dragdrop.DragDropMetricUtils; -import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropTabResult; +import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropResult; import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropType; /** @@ -79,22 +79,23 @@ // This is to prevent tab switcher from receiving drops. We might support dropping // into tab switcher in the future, but this should still be retained to prevent // dropping happens on top of tab switcher toolbar. + boolean isTabGroupDrop = + clipDescription.hasMimeType(MimeTypeUtils.CHROME_MIMETYPE_TAB_GROUP); if (mLayoutStateProviderSupplier.get() == null || mLayoutStateProviderSupplier .get() .isLayoutVisible(LayoutType.TAB_SWITCHER)) { - DragDropMetricUtils.recordTabDragDropResult( - DragDropTabResult.IGNORED_TAB_SWITCHER, isInDesktopWindow); + DragDropMetricUtils.recordDragDropResult( + DragDropResult.IGNORED_TAB_SWITCHER, isInDesktopWindow, isTabGroupDrop); return false; } if (clipDescription == null) return false; - if (clipDescription.hasMimeType(MimeTypeUtils.CHROME_MIMETYPE_TAB)) { + if (isTabGroupDrop) { + return handleGroupDrop(dragEvent, isInDesktopWindow); + } else { + assert clipDescription.hasMimeType(MimeTypeUtils.CHROME_MIMETYPE_TAB); return handleTabDrop(dragEvent, isInDesktopWindow); } - if (clipDescription.hasMimeType(MimeTypeUtils.CHROME_MIMETYPE_TAB_GROUP)) { - return handleGroupDrop(dragEvent); - } - return false; } return false; } @@ -103,13 +104,17 @@ DragDropGlobalState globalState = DragDropGlobalState.getState(dragEvent); Tab draggedTab = ChromeDragDropUtils.getTabFromGlobalState(globalState); if (globalState == null || draggedTab == null) { - DragDropMetricUtils.recordTabDragDropResult( - DragDropTabResult.ERROR_TAB_NOT_FOUND, isInDesktopWindow); + DragDropMetricUtils.recordDragDropResult( + DragDropResult.ERROR_CONTENT_NOT_FOUND, + isInDesktopWindow, + /* isTabGroup= */ false); return false; } if (globalState.isDragSourceInstance(mMultiInstanceManager.getCurrentInstanceId())) { - DragDropMetricUtils.recordTabDragDropResult( - DragDropTabResult.IGNORED_SAME_INSTANCE, isInDesktopWindow); + DragDropMetricUtils.recordDragDropResult( + DragDropResult.IGNORED_SAME_INSTANCE, + isInDesktopWindow, + /* isTabGroup= */ false); return false; } @@ -129,20 +134,27 @@ // Reparent the dragged tab to the destination window. mMultiInstanceManager.moveTabToWindow( mWindowAndroid.getActivity().get(), draggedTab, destIndex); - DragDropMetricUtils.recordTabDragDropType( - DragDropType.TAB_STRIP_TO_CONTENT, isInDesktopWindow); + DragDropMetricUtils.recordDragDropType( + DragDropType.TAB_STRIP_TO_CONTENT, isInDesktopWindow, /* isTabGroup= */ false); return true; } - // TODO(crbug.com/384979079): record metrics for tab group drop. - private boolean handleGroupDrop(DragEvent dragEvent) { + private boolean handleGroupDrop(DragEvent dragEvent, boolean isInDesktopWindow) { DragDropGlobalState globalState = DragDropGlobalState.getState(dragEvent); TabGroupMetadata tabGroupMetadata = ChromeDragDropUtils.getTabGroupMetadataFromGlobalState(globalState); if (globalState == null || tabGroupMetadata == null) { + DragDropMetricUtils.recordDragDropResult( + DragDropResult.ERROR_CONTENT_NOT_FOUND, + isInDesktopWindow, + /* isTabGroup= */ true); return false; } if (globalState.isDragSourceInstance(mMultiInstanceManager.getCurrentInstanceId())) { + DragDropMetricUtils.recordDragDropResult( + DragDropResult.IGNORED_SAME_INSTANCE, + isInDesktopWindow, + /* isTabGroup= */ true); return false; } @@ -157,6 +169,8 @@ // Reparent the dragged tab group to destination window. mMultiInstanceManager.moveTabGroupToWindow( mWindowAndroid.getActivity().get(), tabGroupMetadata, destIndex); + DragDropMetricUtils.recordDragDropType( + DragDropType.TAB_STRIP_TO_CONTENT, isInDesktopWindow, /* isTabGroup= */ true); return true; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java index 867c3b4..8bf468a8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
@@ -63,7 +63,6 @@ import org.chromium.chrome.browser.sync.settings.ManageSyncSettings; import org.chromium.chrome.browser.sync.settings.SignInPreference; import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils; -import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncFeatures; import org.chromium.chrome.browser.toolbar.ToolbarPositionController; import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor; import org.chromium.chrome.browser.toolbar.settings.AddressBarSettingsFragment; @@ -385,17 +384,7 @@ updatePlusAddressesPreference(); updateAddressBarPreference(); updateAppearancePreference(); - - boolean isTabGroupSyncAutoOpenConfigurable = - TabGroupSyncFeatures.isTabGroupSyncEnabled(getProfile()) - && ChromeFeatureList.isEnabled( - ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH); - if (isTabGroupSyncAutoOpenConfigurable - || ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_TAB_DECLUTTER)) { - addPreferenceIfAbsent(PREF_TABS); - } else { - removePreferenceIfPresent(PREF_TABS); - } + addPreferenceIfAbsent(PREF_TABS); Preference homepagePref = addPreferenceIfAbsent(PREF_HOMEPAGE); setOnOffSummary(homepagePref, HomepageManager.getInstance().isHomepageEnabled());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java index 60d55bc..14c5ced2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
@@ -144,11 +144,16 @@ } @Override + public void onStart() { + super.onStart(); + update(); + } + + @Override public void onResume() { super.onResume(); IdentityServicesProvider.get().getSigninManager(getProfile()).addSignInStateObserver(this); mProfileDataCache.addObserver(this); - update(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java index df2cbaf..c049b08 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java
@@ -179,8 +179,8 @@ } @Override - public void onResume() { - super.onResume(); + public void onStart() { + super.onStart(); updatePreferences(); } @@ -303,4 +303,9 @@ } }; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java index ef59a74..882ced0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java
@@ -555,6 +555,13 @@ super.onStart(); mSyncService.addSyncStateChangedListener(this); IdentityServicesProvider.get().getIdentityManager(getProfile()).addObserver(this); + + // This is necessary to refresh the batch upload card if the user leaves Chrome open on the + // settings screen, changes their screen lock settings, and then returns to Chrome. + if (mShouldReplaceSyncSettingsWithAccountSettings) { + mBatchUploadCardPreference.hideBatchUploadCardAndUpdate(); + } + updateSyncPreferences(); } @Override @@ -565,17 +572,6 @@ } @Override - public void onResume() { - super.onResume(); - // This is necessary to refresh the batch upload card if the user leaves Chrome open on the - // settings screen, changes their screen lock settings, and then returns to Chrome. - if (mShouldReplaceSyncSettingsWithAccountSettings) { - mBatchUploadCardPreference.hideBatchUploadCardAndUpdate(); - } - updateSyncPreferences(); - } - - @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (mSyncService.isUsingExplicitPassphrase() && mShouldReplaceSyncSettingsWithAccountSettings @@ -1203,4 +1199,9 @@ private void finishCurrentSettings() { SettingsNavigationFactory.createSettingsNavigation().finishCurrentSettings(this); } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/PersonalizeGoogleServicesSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/PersonalizeGoogleServicesSettings.java index a0a5ab1..6504929 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/PersonalizeGoogleServicesSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/PersonalizeGoogleServicesSettings.java
@@ -56,11 +56,6 @@ public void onStart() { super.onStart(); mSyncService.addSyncStateChangedListener(this); - } - - @Override - public void onResume() { - super.onResume(); updatePreferences(); } @@ -106,4 +101,9 @@ .openLinkedGoogleServicesSettings(getActivity(), signedInAccountName); RecordUserAction.record("Signin_AccountSettings_LinkedGoogleServicesClicked"); } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiveSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiveSettings.java index 078e5678..1cd7f9a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiveSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiveSettings.java
@@ -27,6 +27,14 @@ void onSettingChanged(); } + // The default time to consider a tab as inactive. + static final int DEFAULT_ARCHIVE_TIME_HOURS = 21 * 24; // 21 days. + // The default time interval between same-session declutter passes. + private static final int DEFAULT_DECLUTTER_INTERVAL_TIME_HOURS = 7 * 24; // 7 days. + // The default allowable times we can show an IPH. + private static final int DEFAULT_ALLOWED_IPH_SHOWS = 3; + // The default max simultaneous archives to allow in a single pass. + static final int DEFAULT_MAX_SIMULTANEOUS_ARCHIVES = 150; private static boolean sIphShownThisSession; /** Sets whether the iph was shown this session. */ @@ -92,10 +100,7 @@ // are created, and tabs disappearing from tests is very unexpected. For archive tests, // this will need to be turned on manually. return mPrefsManager.readBoolean( - ChromePreferenceKeys.TAB_DECLUTTER_ARCHIVE_ENABLED, - BuildConfig.IS_FOR_TEST - ? false - : ChromeFeatureList.sAndroidTabDeclutterArchiveEnabled.getValue()); + ChromePreferenceKeys.TAB_DECLUTTER_ARCHIVE_ENABLED, !BuildConfig.IS_FOR_TEST); } /** Sets whether archive is enabled in settings. */ @@ -107,17 +112,12 @@ public int getArchiveTimeDeltaHours() { return mPrefsManager.readInt( ChromePreferenceKeys.TAB_DECLUTTER_ARCHIVE_TIME_DELTA_HOURS, - ChromeFeatureList.sAndroidTabDeclutterArchiveTimeDeltaHours.getValue()); + DEFAULT_ARCHIVE_TIME_HOURS); } /** Similar to above, but the return value is in days. */ public int getArchiveTimeDeltaDays() { - return (int) - TimeUnit.HOURS.toDays( - mPrefsManager.readInt( - ChromePreferenceKeys.TAB_DECLUTTER_ARCHIVE_TIME_DELTA_HOURS, - ChromeFeatureList.sAndroidTabDeclutterArchiveTimeDeltaHours - .getValue())); + return (int) TimeUnit.HOURS.toDays(getArchiveTimeDeltaHours()); } /** Sets the time delta (in hours) used to determine if a tab is eligible for archive. */ @@ -136,7 +136,7 @@ return getArchiveEnabled() && mPrefsManager.readBoolean( ChromePreferenceKeys.TAB_DECLUTTER_AUTO_DELETE_ENABLED, - ChromeFeatureList.sAndroidTabDeclutterAutoDeleteEnabled.getValue()); + ChromeFeatureList.sAndroidTabDeclutterAutoDelete.isEnabled()); } /** Sets whether auto deletion for archived tabs is enabled in settings. */ @@ -169,12 +169,7 @@ /** Similar to above, but the return value is in days. */ public int getAutoDeleteTimeDeltaDays() { - return (int) - TimeUnit.HOURS.toDays( - mPrefsManager.readInt( - ChromePreferenceKeys.TAB_DECLUTTER_AUTO_DELETE_TIME_DELTA_HOURS, - ChromeFeatureList.sAndroidTabDeclutterAutoDeleteTimeDeltaHours - .getValue())); + return (int) TimeUnit.HOURS.toDays(getAutoDeleteTimeDeltaHours()); } /** Sets the time delta used to determine if an archived tab is eligible for auto deletion. */ @@ -185,13 +180,13 @@ /** Returns the interval to perform declutter in hours. */ public int getDeclutterIntervalTimeDeltaHours() { - return ChromeFeatureList.sAndroidTabDeclutterIntervalTimeDeltaHours.getValue(); + return DEFAULT_DECLUTTER_INTERVAL_TIME_HOURS; } /** Returns whether the dialog iph should be shown. */ public boolean shouldShowDialogIph() { return mPrefsManager.readInt(ChromePreferenceKeys.TAB_DECLUTTER_DIALOG_IPH_DISMISS_COUNT, 0) - < ChromeFeatureList.sAndroidTabDeclutterIphMessageDismissThreshold.getValue(); + < DEFAULT_ALLOWED_IPH_SHOWS; } /** Sets whether the dialog iph should be shown. */ @@ -205,10 +200,11 @@ public void setShouldShowDialogIphForTesting(boolean shouldShow) { mPrefsManager.writeInt( ChromePreferenceKeys.TAB_DECLUTTER_DIALOG_IPH_DISMISS_COUNT, - shouldShow - ? 0 - : ChromeFeatureList.sAndroidTabDeclutterIphMessageDismissThreshold - .getValue()); + shouldShow ? 0 : DEFAULT_ALLOWED_IPH_SHOWS); + } + + public int getMaxSimultaneousArchives() { + return DEFAULT_MAX_SIMULTANEOUS_ARCHIVES; } // Private methods.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiverImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiverImpl.java index 6c17814a..b9442c6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiverImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabArchiverImpl.java
@@ -154,8 +154,7 @@ // Maps unique tab group tokens to the eligibility of that group. Map<Token, Boolean> tabGroupIdToArchiveEligibilityMap = new HashMap<>(); - int maxSimultaneousArchives = - ChromeFeatureList.sAndroidTabDeclutterMaxSimultaneousArchives.getValue(); + int maxSimultaneousArchives = mTabArchiveSettings.getMaxSimultaneousArchives(); for (int i = 0; i < model.getCount(); i++) { // TODO(crbug.com/369845089): Investigate a more graceful fix to // batch these so all relevant tabs still get archived in the same
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java index de654a6..1b6dfab 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegate.java
@@ -491,7 +491,8 @@ /** * @return Whether the "New window" menu item should be displayed. */ - protected boolean shouldShowNewWindow() { + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) + public boolean shouldShowNewWindow() { // Hide the menu on automotive devices. if (BuildInfo.getInstance().isAutomotive) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java index 2cbfbb9..7b9c3f3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/DeveloperSettings.java
@@ -64,4 +64,9 @@ public ObservableSupplier<String> getPageTitle() { return mPageTitle; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingCategoriesSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingCategoriesSettings.java index 6080ea2..6d735a4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingCategoriesSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingCategoriesSettings.java
@@ -125,4 +125,9 @@ pref.callChangeListener(pref.isChecked()); } } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingSettings.java index 9e852f4..02e07d4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingSettings.java
@@ -232,9 +232,14 @@ } @Override + public void onStart() { + super.onStart(); + updatePreferences(); + } + + @Override public void onResume() { super.onResume(); - updatePreferences(); TracingController.getInstance().addObserver(this); } @@ -302,4 +307,9 @@ mPrefTracingStatus.setTitle(MSG_ACTIVE_SUMMARY); } } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java index cf1c67b..001df853 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
@@ -193,22 +193,20 @@ } private @DisplayMode.EnumType int resolveDisplayMode() { - if (mWebappExtras.displayMode == DisplayMode.FULLSCREEN) { - return DisplayMode.FULLSCREEN; + if (mWebappExtras.displayMode == DisplayMode.BROWSER) { + // `browser` display mode web apps are not installable by default, because by the spec + // they should be opened in a new tab or browser window, but in Chrome they can be + // forcefully installed via app menu. In this case display mode should resolve to the + // first supported display mode in the "fullscreen -> standalone -> minimal-ui -> + // browser" fallback chain. + if (WebAppHeaderUtils.isMinimalUiFlagEnabled()) { + return DisplayMode.MINIMAL_UI; + } else { + return DisplayMode.STANDALONE; + } } - // `browser` display mode web apps are not installable by default, because by the spec they - // should be opened in a new tab or browser window, but in Chrome they can be forcefully - // installed via app menu. In this case display mode should resolve to the first supported - // display mode in the "fullscreen -> standalone -> minimal-ui -> browser" fallback chain. - boolean shouldUseMinimalUi = - mWebappExtras.displayMode == DisplayMode.MINIMAL_UI - || mWebappExtras.displayMode == DisplayMode.BROWSER; - if (WebAppHeaderUtils.isMinimalUiFlagEnabled() && shouldUseMinimalUi) { - return DisplayMode.MINIMAL_UI; - } - - return DisplayMode.STANDALONE; + return mWebappExtras.displayMode; } private static final class ColorProviderImpl implements ColorProvider {
diff --git a/chrome/android/javatests/BUILD.gn b/chrome/android/javatests/BUILD.gn index 60e5785..1f53e5d8 100644 --- a/chrome/android/javatests/BUILD.gn +++ b/chrome/android/javatests/BUILD.gn
@@ -512,6 +512,7 @@ sources = [ "//chrome/android/java/src/org/chromium/chrome/browser/app/feed/NavigationRecorderTest.java", "src/org/chromium/chrome/browser/app/ContextMenuDragTest.java", + "src/org/chromium/chrome/browser/app/appmenu/MultiWindowAppMenuTest.java", "src/org/chromium/chrome/browser/app/appmenu/OverviewAppMenuTest.java", "src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuPTTest.java", "src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java index 2de53dd..1dd85c47 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -868,10 +868,7 @@ @Test @MediumTest @Feature({"Android-TabSwitcher"}) - @DisableFeatures({ - ChromeFeatureList.ANDROID_TAB_DECLUTTER, - ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH - }) + @DisableFeatures({ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH}) public void testIncognitoTabsNotRestoredAfterSwipe() throws Exception { mActivityTestRule.loadUrl(getUrl(TEST_PAGE_FILE_PATH));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/MultiWindowAppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/MultiWindowAppMenuTest.java new file mode 100644 index 0000000..15495ed2 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/appmenu/MultiWindowAppMenuTest.java
@@ -0,0 +1,69 @@ +// 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.app.appmenu; + +import static org.junit.Assert.assertNotEquals; + +import androidx.test.filters.LargeTest; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.transit.Station; +import org.chromium.base.test.transit.TransitAsserts; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DoNotBatch; +import org.chromium.base.test.util.Restriction; +import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.transit.ChromeTransitTestRules; +import org.chromium.chrome.test.transit.FreshCtaTransitTestRule; +import org.chromium.chrome.test.transit.ntp.IncognitoNewTabPageStation; +import org.chromium.chrome.test.transit.ntp.RegularNewTabPageStation; +import org.chromium.chrome.test.transit.page.WebPageStation; +import org.chromium.ui.base.DeviceFormFactor; +import org.chromium.ui.test.util.DeviceRestriction; + +/** Public Transit tests for operations through the app menu in multi-window. */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@DoNotBatch(reason = "Batching not yet supported in multi-window") +// In phones, the New Window option in the app menu is only enabled when already in multi-window or +// multi-display mode with Chrome not running in an adjacent window. +@Restriction({DeviceFormFactor.TABLET, DeviceRestriction.RESTRICTION_TYPE_NON_AUTO}) +public class MultiWindowAppMenuTest { + @Rule + public FreshCtaTransitTestRule mCtaTestRule = + ChromeTransitTestRules.freshChromeTabbedActivityRule(); + + @Test + @LargeTest + public void testOpenNewWindow_fromWebPage() { + WebPageStation pageInFirstWindow = mCtaTestRule.startOnBlankPage(); + RegularNewTabPageStation pageInSecondWindow = + pageInFirstWindow.openRegularTabAppMenu().openNewWindow(); + + assertInDifferentWindows(pageInFirstWindow, pageInSecondWindow); + TransitAsserts.assertFinalDestinations(pageInFirstWindow, pageInSecondWindow); + } + + @Test + @LargeTest + public void testOpenNewWindow_fromIncognitoNtp() { + IncognitoNewTabPageStation pageInFirstWindow = + mCtaTestRule.startOnBlankPage().openNewIncognitoTabFast(); + RegularNewTabPageStation pageInSecondWindow = + pageInFirstWindow.openAppMenu().openNewWindow(); + + assertInDifferentWindows(pageInFirstWindow, pageInSecondWindow); + TransitAsserts.assertFinalDestinations(pageInFirstWindow, pageInSecondWindow); + } + + static void assertInDifferentWindows(Station<?> station1, Station<?> station2) { + assertNotEquals(station1.getActivity(), station2.getActivity()); + assertNotEquals(station1.getActivity().getWindow(), station2.getActivity().getWindow()); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabModelOrchestratorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabModelOrchestratorTest.java index 5b1a52c..9a9b177 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabModelOrchestratorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabModelOrchestratorTest.java
@@ -72,10 +72,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @DoNotBatch(reason = "Test interacts with activity shutdown and thus is incompatible with batching") -@EnableFeatures({ - ChromeFeatureList.ANDROID_TAB_DECLUTTER, - ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH -}) +@EnableFeatures({ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH}) @DisableFeatures({ ChromeFeatureList.ANDROID_TAB_DECLUTTER_ARCHIVE_ALL_BUT_ACTIVE, ChromeFeatureList.ANDROID_TAB_DECLUTTER_ARCHIVE_TAB_GROUPS
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabsTest.java index a00cda0..afd26338 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/tabmodel/ArchivedTabsTest.java
@@ -46,10 +46,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @DoNotBatch(reason = "Test interacts with activity shutdown and thus is incompatible with batching") -@EnableFeatures({ - ChromeFeatureList.ANDROID_TAB_DECLUTTER, - ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH -}) +@EnableFeatures({ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH}) @DisableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER_ARCHIVE_ALL_BUT_ACTIVE) public class ArchivedTabsTest { private static class FakeDeferredStartupHandler extends DeferredStartupHandler {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java index f160c42..3226323b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java
@@ -17,10 +17,8 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.base.ColdStartTracker; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.metrics.SimpleStartupForegroundSessionDetector; import org.chromium.chrome.browser.paint_preview.services.PaintPreviewTabServiceFactory; @@ -96,7 +94,6 @@ */ @Test @MediumTest - @DisableFeatures({ChromeFeatureList.ANDROID_TAB_DECLUTTER}) @DisabledTest(message = "Pending revival. See crbug.com/333779543.") public void testDisplayOnStartup() throws ExecutionException { mActivityTestRule.startMainActivityWithURL(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java index b232359..e37782d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
@@ -820,58 +820,13 @@ @Test @SmallTest - @EnableFeatures({ - ChromeFeatureList.TAB_GROUP_SYNC_ANDROID, - ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH - }) - @DisableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) - public void testTabsSettingsOn_GroupSync_KillSwitchInactive() { + public void testTabsSettingsOn() { startSettings(); assertSettingsExists(MainSettings.PREF_TABS, TabsSettings.class); } @Test @SmallTest - @EnableFeatures(ChromeFeatureList.TAB_GROUP_SYNC_ANDROID) - @DisableFeatures({ - ChromeFeatureList.ANDROID_TAB_DECLUTTER, - ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH - }) - public void testTabsSettingsOn_GroupSync_KillSwitchActive() { - startSettings(); - Assert.assertNull( - "Tabs settings should not be shown", - mMainSettings.findPreference(MainSettings.PREF_TABS)); - } - - @Test - @SmallTest - @DisableFeatures({ - ChromeFeatureList.TAB_GROUP_SYNC_ANDROID, - ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH - }) - @EnableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) - public void testTabsSettingsOn_Declutter() { - startSettings(); - assertSettingsExists(MainSettings.PREF_TABS, TabsSettings.class); - } - - @Test - @SmallTest - @DisableFeatures({ - ChromeFeatureList.ANDROID_TAB_DECLUTTER, - ChromeFeatureList.TAB_GROUP_SYNC_ANDROID - }) - @EnableFeatures(ChromeFeatureList.TAB_GROUP_SYNC_AUTO_OPEN_KILL_SWITCH) - public void testTabsSettingsOff() { - startSettings(); - Assert.assertNull( - "Tabs settings should not be shown", - mMainSettings.findPreference(MainSettings.PREF_TABS)); - } - - @Test - @SmallTest @EnableFeatures(ChromeFeatureList.SAFETY_HUB) public void testSafetyHubFlagOn() { startSettings();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java index e535ac2..05cd1da 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninFirstRunFragmentTest.java
@@ -1111,13 +1111,6 @@ sdk_is_greater_than = Build.VERSION_CODES.S_V2, message = "Flaky, crbug.com/358148764") public void testFragmentSigninWhenAddedAccountIsNotYetAvailable() { - final String continueAsText = - mActivityTestRule - .getActivity() - .getString( - R.string.sync_promo_continue_as, - TestAccounts.TEST_ACCOUNT_NO_NAME.getEmail()); - // This will freeze AccountManagerFacade with the currently available list of accounts. // The added account from add account flow later on will not be available. try (var ignored = @@ -1126,15 +1119,19 @@ onView(withText(R.string.signin_add_account_to_device)).perform(click()); mSigninTestRule.setAddAccountFlowResult(TestAccounts.TEST_ACCOUNT_NO_NAME); onViewWaiting(AccountManagerTestRule.ADD_ACCOUNT_BUTTON_MATCHER).perform(click()); - checkFragmentWithSelectedAccount(TestAccounts.TEST_ACCOUNT_NO_NAME); - clickContinueButton(continueAsText); - - // The click on continue button should be a no-op. - verify(mFirstRunPageDelegateMock, never()).advanceToNextPage(); - checkFragmentWithSelectedAccount(TestAccounts.TEST_ACCOUNT_NO_NAME); + // The account is not visible and thus add account button is shown. + onView(withText(R.string.signin_add_account_to_device)).check(matches(isDisplayed())); } + // Allow account list update and the continue button starts sign-in. + checkFragmentWithSelectedAccount(TestAccounts.TEST_ACCOUNT_NO_NAME); + String continueAsText = + mActivityTestRule + .getActivity() + .getString( + R.string.sync_promo_continue_as, + TestAccounts.TEST_ACCOUNT_NO_NAME.getEmail()); clickContinueButton(continueAsText); verify(mFirstRunPageDelegateMock, timeout(CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL)) .advanceToNextPage();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabArchiverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabArchiverTest.java index bb0eb095..56ed93e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabArchiverTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabArchiverTest.java
@@ -75,10 +75,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Batch(Batch.PER_CLASS) -@EnableFeatures({ - ChromeFeatureList.ANDROID_TAB_DECLUTTER, - ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH -}) +@EnableFeatures({ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH}) @DisableFeatures({ChromeFeatureList.ANDROID_TAB_DECLUTTER_ARCHIVE_TAB_GROUPS}) public class TabArchiverTest { @ClassRule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImplTest.java index 85e3e3e..a001907 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImplTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImplTest.java
@@ -21,11 +21,8 @@ import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.Features.DisableFeatures; -import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.app.tabmodel.ArchivedTabModelOrchestrator; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.ntp.RecentlyClosedBulkEvent; import org.chromium.chrome.browser.ntp.RecentlyClosedEntry; @@ -63,7 +60,6 @@ ChromeSwitches.DISABLE_STARTUP_PROMOS }) @Batch(Batch.PER_CLASS) -@DisableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) public class HistoricalTabSaverImplTest { private static final String TEST_PAGE_1 = "/chrome/test/data/android/about.html"; private static final String TEST_PAGE_2 = "/chrome/test/data/android/simple.html"; @@ -435,7 +431,6 @@ @Test @MediumTest - @EnableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) public void testArchivedTabsAreExcluded() { ArchivedTabModelOrchestrator archivedTabModelOrchestrator = runOnUiThreadBlocking(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ArchivedTabCreatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ArchivedTabCreatorTest.java index 253c7aab..b46d5b8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ArchivedTabCreatorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/ArchivedTabCreatorTest.java
@@ -42,10 +42,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Batch(Batch.PER_CLASS) -@EnableFeatures({ - ChromeFeatureList.ANDROID_TAB_DECLUTTER, - ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH -}) +@EnableFeatures({ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH}) public class ArchivedTabCreatorTest { @ClassRule public static ChromeTabbedActivityTestRule sActivityTestRule =
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/app/tabmodel/TabPersistentStoreIntegrationTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/app/tabmodel/TabPersistentStoreIntegrationTest.java index 9c5446c..2216138 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/app/tabmodel/TabPersistentStoreIntegrationTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/app/tabmodel/TabPersistentStoreIntegrationTest.java
@@ -85,7 +85,6 @@ @LooperMode(Mode.PAUSED) @EnableFeatures({ChromeFeatureList.PROCESS_RANK_POLICY_ANDROID}) @DisableFeatures({ - ChromeFeatureList.ANDROID_TAB_DECLUTTER, ChromeFeatureList.ANDROID_TAB_DECLUTTER_RESCUE_KILLSWITCH, ChromeFeatureList.CHANGE_UNFOCUSED_PRIORITY })
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManagerTest.java index 9419ea8..5b22af1 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/controller/TrustedWebActivityBrowserControlsVisibilityManagerTest.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller; +import static androidx.browser.customtabs.CustomTabsIntent.COLOR_SCHEME_LIGHT; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -16,7 +18,19 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; import android.graphics.Rect; +import android.os.Build; +import android.view.ContextThemeWrapper; + +import androidx.browser.customtabs.CustomTabsIntent; +import androidx.browser.customtabs.CustomTabsSession; +import androidx.browser.customtabs.TrustedWebUtils; +import androidx.browser.trusted.TrustedWebActivityDisplayMode; +import androidx.browser.trusted.TrustedWebActivityIntentBuilder; +import androidx.test.core.app.ApplicationProvider; import org.junit.Before; import org.junit.Rule; @@ -29,14 +43,19 @@ import org.robolectric.annotation.Config; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.blink.mojom.DisplayMode; import org.chromium.build.annotations.Nullable; import org.chromium.cc.input.BrowserControlsState; +import org.chromium.chrome.R; import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.customtabs.CloseButtonVisibilityManager; +import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider; import org.chromium.chrome.browser.customtabs.content.TabObserverRegistrar; import org.chromium.chrome.browser.customtabs.features.toolbar.CustomTabToolbarCoordinator; +import org.chromium.chrome.browser.document.ChromeLauncherActivity; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.util.browser.webapps.WebApkIntentDataProviderBuilder; import org.chromium.components.browser_ui.desktop_windowing.AppHeaderState; @@ -64,6 +83,7 @@ @Mock TrustedWebActivityBrowserControlsVisibilityManager mController; private @Nullable AppHeaderState mAppHeaderState; + private Context mContext; @Before public void setUp() { @@ -71,6 +91,11 @@ when(mTabProvider.getTab()).thenReturn(mTab); doReturn(Tab.INVALID_TAB_ID).when(mTab).getParentId(); setTabSecurityLevel(ConnectionSecurityLevel.NONE); + + mContext = + new ContextThemeWrapper( + ApplicationProvider.getApplicationContext(), + R.style.Theme_BrowserUI_DayNight); } /** Browser controls should be shown for pages with certificate errors. */ @@ -127,6 +152,8 @@ } @Test + @Config(sdk = Build.VERSION_CODES.VANILLA_ICE_CREAM) + @EnableFeatures({ChromeFeatureList.ANDROID_MINIMAL_UI_LARGE_SCREEN}) public void testMinimalUiExitDesktopWindowingInAppMode_ShowBrowserControls() { setupDesktopWindowing(/* isInDesktopWindow= */ true); mController = buildController(buildWebApkIntentDataProvider(DisplayMode.MINIMAL_UI)); @@ -134,11 +161,16 @@ setupDesktopWindowing(/* isInDesktopWindow= */ false); mController.onDesktopWindowingModeChanged(mAppHeaderState.isInDesktopWindow()); - assertEquals(BrowserControlsState.BOTH, getLastBrowserControlsState()); + assertEquals( + "Browser controls should be shown", + BrowserControlsState.BOTH, + getLastBrowserControlsState()); assertFalse("Close button should be hidden in minimal ui", getLastCloseButtonVisibility()); } @Test + @Config(sdk = Build.VERSION_CODES.VANILLA_ICE_CREAM) + @EnableFeatures({ChromeFeatureList.ANDROID_MINIMAL_UI_LARGE_SCREEN}) public void testMinUiExitDwAndEnterAppMode_KeepBrowserControlsHidden() { // navigate out of scope in DW mController = buildController(buildWebApkIntentDataProvider(DisplayMode.MINIMAL_UI)); @@ -196,7 +228,12 @@ /** Browser controls should not be shown for TWAs while in TWA mode. */ @Test public void testTwa() { - mController = buildController(mock(BrowserServicesIntentDataProvider.class)); + var intent = buildTwaIntent(); + intent.putExtra( + TrustedWebActivityIntentBuilder.EXTRA_DISPLAY_MODE, + new TrustedWebActivityDisplayMode.DefaultMode().toBundle()); + mController = buildController(buildCustomTabIntentProvider(intent)); + mController.updateIsInAppMode(true); assertEquals(BrowserControlsState.HIDDEN, getLastBrowserControlsState()); } @@ -207,8 +244,65 @@ mController = buildController(mock(BrowserServicesIntentDataProvider.class)); mController.updateIsInAppMode(true); mController.updateIsInAppMode(false); - assertEquals(BrowserControlsState.BOTH, getLastBrowserControlsState()); - assertTrue(getLastCloseButtonVisibility()); + assertEquals( + "Browser controls should be visible", + BrowserControlsState.BOTH, + getLastBrowserControlsState()); + assertTrue("Close button should be visible", getLastCloseButtonVisibility()); + } + + @Test + public void testTwaMinimalUi_KeepBrowserControlsHidden() { + var intent = buildTwaIntent(); + intent.putExtra( + TrustedWebActivityIntentBuilder.EXTRA_DISPLAY_MODE, + new TrustedWebActivityDisplayMode.MinimalUiMode().toBundle()); + mController = buildController(buildCustomTabIntentProvider(intent)); + + mController.updateIsInAppMode(true); + assertEquals( + "Browser controls should be hidden", + BrowserControlsState.HIDDEN, + getLastBrowserControlsState()); + assertTrue( + "Close button should be visible for future layout", getLastCloseButtonVisibility()); + } + + @Test + @EnableFeatures({ChromeFeatureList.ANDROID_MINIMAL_UI_LARGE_SCREEN}) + public void testTwaMinimalUiEnterDesktopWindowing_KeepBrowserControlsHidden() { + setupDesktopWindowing(/* isInDesktopWindow= */ false); + var intent = buildTwaIntent(); + intent.putExtra( + TrustedWebActivityIntentBuilder.EXTRA_DISPLAY_MODE, + new TrustedWebActivityDisplayMode.MinimalUiMode().toBundle()); + mController = buildController(buildCustomTabIntentProvider(intent)); + mController.updateIsInAppMode(true); + setupDesktopWindowing(/* isInDesktopWindow= */ true); + + mController.onDesktopWindowingModeChanged(mAppHeaderState.isInDesktopWindow()); + assertEquals( + "Browser controls should be hidden", + BrowserControlsState.HIDDEN, + getLastBrowserControlsState()); + assertTrue( + "Close button should be visible for future layout", getLastCloseButtonVisibility()); + } + + @Test + @EnableFeatures({ChromeFeatureList.ANDROID_MINIMAL_UI_LARGE_SCREEN}) + public void testTwaMinimalUiEnterDesktopWindowingNotInAppMode_DoNotUpdateAnything() { + setupDesktopWindowing(/* isInDesktopWindow= */ false); + var intent = buildTwaIntent(); + intent.putExtra( + TrustedWebActivityIntentBuilder.EXTRA_DISPLAY_MODE, + new TrustedWebActivityDisplayMode.MinimalUiMode().toBundle()); + mController = buildController(buildCustomTabIntentProvider(intent)); + mController.updateIsInAppMode(false); + setupDesktopWindowing(/* isInDesktopWindow= */ true); + + mController.onDesktopWindowingModeChanged(mAppHeaderState.isInDesktopWindow()); + verifyNoInteractions(mToolbarCoordinator); } private void setTabSecurityLevel(int securityLevel) { @@ -222,6 +316,19 @@ .build(); } + private Intent buildTwaIntent() { + CustomTabsSession session = + CustomTabsSession.createMockSessionForTesting( + new ComponentName(mContext, ChromeLauncherActivity.class)); + var intent = new CustomTabsIntent.Builder(session).build().intent; + intent.putExtra(TrustedWebUtils.EXTRA_LAUNCH_AS_TRUSTED_WEB_ACTIVITY, true); + return intent; + } + + private CustomTabIntentDataProvider buildCustomTabIntentProvider(Intent intent) { + return new CustomTabIntentDataProvider(intent, mContext, COLOR_SCHEME_LIGHT); + } + private TrustedWebActivityBrowserControlsVisibilityManager buildController( BrowserServicesIntentDataProvider intentDataProvider) { return spy(
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java index 7660983e..e93cbd1 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
@@ -18,6 +18,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; @@ -206,6 +207,7 @@ @Mock private ServiceStatus mServiceStatus; @Mock private DataSharingUIDelegate mDataSharingUiDelegate; @Mock private Bitmap mAvatarBitmap; + @Mock private TintedCompositorButton mCloseButton; @Mock TabStripIphController mController; @Captor private ArgumentCaptor<DataSharingService.Observer> mSharingObserverCaptor; @Captor private ArgumentCaptor<Callback<Boolean>> mSharedImageTilesCaptor; @@ -2152,6 +2154,93 @@ @Test @EnableFeatures({ChromeFeatureList.TAB_STRIP_CONTEXT_MENU}) @Feature("Tab Context Menu") + public void testTabContextMenu_PreventsHovercard() { + // Setup. + initializeTabHoverTest(); + mStripLayoutHelper.setTabContextMenuCoordinatorForTesting(mTabContextMenuCoordinator); + when(mTabContextMenuCoordinator.isMenuShowing()).thenReturn(true); + + // Now try to hover on the tab. + mStripLayoutHelper.updateLastHoveredTab( + mStripLayoutHelper.getStripLayoutTabsForTesting()[0]); + + verify(mTabHoverCardView, never()) + .show( + nullable(Tab.class), + anyBoolean(), + anyFloat(), + anyFloat(), + anyFloat(), + anyFloat()); + } + + @Test + @EnableFeatures({ChromeFeatureList.TAB_STRIP_CONTEXT_MENU}) + @Feature("Tab Group Context Menu") + public void testTabGroupContextMenu_PreventsHovercard() { + // Setup. + initializeTabHoverTest(); + mStripLayoutHelper.setTabGroupContextMenuCoordinatorForTesting( + mTabGroupContextMenuCoordinator); + when(mTabGroupContextMenuCoordinator.isMenuShowing()).thenReturn(true); + + // Now try to hover on the tab. + mStripLayoutHelper.updateLastHoveredTab( + mStripLayoutHelper.getStripLayoutTabsForTesting()[0]); + + verify(mTabHoverCardView, never()) + .show( + nullable(Tab.class), + anyBoolean(), + anyFloat(), + anyFloat(), + anyFloat(), + anyFloat()); + } + + @Test + @EnableFeatures({ChromeFeatureList.TAB_STRIP_CONTEXT_MENU}) + @Feature("Advanced Peripherals Support") + public void testCloseTabsContextMenu_PreventsHovercard() { + // Set up: see testOnLongPress_OnCloseButton setup. + initializeTest(false, false, 0); + StripLayoutTab[] tabs = getMockedStripLayoutTabs(150f); + mStripLayoutHelper.setStripLayoutTabsForTesting(tabs); + + // Mock tab's view. + View tabView = new View(mActivity); + tabView.setLayoutParams(new MarginLayoutParams(150, 50)); + when(mModel.getTabAt(1).getView()).thenReturn(tabView); + + // Long press on second tab's close button. + StripLayoutTab tab = tabs[1]; + when(tab.checkCloseHitTest(anyFloat(), anyFloat())).thenReturn(true); + when(tab.getCloseButton()).thenReturn(mCloseButton); + when(mCloseButton.getParentView()).thenReturn(tab); + when(mCloseButton.getType()).thenReturn(ButtonType.TAB_CLOSE); + mStripLayoutHelper.setTabAtPositionForTesting(tab); + mStripLayoutHelper.onLongPress(150f, 0f); + + assertTrue( + "Expected 'close all tabs' context menu to be showing", + mStripLayoutHelper.isCloseButtonMenuShowingForTesting()); + + // Now try to hover on the tab. + mStripLayoutHelper.updateLastHoveredTab(tab); + + verify(mTabHoverCardView, never()) + .show( + nullable(Tab.class), + anyBoolean(), + anyFloat(), + anyFloat(), + anyFloat(), + anyFloat()); + } + + @Test + @EnableFeatures({ChromeFeatureList.TAB_STRIP_CONTEXT_MENU}) + @Feature("Tab Context Menu") public void testBottomSheet_constructedWithoutDestroyHide() { var tabs = initializeTest_ForTab(); setupForContextMenu();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabDragSourceTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabDragSourceTest.java index 2e9bffed..b0027418 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabDragSourceTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/reorder/TabDragSourceTest.java
@@ -98,7 +98,7 @@ import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.dragdrop.DragAndDropDelegate; import org.chromium.ui.dragdrop.DragDropGlobalState; -import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropTabResult; +import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropResult; import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropType; import org.chromium.ui.dragdrop.DropDataAndroid; import org.chromium.ui.util.XrUtils; @@ -248,6 +248,7 @@ mTabStripHeightSupplier, mDesktopWindowStateManager); mDestInstance.setTabModelSelector(mTabModelSelector); + mSourceInstance.createUmaStateForTesting(); when(mSourceMultiInstanceManager.closeChromeWindowIfEmpty(anyInt())).thenReturn(false); @@ -265,9 +266,9 @@ ShadowToast.reset(); ToastManager.resetForTesting(); mSharedPreferencesManager.removeKey( - ChromePreferenceKeys.TAB_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS); + ChromePreferenceKeys.TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS); mSharedPreferencesManager.removeKey( - ChromePreferenceKeys.TAB_TEARING_MAX_INSTANCES_FAILURE_COUNT); + ChromePreferenceKeys.TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_COUNT); XrUtils.resetXrDeviceForTesting(); } @@ -574,18 +575,7 @@ /** Test for tab drag {@link #ONDRAG_TEST_CASES} - Scenario A */ @Test public void test_onDrag_dropInStrip_source() { - HistogramWatcher histogramExpectation = - HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result", DragDropTabResult.SUCCESS) - .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") - .expectNoRecords("Android.DragDrop.Tab.Type") - .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") - .expectBooleanRecord("Android.DragDrop.Tab.ReorderStripWithDragDrop", false) - .expectNoRecords("Android.DragDrop.Tab.Duration.WithinDestStrip") - .build(); doTestOnDragDropInStripSource(/* isGroupDrag= */ false); - histogramExpectation.assertExpected(); } /** Test for tab group drag {@link #ONDRAG_TEST_CASES} - Scenario A */ @@ -597,19 +587,7 @@ /** Test for tab drag {@link #ONDRAG_TEST_CASES} - Scenario B */ @Test public void test_onDrag_dropInToolbarContainer_source() { - HistogramWatcher histogramExpectation = - HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result", - DragDropTabResult.IGNORED_TOOLBAR) - .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") - .expectNoRecords("Android.DragDrop.Tab.Type") - .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") - .expectNoRecords("Android.DragDrop.Tab.ReorderStripWithDragDrop") - .expectNoRecords("Android.DragDrop.Tab.Duration.WithinDestStrip") - .build(); doTestOnDragDropInToolbarContainerSource(/* isGroupDrag= */ false); - histogramExpectation.assertExpected(); } /** Test for tab group drag {@link #ONDRAG_TEST_CASES} - Scenario B */ @@ -619,8 +597,8 @@ } /** - * Test for tab drag {@link #ONDRAG_TEST_CASES} - Scenario C.1 - XR-specific flow that we - * currently does not support moving tab groups. + * Test for tab drag {@link #ONDRAG_TEST_CASES} - Scenario C.1 - XR-specific flow currently does + * not support moving tab groups. */ @Test public void test_onDrag_dropOutsideToolbarContainer() { @@ -657,8 +635,8 @@ } /** - * Test for {@link #ONDRAG_TEST_CASES} - Scenario C.2 - XR-specific flow that we currently does - * not support moving tab groups. + * Test for {@link #ONDRAG_TEST_CASES} - Scenario C.2 - XR-specific flow currently does not + * support moving tab groups. */ @Test public void test_onDrag_dropOutsideToolbarContainer_dragAsWindow() { @@ -709,21 +687,45 @@ } @Test + public void test_onDrag_unhandledDropOutside_maxChromeInstances_tabGroup_desktopWindow() { + doTestUnhandledDropOutsideWithMaxInstances( + /* isInDesktopWindow= */ true, /* isGroupDrag= */ true); + } + + @Test public void test_onDrag_multipleUnhandledDropsOutside_maxChromeInstances() { MultiWindowUtils.setInstanceCountForTesting(5); MultiWindowUtils.setMaxInstancesForTesting(5); // Simulate failures on day 1. - doTriggerUnhandledDrop(4); + doTriggerUnhandledDrop(4, /* isGroupDrag= */ false); // Force update the count start time saved in SharedPreferences for day 1 to restart count // for next day. mSharedPreferencesManager.writeLong( - ChromePreferenceKeys.TAB_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, + ChromePreferenceKeys.TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS - 1); // Simulate a failure on day 2. - doTriggerUnhandledDrop(1); + doTriggerUnhandledDrop(1, /* isGroupDrag= */ false); + } + + @Test + public void test_onDrag_multipleUnhandledDropsOutside_maxChromeInstances_tabGroup() { + MultiWindowUtils.setInstanceCountForTesting(5); + MultiWindowUtils.setMaxInstancesForTesting(5); + + // Simulate failures on day 1. + doTriggerUnhandledDrop(4, /* isGroupDrag= */ true); + + // Force update the count start time saved in SharedPreferences for day 1 to restart count + // for next day. + mSharedPreferencesManager.writeLong( + ChromePreferenceKeys.TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, + System.currentTimeMillis() - DateUtils.DAY_IN_MILLIS - 1); + + // Simulate a failure on day 2. + doTriggerUnhandledDrop(1, /* isGroupDrag= */ true); } /** Test for Tab Drag {@link #ONDRAG_TEST_CASES} - Scenario D.1 */ @@ -740,7 +742,7 @@ @Test public void test_onDrag_dropInStrip_destination_tabGroup() { doTestDropInStripDestination( - /* isInDesktopWindow= */ true, + /* isInDesktopWindow= */ false, /* isGroupDrag= */ true, /* isGroupShared= */ false, /* mhtmlTabTitle= */ null); @@ -760,6 +762,12 @@ /** Test for Tab Group Drag {@link #ONDRAG_TEST_CASES} - Scenario D.1 */ @Test public void test_onDrag_dropInStrip_hasMhtmlTab_destination_tabGroup() { + HistogramWatcher.Builder builder = + HistogramWatcher.newBuilder() + .expectIntRecord( + "Android.DragDrop.TabGroup.FromStrip.Result", + DragDropResult.IGNORED_MHTML_TAB); + HistogramWatcher histogramExpectation = builder.build(); String url = "file:///example.mhtml"; Uri uri = Uri.parse(url); GURL gurl = new GURL(uri.toString()); @@ -777,6 +785,8 @@ /* isGroupDrag= */ true, /* isGroupShared= */ false, /* mhtmlTabTitle= */ mhtmlTabTitle); + // Verify histogram recorded for ignored mhtml tab group . + histogramExpectation.assertExpected(); } /** Test for Desktop Window {@link #ONDRAG_TEST_CASES} - Scenario D.1 */ @@ -789,22 +799,20 @@ /* mhtmlTabTitle= */ null); } + /** Test for Tab Group Drag in Desktop Window {@link #ONDRAG_TEST_CASES} - Scenario D.1 */ + @Test + public void test_onDrag_dropInStrip_destination_tabGroup_desktopWindow() { + doTestDropInStripDestination( + /* isInDesktopWindow= */ true, + /* isGroupDrag= */ true, + /* isGroupShared= */ false, + /* mhtmlTabTitle= */ null); + } + /** Test for Tab Drag {@link #ONDRAG_TEST_CASES} - Scenario D.2 */ @Test public void test_onDrag_dropInStrip_differentModel_destination() { - HistogramWatcher histogramExpectation = - HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result", DragDropTabResult.SUCCESS) - .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") - .expectIntRecord( - "Android.DragDrop.Tab.Type", DragDropType.TAB_STRIP_TO_TAB_STRIP) - .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") - .expectNoRecords("Android.DragDrop.Tab.ReorderStripWithDragDrop") - .expectAnyRecord("Android.DragDrop.Tab.Duration.WithinDestStrip") - .build(); doTestDropInDestinationDifferentModel(/* isGroupDrag= */ false); - histogramExpectation.assertExpected(); } /** Test for Tab Group Drag {@link #ONDRAG_TEST_CASES} - Scenario D.2 */ @@ -814,8 +822,8 @@ } /** - * Test for {@link #ONDRAG_TEST_CASES} - Scenario D.3 - XR-specific flow that we currently does - * not support moving tab groups. + * Test for {@link #ONDRAG_TEST_CASES} - Scenario D.3 - XR-specific flow currently does not + * support moving tab groups. */ @Test public void test_onDrag_dropInStrip_withDragAsWindowFF_destination() { @@ -832,19 +840,7 @@ /** Test for Tab Drag {@link #ONDRAG_TEST_CASES} - Scenario E */ @Test public void test_onDrag_dropInToolbarContainer_destination() { - HistogramWatcher histogramExpectation = - HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result", - DragDropTabResult.IGNORED_TOOLBAR) - .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") - .expectNoRecords("Android.DragDrop.Tab.Type") - .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") - .expectNoRecords("Android.DragDrop.Tab.ReorderStripWithDragDrop") - .expectAnyRecord("Android.DragDrop.Tab.Duration.WithinDestStrip") - .build(); doTestDropInDestinationToolbarContainer(/* isGroupDrag= */ false); - histogramExpectation.assertExpected(); } /** Test for Tab Group Drag {@link #ONDRAG_TEST_CASES} - Scenario E */ @@ -856,18 +852,7 @@ /** Test for Tab Drag {@link #ONDRAG_TEST_CASES} - Scenario F */ @Test public void test_onDrag_exitIntoToolbarAndRenterStripAndDrop_source() { - HistogramWatcher histogramExpectation = - HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result", DragDropTabResult.SUCCESS) - .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") - .expectNoRecords("Android.DragDrop.Tab.Type") - .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") - .expectBooleanRecord("Android.DragDrop.Tab.ReorderStripWithDragDrop", true) - .expectNoRecords("Android.DragDrop.Tab.Duration.WithinDestStrip") - .build(); doTestExitIntoSourceToolbarAndRenterStripAndDrop(/* isGroupDrag= */ false); - histogramExpectation.assertExpected(); } /** Test for Tab Group Drag {@link #ONDRAG_TEST_CASES} - Scenario F */ @@ -1046,6 +1031,27 @@ } private void doTestOnDragDropInStripSource(boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + String reorderHistogram = + String.format( + "Android.DragDrop.%s.ReorderStripWithDragDrop", + isGroupDrag ? "TabGroup" : "Tab"); + HistogramWatcher histogramExpectation = + HistogramWatcher.newBuilder() + .expectIntRecord(resultHistogram, DragDropResult.SUCCESS) + .expectBooleanRecord(reorderHistogram, false) + .expectNoRecords("Android.DragDrop.TabGroup.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Type") + .expectNoRecords("Android.DragDrop.TabGroup.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Duration.WithinDestStrip") + .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.Type") + .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.Duration.WithinDestStrip") + .build(); + new DragEventInvoker(isGroupDrag, /* isGroupShared= */ false) .drop(mSourceInstance) .end(true); @@ -1060,9 +1066,28 @@ verifyViewNotMovedToWindow(isGroupDrag); // Verify destination strip not invoked. verifyNoInteractions(mDestStripLayoutHelper); + // Verify histograms. + histogramExpectation.assertExpected(); } private void doTestOnDragDropInToolbarContainerSource(boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + HistogramWatcher histogramExpectation = + HistogramWatcher.newBuilder() + .expectIntRecord(resultHistogram, DragDropResult.IGNORED_TOOLBAR) + .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.Type") + .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.ReorderStripWithDragDrop") + .expectNoRecords("Android.DragDrop.Tab.Duration.WithinDestStrip") + .expectNoRecords("Android.DragDrop.TabGroup.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Type") + .expectNoRecords("Android.DragDrop.TabGroup.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.ReorderStripWithDragDrop") + .expectNoRecords("Android.DragDrop.TabGroup.Duration.WithinDestStrip") + .build(); new DragEventInvoker(isGroupDrag, /* isGroupShared= */ false) // Drag our of strip but within toolbar container. .dragLocationY(mSourceInstance, 3 * DRAG_MOVE_DISTANCE) @@ -1083,6 +1108,8 @@ verify(mSourceStripLayoutHelper, times(1)).stopReorderMode(); // Verify destination strip not invoked. verifyNoInteractions(mDestStripLayoutHelper); + // Verify histograms. + histogramExpectation.assertExpected(); } private void verifyDropOutsideToolbarContainerAsWindow() { @@ -1108,11 +1135,15 @@ private void doTestUnhandledDropOutsideWithMaxInstances( boolean isInDesktopWindow, boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + HistogramWatcher.Builder builder = HistogramWatcher.newBuilder() .expectIntRecord( "Android.DragDrop.Tab.FromStrip.Result", - DragDropTabResult.IGNORED_MAX_INSTANCES) + DragDropResult.IGNORED_MAX_INSTANCES) .expectNoRecords("Android.DragDrop.Tab.Type") .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") .expectNoRecords("Android.DragDrop.Tab.ReorderStripWithDragDrop") @@ -1121,10 +1152,9 @@ if (isInDesktopWindow) { AppHeaderUtils.setAppInDesktopWindowForTesting(true); builder.expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result.DesktopWindow", - DragDropTabResult.IGNORED_MAX_INSTANCES); + resultHistogram + ".DesktopWindow", DragDropResult.IGNORED_MAX_INSTANCES); } else { - builder.expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow"); + builder.expectNoRecords(resultHistogram + ".DesktopWindow"); } HistogramWatcher histogramExpectation = builder.build(); @@ -1141,37 +1171,38 @@ } } - private void doTriggerUnhandledDrop(int failureCount) { + private void doTriggerUnhandledDrop(int failureCount, boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + String failureHistogram = "Android.DragDrop.TabOrGroup.MaxInstanceFailureCount"; var histogramBuilder = HistogramWatcher.newBuilder() .expectIntRecordTimes( - "Android.DragDrop.Tab.FromStrip.Result", - DragDropTabResult.IGNORED_MAX_INSTANCES, - failureCount) - .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow"); + resultHistogram, DragDropResult.IGNORED_MAX_INSTANCES, failureCount) + .expectNoRecords(resultHistogram + ".DesktopWindow"); // Set histogram expectation. for (int i = 0; i < failureCount; i++) { - histogramBuilder = - histogramBuilder.expectIntRecord( - "Android.DragDrop.Tab.MaxInstanceFailureCount", i + 1); + histogramBuilder = histogramBuilder.expectIntRecord(failureHistogram, i + 1); } var histogramExpectation = histogramBuilder.build(); // Simulate unhandled tab drops |failureCount| number of times. for (int i = 0; i < failureCount; i++) { - new DragEventInvoker(/* isGroupDrag= */ false, /* isGroupShared= */ false) + new DragEventInvoker(isGroupDrag, /* isGroupShared= */ false) .dragExit(mSourceInstance) .end(false); } // Verify that the count is correctly updated in SharedPreferences and the histogram is // emitted as expected. + String maxInstanceFailureKey = + ChromePreferenceKeys.TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_COUNT; assertEquals( "Tab drag max-instance failure count saved in shared prefs is incorrect.", failureCount, - mSharedPreferencesManager.readInt( - ChromePreferenceKeys.TAB_TEARING_MAX_INSTANCES_FAILURE_COUNT)); + mSharedPreferencesManager.readInt(maxInstanceFailureKey)); histogramExpectation.assertExpected(); } @@ -1180,30 +1211,36 @@ boolean isGroupDrag, boolean isGroupShared, String mhtmlTabTitle) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + String typeHistogram = + String.format("Android.DragDrop.%s.Type", isGroupDrag ? "TabGroup" : "Tab"); + String durationHistogram = + String.format( + "Android.DragDrop.%s.Duration.WithinDestStrip", + isGroupDrag ? "TabGroup" : "Tab"); HistogramWatcher.Builder builder = HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result", DragDropTabResult.SUCCESS) - .expectIntRecord( - "Android.DragDrop.Tab.Type", DragDropType.TAB_STRIP_TO_TAB_STRIP) + .expectIntRecord(resultHistogram, DragDropResult.SUCCESS) + .expectIntRecord(typeHistogram, DragDropType.TAB_STRIP_TO_TAB_STRIP) .expectNoRecords("Android.DragDrop.Tab.ReorderStripWithDragDrop") - .expectAnyRecord("Android.DragDrop.Tab.Duration.WithinDestStrip"); + .expectNoRecords("Android.DragDrop.TabGroup.ReorderStripWithDragDrop") + .expectAnyRecord(durationHistogram); if (isInDesktopWindow) { AppHeaderUtils.setAppInDesktopWindowForTesting(true); - builder.expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result.DesktopWindow", - DragDropTabResult.SUCCESS) + builder.expectIntRecord(resultHistogram + ".DesktopWindow", DragDropResult.SUCCESS) .expectIntRecord( - "Android.DragDrop.Tab.Type.DesktopWindow", - DragDropType.TAB_STRIP_TO_TAB_STRIP); + typeHistogram + ".DesktopWindow", DragDropType.TAB_STRIP_TO_TAB_STRIP); } HistogramWatcher histogramExpectation = builder.build(); when(mDestStripLayoutHelper.getTabIndexForTabDrop(anyFloat())).thenReturn(TAB_INDEX); // Invoke drop. - invokeDropInDestinationStrip(/* dragEndRes= */ true, isGroupDrag, isGroupShared); + invokeDropInDestinationStrip( + /* dragEndRes= */ mhtmlTabTitle == null, isGroupDrag, isGroupShared); // Verify - drop failed and toast is shown for group that has mhtml tab. if (mhtmlTabTitle != null) { @@ -1225,12 +1262,32 @@ verify(mDestStripLayoutHelper).stopReorderMode(); assertNull(ShadowToast.getLatestToast()); - if (!isGroupDrag) { - histogramExpectation.assertExpected(); - } + histogramExpectation.assertExpected(); } private void doTestDropInDestinationDifferentModel(boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + String typeHistogram = + String.format("Android.DragDrop.%s.Type", isGroupDrag ? "TabGroup" : "Tab"); + String durationHistogram = + String.format( + "Android.DragDrop.%s.Duration.WithinDestStrip", + isGroupDrag ? "TabGroup" : "Tab"); + HistogramWatcher histogramExpectation = + HistogramWatcher.newBuilder() + .expectIntRecord(resultHistogram, DragDropResult.SUCCESS) + .expectIntRecord(typeHistogram, DragDropType.TAB_STRIP_TO_TAB_STRIP) + .expectAnyRecord(durationHistogram) + .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.ReorderStripWithDragDrop") + .expectNoRecords("Android.DragDrop.TabGroup.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.ReorderStripWithDragDrop") + .build(); + // Destination tab model is incognito. when(mTabModel.isIncognitoBranded()).thenReturn(true); TabModel standardModelDestination = mock(TabModel.class); @@ -1248,9 +1305,33 @@ ContextUtils.getApplicationContext() .getString(R.string.tab_dropped_different_model)); assertNotNull(ShadowToast.getLatestToast()); + + // Verify histograms. + histogramExpectation.assertExpected(); } private void doTestDropInDestinationToolbarContainer(boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + String durationHistogram = + String.format( + "Android.DragDrop.%s.Duration.WithinDestStrip", + isGroupDrag ? "TabGroup" : "Tab"); + + HistogramWatcher histogramExpectation = + HistogramWatcher.newBuilder() + .expectIntRecord(resultHistogram, DragDropResult.IGNORED_TOOLBAR) + .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.Type") + .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.ReorderStripWithDragDrop") + .expectAnyRecord(durationHistogram) + .expectNoRecords("Android.DragDrop.TabGroup.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Type") + .expectNoRecords("Android.DragDrop.TabGroup.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.ReorderStripWithDragDrop") + .build(); new DragEventInvoker(isGroupDrag, /* isGroupShared= */ false) .dragExit(mSourceInstance) .verifyShadowVisibility(true) @@ -1278,9 +1359,33 @@ // Verify tab cleared. verify(mSourceStripLayoutHelper, times(1)).stopReorderMode(); + + // Verify histograms. + histogramExpectation.assertExpected(); } private void doTestExitIntoSourceToolbarAndRenterStripAndDrop(boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + String reorderHistogram = + String.format( + "Android.DragDrop.%s.ReorderStripWithDragDrop", + isGroupDrag ? "TabGroup" : "Tab"); + HistogramWatcher histogramExpectation = + HistogramWatcher.newBuilder() + .expectIntRecord(resultHistogram, DragDropResult.SUCCESS) + .expectBooleanRecord(reorderHistogram, true) + .expectNoRecords("Android.DragDrop.TabGroup.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Type") + .expectNoRecords("Android.DragDrop.TabGroup.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Duration.WithinDestStrip") + .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.Type") + .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.Duration.WithinDestStrip") + .build(); + new DragEventInvoker(isGroupDrag, /* isGroupShared= */ false) .dragLocationY(mSourceInstance, 3 * DRAG_MOVE_DISTANCE) // move to toolbar .verifyShadowVisibility(true) @@ -1301,6 +1406,9 @@ // Verify destination strip not invoked. verifyNoInteractions(mDestStripLayoutHelper); + + // Verify histograms. + histogramExpectation.assertExpected(); } private void doTestOnDragInvalidClipData(boolean isGroupDrag) { @@ -1516,8 +1624,8 @@ } public DragEventInvoker end(boolean res) { - mSourceInstance.onDrag(mTabsToolbarView, mockDragEndEvent(res, mIsGroupDrag)); mDestInstance.onDrag(mTabsToolbarView, mockDragEndEvent(res, mIsGroupDrag)); + mSourceInstance.onDrag(mTabsToolbarView, mockDragEndEvent(res, mIsGroupDrag)); assertFalse( "Global state should be cleared on all drag end", DragDropGlobalState.hasValue()); @@ -1559,8 +1667,9 @@ TabGroupMetadata tabGroupMetadata, boolean isGroupDrag) { DragEvent event = mock(DragEvent.class); + ChromeDropDataAndroid dropData; if (isGroupDrag) { - ChromeDropDataAndroid dropData = + dropData = new ChromeTabGroupDropDataAndroid.Builder() .withTabGroupMetadata(tabGroupMetadata) .build(); @@ -1573,8 +1682,7 @@ when(event.getClipDescription()) .thenReturn(new ClipDescription("", SUPPORTED_GROUP_MIME_TYPES)); } else { - ChromeDropDataAndroid dropData = - new ChromeTabDropDataAndroid.Builder().withTab(tab).build(); + dropData = new ChromeTabDropDataAndroid.Builder().withTab(tab).build(); when(event.getClipData()) .thenReturn( new ClipData(
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListenerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListenerUnitTest.java index d384612..85b3785 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListenerUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/dragdrop/ChromeTabbedOnDragListenerUnitTest.java
@@ -33,13 +33,14 @@ import org.chromium.chrome.browser.layouts.LayoutType; import org.chromium.chrome.browser.multiwindow.MultiInstanceManager; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.TabGroupMetadata; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.ui.desktop_windowing.AppHeaderUtils; import org.chromium.components.browser_ui.desktop_windowing.DesktopWindowStateManager; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.dragdrop.DragDropGlobalState; -import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropTabResult; +import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropResult; import org.chromium.ui.dragdrop.DragDropMetricUtils.DragDropType; import java.lang.ref.WeakReference; @@ -55,6 +56,7 @@ @Mock private LayoutStateProvider mLayoutStateProvider; @Mock private DragDropGlobalState mDragDropGlobalState; @Mock private Tab mTab; + @Mock private TabGroupMetadata mTabGroupMetadata; @Mock private DesktopWindowStateManager mDesktopWindowStateManager; private OneshotSupplierImpl<LayoutStateProvider> mLayoutStateProviderSupplierImpl; private ClipDescription mTabClipDescription = @@ -85,8 +87,6 @@ when(mCurrentTab.getId()).thenReturn(1); when(mTabModelSelector.getModel(false)).thenReturn(Mockito.mock(TabModel.class)); when(mMultiInstanceManager.getCurrentInstanceId()).thenReturn(SOURCE_INSTANCE_ID); - when(mDragDropGlobalState.getData()) - .thenReturn(new ChromeTabDropDataAndroid.Builder().withTab(mTab).build()); when(mDragDropGlobalState.isDragSourceInstance(SOURCE_INSTANCE_ID)).thenReturn(true); DragDropGlobalState.setInstanceForTesting(mDragDropGlobalState); Activity activity = Mockito.mock(Activity.class); @@ -106,7 +106,7 @@ } private void doTestOnDragActionDragStarted(boolean isGroupDrag) { - // Drag started should return false, since drag source is not chrome tab. + // Drag started should return false, since drag source is not chrome tab or group. assertFalse( "Drag started should return false.", mChromeTabbedOnDragListener.onDrag( @@ -147,17 +147,7 @@ @Test public void testOnDrag_ActionDrop_TabSwitcher() { - HistogramWatcher histogramExpectation = - HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result", - DragDropTabResult.IGNORED_TAB_SWITCHER) - .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") - .expectNoRecords("Android.DragDrop.Tab.Type") - .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") - .build(); doTestOnDragActionDropInTabSwitcher(/* isGroupDrag= */ false); - histogramExpectation.assertExpected(); } @Test @@ -166,6 +156,18 @@ } private void doTestOnDragActionDropInTabSwitcher(boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + HistogramWatcher histogramExpectation = + HistogramWatcher.newBuilder() + .expectIntRecord(resultHistogram, DragDropResult.IGNORED_TAB_SWITCHER) + .expectNoRecords(resultHistogram + ".DesktopWindow") + .expectNoRecords("Android.DragDrop.Tab.Type") + .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Type") + .expectNoRecords("Android.DragDrop.TabGroup.Type.DesktopWindow") + .build(); // Call drag start to set states. assertTrue( "Drag started should return true.", @@ -181,24 +183,13 @@ mChromeTabbedOnDragListener.onDrag( mCompositorViewHolder, mockDragEvent(DragEvent.ACTION_DROP, /* result= */ false, isGroupDrag))); + // Verify histograms. + histogramExpectation.assertExpected(); } @Test public void testOnDrag_ActionDrop_SameInstance() { - AppHeaderUtils.setAppInDesktopWindowForTesting(true); - HistogramWatcher histogramExpectation = - HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result", - DragDropTabResult.IGNORED_SAME_INSTANCE) - .expectIntRecord( - "Android.DragDrop.Tab.FromStrip.Result.DesktopWindow", - DragDropTabResult.IGNORED_SAME_INSTANCE) - .expectNoRecords("Android.DragDrop.Tab.Type") - .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") - .build(); doTestOnDragActionDropInSameInstance(/* isGroupDrag= */ false); - histogramExpectation.assertExpected(); } @Test @@ -207,6 +198,22 @@ } private void doTestOnDragActionDropInSameInstance(boolean isGroupDrag) { + String resultHistogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isGroupDrag ? "TabGroup" : "Tab"); + AppHeaderUtils.setAppInDesktopWindowForTesting(true); + HistogramWatcher histogramExpectation = + HistogramWatcher.newBuilder() + .expectIntRecord(resultHistogram, DragDropResult.IGNORED_SAME_INSTANCE) + .expectIntRecord( + resultHistogram + ".DesktopWindow", + DragDropResult.IGNORED_SAME_INSTANCE) + .expectNoRecords("Android.DragDrop.Tab.Type") + .expectNoRecords("Android.DragDrop.Tab.Type.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.Type") + .expectNoRecords("Android.DragDrop.TabGroup.Type.DesktopWindow") + .build(); + setGlobalStateData(isGroupDrag); // Call drag start to set states. assertTrue( "Drag started should return true.", @@ -222,10 +229,15 @@ mChromeTabbedOnDragListener.onDrag( mCompositorViewHolder, mockDragEvent(DragEvent.ACTION_DROP, /* result= */ false, isGroupDrag))); + // Verify histograms. + histogramExpectation.assertExpected(); } @Test public void testOnDrag_ActionDrop_Success() { + // Setup drag drop global state. + setGlobalStateData(/* isGroupDrag= */ false); + // Verify action drop is success. verifyActionDropSuccess(/* isInDesktopWindow= */ false, /* isGroupDrag= */ false); @@ -238,13 +250,10 @@ } @Test - public void testOnDrag_ActionDrop_Success_tabGroup() { - // Verify action drop is success. - verifyActionDropSuccess(/* isInDesktopWindow= */ false, /* isGroupDrag= */ true); - } - - @Test public void testOnDrag_ActionDrop_Success_DesktopWindow() { + // Setup drag drop global state. + setGlobalStateData(/* isGroupDrag= */ false); + // Verify action drop is success. verifyActionDropSuccess(/* isInDesktopWindow= */ true, /* isGroupDrag= */ false); @@ -276,17 +285,45 @@ mUserActionTest.getActionCount("MobileToolbarReorderTab.TabRemovedFromGroup")); } + @Test + public void testOnDrag_ActionDrop_Success_TabGroup_DesktopWindow() { + // Setup drag drop global state. + setGlobalStateData(/* isGroupDrag= */ true); + + // Verify action drop is success. + verifyActionDropSuccess(/* isInDesktopWindow= */ true, /* isGroupDrag= */ true); + } + + @Test + public void testOnDrag_ActionDrop_Success_TabGroup() { + // Setup drag drop global state. + setGlobalStateData(/* isGroupDrag= */ true); + + // Verify action drop is success. + verifyActionDropSuccess(/* isInDesktopWindow= */ false, /* isGroupDrag= */ true); + } + private void verifyActionDropSuccess(boolean isInDesktopWindow, boolean isGroupDrag) { - HistogramWatcher.Builder histogramExpectationBuilder = + String histogram = + String.format("Android.DragDrop.%s.Type", isGroupDrag ? "TabGroup" : "Tab"); + AppHeaderUtils.setAppInDesktopWindowForTesting(isInDesktopWindow); + + HistogramWatcher.Builder builder = HistogramWatcher.newBuilder() - .expectIntRecord( - "Android.DragDrop.Tab.Type", DragDropType.TAB_STRIP_TO_CONTENT); + .expectIntRecord(histogram, DragDropType.TAB_STRIP_TO_CONTENT) + .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result") + .expectNoRecords("Android.DragDrop.Tab.FromStrip.Result.DesktopWindow") + .expectNoRecords("Android.DragDrop.TabGroup.FromStrip.Result") + .expectNoRecords( + "Android.DragDrop.TabGroup.FromStrip.Result.DesktopWindow"); if (isInDesktopWindow) { - AppHeaderUtils.setAppInDesktopWindowForTesting(true); - histogramExpectationBuilder.expectIntRecord( - "Android.DragDrop.Tab.Type.DesktopWindow", DragDropType.TAB_STRIP_TO_CONTENT); + builder.expectIntRecord( + histogram + ".DesktopWindow", DragDropType.TAB_STRIP_TO_CONTENT); + } else { + builder.expectNoRecords(histogram + ".DesktopWindow"); } - HistogramWatcher histogramWatcher = histogramExpectationBuilder.build(); + HistogramWatcher histogramWatcher = builder.build(); + // Call drag start to set states. assertTrue( "Drag started should return true.", @@ -303,10 +340,7 @@ "Action drop should return true", mChromeTabbedOnDragListener.onDrag( mCompositorViewHolder, - mockDragEvent( - DragEvent.ACTION_DROP, - /* result= */ false, - /* isGroupDrag= */ false))); + mockDragEvent(DragEvent.ACTION_DROP, /* result= */ false, isGroupDrag))); histogramWatcher.assertExpected(); } @@ -322,4 +356,17 @@ doReturn(action).when(event).getAction(); return event; } + + private void setGlobalStateData(boolean isGroupDrag) { + if (isGroupDrag) { + when(mDragDropGlobalState.getData()) + .thenReturn( + new ChromeTabGroupDropDataAndroid.Builder() + .withTabGroupMetadata(mTabGroupMetadata) + .build()); + } else { + when(mDragDropGlobalState.getData()) + .thenReturn(new ChromeTabDropDataAndroid.Builder().withTab(mTab).build()); + } + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java index bb64c3b3..30087e1b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java
@@ -1324,7 +1324,6 @@ @Test @Config(sdk = 31) - @DisableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) public void testCleanupIfLastInstance() { TabGroupSyncServiceFactory.setForTesting(mTabGroupSyncService); when(mTabGroupSyncService.getAllGroupIds()).thenReturn(new String[] {}); @@ -1357,7 +1356,6 @@ @Test @Config(sdk = 31) - @DisableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) public void testCleanupSyncedTabGroupsIfOnlyInstance() { mMultiInstanceManager.mTestBuildInstancesList = true; when(mTabGroupSyncService.getAllGroupIds()).thenReturn(new String[] {});
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabArchiveSettingsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabArchiveSettingsTest.java index d60aece88..9efc8d1 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabArchiveSettingsTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabArchiveSettingsTest.java
@@ -5,7 +5,6 @@ package org.chromium.chrome.browser.tab; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Before; @@ -13,7 +12,6 @@ import org.junit.runner.RunWith; import org.robolectric.annotation.Config; -import org.chromium.base.FeatureOverrides; import org.chromium.base.shared_preferences.SharedPreferencesManager; import org.chromium.base.task.TaskTraits; import org.chromium.base.task.test.ShadowPostTask; @@ -28,14 +26,7 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(shadows = {ShadowPostTask.class}) public class TabArchiveSettingsTest { - - static final String ARCHIVE_ENABLED_PARAM = "android_tab_declutter_archive_enabled"; - static final String ARCHIVE_TIME_DELTA_PARAM = "android_tab_declutter_archive_time_delta_hours"; - static final int ARCHIVE_TIME_DELTA_HOURS_DEFAULT = 21 * 24; - static final String AUTO_DELETE_ENABLED_PARAM = "android_tab_declutter_auto_delete_enabled"; - static final String AUTO_DELETE_TIME_DELTA_PARAM = - "android_tab_declutter_auto_delete_time_delta_hours"; - static final int AUTO_DELETE_TIME_DELTA_HOURS_DEFAULT = 60 * 24; + private static final int AUTO_DELETE_TIME_DELTA_HOURS_DEFAULT = 60 * 24; // 60 days. private TabArchiveSettings mSettings; private SharedPreferencesManager mPrefsManager; @@ -58,29 +49,20 @@ } @Test - public void testSettings() { + public void testDefaultSettings() { // Archive is disabled for tests, reset it to the default param value. - mSettings.setArchiveEnabled( - ChromeFeatureList.sAndroidTabDeclutterArchiveEnabled.getValue()); - assertEquals( - ChromeFeatureList.sAndroidTabDeclutterArchiveEnabled.getValue(), - mSettings.getArchiveEnabled()); - assertEquals(ARCHIVE_TIME_DELTA_HOURS_DEFAULT, mSettings.getArchiveTimeDeltaHours()); - assertEquals(false, mSettings.isAutoDeleteEnabled()); - assertEquals(AUTO_DELETE_TIME_DELTA_HOURS_DEFAULT, mSettings.getAutoDeleteTimeDeltaHours()); - - mSettings.setArchiveEnabled(false); - assertFalse(mSettings.getArchiveEnabled()); - - mSettings.setArchiveTimeDeltaHours(1); - assertEquals(1, mSettings.getArchiveTimeDeltaHours()); - mSettings.setArchiveEnabled(true); - mSettings.setAutoDeleteEnabled(true); - assertTrue(mSettings.isAutoDeleteEnabled()); - - mSettings.setAutoDeleteTimeDeltaHours(1); - assertEquals(1, mSettings.getArchiveTimeDeltaHours()); + assertTrue(mSettings.getArchiveEnabled()); + assertEquals( + TabArchiveSettings.DEFAULT_ARCHIVE_TIME_HOURS, + mSettings.getArchiveTimeDeltaHours()); + assertEquals( + ChromeFeatureList.sAndroidTabDeclutterAutoDelete.isEnabled(), + mSettings.isAutoDeleteEnabled()); + assertEquals(AUTO_DELETE_TIME_DELTA_HOURS_DEFAULT, mSettings.getAutoDeleteTimeDeltaHours()); + assertEquals( + TabArchiveSettings.DEFAULT_MAX_SIMULTANEOUS_ARCHIVES, + mSettings.getMaxSimultaneousArchives()); } @Test @@ -91,38 +73,6 @@ } @Test - public void testSettingsDefaultOverriddenByFinch() { - // Archive is disabled for tests, reset it to the default param value. - mSettings.setArchiveEnabled( - ChromeFeatureList.sAndroidTabDeclutterArchiveEnabled.getValue()); - assertTrue(mSettings.getArchiveEnabled()); - assertFalse(mSettings.isAutoDeleteEnabled()); - - FeatureOverrides.newBuilder() - .param(ChromeFeatureList.ANDROID_TAB_DECLUTTER, ARCHIVE_ENABLED_PARAM, false) - .param(ChromeFeatureList.ANDROID_TAB_DECLUTTER, ARCHIVE_TIME_DELTA_PARAM, 10) - .param(ChromeFeatureList.ANDROID_TAB_DECLUTTER, AUTO_DELETE_ENABLED_PARAM, true) - .param(ChromeFeatureList.ANDROID_TAB_DECLUTTER, AUTO_DELETE_TIME_DELTA_PARAM, 20) - .apply(); - - // Archive is disabled for tests, reset it to the default param value. - mSettings.setArchiveEnabled( - ChromeFeatureList.sAndroidTabDeclutterArchiveEnabled.getValue()); - assertFalse(mSettings.getArchiveEnabled()); - assertFalse(mSettings.isAutoDeleteEnabled()); - mSettings.setArchiveEnabled(true); - assertTrue(mSettings.isAutoDeleteEnabled()); - assertEquals(10, mSettings.getArchiveTimeDeltaHours()); - assertEquals(20, mSettings.getAutoDeleteTimeDeltaHours()); - - mSettings.setArchiveTimeDeltaHours(1); - assertEquals(1, mSettings.getArchiveTimeDeltaHours()); - - mSettings.setAutoDeleteTimeDeltaHours(1); - assertEquals(1, mSettings.getArchiveTimeDeltaHours()); - } - - @Test public void testNotifyObservers() throws Exception { CallbackHelper callbackHelper = new CallbackHelper(); Observer obs =
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabArchiverUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabArchiverUnitTest.java index 652ea94..0fea33b4 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabArchiverUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabArchiverUnitTest.java
@@ -4,12 +4,12 @@ package org.chromium.chrome.browser.tab; -import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import org.junit.Before; import org.junit.Rule; @@ -25,9 +25,7 @@ import org.chromium.base.task.test.ShadowPostTask; import org.chromium.base.task.test.ShadowPostTask.TestImpl; import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.HistogramWatcher; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tabmodel.TabCreator; import org.chromium.chrome.browser.tabmodel.TabGroupModelFilter; @@ -39,7 +37,6 @@ /** Tests for {@link TabArchiveSettings}. */ @RunWith(BaseRobolectricTestRunner.class) @Config(shadows = {ShadowPostTask.class}) -@EnableFeatures(ChromeFeatureList.ANDROID_TAB_DECLUTTER) public class TabArchiverUnitTest { public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.LENIENT); @@ -116,11 +113,8 @@ } @Test - @EnableFeatures( - ChromeFeatureList.ANDROID_TAB_DECLUTTER - + ":android_tab_declutter_max_simultaneous_archives/20") public void testMaxSimultaneousArchives() { - assertEquals(20, ChromeFeatureList.sAndroidTabDeclutterMaxSimultaneousArchives.getValue()); + when(mTabArchiveSettings.getMaxSimultaneousArchives()).thenReturn(20); HistogramWatcher watcher = HistogramWatcher.newSingleRecordWatcher("Tabs.ArchivedTabs.MaxLimitReachedAt", 20);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappIntentDataProviderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappIntentDataProviderTest.java index 4ade676e..96ae0a7e 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappIntentDataProviderTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappIntentDataProviderTest.java
@@ -98,7 +98,7 @@ assertEquals( "Should resolve to standalone", - DisplayMode.STANDALONE, + DisplayMode.MINIMAL_UI, intentDataProvider.getResolvedDisplayMode()); } @@ -117,19 +117,6 @@ @Test @Config(sdk = Build.VERSION_CODES.VANILLA_ICE_CREAM) - @DisableFeatures({ChromeFeatureList.ANDROID_MINIMAL_UI_LARGE_SCREEN}) - public void testMinUiModeDisabled_ResolveToStandalone() { - var intentDataProvider = - buildWebAppIntentDataProvider(mIntent, buildWebAppExtras(DisplayMode.MINIMAL_UI)); - - assertEquals( - "Should resolve to standalone", - DisplayMode.STANDALONE, - intentDataProvider.getResolvedDisplayMode()); - } - - @Test - @Config(sdk = Build.VERSION_CODES.VANILLA_ICE_CREAM) @EnableFeatures({ChromeFeatureList.ANDROID_MINIMAL_UI_LARGE_SCREEN}) public void testBrowserModeWithMinUiEnabled_ResolveToMinUi() { var intentDataProvider =
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index f4eabcc..5734eb32 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-138.0.7155.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-138.0.7164.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/version_assembly/BUILD.gn b/chrome/app/version_assembly/BUILD.gn index f7dd033..fe7d4875 100644 --- a/chrome/app/version_assembly/BUILD.gn +++ b/chrome/app/version_assembly/BUILD.gn
@@ -32,7 +32,7 @@ sources += [ segment_heap_manifest ] } - deps = [ ":chrome_exe_version_manifest" ] + public_deps = [ ":chrome_exe_version_manifest" ] } # Generates the manifest for the version assembly, which is the versioned
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 47d351af..7be63e23 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2903,6 +2903,8 @@ "android/webapps/webapp_registry.h", "auxiliary_search/auxiliary_search_provider.cc", "auxiliary_search/auxiliary_search_provider.h", + "auxiliary_search/auxiliary_search_top_site_provider_bridge.cc", + "auxiliary_search/auxiliary_search_top_site_provider_bridge.h", "auxiliary_search/fetch_and_rank_helper.cc", "auxiliary_search/fetch_and_rank_helper.h", "banners/android/chrome_app_banner_manager_android.cc", @@ -4268,6 +4270,8 @@ "webauthn/gpm_enclave_transaction.h", "webauthn/gpm_user_verification_policy.cc", "webauthn/gpm_user_verification_policy.h", + "webauthn/immediate_request_rate_limiter_factory.cc", + "webauthn/immediate_request_rate_limiter_factory.h", "webauthn/local_authentication_token.h", "webauthn/local_credential_management.cc", "webauthn/local_credential_management.h", @@ -6279,8 +6283,6 @@ "win/chrome_elf_init.h", "win/chrome_select_file_dialog_factory.cc", "win/chrome_select_file_dialog_factory.h", - "win/cloud_synced_folder_checker.cc", - "win/cloud_synced_folder_checker.h", "win/conflicts/enumerate_input_method_editors.cc", "win/conflicts/enumerate_input_method_editors.h", "win/conflicts/enumerate_shell_extensions.cc", @@ -6334,6 +6336,7 @@ "//chrome/browser/os_crypt", "//chrome/browser/shortcuts", "//chrome/browser/web_applications/chrome_pwa_launcher:util", + "//chrome/browser/win:cloud_synced_folder_checker", "//chrome/browser/win:mica_titlebar", "//chrome/browser/win/conflicts:module_info", "//chrome/chrome_elf:constants", @@ -9296,7 +9299,6 @@ deps = [ ":browser", "//base", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", "//third_party/protobuf:protobuf_lite", ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 989d8e44..1506274 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -7511,7 +7511,7 @@ flag_descriptions::kNavigationCaptureRefactorAndroidName, flag_descriptions::kNavigationCaptureRefactorAndroidDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kNavigationCaptureRefactorAndroid)}, + FEATURE_VALUE_TYPE(external_intents::kNavigationCaptureRefactorAndroid)}, {"enable-magic-stack-android", flag_descriptions::kMagicStackAndroidName, flag_descriptions::kMagicStackAndroidDescription, kOsAndroid, @@ -10766,10 +10766,6 @@ #endif // BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_ANDROID) - {"android-tab-declutter", flag_descriptions::kAndroidTabDeclutterName, - flag_descriptions::kAndroidTabDeclutterDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kAndroidTabDeclutter)}, - {"android-tab-declutter-archive-all-but-active-tab", flag_descriptions::kAndroidTabDeclutterArchiveAllButActiveTabName, flag_descriptions::kAndroidTabDeclutterArchiveAllButActiveTabDescription, @@ -10790,6 +10786,11 @@ kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kAndroidTabDeclutterArchiveTabGroups)}, + {"android-tab-declutter-auto-delete", + flag_descriptions::kAndroidTabDeclutterAutoDeleteName, + flag_descriptions::kAndroidTabDeclutterAutoDeleteDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kAndroidTabDeclutterAutoDelete)}, + {"android-tab-declutter-performance-improvements", flag_descriptions::kAndroidTabDeclutterPerformanceImprovementsName, flag_descriptions::kAndroidTabDeclutterPerformanceImprovementsDescription, @@ -12412,6 +12413,12 @@ FEATURE_VALUE_TYPE(ash::features::kFwupdDeveloperMode)}, #endif // BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_ANDROID) + {"android-sms-otp-filling", flag_descriptions::kAndroidSmsOtpFillingName, + flag_descriptions::kAndroidSmsOtpFillingDescription, kOsAndroid, + FEATURE_VALUE_TYPE(password_manager::features::kAndroidSmsOtpFilling)}, +#endif // BUILDFLAG(IS_ANDROID) + // Add new entries above this line. // NOTE: Adding a new flag requires adding a corresponding entry to enum
diff --git a/chrome/browser/actor/BUILD.gn b/chrome/browser/actor/BUILD.gn index 6661c62..db6fdf42 100644 --- a/chrome/browser/actor/BUILD.gn +++ b/chrome/browser/actor/BUILD.gn
@@ -92,6 +92,7 @@ testonly = true defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] sources = [ + "actor_coordinator_browsertest.cc", "site_policy_browsertest.cc", "tools/tools_browsertest.cc", ] @@ -99,6 +100,7 @@ ":actor", ":test_support", "//base/test:test_support", + "//chrome/browser/glic:glic", "//chrome/browser/optimization_guide:test_support", "//chrome/browser/safe_browsing", "//chrome/browser/ui:ui",
diff --git a/chrome/browser/actor/actor_coordinator.cc b/chrome/browser/actor/actor_coordinator.cc index 14215f41..1affef8 100644 --- a/chrome/browser/actor/actor_coordinator.cc +++ b/chrome/browser/actor/actor_coordinator.cc
@@ -169,6 +169,11 @@ return !!task_state_; } +bool ActorCoordinator::HasTaskForTab(const content::WebContents* tab) const { + return HasTask() && task_state_->HasTab() && + task_state_->tab->GetContents() == tab; +} + void ActorCoordinator::StartTaskForTesting(tabs::TabInterface* tab) { CHECK(tab); CHECK(!task_state_);
diff --git a/chrome/browser/actor/actor_coordinator.h b/chrome/browser/actor/actor_coordinator.h index a2c40eb8..95d7480c 100644 --- a/chrome/browser/actor/actor_coordinator.h +++ b/chrome/browser/actor/actor_coordinator.h
@@ -77,6 +77,9 @@ // Returns true if a task is currently active. bool HasTask() const; + // Returns true if a task is currently active in `tab`. + bool HasTaskForTab(const content::WebContents* tab) const; + // Starts new task with an existing tab, for testing only. Intended for unit // tests that do not use a browser and actual navigation. void StartTaskForTesting(tabs::TabInterface* tab);
diff --git a/chrome/browser/actor/actor_coordinator_browsertest.cc b/chrome/browser/actor/actor_coordinator_browsertest.cc new file mode 100644 index 0000000..8f6d32c --- /dev/null +++ b/chrome/browser/actor/actor_coordinator_browsertest.cc
@@ -0,0 +1,115 @@ +// 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/actor/actor_coordinator.h" + +#include <optional> +#include <string_view> + +#include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" +#include "chrome/browser/actor/actor_test_util.h" +#include "chrome/browser/glic/glic_keyed_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_features.h" +#include "chrome/test/base/chrome_test_utils.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/optimization_guide/proto/features/actions_data.pb.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_frame_navigation_observer.h" +#include "net/dns/mock_host_resolver.h" + +using ::base::test::TestFuture; +using ::optimization_guide::proto::BrowserAction; + +namespace actor { + +namespace { + +class ActorCoordinatorBrowserTest : public InProcessBrowserTest { + public: + ActorCoordinatorBrowserTest() { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{features::kGlic, features::kTabstripComboButton, + features::kGlicActor}, + /*disabled_features=*/{features::kGlicWarming}); + } + ActorCoordinatorBrowserTest(const ActorCoordinatorBrowserTest&) = delete; + ActorCoordinatorBrowserTest& operator=(const ActorCoordinatorBrowserTest&) = + delete; + + ~ActorCoordinatorBrowserTest() override = default; + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + host_resolver()->AddRule("*", "127.0.0.1"); + ASSERT_TRUE(embedded_test_server()->Start()); + + // TODO(crbug.com/409564704): Mock the delay so that tests can run at + // reasonable speed. Remove once there is a more permanent approach. + OverrideActionObservationDelay(base::Milliseconds(10)); + + actor_coordinator().StartTaskForTesting(browser()->GetActiveTabInterface()); + } + + protected: + content::WebContents* web_contents() { + return chrome_test_utils::GetActiveWebContents(this); + } + + content::RenderFrameHost* main_frame() { + return web_contents()->GetPrimaryMainFrame(); + } + + ActorCoordinator& actor_coordinator() { + Profile* profile = chrome_test_utils::GetProfile(this); + auto* glic_service = glic::GlicKeyedService::Get(profile); + return glic_service->GetActorCoordinatorForTesting(); + } + + void ClickTarget(std::string_view query_selector) { + std::optional<int> dom_node_id = + content::GetDOMNodeId(*main_frame(), query_selector); + ASSERT_TRUE(dom_node_id); + BrowserAction action = MakeClick(dom_node_id.value()); + TestFuture<bool> result; + actor_coordinator().Act(action, result.GetCallback()); + EXPECT_TRUE(result.Get()); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// The coordinator does not yet handle multi-tab cases. For now, +// while acting on a tab, we override attempts by the page to create new +// tabs, and instead navigate the existing tab. +IN_PROC_BROWSER_TEST_F(ActorCoordinatorBrowserTest, ForceSameTabNavigation) { + const GURL url = + embedded_test_server()->GetURL("/actor/target_blank_links.html"); + ASSERT_TRUE(content::NavigateToURL(web_contents(), url)); + + // Check specifically that it's the existing frame that navigates. + content::TestFrameNavigationObserver frame_nav_observer(main_frame()); + ClickTarget("#anchorTarget"); + frame_nav_observer.Wait(); +} + +IN_PROC_BROWSER_TEST_F(ActorCoordinatorBrowserTest, + ForceSameTabNavigationByScript) { + const GURL url = + embedded_test_server()->GetURL("/actor/target_blank_links.html"); + ASSERT_TRUE(content::NavigateToURL(web_contents(), url)); + + // Check specifically that it's the existing frame that navigates. + content::TestFrameNavigationObserver frame_nav_observer(main_frame()); + ClickTarget("#scriptOpen"); + frame_nav_observer.Wait(); +} + +} // namespace + +} // namespace actor
diff --git a/chrome/browser/ai/ai_data_keyed_service.cc b/chrome/browser/ai/ai_data_keyed_service.cc index b3be43b..98b9b87 100644 --- a/chrome/browser/ai/ai_data_keyed_service.cc +++ b/chrome/browser/ai/ai_data_keyed_service.cc
@@ -935,6 +935,15 @@ #endif // BUILDFLAG(ENABLE_GLIC) } +bool AiDataKeyedService::IsActorCoordinatorActingOnTab( + const content::WebContents* tab) const { +#if BUILDFLAG(ENABLE_GLIC) + return actor_coordinator_ && actor_coordinator_->HasTaskForTab(tab); +#else + return false; +#endif +} + #if BUILDFLAG(ENABLE_GLIC) void AiDataKeyedService::OnTaskCreated( base::OnceCallback<void(optimization_guide::proto::BrowserStartTaskResult)>
diff --git a/chrome/browser/ai/ai_data_keyed_service.h b/chrome/browser/ai/ai_data_keyed_service.h index 5ff3b9c..23151a1 100644 --- a/chrome/browser/ai/ai_data_keyed_service.h +++ b/chrome/browser/ai/ai_data_keyed_service.h
@@ -28,7 +28,8 @@ class BrowserContext; } // namespace content -// Browser service to collect AI data. +// Browser service to collect AI data, including data resulting from triggering +// actor tasks. class AiDataKeyedService : public KeyedService { public: // Data related to AiData collection. @@ -82,6 +83,11 @@ base::OnceCallback<void(optimization_guide::proto::BrowserActionResult)> callback); + // Returns true if the associated ActorCoordinator is active on the given + // `tab`. This can be used by callers to customize certain behaviour that + // might interfere with the ActorCoordinator. + bool IsActorCoordinatorActingOnTab(const content::WebContents* tab) const; + static const base::Feature& GetAllowlistedAiDataExtensionsFeatureForTesting(); static const base::Feature& GetAllowlistedActionsExtensionsFeatureForTesting();
diff --git a/chrome/browser/ai/ai_data_keyed_service_browsertest.cc b/chrome/browser/ai/ai_data_keyed_service_browsertest.cc index 9fb79ac..36381ff8 100644 --- a/chrome/browser/ai/ai_data_keyed_service_browsertest.cc +++ b/chrome/browser/ai/ai_data_keyed_service_browsertest.cc
@@ -48,6 +48,7 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test_utils.h" #include "content/public/test/fenced_frame_test_util.h" +#include "content/public/test/test_frame_navigation_observer.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/request_handler_util.h" #include "testing/gmock/include/gmock/gmock.h" @@ -55,6 +56,8 @@ namespace { +using ::base::test::TestFuture; +using ::optimization_guide::proto::ClickAction; using ::testing::ReturnRef; using AiData = AiDataKeyedService::AiData; using AiDataSpecifier = AiDataKeyedService::AiDataSpecifier; @@ -612,6 +615,55 @@ base::BindLambdaForTesting(start_task_callback_2)); run_loop->Run(); } + +// See ActorCoordinatorBrowserTest.ForceSameTabNavigation +IN_PROC_BROWSER_TEST_F(AiDataKeyedServiceActorBrowserTest, + ForceSameTabNavigation) { + TestFuture<optimization_guide::proto::BrowserStartTaskResult> + start_task_result; + int id = 1; + ai_data_service().StartTask(/*task=*/{}, start_task_result.GetCallback()); + auto& task = start_task_result.Get(); + EXPECT_EQ(task.task_id(), id); + EXPECT_EQ(task.tab_id(), id); + + const GURL url = https_server()->GetURL("/actor/target_blank_links.html"); + TestFuture<optimization_guide::proto::BrowserActionResult> navigate_result; + optimization_guide::proto::BrowserAction action_request; + action_request.set_task_id(id); + action_request.set_tab_id(id); + action_request.add_action_information()->mutable_navigate()->set_url( + url.spec()); + ai_data_service().ExecuteAction(std::move(action_request), + navigate_result.GetCallback()); + auto& navigate_response = navigate_result.Get(); + EXPECT_EQ(navigate_response.task_id(), id); + EXPECT_EQ(navigate_response.tab_id(), id); + + std::optional<int> anchor_dom_node_id = content::GetDOMNodeId( + *web_contents()->GetPrimaryMainFrame(), "#anchorTarget"); + ASSERT_TRUE(anchor_dom_node_id); + + TestFuture<optimization_guide::proto::BrowserActionResult> click_result; + optimization_guide::proto::BrowserAction click_request; + click_request.set_task_id(id); + click_request.set_tab_id(id); + ClickAction* click = click_request.add_action_information()->mutable_click(); + click->mutable_target()->set_content_node_id(anchor_dom_node_id.value()); + click->set_click_type(ClickAction::LEFT); + click->set_click_count(ClickAction::SINGLE); + + // Check specifically that it's the existing frame that navigates. + content::TestFrameNavigationObserver frame_nav_observer( + web_contents()->GetPrimaryMainFrame()); + ai_data_service().ExecuteAction(std::move(click_request), + click_result.GetCallback()); + auto& click_response = click_result.Get(); + EXPECT_EQ(click_response.task_id(), id); + EXPECT_EQ(click_response.tab_id(), id); + frame_nav_observer.Wait(); +} + #endif // BUILDFLAG(ENABLE_GLIC) } // namespace
diff --git a/chrome/browser/android/BUILD.gn b/chrome/browser/android/BUILD.gn index 02f3e08..8d5f069 100644 --- a/chrome/browser/android/BUILD.gn +++ b/chrome/browser/android/BUILD.gn
@@ -17,6 +17,7 @@ deps = [ ":tabs_public", "//chrome/browser/sync", + "//components/external_intents/android", "//components/favicon/content", "//components/metrics:content", "//content/public/browser",
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc index 33818ac..9c42813 100644 --- a/chrome/browser/android/tab_web_contents_delegate_android.cc +++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -55,6 +55,7 @@ #include "components/blocked_content/popup_tracker.h" #include "components/browser_ui/sms/android/sms_infobar.h" #include "components/browser_ui/util/android/url_constants.h" +#include "components/external_intents/android/external_intents_features.h" #include "components/find_in_page/find_notification_details.h" #include "components/find_in_page/find_tab_helper.h" #include "components/infobars/content/content_infobar_manager.h" @@ -297,7 +298,7 @@ } if (base::FeatureList::IsEnabled( - chrome::android::kNavigationCaptureRefactorAndroid)) { + external_intents::kNavigationCaptureRefactorAndroid)) { if (IsCustomTab() && disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB) { if (OpenInAppOrChromeFromCct(params.url)) {
diff --git a/chrome/browser/android/vr/arcore_device/fake_arcore.cc b/chrome/browser/android/vr/arcore_device/fake_arcore.cc index c7b4d9b..2d06d2d 100644 --- a/chrome/browser/android/vr/arcore_device/fake_arcore.cc +++ b/chrome/browser/android/vr/arcore_device/fake_arcore.cc
@@ -322,15 +322,20 @@ result->light_probe->spherical_harmonics->coefficients.resize(9); // Initialize reflection_probe to black + const uint32_t cube_map_side_size = 16; + const uint64_t num_components = mojom::XRCubeMap::kNumComponentsPerPixel; + const size_t cube_map_size = + cube_map_side_size * cube_map_side_size * num_components; + result->reflection_probe = mojom::XRReflectionProbe::New(); result->reflection_probe->cube_map = mojom::XRCubeMap::New(); - result->reflection_probe->cube_map->width_and_height = 16; - result->reflection_probe->cube_map->positive_x.resize(16 * 16); - result->reflection_probe->cube_map->negative_x.resize(16 * 16); - result->reflection_probe->cube_map->positive_y.resize(16 * 16); - result->reflection_probe->cube_map->negative_y.resize(16 * 16); - result->reflection_probe->cube_map->positive_z.resize(16 * 16); - result->reflection_probe->cube_map->negative_z.resize(16 * 16); + result->reflection_probe->cube_map->width_and_height = cube_map_side_size; + result->reflection_probe->cube_map->positive_x.resize(cube_map_size); + result->reflection_probe->cube_map->negative_x.resize(cube_map_size); + result->reflection_probe->cube_map->positive_y.resize(cube_map_size); + result->reflection_probe->cube_map->negative_y.resize(cube_map_size); + result->reflection_probe->cube_map->positive_z.resize(cube_map_size); + result->reflection_probe->cube_map->negative_z.resize(cube_map_size); return result; }
diff --git a/chrome/browser/apps/app_service/publishers/chrome_app_deprecation.cc b/chrome/browser/apps/app_service/publishers/chrome_app_deprecation.cc index 41be9a8..d715587 100644 --- a/chrome/browser/apps/app_service/publishers/chrome_app_deprecation.cc +++ b/chrome/browser/apps/app_service/publishers/chrome_app_deprecation.cc
@@ -6,6 +6,7 @@ #include "ash/public/cpp/system_notification_builder.h" #include "base/containers/fixed_flat_set.h" +#include "base/metrics/histogram_functions.h" #include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/extensions/extension_service.h" @@ -29,7 +30,6 @@ base::FEATURE_ENABLED_BY_DEFAULT); namespace { -// TODO(crbug.com/413912653): Split the allowlists per context. constexpr auto kCommonAllowlist = base::MakeFixedFlatSet<std::string_view>( {"aakfkoilmhehmmadlkedfbcelkbamdkj", "aepgaekjheajlcifmpjcnpbjcencoefn", "afoipjmffplafpbfjopglheidddioiai", "afpnehpifljbjjplppeplamalioanmio", @@ -107,7 +107,6 @@ constexpr auto kUserInstalledAllowlist = base::flat_set<std::string_view>(); -// TODO(crbug.com/383754553): Add the finalised list only in M138 builds. constexpr auto kKioskSessionAllowlist = base::MakeFixedFlatSet<std::string_view>( {"adbijfidmjidmkkpiglnfkflcoblkfmn", "adpfhflbokfdhnfakijgjkpkjegncbpl", @@ -167,6 +166,38 @@ // because the allowlist are always valid while Chrome is running. static base::NoDestructor<std::unordered_set<std::string>> testAllowlistedApps; +// This enum lists the possible outcomes of the deprecation checks performed +// during the launch of a ChromeApp. +// +// These values are persisted to logs and the values match the entries of +// `enum ChromeAppDeprecationLaunchOutcome` in +// `tools/metrics/histograms/metadata/apps/enums.xml`. +// Entries should not be renumbered and numeric values should never be reused. +// LINT.IfChange(ChromeAppDeprecationLaunchOutcome) +enum class DeprecationCheckOutcome { + kUserInstalledAllowedByFlag = 0, + kUserInstalledAllowedByAllowlist = 1, + kUserInstalledBlocked = 2, + kKioskModeAllowedByFlag = 3, + kKioskModeAllowedByAllowlist = 4, + kKioskModeAllowedByAdminPolicy = 5, + kKioskModeBlocked = 6, + kManagedAllowedByFlag = 7, + kManagedAllowedByAllowlist = 8, + kManagedAllowedByAdminPolicy = 9, + kManagedBlocked = 10, + kAllowedNotChromeApp = 11, + kAllowedDefault = 12, + kBlockedDefault = 13, + kMaxValue = kBlockedDefault +}; +// LINT.ThenChange(//tools/metrics/histograms/metadata/apps/enums.xml:ChromeAppDeprecationLaunchOutcome) + +void ReportMetric(DeprecationCheckOutcome outcome) { + base::UmaHistogramEnumeration("Apps.AppLaunch.ChromeAppsDeprecationCheck", + outcome); +} + static bool fakeKioskSessionForTesting = false; enum class AllowlistContext { UserInstalled, KioskSession }; @@ -223,14 +254,17 @@ Profile* profile) { // TODO(crbug.com/379261516): Block the execution in M139. if (IsAllowlisted(app.id(), AllowlistContext::UserInstalled)) { + ReportMetric(DeprecationCheckOutcome::kUserInstalledAllowedByAllowlist); return DeprecationStatus::kLaunchAllowed; } if (base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)) { ShowNotification(app, profile); + ReportMetric(DeprecationCheckOutcome::kUserInstalledAllowedByFlag); return DeprecationStatus::kLaunchAllowed; } + ReportMetric(DeprecationCheckOutcome::kUserInstalledBlocked); return DeprecationStatus::kLaunchBlocked; } @@ -238,17 +272,21 @@ Profile* profile) { // TODO(crbug.com/379262711): Block the execution in M151. if (IsAllowlisted(app.id(), AllowlistContext::KioskSession)) { + ReportMetric(DeprecationCheckOutcome::kKioskModeAllowedByAllowlist); return DeprecationStatus::kLaunchAllowed; } if (profile->GetPrefs()->GetBoolean(prefs::kKioskChromeAppsForceAllowed)) { + ReportMetric(DeprecationCheckOutcome::kKioskModeAllowedByAdminPolicy); return DeprecationStatus::kLaunchAllowed; } if (base::FeatureList::IsEnabled(kAllowChromeAppsInKioskSessions)) { + ReportMetric(DeprecationCheckOutcome::kKioskModeAllowedByFlag); return DeprecationStatus::kLaunchAllowed; } + ReportMetric(DeprecationCheckOutcome::kKioskModeBlocked); return DeprecationStatus::kLaunchBlocked; } } // namespace @@ -259,6 +297,7 @@ app_id.data()); if (!app || !app->is_app()) { + ReportMetric(DeprecationCheckOutcome::kAllowedNotChromeApp); return DeprecationStatus::kLaunchAllowed; } @@ -270,6 +309,7 @@ return HandleUserInstalledApp(*app, profile); } + ReportMetric(DeprecationCheckOutcome::kAllowedDefault); return DeprecationStatus::kLaunchAllowed; } @@ -281,8 +321,8 @@ testAllowlistedApps->clear(); } -void SetKioskSessionForTesting() { - fakeKioskSessionForTesting = true; +void SetKioskSessionForTesting(bool value) { + fakeKioskSessionForTesting = value; } } // namespace apps::chrome_app_deprecation
diff --git a/chrome/browser/apps/app_service/publishers/chrome_app_deprecation.h b/chrome/browser/apps/app_service/publishers/chrome_app_deprecation.h index 9d26e046..77b33b8 100644 --- a/chrome/browser/apps/app_service/publishers/chrome_app_deprecation.h +++ b/chrome/browser/apps/app_service/publishers/chrome_app_deprecation.h
@@ -23,7 +23,7 @@ void AddAppToAllowlistForTesting(std::string_view app_id); void ResetAllowlistForTesting(); -void SetKioskSessionForTesting(); +void SetKioskSessionForTesting(bool value = true); BASE_DECLARE_FEATURE(kAllowUserInstalledChromeApps); BASE_DECLARE_FEATURE(kAllowChromeAppsInKioskSessions);
diff --git a/chrome/browser/apps/app_service/publishers/chrome_app_deprecation_unittest.cc b/chrome/browser/apps/app_service/publishers/chrome_app_deprecation_unittest.cc index 1f3aaf5..b8abea1 100644 --- a/chrome/browser/apps/app_service/publishers/chrome_app_deprecation_unittest.cc +++ b/chrome/browser/apps/app_service/publishers/chrome_app_deprecation_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/apps/app_service/publishers/chrome_app_deprecation.h" #include "base/feature_list.h" +#include "base/test/metrics/histogram_tester.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_service_test_base.h" @@ -25,6 +26,9 @@ namespace apps::chrome_app_deprecation { +constexpr std::string_view kHistogram = + "Apps.AppLaunch.ChromeAppsDeprecationCheck"; + class ChromeAppDeprecationTest : public extensions::ExtensionServiceTestBase { protected: void SetUp() override { @@ -65,6 +69,8 @@ base::test::ScopedFeatureList scoped_feature_list_; scoped_refptr<const Extension> app_; + + base::HistogramTester histogram_tester_; }; TEST_F(ChromeAppDeprecationTest, DefaultFeatureFlag) { @@ -73,6 +79,23 @@ EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kUserInstalledAllowedByFlag*/ 0, 1))); +} + +TEST_F(ChromeAppDeprecationTest, DefaultFeatureFlagNotChromeApp) { + scoped_feature_list_.InitWithEmptyFeatureAndFieldTrialLists(); + ASSERT_TRUE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); + + EXPECT_EQ(HandleDeprecation("Not a Chrome App id", profile()), + DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT(histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kAllowedNotChromeApp*/ 11, 1))); } TEST_F(ChromeAppDeprecationTest, DisabledFeatureFlag) { @@ -81,6 +104,22 @@ EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchBlocked); + + EXPECT_THAT(histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kUserInstalledBlocked*/ 2, 1))); +} + +TEST_F(ChromeAppDeprecationTest, DisabledFeatureFlagNotChromeApp) { + scoped_feature_list_.InitAndDisableFeature(kAllowUserInstalledChromeApps); + ASSERT_FALSE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); + + EXPECT_EQ(HandleDeprecation("Not a Chrome App id", profile()), + DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT(histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kAllowedNotChromeApp*/ 11, 1))); } TEST_F(ChromeAppDeprecationTest, EnabledFeatureFlag) { @@ -89,14 +128,38 @@ EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kUserInstalledAllowedByFlag*/ 0, 1))); +} + +TEST_F(ChromeAppDeprecationTest, EnabledFeatureFlagNotChromeApp) { + scoped_feature_list_.InitAndEnableFeature(kAllowUserInstalledChromeApps); + ASSERT_TRUE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); + + EXPECT_EQ(HandleDeprecation("Not a Chrome App id", profile()), + DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT(histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kAllowedNotChromeApp*/ 11, 1))); } class ChromeAppDeprecationKioskTest : public ChromeAppDeprecationTest { + protected: void SetUp() override { ChromeAppDeprecationTest::SetUp(); SetKioskSessionForTesting(); } + + void TearDown() override { + SetKioskSessionForTesting(false); + + ChromeAppDeprecationTest::TearDown(); + } }; TEST_F(ChromeAppDeprecationKioskTest, DefaultFeatureFlag) { @@ -105,6 +168,10 @@ EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT(histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kKioskModeAllowedByFlag*/ 3, 1))); } TEST_F(ChromeAppDeprecationKioskTest, DisabledFeatureFlag) { @@ -113,6 +180,10 @@ EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchBlocked); + + EXPECT_THAT(histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kKioskModeBlocked*/ 6, 1))); } TEST_F(ChromeAppDeprecationKioskTest, EnabledFeatureFlag) { @@ -121,6 +192,10 @@ EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT(histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kKioskModeAllowedByFlag*/ 3, 1))); } TEST_F(ChromeAppDeprecationKioskTest, DisabledFeatureFlagDefaultPolicy) { @@ -131,6 +206,10 @@ EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchBlocked); + + EXPECT_THAT(histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kKioskModeBlocked*/ 6, 1))); } TEST_F(ChromeAppDeprecationKioskTest, DisabledFeatureFlagOverridenByPolicy) { @@ -143,9 +222,15 @@ EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kKioskModeAllowedByAdminPolicy*/ 5, 1))); } -class ChromeAppDeprecationAllowlistTest : public ChromeAppDeprecationTest { +class ChromeAppDeprecationUserInstalledAllowlistTest + : public ChromeAppDeprecationTest { protected: void SetUp() override { ChromeAppDeprecationTest::SetUp(); @@ -160,27 +245,98 @@ } }; -TEST_F(ChromeAppDeprecationAllowlistTest, DefaultFeatureFlag) { +TEST_F(ChromeAppDeprecationUserInstalledAllowlistTest, DefaultFeatureFlag) { scoped_feature_list_.InitWithEmptyFeatureAndFieldTrialLists(); ASSERT_TRUE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kUserInstalledAllowedByAllowlist*/ 1, 1))); } -TEST_F(ChromeAppDeprecationAllowlistTest, DisabledFeatureFlag) { +TEST_F(ChromeAppDeprecationUserInstalledAllowlistTest, DisabledFeatureFlag) { scoped_feature_list_.InitAndDisableFeature(kAllowUserInstalledChromeApps); ASSERT_FALSE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kUserInstalledAllowedByAllowlist*/ 1, 1))); } -TEST_F(ChromeAppDeprecationAllowlistTest, EnabledFeatureFlag) { +TEST_F(ChromeAppDeprecationUserInstalledAllowlistTest, EnabledFeatureFlag) { scoped_feature_list_.InitAndEnableFeature(kAllowUserInstalledChromeApps); ASSERT_TRUE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); EXPECT_EQ(HandleDeprecation(app_->id(), profile()), DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kUserInstalledAllowedByAllowlist*/ 1, 1))); } + +class ChromeAppDeprecationKioskAllowlistTest + : public ChromeAppDeprecationKioskTest { + protected: + void SetUp() override { + ChromeAppDeprecationKioskTest::SetUp(); + + AddAppToAllowlistForTesting(app_->id()); + } + + void TearDown() override { + ResetAllowlistForTesting(); + + ChromeAppDeprecationKioskTest::TearDown(); + } +}; + +TEST_F(ChromeAppDeprecationKioskAllowlistTest, DefaultFeatureFlag) { + scoped_feature_list_.InitWithEmptyFeatureAndFieldTrialLists(); + ASSERT_TRUE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); + + EXPECT_EQ(HandleDeprecation(app_->id(), profile()), + DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kKioskModeAllowedByAllowlist*/ 4, 1))); +} + +TEST_F(ChromeAppDeprecationKioskAllowlistTest, DisabledFeatureFlag) { + scoped_feature_list_.InitAndDisableFeature(kAllowUserInstalledChromeApps); + ASSERT_FALSE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); + + EXPECT_EQ(HandleDeprecation(app_->id(), profile()), + DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kKioskModeAllowedByAllowlist*/ 4, 1))); +} + +TEST_F(ChromeAppDeprecationKioskAllowlistTest, EnabledFeatureFlag) { + scoped_feature_list_.InitAndEnableFeature(kAllowUserInstalledChromeApps); + ASSERT_TRUE(base::FeatureList::IsEnabled(kAllowUserInstalledChromeApps)); + + EXPECT_EQ(HandleDeprecation(app_->id(), profile()), + DeprecationStatus::kLaunchAllowed); + + EXPECT_THAT( + histogram_tester_.GetAllSamples(kHistogram), + BucketsAre(base::Bucket( + /*DeprecationCheckOutcome::kKioskModeAllowedByAllowlist*/ 4, 1))); +} + } // namespace apps::chrome_app_deprecation
diff --git a/chrome/browser/ash/app_mode/BUILD.gn b/chrome/browser/ash/app_mode/BUILD.gn index 6ee39a13..bd19c913 100644 --- a/chrome/browser/ash/app_mode/BUILD.gn +++ b/chrome/browser/ash/app_mode/BUILD.gn
@@ -81,6 +81,7 @@ "//chromeos/ash/components/kiosk/vision", "//chromeos/ash/components/login/auth", "//chromeos/ash/components/network", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//chromeos/crosapi/mojom", "//chromeos/crosapi/mojom:mojom_shared_cpp_sources", @@ -191,6 +192,7 @@ "//chrome/common:non_code_constants", "//chrome/test:test_support_ui", "//chrome/test/data/chromeos/app_mode/webstore/itemsnippet", + "//chromeos/ash/components/policy/device_local_account", ] data_deps = [ "//chrome/test/data/chromeos/app_mode/webstore/itemsnippet:generated_protobufs" ] } @@ -228,6 +230,7 @@ "//chrome/test:test_support_ui", "//chromeos/ash/components/login/login_state", "//chromeos/ash/components/network:test_support", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/sync_wifi:test_support", "//components/prefs:test_support", "//components/webapps/browser", @@ -291,6 +294,7 @@ "//chromeos/ash/components/dbus/session_manager", "//chromeos/ash/components/dbus/shill", "//chromeos/ash/components/dbus/update_engine:update_engine", + "//chromeos/ash/components/policy/device_local_account", "//components/crx_file", "//components/ownership", "//content/test:test_support",
diff --git a/chrome/browser/ash/app_mode/consumer_kiosk_test_helper.cc b/chrome/browser/ash/app_mode/consumer_kiosk_test_helper.cc index d5bb9b9..de80e18 100644 --- a/chrome/browser/ash/app_mode/consumer_kiosk_test_helper.cc +++ b/chrome/browser/ash/app_mode/consumer_kiosk_test_helper.cc
@@ -16,8 +16,8 @@ #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash.h" #include "chrome/browser/ash/policy/core/device_local_account.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" -#include "components/policy/core/common/device_local_account_type.h" namespace ash {
diff --git a/chrome/browser/ash/app_mode/isolated_web_app/BUILD.gn b/chrome/browser/ash/app_mode/isolated_web_app/BUILD.gn index 2baf38c30..3c8b5775 100644 --- a/chrome/browser/ash/app_mode/isolated_web_app/BUILD.gn +++ b/chrome/browser/ash/app_mode/isolated_web_app/BUILD.gn
@@ -20,6 +20,7 @@ "//chrome/browser/ash/policy/core", "//chrome/browser/chromeos/app_mode", "//chrome/browser/web_applications", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//components/prefs", "//components/web_package", @@ -38,6 +39,7 @@ deps = [ "//ash/constants", "//chrome/browser/ash/policy/core", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//components/account_id", "//components/prefs", @@ -58,6 +60,7 @@ "//chrome/browser/ash/settings", "//chrome/browser/web_applications", "//chrome/test:test_support", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//components/policy/core/common", "//testing/gtest",
diff --git a/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_data_unittest.cc b/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_data_unittest.cc index 7fb32cb..4479d6e 100644 --- a/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_data_unittest.cc +++ b/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_data_unittest.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/url_constants.h" -#include "components/policy/core/common/device_local_account_type.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/prefs/testing_pref_service.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h"
diff --git a/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_manager.cc b/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_manager.cc index a838f609..df3f4fe 100644 --- a/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_manager.cc +++ b/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_manager.cc
@@ -26,9 +26,9 @@ #include "chrome/browser/chromeos/app_mode/kiosk_web_app_update_observer.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/web_app_install_info.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "url/origin.h"
diff --git a/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_manager_unittest.cc b/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_manager_unittest.cc index 6deb0b6d..ea9925d 100644 --- a/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_manager_unittest.cc +++ b/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_manager_unittest.cc
@@ -21,10 +21,10 @@ #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_policy_util.cc b/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_policy_util.cc index 25cd252..c975efb 100644 --- a/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_policy_util.cc +++ b/chrome/browser/ash/app_mode/isolated_web_app/kiosk_iwa_policy_util.cc
@@ -14,9 +14,9 @@ #include "base/check_op.h" #include "base/notreached.h" #include "chrome/browser/ash/policy/core/device_local_account.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
diff --git a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.cc b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.cc index 0aed76e..732217e 100644 --- a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.cc +++ b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager.cc
@@ -54,10 +54,10 @@ #include "chrome/browser/extensions/external_provider_impl.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/common/chrome_paths.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc index 994cdc5..eceed3c 100644 --- a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc +++ b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc
@@ -50,10 +50,10 @@ #include "chrome/browser/ui/browser.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/crx_file/crx_verifier.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc index 25c7590..9522097b 100644 --- a/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc +++ b/chrome/browser/ash/app_mode/kiosk_crash_restore_browsertest.cc
@@ -29,9 +29,9 @@ #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h" #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/device_settings_cache.h" #include "components/ownership/mock_owner_key_util.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc b/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc index 7fce8d3..a9df4241 100644 --- a/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc +++ b/chrome/browser/ash/app_mode/startup_app_launcher_unittest.cc
@@ -50,9 +50,9 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" #include "chromeos/ash/components/login/login_state/login_state.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/sync/model/string_ordinal.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/ash/app_mode/test/BUILD.gn b/chrome/browser/ash/app_mode/test/BUILD.gn index 750339d6..63927ef97 100644 --- a/chrome/browser/ash/app_mode/test/BUILD.gn +++ b/chrome/browser/ash/app_mode/test/BUILD.gn
@@ -51,6 +51,7 @@ "//chrome/test:test_support", "//chrome/test:test_support_ui", "//chromeos/ash/components/disks:test_support", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/system", "//components/services/app_service/public/cpp:app_types", "//components/web_package", @@ -91,6 +92,7 @@ "//chrome/browser/chromeos/app_mode", "//chrome/test:test_support_ui", "//chromeos/ash/components/network:test_support", + "//chromeos/ash/components/policy/device_local_account", "//components/web_package", ] }
diff --git a/chrome/browser/ash/app_mode/test/kiosk_misconfigured_user_browsertest.cc b/chrome/browser/ash/app_mode/test/kiosk_misconfigured_user_browsertest.cc index 25d34c0..ce16f6c 100644 --- a/chrome/browser/ash/app_mode/test/kiosk_misconfigured_user_browsertest.cc +++ b/chrome/browser/ash/app_mode/test/kiosk_misconfigured_user_browsertest.cc
@@ -11,8 +11,8 @@ #include "chrome/browser/ash/app_mode/test/kiosk_mixin.h" #include "chrome/browser/ash/app_mode/test/kiosk_test_utils.h" #include "chrome/test/base/mixin_based_in_process_browser_test.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/pref_service.h" #include "components/user_manager/user_directory_integrity_manager.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ash/app_mode/test/kiosk_test_utils.cc b/chrome/browser/ash/app_mode/test/kiosk_test_utils.cc index 7aba0d7..c70cf926 100644 --- a/chrome/browser/ash/app_mode/test/kiosk_test_utils.cc +++ b/chrome/browser/ash/app_mode/test/kiosk_test_utils.cc
@@ -41,9 +41,9 @@ #include "chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/error_screen_handler.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" #include "extensions/browser/extension_registry.h"
diff --git a/chrome/browser/ash/app_mode/test/kiosk_test_utils.h b/chrome/browser/ash/app_mode/test/kiosk_test_utils.h index c2a7311d..ee6093e 100644 --- a/chrome/browser/ash/app_mode/test/kiosk_test_utils.h +++ b/chrome/browser/ash/app_mode/test/kiosk_test_utils.h
@@ -14,9 +14,9 @@ #include "chrome/browser/ash/app_mode/kiosk_app.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/account_id/account_id.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" namespace ash::kiosk::test {
diff --git a/chrome/browser/ash/boca/DEPS b/chrome/browser/ash/boca/DEPS index a317330..bbbf67e 100644 --- a/chrome/browser/ash/boca/DEPS +++ b/chrome/browser/ash/boca/DEPS
@@ -44,12 +44,15 @@ "+components/sessions", # Files needed by babelorca/ "+chrome/browser/ash/accessibility/live_caption/system_live_caption_service.h", - "+chrome/browser/browser_process.h", # Files needed by spotlight/ "+chrome/browser/ash/policy/remote_commands/crd/public", ] specific_include_rules = { + "boca_manager_factory\\.cc": [ + "+chrome/browser/browser_process.h", + ], + "content_settings_handler_unittest.cc": [ "+chrome/browser/content_settings/host_content_settings_map_factory.h", ],
diff --git a/chrome/browser/ash/child_accounts/time_limit_consistency_test/BUILD.gn b/chrome/browser/ash/child_accounts/time_limit_consistency_test/BUILD.gn index bab2556..948c9e2c 100644 --- a/chrome/browser/ash/child_accounts/time_limit_consistency_test/BUILD.gn +++ b/chrome/browser/ash/child_accounts/time_limit_consistency_test/BUILD.gn
@@ -33,7 +33,6 @@ "//chrome/browser/ash/child_accounts", "//chrome/browser/ash/child_accounts:test_support", "//chromeos/ash/components/settings", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", "//testing/gmock", "//testing/gtest",
diff --git a/chrome/browser/ash/extensions/autotest_private/BUILD.gn b/chrome/browser/ash/extensions/autotest_private/BUILD.gn index 80780f970..eae388d 100644 --- a/chrome/browser/ash/extensions/autotest_private/BUILD.gn +++ b/chrome/browser/ash/extensions/autotest_private/BUILD.gn
@@ -63,7 +63,6 @@ "//chromeos/ash/components/settings", "//chromeos/ash/experiences/arc", "//chromeos/ash/experiences/arc/mojom", - "//chromeos/ash/services/assistant:lib", "//chromeos/ash/services/assistant/public/cpp", "//chromeos/components/quick_answers/public/cpp", "//chromeos/components/quick_answers/public/cpp:prefs",
diff --git a/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc index da4640a..37c807d 100644 --- a/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc
@@ -177,7 +177,6 @@ #include "chromeos/ash/experiences/arc/session/arc_bridge_service.h" #include "chromeos/ash/experiences/arc/session/arc_service_manager.h" #include "chromeos/ash/experiences/arc/system_ui/arc_system_ui_bridge.h" -#include "chromeos/ash/services/assistant/assistant_manager_service_impl.h" #include "chromeos/ash/services/assistant/public/cpp/assistant_prefs.h" #include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" #include "chromeos/components/quick_answers/public/cpp/quick_answers_prefs.h" @@ -3255,15 +3254,6 @@ return RespondNow(Error("Assistant is already enabled.")); } - // We can set this callback only when assistant status is NOT_READY. We should - // call this before we try to enable Assistant to avoid causing some timing - // issue. - ash::assistant::AssistantManagerServiceImpl:: - SetInitializedInternalCallbackForTesting(base::BindOnce( - &AutotestPrivateEnableAssistantAndWaitForReadyFunction:: - OnInitializedInternal, - this)); - Profile* profile = Profile::FromBrowserContext(browser_context()); const std::string& err_msg = SetAllowedPref( profile, ash::assistant::prefs::kAssistantEnabled, base::Value(true));
diff --git a/chrome/browser/ash/extensions/file_manager/BUILD.gn b/chrome/browser/ash/extensions/file_manager/BUILD.gn index 2365423d1..0c82e20 100644 --- a/chrome/browser/ash/extensions/file_manager/BUILD.gn +++ b/chrome/browser/ash/extensions/file_manager/BUILD.gn
@@ -253,7 +253,6 @@ ":file_manager", "//base", "//chrome/browser", - "//components/exo/wayland:test_controller", "//components/exo/wayland:ui_controls_protocol", ] } @@ -265,7 +264,6 @@ "//base", "//chrome/browser", "//chrome/browser/ash/fileapi", - "//components/exo/wayland:test_controller", "//components/exo/wayland:ui_controls_protocol", ] }
diff --git a/chrome/browser/ash/file_manager/BUILD.gn b/chrome/browser/ash/file_manager/BUILD.gn index 5472676..4a0c5f7 100644 --- a/chrome/browser/ash/file_manager/BUILD.gn +++ b/chrome/browser/ash/file_manager/BUILD.gn
@@ -445,6 +445,7 @@ "//chrome/browser/ash/guest_os", "//chrome/browser/ash/guest_os/public", "//chrome/browser/ash/login/test:test_support", + "//chrome/browser/ash/policy/core:test_support", "//chrome/browser/ash/policy/dlp", "//chrome/browser/ash/policy/dlp/dialogs", "//chrome/browser/ash/policy/dlp/test:test_support", @@ -485,6 +486,7 @@ "//chromeos/ash/components/drivefs/mojom", "//chromeos/ash/components/file_manager:constants", "//chromeos/ash/components/settings", + "//chromeos/ash/components/settings:test_support", "//chromeos/ash/components/smbfs", "//chromeos/ash/components/smbfs/mojom", "//chromeos/ash/experiences/arc:arc_base_utils",
diff --git a/chrome/browser/ash/file_manager/app_service_file_tasks.cc b/chrome/browser/ash/file_manager/app_service_file_tasks.cc index 83a4a076..24c4d2c4 100644 --- a/chrome/browser/ash/file_manager/app_service_file_tasks.cc +++ b/chrome/browser/ash/file_manager/app_service_file_tasks.cc
@@ -265,8 +265,7 @@ if (app_type == apps::AppType::kWeb || app_type == apps::AppType::kSystemWeb) { // Check the origin trial and feature flag for file handling in web apps. - // TODO(1240018): Remove when this feature is fully launched. This check - // will not work for lacros web apps. + // TODO(crbug.com/255838199): Remove when this feature is fully launched. web_app::WebAppProvider* provider = web_app::WebAppProvider::GetDeprecated(profile_with_app_service); web_app::OsIntegrationManager& os_integration_manager =
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc index 6825f0c..f9b294d 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -30,8 +30,7 @@ #include "chrome/browser/ash/file_manager/io_task.h" #include "chrome/browser/ash/login/test/device_state_mixin.h" #include "chrome/browser/ash/login/test/logged_in_user_mixin.h" -#include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" -#include "chrome/browser/ash/settings/stub_cros_settings_provider.h" +#include "chrome/browser/ash/policy/core/device_policy_cros_test_helper.h" #include "chrome/browser/extensions/component_loader.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/signin/identity_manager_factory.h" @@ -42,6 +41,7 @@ #include "chrome/test/base/fake_gaia_mixin.h" #include "chrome/test/base/ui_test_utils.h" #include "chromeos/ash/components/settings/cros_settings_names.h" +#include "chromeos/ash/components/settings/device_settings_cache_test_support.h" #include "chromeos/constants/chromeos_features.h" #include "components/account_id/account_id.h" #include "components/download/public/common/download_item.h" @@ -58,10 +58,11 @@ using file_manager::test::TestCase; +namespace em = enterprise_management; + namespace file_manager { namespace { constexpr char kOwnerEmail[] = "owner@example.com"; - } // namespace // FilesApp browser test. @@ -121,6 +122,10 @@ LogInTypeFor(GetOptions().test_account_type), /*include_initial_user=*/true, AccountIdFor(GetOptions().test_account_type)); + } + + void SetUpLocalStatePrefService(PrefService* local_state) override { + FilesAppBrowserTest::SetUpLocalStatePrefService(local_state); // Set up owner email of a device. We set up owner email only if a device is // kConsumerOwned. If a device is enrolled, an account cannot be an owner of @@ -141,8 +146,14 @@ break; } - scoped_testing_cros_settings_.device_settings()->Set( - ash::kDeviceOwner, base::Value(owner_email)); + ash::device_settings_cache::Update( + local_state, + [&](em::PolicyData& policy) { policy.set_username(owner_email); }); + + policy_helper_.device_policy()->policy_data().set_username(owner_email); + policy_helper_.device_policy()->policy_data().set_management_mode( + em::PolicyData::LOCAL_OWNER); + policy_helper_.RefreshDevicePolicy(); } } @@ -172,7 +183,7 @@ std::unique_ptr<ash::LoggedInUserMixin> logged_in_user_mixin_; std::unique_ptr<ash::DeviceStateMixin> device_state_mixin_; - ash::ScopedTestingCrosSettings scoped_testing_cros_settings_; + policy::DevicePolicyCrosTestHelper policy_helper_; }; IN_PROC_BROWSER_TEST_P(LoggedInUserFilesAppBrowserTest, Test) {
diff --git a/chrome/browser/ash/file_manager/file_tasks.cc b/chrome/browser/ash/file_manager/file_tasks.cc index bad56155..b851df2 100644 --- a/chrome/browser/ash/file_manager/file_tasks.cc +++ b/chrome/browser/ash/file_manager/file_tasks.cc
@@ -860,8 +860,6 @@ task.task_type == TASK_TYPE_BRUSCHETTA_APP || task.task_type == TASK_TYPE_CROSTINI_APP || task.task_type == TASK_TYPE_PLUGIN_VM_APP) { - // TODO(petermarshall): Implement GetProfileForExtensionTask in Lacros if - // necessary, for Chrome Apps. extensions::app_file_handler_util::MimeTypeCollector* mime_collector = new extensions::app_file_handler_util::MimeTypeCollector(profile); mime_collector->CollectForURLs(
diff --git a/chrome/browser/ash/file_manager/office_file_tasks.cc b/chrome/browser/ash/file_manager/office_file_tasks.cc index 70066da..d705bfd 100644 --- a/chrome/browser/ash/file_manager/office_file_tasks.cc +++ b/chrome/browser/ash/file_manager/office_file_tasks.cc
@@ -459,8 +459,7 @@ if (!proxy) { return false; } - // The AppRegistryCache will contain the QuickOffice extension whether on Ash - // or Lacros. + // The AppRegistryCache will contain the QuickOffice extension on Ash. bool installed = false; proxy->AppRegistryCache().ForOneApp( extension_misc::kQuickOfficeComponentExtensionId,
diff --git a/chrome/browser/ash/fileapi/recent_model.cc b/chrome/browser/ash/fileapi/recent_model.cc index 2b4ac7f..fa16d03 100644 --- a/chrome/browser/ash/fileapi/recent_model.cc +++ b/chrome/browser/ash/fileapi/recent_model.cc
@@ -90,11 +90,10 @@ if (!volume || volume->type() != file_manager::VOLUME_TYPE_PROVIDED || volume->file_system_type() == file_manager::util::kFuseBox) { // Provided volume types are served via two file system types: fusebox - // (usable from ash or lacros, but requires ChromeOS' /usr/bin/fusebox - // daemon process to be running) and non-fusebox (ash only, no separate - // process required). The Files app runs in ash and could use either. - // Using both would return duplicate results. We therefore filter out - // the fusebox file system type. + // (requires ChromeOS' /usr/bin/fusebox daemon process to be running) and + // non-fusebox. The Files app runs in ash and could use either. Using both + // would return duplicate results. We therefore filter out the fusebox + // file system type. continue; } sources.emplace_back(std::make_unique<RecentDiskSource>(
diff --git a/chrome/browser/ash/fusebox/README.md b/chrome/browser/ash/fusebox/README.md index cf28293..37e2807 100644 --- a/chrome/browser/ash/fusebox/README.md +++ b/chrome/browser/ash/fusebox/README.md
@@ -7,16 +7,17 @@ FUSE](https://www.kernel.org/doc/html/latest/filesystems/fuse.html) protocol. It enables sharing virtual-file-like things *across processes* (e.g. between -ash-chrome and lacros-chrome) or *with Virtual Machines* (e.g. the Android or -Crostini VMs) just by sharing a string file name or an integer file descriptor. +ash-chrome and lacros-chrome, although lacros-chrome is now deprecated) or +*with Virtual Machines* (e.g. the Android or Crostini VMs) just by sharing a +string file name or an integer file descriptor. Fusebox doesn't *replace* the `storage` C++ API. It provides *an alternative mechanism* for accessing those virtual files. Workflows that stay entirely within ash-chrome can continue to use the C++ API. But when the GMail web-app -(running in a sandboxed lacros-chrome process) wants to upload files from a -phone attached to a Chromebook via USB cable, and the MTP (Media Transfer -Protocol) volume (virtual directory) is served by ash-chrome code, that access -is facilitated by Fusebox. +(running in a sandboxed and now deprecated lacros-chrome process) wants to +upload files from a phone attached to a Chromebook via USB cable, and the MTP +(Media Transfer Protocol) volume (virtual directory) is served by ash-chrome +code, that access is facilitated by Fusebox. ## Structure
diff --git a/chrome/browser/ash/login/BUILD.gn b/chrome/browser/ash/login/BUILD.gn index 54e2aab..ff84d71 100644 --- a/chrome/browser/ash/login/BUILD.gn +++ b/chrome/browser/ash/login/BUILD.gn
@@ -474,6 +474,7 @@ "//chromeos/ash/components/install_attributes:test_support", "//chromeos/ash/components/language_preferences", "//chromeos/ash/components/network:test_support", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//chromeos/ash/components/system", "//chromeos/ash/components/timezone", @@ -593,6 +594,7 @@ "//chromeos/ash/components/login/auth", "//chromeos/ash/components/login/auth/public:authpublic", "//chromeos/ash/components/network:test_support", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//chromeos/ash/components/system", "//chromeos/ash/services/network_config/public/cpp:test_support",
diff --git a/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc b/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc index f493775..3c78cf9c 100644 --- a/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc +++ b/chrome/browser/ash/login/app_mode/kiosk_launch_controller_unittest.cc
@@ -60,10 +60,10 @@ #include "chrome/test/base/testing_profile_manager.h" #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" #include "chromeos/ash/components/network/network_handler.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/account_id/account_id.h" #include "components/crash/core/common/crash_key.h" #include "components/policy/core/browser/browser_policy_connector_base.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_types.h" #include "components/policy/policy_constants.h"
diff --git a/chrome/browser/ash/login/app_mode/test/BUILD.gn b/chrome/browser/ash/login/app_mode/test/BUILD.gn index 2f5122a96..e2202da 100644 --- a/chrome/browser/ash/login/app_mode/test/BUILD.gn +++ b/chrome/browser/ash/login/app_mode/test/BUILD.gn
@@ -58,6 +58,7 @@ "//chrome/browser/chromeos/app_mode", "//chrome/browser/ui", "//chrome/browser/ui/ash/login", + "//chromeos/ash/components/policy/device_local_account", "//components/policy:generated", "//components/policy:policy_code_generate", "//components/policy/core/common",
diff --git a/chrome/browser/ash/login/app_mode/test/auto_launched_kiosk_browsertest.cc b/chrome/browser/ash/login/app_mode/test/auto_launched_kiosk_browsertest.cc index 89000d3..2a07ff18 100644 --- a/chrome/browser/ash/login/app_mode/test/auto_launched_kiosk_browsertest.cc +++ b/chrome/browser/ash/login/app_mode/test/auto_launched_kiosk_browsertest.cc
@@ -38,8 +38,8 @@ #include "chrome/test/base/mixin_based_in_process_browser_test.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/ash/components/dbus/session_manager/session_manager_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/crx_file/crx_verifier.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.cc b/chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.cc index ec7ff02..b05188b8 100644 --- a/chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.cc +++ b/chrome/browser/ash/login/app_mode/test/web_kiosk_base_test.cc
@@ -19,8 +19,8 @@ #include "chrome/browser/ash/ownership/fake_owner_settings_service.h" // IWYU pragma: keep #include "chrome/browser/ash/policy/core/device_local_account.h" #include "chrome/browser/ui/browser_list.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h"
diff --git a/chrome/browser/ash/login/demo_mode/BUILD.gn b/chrome/browser/ash/login/demo_mode/BUILD.gn index 68abaa0..f1a8b11 100644 --- a/chrome/browser/ash/login/demo_mode/BUILD.gn +++ b/chrome/browser/ash/login/demo_mode/BUILD.gn
@@ -252,6 +252,7 @@ "//chromeos/ash/components/demo_mode", "//chromeos/ash/components/install_attributes:test_support", "//chromeos/ash/components/login/auth", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/system", "//chromeos/constants", "//components/component_updater/ash:test_support",
diff --git a/chrome/browser/ash/login/demo_mode/demo_login_controller_unittest.cc b/chrome/browser/ash/login/demo_mode/demo_login_controller_unittest.cc index b18fc950..c6f2338 100644 --- a/chrome/browser/ash/login/demo_mode/demo_login_controller_unittest.cc +++ b/chrome/browser/ash/login/demo_mode/demo_login_controller_unittest.cc
@@ -25,6 +25,7 @@ #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/ash/components/demo_mode/utils/demo_session_utils.h" #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/system/fake_statistics_provider.h" #include "chromeos/dbus/power/fake_power_manager_client.h" @@ -34,7 +35,6 @@ #include "components/policy/core/common/cloud/mock_cloud_policy_manager.h" #include "components/policy/core/common/cloud/mock_cloud_policy_service.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/session_manager/core/session_manager.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/login/existing_user_controller_auto_login_unittest.cc b/chrome/browser/ash/login/existing_user_controller_auto_login_unittest.cc index 3f8b383..4fe5cd3 100644 --- a/chrome/browser/ash/login/existing_user_controller_auto_login_unittest.cc +++ b/chrome/browser/ash/login/existing_user_controller_auto_login_unittest.cc
@@ -16,10 +16,10 @@ #include "chrome/test/base/testing_browser_process.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/ash/components/login/auth/auth_events_recorder.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/ownership/mock_owner_key_util.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/session_manager/core/session_manager.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/login/existing_user_controller_browsertest.cc b/chrome/browser/ash/login/existing_user_controller_browsertest.cc index 64618f4..f8d48df 100644 --- a/chrome/browser/ash/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/ash/login/existing_user_controller_browsertest.cc
@@ -68,6 +68,7 @@ #include "chromeos/ash/components/login/auth/public/user_context.h" #include "chromeos/ash/components/login/auth/stub_authenticator_builder.h" #include "chromeos/ash/components/network/network_state_test_helper.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/settings/cros_settings_provider.h" @@ -81,7 +82,6 @@ #include "components/policy/core/common/cloud/cloud_policy_store.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/policy_constants.h" #include "components/policy/proto/chrome_device_policy.pb.h"
diff --git a/chrome/browser/ash/login/reporting/BUILD.gn b/chrome/browser/ash/login/reporting/BUILD.gn index 8ea10b6..fbbd24c 100644 --- a/chrome/browser/ash/login/reporting/BUILD.gn +++ b/chrome/browser/ash/login/reporting/BUILD.gn
@@ -30,6 +30,7 @@ "//chrome/browser/ash/profiles", "//chrome/browser/profiles:profile_util", "//chromeos/ash/components/login/auth/public:authpublic", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//components/policy/core/common", "//components/prefs", @@ -128,6 +129,7 @@ "//chrome/test:test_support", "//chromeos/ash/components/login/auth/public:authpublic", "//chromeos/ash/components/login/session", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/dbus/power", "//components/policy/core/common", "//components/reporting/client:test_support",
diff --git a/chrome/browser/ash/login/reporting/login_logout_reporter.cc b/chrome/browser/ash/login/reporting/login_logout_reporter.cc index 50ad4f0..ce01dd4d 100644 --- a/chrome/browser/ash/login/reporting/login_logout_reporter.cc +++ b/chrome/browser/ash/login/reporting/login_logout_reporter.cc
@@ -18,8 +18,8 @@ #include "chrome/browser/policy/messaging_layer/proto/synced/login_logout_event.pb.h" #include "chrome/browser/profiles/reporting_util.h" #include "chromeos/ash/components/login/auth/public/auth_failure.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h"
diff --git a/chrome/browser/ash/login/reporting/login_logout_reporter_browsertest.cc b/chrome/browser/ash/login/reporting/login_logout_reporter_browsertest.cc index 889be61..d28631e 100644 --- a/chrome/browser/ash/login/reporting/login_logout_reporter_browsertest.cc +++ b/chrome/browser/ash/login/reporting/login_logout_reporter_browsertest.cc
@@ -44,13 +44,13 @@ #include "chromeos/ash/components/login/auth/public/user_context.h" #include "chromeos/ash/components/login/auth/stub_authenticator_builder.h" #include "chromeos/ash/components/login/login_state/login_state.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/dbus/missive/missive_client.h" #include "chromeos/dbus/missive/missive_client_test_observer.h" #include "components/account_id/account_id.h" #include "components/policy/core/common/cloud/cloud_policy_store.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/reporting/proto/synced/record.pb.h"
diff --git a/chrome/browser/ash/login/reporting/login_logout_reporter_unittest.cc b/chrome/browser/ash/login/reporting/login_logout_reporter_unittest.cc index ed3efac2..ac32d06e 100644 --- a/chrome/browser/ash/login/reporting/login_logout_reporter_unittest.cc +++ b/chrome/browser/ash/login/reporting/login_logout_reporter_unittest.cc
@@ -17,8 +17,8 @@ #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/login/auth/public/auth_failure.h" #include "chromeos/ash/components/login/session/session_termination_manager.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/dbus/power/fake_power_manager_client.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/reporting/client/mock_report_queue.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user_names.h"
diff --git a/chrome/browser/ash/login/screens/BUILD.gn b/chrome/browser/ash/login/screens/BUILD.gn index 64d02ed2..05942b9 100644 --- a/chrome/browser/ash/login/screens/BUILD.gn +++ b/chrome/browser/ash/login/screens/BUILD.gn
@@ -405,7 +405,6 @@ "add_child_screen_browsertest.cc", "ai_intro_screen_browsertest.cc", "app_downloading_screen_browsertest.cc", - "assistant_optin_flow_screen_browsertest.cc", "categories_selection_screen_browsertest.cc", "choobe_screen_browsertest.cc", "consolidated_consent_screen_browsertest.cc", @@ -513,6 +512,7 @@ "//chromeos/ash/components/network", "//chromeos/ash/components/network:test_support", "//chromeos/ash/components/osauth/public", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/quick_start", "//chromeos/ash/components/settings", "//chromeos/ash/components/system", @@ -521,7 +521,6 @@ "//chromeos/ash/experiences/arc:prefs", "//chromeos/ash/experiences/arc/session", "//chromeos/ash/experiences/arc/session:arc_base_enums", - "//chromeos/ash/services/assistant:lib", "//chromeos/ash/services/assistant/public/cpp", "//chromeos/ash/services/assistant/public/proto", "//chromeos/ash/services/bluetooth_config/public/mojom:mojom_shared_cpp_sources",
diff --git a/chrome/browser/ash/login/screens/assistant_optin_flow_screen_browsertest.cc b/chrome/browser/ash/login/screens/assistant_optin_flow_screen_browsertest.cc deleted file mode 100644 index 004c373..0000000 --- a/chrome/browser/ash/login/screens/assistant_optin_flow_screen_browsertest.cc +++ /dev/null
@@ -1,1186 +0,0 @@ -// Copyright 2019 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/ash/login/screens/assistant_optin_flow_screen.h" - -#include <memory> -#include <set> -#include <string_view> - -#include "ash/constants/ash_features.h" -#include "base/files/file_path.h" -#include "base/functional/bind.h" -#include "base/metrics/histogram_base.h" -#include "base/path_service.h" -#include "base/strings/strcat.h" -#include "base/test/metrics/histogram_tester.h" -#include "base/test/test_future.h" -#include "chrome/browser/ash/login/login_wizard.h" -#include "chrome/browser/ash/login/oobe_screen.h" -#include "chrome/browser/ash/login/screens/sync_consent_screen.h" -#include "chrome/browser/ash/login/test/js_checker.h" -#include "chrome/browser/ash/login/test/login_manager_mixin.h" -#include "chrome/browser/ash/login/test/oobe_base_test.h" -#include "chrome/browser/ash/login/test/oobe_screen_exit_waiter.h" -#include "chrome/browser/ash/login/test/oobe_screen_waiter.h" -#include "chrome/browser/ash/login/wizard_controller.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/ash/login/login_display_host.h" -#include "chrome/browser/ui/webui/ash/login/assistant_optin_flow_screen_handler.h" -#include "chrome/browser/ui/webui/ash/login/gaia_screen_handler.h" -#include "chrome/browser/ui/webui/ash/login/oobe_ui.h" -#include "chrome/common/chrome_paths.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_prefs.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_settings.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/assistant/public/proto/activity_control_settings_common.pb.h" -#include "chromeos/ash/services/assistant/public/proto/get_settings_ui.pb.h" -#include "chromeos/ash/services/assistant/public/proto/settings_ui.pb.h" -#include "chromeos/ash/services/assistant/service.h" -#include "components/prefs/pref_service.h" -#include "content/public/test/browser_test.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver_set.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "net/dns/mock_host_resolver.h" -#include "net/test/embedded_test_server/default_handlers.h" -#include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/embedded_test_server/http_request.h" -#include "net/test/embedded_test_server/http_response.h" - -namespace ash { - -namespace { - -using ::net::test_server::BasicHttpResponse; -using ::net::test_server::HttpRequest; -using ::net::test_server::HttpResponse; - -constexpr char kTestUser[] = "test-user1@gmail.com"; - -constexpr char kAssistantConsentToken[] = "consent_token"; -constexpr char kAssistantUiAuditKey[] = "ui_audit_key"; - -constexpr char kAssistantOptInId[] = "assistant-optin-flow"; -constexpr char kAssistantOptInFlowCard[] = "card"; -constexpr char kLoading[] = "loading"; -constexpr char kValueProp[] = "valueProp"; -constexpr char kRelatedInfo[] = "relatedInfo"; -constexpr char kVoiceMatch[] = "voiceMatch"; - -constexpr char kSettingsZippyTitle[] = "Settings-Zippy-Title"; -constexpr char kSettingsZippyDescription[] = "Settings-Zippy-Description"; -constexpr char kSettingsZippyAdditionalInfo[] = - "Settings-Zippy-Additional-Info"; -constexpr char kSettingsZippyLearnMoreLink[] = "Learn more"; - -//   -constexpr char kEnsp[] = "\xe2\x80\x82"; - -const test::UIPath kAssistantLoading = {kAssistantOptInId, - kAssistantOptInFlowCard, kLoading}; -const test::UIPath kLoadingRetryButton = { - kAssistantOptInId, kAssistantOptInFlowCard, kLoading, "retry-button"}; -const test::UIPath kSettingsZippyTitleFirst = { - kAssistantOptInId, kAssistantOptInFlowCard, kValueProp, "title-0"}; -const test::UIPath kSettingsZippyDescriptionFirst = { - kAssistantOptInId, kAssistantOptInFlowCard, kValueProp, "description-0"}; -const test::UIPath kSettingsZippyAdditionalInfoFirst = { - kAssistantOptInId, kAssistantOptInFlowCard, kValueProp, - "additional-info-0"}; - -const test::UIPath kAssistantValueProp = {kAssistantOptInId, - kAssistantOptInFlowCard, kValueProp}; -const test::UIPath kValuePropNextButton = { - kAssistantOptInId, kAssistantOptInFlowCard, kValueProp, "next-button"}; -const test::UIPath kValuePropSkipButton = { - kAssistantOptInId, kAssistantOptInFlowCard, kValueProp, "skip-button"}; - -const test::UIPath kAssistantRelatedInfo = { - kAssistantOptInId, kAssistantOptInFlowCard, kRelatedInfo}; -const test::UIPath kRelatedInfoNextButton = { - kAssistantOptInId, kAssistantOptInFlowCard, kRelatedInfo, "next-button"}; -const test::UIPath kRelatedInfoSkipButton = { - kAssistantOptInId, kAssistantOptInFlowCard, kRelatedInfo, "skip-button"}; - -const test::UIPath kAssistantVoiceMatch = { - kAssistantOptInId, kAssistantOptInFlowCard, kVoiceMatch}; -const test::UIPath kVoiceMatchAgreeButton = { - kAssistantOptInId, kAssistantOptInFlowCard, kVoiceMatch, "agree-button"}; -const test::UIPath kVoiceMatchLaterButton = { - kAssistantOptInId, kAssistantOptInFlowCard, kVoiceMatch, "later-button"}; -const test::UIPath kVoiceMatchEntry0 = { - kAssistantOptInId, kAssistantOptInFlowCard, kVoiceMatch, "voice-entry-0"}; -const test::UIPath kVoiceMatchEntry1 = { - kAssistantOptInId, kAssistantOptInFlowCard, kVoiceMatch, "voice-entry-1"}; -const test::UIPath kVoiceMatchEntry2 = { - kAssistantOptInId, kAssistantOptInFlowCard, kVoiceMatch, "voice-entry-2"}; -const test::UIPath kVoiceMatchEntry3 = { - kAssistantOptInId, kAssistantOptInFlowCard, kVoiceMatch, "voice-entry-3"}; - -constexpr char kAssistantOptInScreenExitReason[] = - "OOBE.StepCompletionTimeByExitReason.Assistant-optin-flow.Next"; -constexpr char kAssistantOptInScreenStepCompletionTime[] = - "OOBE.StepCompletionTime.Assistant-optin-flow"; - -class ScopedAssistantSettings : public assistant::AssistantSettings { - public: - // Flags to configure GetSettings response. - static constexpr int CONSENT_UI_FLAGS_NONE = 0; - static constexpr int CONSENT_UI_FLAG_SKIP_ACTIVITY_CONTROL = 1; - static constexpr int CONSENT_UI_FLAG_WAA_DISABLED_BY_POLICY = 1 << 1; - static constexpr int CONSENT_UI_FLAG_ASSISTANT_DISABLED_BY_POLICY = 1 << 2; - - enum class SpeakerIdEnrollmentMode { - // On speaker enrollment request, the client will be notified that the - // enrollment is done immediately. - IMMEDIATE, - // Speaker enrollment requests will not respond immediately, test will have - // to run through enrollment responses by calling - // AdvanceSpeakerIdEnrollment(). - STEP_BY_STEP - }; - - enum class OptIn { - ACTIVITY_CONTROL, - EMAIL, - }; - - ScopedAssistantSettings() = default; - - ScopedAssistantSettings(const ScopedAssistantSettings&) = delete; - ScopedAssistantSettings& operator=(const ScopedAssistantSettings&) = delete; - - ~ScopedAssistantSettings() override = default; - - void set_consent_ui_flags(int flags) { consent_ui_flags_ = flags; } - - void set_speaker_id_enrollment_mode(SpeakerIdEnrollmentMode mode) { - speaker_id_enrollment_mode_ = mode; - } - - void set_setting_zippy_size(int size) { setting_zippy_size_ = size; } - - void set_is_minor_user(bool is_minor_user) { is_minor_user_ = is_minor_user; } - - const std::set<OptIn>& collected_optins() const { return collected_optins_; } - - // Advances speaker ID enrollment to the next state. - // Returns whether the speaker ID enrollment state changed, which amounts to - // whether the speaker ID enrollment is currently in progress. - bool AdvanceSpeakerIdEnrollmentState() { - switch (speaker_id_enrollment_state_) { - case SpeakerIdEnrollmentState::IDLE: - return false; - case SpeakerIdEnrollmentState::REQUESTED: - speaker_id_enrollment_state_ = SpeakerIdEnrollmentState::LISTENING; - speaker_id_enrollment_client_->OnListeningHotword(); - return true; - case SpeakerIdEnrollmentState::LISTENING: - speaker_id_enrollment_state_ = SpeakerIdEnrollmentState::PROCESSING; - speaker_id_enrollment_client_->OnProcessingHotword(); - return true; - case SpeakerIdEnrollmentState::PROCESSING: - ++processed_hotwords_; - if (processed_hotwords_ == 4) { - speaker_id_enrollment_state_ = SpeakerIdEnrollmentState::IDLE; - speaker_id_enrollment_client_->OnSpeakerIdEnrollmentDone(); - } else { - speaker_id_enrollment_state_ = SpeakerIdEnrollmentState::LISTENING; - speaker_id_enrollment_client_->OnListeningHotword(); - } - return true; - } - return false; - } - - bool IsSpeakerIdEnrollmentActive() const { - return speaker_id_enrollment_state_ != SpeakerIdEnrollmentState::IDLE; - } - - void FailSpeakerIdEnrollment() { - ASSERT_NE(speaker_id_enrollment_state_, SpeakerIdEnrollmentState::IDLE); - speaker_id_enrollment_client_->OnSpeakerIdEnrollmentFailure(); - processed_hotwords_ = 0; - speaker_id_enrollment_state_ = SpeakerIdEnrollmentState::IDLE; - } - - // assistant::AssistantSettings: - void GetSettings(const std::string& selector, - GetSettingsCallback callback) override {} - - void GetSettingsWithHeader(const std::string& selector, - GetSettingsCallback callback) override { - assistant::SettingsUiSelector selector_proto; - ASSERT_TRUE(selector_proto.ParseFromString(selector)); - EXPECT_FALSE(selector_proto.about_me_settings()); - EXPECT_TRUE(selector_proto.has_consent_flow_ui_selector()); - EXPECT_EQ(assistant::ActivityControlSettingsUiSelector:: - ASSISTANT_SUW_ONBOARDING_ON_CHROME_OS, - selector_proto.consent_flow_ui_selector().flow_id()); - - assistant::GetSettingsUiResponse response; - - if (is_minor_user_) { - auto* header = response.mutable_header(); - header->set_footer_button_layout( - assistant::SettingsResponseHeader_AcceptRejectLayout_EQUAL_WEIGHT); - } - - auto* settings_ui = response.mutable_settings(); - auto* gaia_user_context_ui = settings_ui->mutable_gaia_user_context_ui(); - gaia_user_context_ui->set_is_gaia_user(true); - gaia_user_context_ui->set_waa_disabled_by_dasher_domain( - (consent_ui_flags_ & CONSENT_UI_FLAG_WAA_DISABLED_BY_POLICY)); - gaia_user_context_ui->set_assistant_disabled_by_dasher_domain( - (consent_ui_flags_ & CONSENT_UI_FLAG_ASSISTANT_DISABLED_BY_POLICY)); - - auto* consent_flow_ui = settings_ui->mutable_consent_flow_ui(); - consent_flow_ui->set_consent_status( - assistant::ConsentFlowUi_ConsentStatus_ASK_FOR_CONSENT); - consent_flow_ui->mutable_consent_ui()->set_accept_button_text("OK"); - consent_flow_ui->mutable_consent_ui()->set_reject_button_text( - "No, thank you"); - - if (!(consent_ui_flags_ & CONSENT_UI_FLAG_SKIP_ACTIVITY_CONTROL)) { - PopulateActivityControlData(consent_flow_ui->mutable_consent_ui()); - for (int i = 0; i < setting_zippy_size_; i++) { - auto* multi_consent_ui = consent_flow_ui->add_multi_consent_ui(); - PopulateActivityControlData(multi_consent_ui); - } - } - - std::string message; - EXPECT_TRUE(response.SerializeToString(&message)); - std::move(callback).Run(message); - } - - void PopulateActivityControlData( - assistant::ConsentFlowUi_ConsentUi* consent_ui) { - auto* activity_control_ui = consent_ui->mutable_activity_control_ui(); - activity_control_ui->set_consent_token(kAssistantConsentToken); - activity_control_ui->set_ui_audit_key(kAssistantUiAuditKey); - activity_control_ui->set_title("Title"); - activity_control_ui->set_identity(kTestUser); - activity_control_ui->add_intro_text_paragraph(); - activity_control_ui->set_intro_text_paragraph(0, "Here's an intro"); - activity_control_ui->add_footer_paragraph(); - activity_control_ui->set_footer_paragraph(0, "A footer"); - auto* setting = activity_control_ui->add_setting_zippy(); - setting->set_title(kSettingsZippyTitle); - setting->add_description_paragraph(); - setting->set_description_paragraph(0, kSettingsZippyDescription); - setting->add_additional_info_paragraph(); - setting->set_additional_info_paragraph(0, kSettingsZippyAdditionalInfo); - setting->set_icon_uri("assistant_icon"); - setting->set_setting_set_id(assistant::SettingSetId::WAA); - } - - void UpdateSettings(const std::string& update, - UpdateSettingsCallback callback) override { - assistant::SettingsUiUpdate update_proto; - ASSERT_TRUE(update_proto.ParseFromString(update)); - EXPECT_FALSE(update_proto.has_about_me_settings_update()); - EXPECT_FALSE(update_proto.has_assistant_device_settings_update()); - - assistant::SettingsUiUpdateResult update_result; - if (update_proto.has_consent_flow_ui_update()) { - EXPECT_EQ(kAssistantConsentToken, - update_proto.consent_flow_ui_update().consent_token()); - EXPECT_FALSE( - update_proto.consent_flow_ui_update().saw_third_party_disclosure()); - EXPECT_EQ(assistant::ActivityControlSettingsUiSelector:: - ASSISTANT_SUW_ONBOARDING_ON_CHROME_OS, - update_proto.consent_flow_ui_update().flow_id()); - collected_optins_.insert(OptIn::ACTIVITY_CONTROL); - update_result.mutable_consent_flow_update_result()->set_update_status( - assistant::ConsentFlowUiUpdateResult::SUCCESS); - } - std::string message; - EXPECT_TRUE(update_result.SerializeToString(&message)); - std::move(callback).Run(message); - } - - void StartSpeakerIdEnrollment( - bool skip_cloud_enrollment, - base::WeakPtr<assistant::SpeakerIdEnrollmentClient> client) override { - if (speaker_id_enrollment_mode_ == SpeakerIdEnrollmentMode::IMMEDIATE) { - client->OnSpeakerIdEnrollmentDone(); - return; - } - ASSERT_FALSE(speaker_id_enrollment_client_); - processed_hotwords_ = 0; - speaker_id_enrollment_client_ = std::move(client); - speaker_id_enrollment_state_ = SpeakerIdEnrollmentState::REQUESTED; - } - - void StopSpeakerIdEnrollment() override { - processed_hotwords_ = 0; - speaker_id_enrollment_state_ = SpeakerIdEnrollmentState::IDLE; - speaker_id_enrollment_client_.reset(); - } - - void SyncSpeakerIdEnrollmentStatus() override {} - - private: - enum class SpeakerIdEnrollmentState { - IDLE, - REQUESTED, - LISTENING, - PROCESSING - }; - - // The service test config: - int consent_ui_flags_ = CONSENT_UI_FLAGS_NONE; - SpeakerIdEnrollmentMode speaker_id_enrollment_mode_ = - SpeakerIdEnrollmentMode::IMMEDIATE; - - // Speaker ID enrollment state: - SpeakerIdEnrollmentState speaker_id_enrollment_state_ = - SpeakerIdEnrollmentState::IDLE; - base::WeakPtr<assistant::SpeakerIdEnrollmentClient> - speaker_id_enrollment_client_; - int processed_hotwords_ = 0; - - // Set of opt ins given by the user. - std::set<OptIn> collected_optins_; - - int setting_zippy_size_ = 1; - bool is_minor_user_ = false; -}; - -class AssistantOptInFlowBaseTest : public OobeBaseTest { - public: - AssistantOptInFlowBaseTest() = default; - ~AssistantOptInFlowBaseTest() override = default; - - void RegisterAdditionalRequestHandlers() override { - embedded_test_server()->RegisterRequestHandler(base::BindRepeating( - &AssistantOptInFlowBaseTest::HandleRequest, base::Unretained(this))); - } - - void SetUpOnMainThread() override { - OobeBaseTest::SetUpOnMainThread(); - assistant_settings_ = std::make_unique<ScopedAssistantSettings>(); - - AssistantOptInFlowScreen* assistant_optin_flow_screen = - WizardController::default_controller() - ->GetScreen<AssistantOptInFlowScreen>(); - original_callback_ = - assistant_optin_flow_screen->get_exit_callback_for_testing(); - assistant_optin_flow_screen->set_exit_callback_for_testing( - base::BindRepeating(&AssistantOptInFlowBaseTest::HandleScreenExit, - base::Unretained(this))); - } - - void TearDownOnMainThread() override { - assistant_settings_.reset(); - OobeBaseTest::TearDownOnMainThread(); - } - - void ShowAssistantOptInFlowScreen() { - login_manager_.LoginAsNewRegularUser(); - OobeScreenExitWaiter(GetFirstSigninScreen()).Wait(); - if (!screen_exited_) { - LoginDisplayHost::default_host()->StartWizard( - AssistantOptInFlowScreenView::kScreenId); - } - } - - // Waits for the OOBE UI to complete initialization, and overrides: - // * the assistant value prop webview URL with the one provided by embedded - // https proxy. - // * the timeout delay for sending done user action from voice match screen. - void SetUpAssistantScreensForTest() { - std::string url_template = embedded_test_server() - ->GetURL("/test_assistant/$/value_prop.html") - .spec(); - test::OobeJS().Evaluate(test::GetOobeElementPath(kAssistantValueProp) + - ".setUrlTemplateForTesting('" + url_template + - "')"); - test::OobeJS().Evaluate(test::GetOobeElementPath(kAssistantRelatedInfo) + - ".setUrlTemplateForTesting('" + url_template + - "')"); - test::OobeJS().Evaluate(test::GetOobeElementPath(kAssistantVoiceMatch) + - ".setDoneActionDelayForTesting(0)"); - } - - // Waits for the button specified by IDs in `button_path` to become enabled, - // and then taps it. - void TapWhenEnabled(std::initializer_list<std::string_view> button_path) { - test::OobeJS().CreateEnabledWaiter(true, button_path)->Wait(); - test::OobeJS().TapOnPath(button_path); - } - - bool ElementHasAttribute(std::initializer_list<std::string_view> element, - const std::string& attribute) { - return test::OobeJS().GetBool(test::GetOobeElementPath(element) + - ".getAttribute('" + attribute + "')"); - } - - void WaitForElementAttribute(std::initializer_list<std::string_view> element, - const std::string& attribute) { - test::OobeJS() - .CreateWaiter(test::GetOobeElementPath(element) + ".getAttribute('" + - attribute + "')") - ->Wait(); - } - - void ExpectCollectedOptIns( - const std::set<ScopedAssistantSettings::OptIn>& opt_ins) { - EXPECT_EQ(opt_ins, assistant_settings_->collected_optins()); - } - - void WaitForScreenExit() { - if (screen_exited_) { - return; - } - base::test::TestFuture<void> waiter; - screen_exit_callback_ = waiter.GetCallback(); - EXPECT_TRUE(waiter.Wait()); - } - - std::unique_ptr<ScopedAssistantSettings> assistant_settings_; - - std::optional<AssistantOptInFlowScreen::Result> screen_result_; - base::HistogramTester histogram_tester_; - - // If set, HandleRequest will return an error for the next value prop URL - // request.. - bool fail_next_value_prop_url_request_ = false; - - base::test::ScopedFeatureList scoped_feature_list_; - - private: - std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { - auto response = std::make_unique<BasicHttpResponse>(); - if (request.relative_url != "/test_assistant/en_us/value_prop.html" || - fail_next_value_prop_url_request_) { - fail_next_value_prop_url_request_ = false; - response->set_code(net::HTTP_NOT_FOUND); - } else { - response->set_code(net::HTTP_OK); - response->set_content("Test content"); - response->set_content_type("text/plain"); - } - return std::move(response); - } - - void HandleScreenExit(AssistantOptInFlowScreen::Result result) { - ASSERT_FALSE(screen_exited_); - screen_exited_ = true; - screen_result_ = result; - original_callback_.Run(result); - if (screen_exit_callback_) - std::move(screen_exit_callback_).Run(); - } - - bool screen_exited_ = false; - base::OnceClosure screen_exit_callback_; - AssistantOptInFlowScreen::ScreenExitCallback original_callback_; - - LoginManagerMixin login_manager_{&mixin_host_}; -}; - -class AssistantOptInFlowTest : public AssistantOptInFlowBaseTest { - public: - AssistantOptInFlowTest() { - scoped_feature_list_.InitWithFeatures( - {}, {ash::features::kOobeSkipAssistant, - ash::assistant::features::kEnableNewEntryPoint}); - } - ~AssistantOptInFlowTest() override = default; -}; - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, Basic) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - EXPECT_TRUE(test::OobeJS().GetAttributeBool("inverse", kValuePropNextButton)); - TapWhenEnabled(kValuePropNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - EXPECT_TRUE( - test::OobeJS().GetAttributeBool("inverse", kRelatedInfoNextButton)); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - EXPECT_TRUE( - test::OobeJS().GetAttributeBool("inverse", kVoiceMatchAgreeButton)); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({ScopedAssistantSettings::OptIn::ACTIVITY_CONTROL}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, DisableScreenContext) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - TapWhenEnabled(kValuePropNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoSkipButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({ScopedAssistantSettings::OptIn::ACTIVITY_CONTROL}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, AssistantStateUpdateAfterShow) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - TapWhenEnabled(kValuePropNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({ScopedAssistantSettings::OptIn::ACTIVITY_CONTROL}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -// TODO(crbug.com/41486294): Flaky on ChromeOS. -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, - DISABLED_RetryOnWebviewLoadFail) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - SetUpAssistantScreensForTest(); - fail_next_value_prop_url_request_ = true; - - ShowAssistantOptInFlowScreen(); - - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - // Value prop webview requests are set to fail - loading screen should display - // an error and an option to retry the request. - test::OobeJS().CreateVisibilityWaiter(true, kAssistantLoading)->Wait(); - TapWhenEnabled(kLoadingRetryButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - TapWhenEnabled(kValuePropNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({ScopedAssistantSettings::OptIn::ACTIVITY_CONTROL}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, RejectValueProp) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - SetUpAssistantScreensForTest(); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - TapWhenEnabled(kValuePropSkipButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kUnknown, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -// TODO(crbug.com/40917081): Flaky on ChromeOS. -#if BUILDFLAG(IS_CHROMEOS) -#define MAYBE_SkipShowingValueProp DISABLED_SkipShowingValueProp -#else -#define MAYBE_SkipShowingValueProp SkipShowingValueProp -#endif -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, MAYBE_SkipShowingValueProp) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_consent_ui_flags( - ScopedAssistantSettings::CONSENT_UI_FLAG_SKIP_ACTIVITY_CONTROL); - - SetUpAssistantScreensForTest(); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, SpeakerIdEnrollment) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_consent_ui_flags( - ScopedAssistantSettings::CONSENT_UI_FLAG_SKIP_ACTIVITY_CONTROL); - assistant_settings_->set_speaker_id_enrollment_mode( - ScopedAssistantSettings::SpeakerIdEnrollmentMode::STEP_BY_STEP); - - SetUpAssistantScreensForTest(); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry0, "active"); - test::OobeJS().ExpectVisiblePath(kVoiceMatchLaterButton); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry0, "completed"); - test::OobeJS().ExpectVisiblePath(kVoiceMatchLaterButton); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry1, "active"); - test::OobeJS().ExpectVisiblePath(kVoiceMatchLaterButton); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry1, "completed"); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry2, "active"); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry2, "completed"); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry3, "active"); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry3, "completed"); - test::OobeJS().ExpectHiddenPath(kVoiceMatchLaterButton); - - // This should finish the enrollment. - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - EXPECT_FALSE(assistant_settings_->IsSpeakerIdEnrollmentActive()); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, - FeatureDisabledDuringSpeakerIdEnrollment) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_consent_ui_flags( - ScopedAssistantSettings::CONSENT_UI_FLAG_SKIP_ACTIVITY_CONTROL); - assistant_settings_->set_speaker_id_enrollment_mode( - ScopedAssistantSettings::SpeakerIdEnrollmentMode::STEP_BY_STEP); - - SetUpAssistantScreensForTest(); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - prefs->SetBoolean(assistant::prefs::kAssistantEnabled, false); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - EXPECT_FALSE(assistant_settings_->IsSpeakerIdEnrollmentActive()); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, - BailOutDuringSpeakerIdEnrollment) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_consent_ui_flags( - ScopedAssistantSettings::CONSENT_UI_FLAG_SKIP_ACTIVITY_CONTROL); - assistant_settings_->set_speaker_id_enrollment_mode( - ScopedAssistantSettings::SpeakerIdEnrollmentMode::STEP_BY_STEP); - - SetUpAssistantScreensForTest(); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry0, "active"); - test::OobeJS().ExpectVisiblePath(kVoiceMatchLaterButton); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry0, "completed"); - - test::OobeJS().TapOnPath(kVoiceMatchLaterButton); - EXPECT_FALSE(assistant_settings_->IsSpeakerIdEnrollmentActive()); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, - SpeakerIdEnrollmentFailureAndRetry) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_consent_ui_flags( - ScopedAssistantSettings::CONSENT_UI_FLAG_SKIP_ACTIVITY_CONTROL); - assistant_settings_->set_speaker_id_enrollment_mode( - ScopedAssistantSettings::SpeakerIdEnrollmentMode::STEP_BY_STEP); - - SetUpAssistantScreensForTest(); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - ASSERT_TRUE(assistant_settings_->AdvanceSpeakerIdEnrollmentState()); - WaitForElementAttribute(kVoiceMatchEntry0, "active"); - test::OobeJS().ExpectVisiblePath(kVoiceMatchLaterButton); - - assistant_settings_->FailSpeakerIdEnrollment(); - - // Failure should cause an error screen to be shown, with retry button - // available. - test::OobeJS().CreateVisibilityWaiter(true, kAssistantLoading)->Wait(); - - // Make enrollment succeed immediately next time. - assistant_settings_->set_speaker_id_enrollment_mode( - ScopedAssistantSettings::SpeakerIdEnrollmentMode::IMMEDIATE); - - TapWhenEnabled(kLoadingRetryButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, WAADisabledByPolicy) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_consent_ui_flags( - ScopedAssistantSettings::CONSENT_UI_FLAG_WAA_DISABLED_BY_POLICY); - - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantEnabled)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, AssistantDisabledByPolicy) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_consent_ui_flags( - ScopedAssistantSettings::CONSENT_UI_FLAG_ASSISTANT_DISABLED_BY_POLICY); - - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantDisabledByPolicy)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantEnabled)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowTest, AssistantSkippedNoLib) { - auto force_lib_assistant_disabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(false); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - EXPECT_EQ(screen_result_.value(), - AssistantOptInFlowScreen::Result::NOT_APPLICABLE); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 0); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 0); -} - -class AssistantOptInFlowMinorModeTest : public AssistantOptInFlowTest { - public: - AssistantOptInFlowMinorModeTest() = default; - - void SetUpOnMainThread() override { - AssistantOptInFlowTest::SetUpOnMainThread(); - assistant_settings_->set_is_minor_user(true); - } -}; - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowMinorModeTest, - AcceptMultipleValuePropConsentsForMinors) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_setting_zippy_size(2); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - EXPECT_FALSE( - test::OobeJS().GetAttributeBool("inverse", kValuePropNextButton)); - test::OobeJS().ExpectElementText(kSettingsZippyTitle, - kSettingsZippyTitleFirst); - test::OobeJS().ExpectElementText( - base::StrCat( - {kSettingsZippyDescription, kEnsp, kSettingsZippyLearnMoreLink}), - kSettingsZippyDescriptionFirst); - test::OobeJS().ExpectElementText(kSettingsZippyAdditionalInfo, - kSettingsZippyAdditionalInfoFirst); - TapWhenEnabled(kValuePropNextButton); - EXPECT_FALSE( - test::OobeJS().GetAttributeBool("inverse", kValuePropNextButton)); - TapWhenEnabled(kValuePropNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - EXPECT_FALSE( - test::OobeJS().GetAttributeBool("inverse", kRelatedInfoNextButton)); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - EXPECT_FALSE( - test::OobeJS().GetAttributeBool("inverse", kVoiceMatchAgreeButton)); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({ScopedAssistantSettings::OptIn::ACTIVITY_CONTROL}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kActivityControlAccepted, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowMinorModeTest, - DeclineMultipleValuePropConsentsForMinors) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_setting_zippy_size(2); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - TapWhenEnabled(kValuePropSkipButton); - TapWhenEnabled(kValuePropSkipButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kUnknown, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowMinorModeTest, - AcceptFirstAndDeclineSecondValuePropConsentsForMinors) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_setting_zippy_size(2); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - TapWhenEnabled(kValuePropNextButton); - TapWhenEnabled(kValuePropSkipButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({ScopedAssistantSettings::OptIn::ACTIVITY_CONTROL}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kUnknown, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowMinorModeTest, - DeclineFirstAndAcceptSecondValuePropConsentsForMinors) { - auto force_lib_assistant_enabled = - AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true); - assistant_settings_->set_setting_zippy_size(2); - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - - SetUpAssistantScreensForTest(); - ShowAssistantOptInFlowScreen(); - - OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId); - screen_waiter.Wait(); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantValueProp)->Wait(); - TapWhenEnabled(kValuePropSkipButton); - TapWhenEnabled(kValuePropNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantRelatedInfo)->Wait(); - TapWhenEnabled(kRelatedInfoNextButton); - - test::OobeJS().CreateVisibilityWaiter(true, kAssistantVoiceMatch)->Wait(); - TapWhenEnabled(kVoiceMatchAgreeButton); - - WaitForScreenExit(); - - ExpectCollectedOptIns({ScopedAssistantSettings::OptIn::ACTIVITY_CONTROL}); - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_EQ(assistant::prefs::ConsentStatus::kUnknown, - prefs->GetInteger(assistant::prefs::kAssistantConsentStatus)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_TRUE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); - EXPECT_EQ(screen_result_.value(), AssistantOptInFlowScreen::Result::NEXT); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 1); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 1); -} - -class AssistantOptInFlowSkipFeatureTest : public AssistantOptInFlowBaseTest { - public: - AssistantOptInFlowSkipFeatureTest() { - scoped_feature_list_.InitAndEnableFeature( - ash::features::kOobeSkipAssistant); - } -}; - -IN_PROC_BROWSER_TEST_F(AssistantOptInFlowSkipFeatureTest, AssistantSkipped) { - AssistantState::Get()->NotifyStatusChanged(assistant::AssistantStatus::READY); - ShowAssistantOptInFlowScreen(); - WaitForScreenExit(); - EXPECT_EQ(screen_result_.value(), - AssistantOptInFlowScreen::Result::NOT_APPLICABLE); - - ExpectCollectedOptIns({}); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenExitReason, 0); - histogram_tester_.ExpectTotalCount(kAssistantOptInScreenStepCompletionTime, - 0); - - PrefService* const prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)); - EXPECT_FALSE(prefs->GetBoolean(assistant::prefs::kAssistantContextEnabled)); -} - -} // namespace -} // namespace ash
diff --git a/chrome/browser/ash/login/screens/terms_of_service_screen_browsertest.cc b/chrome/browser/ash/login/screens/terms_of_service_screen_browsertest.cc index 5c2f54f..194ce47 100644 --- a/chrome/browser/ash/login/screens/terms_of_service_screen_browsertest.cc +++ b/chrome/browser/ash/login/screens/terms_of_service_screen_browsertest.cc
@@ -39,8 +39,8 @@ #include "chrome/browser/ui/webui/ash/login/sync_consent_screen_handler.h" #include "chrome/browser/ui/webui/ash/login/terms_of_service_screen_handler.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/prefs/pref_service.h" #include "components/user_manager/known_user.h"
diff --git a/chrome/browser/ash/login/users/BUILD.gn b/chrome/browser/ash/login/users/BUILD.gn index 103c771..545076ec 100644 --- a/chrome/browser/ash/login/users/BUILD.gn +++ b/chrome/browser/ash/login/users/BUILD.gn
@@ -60,6 +60,7 @@ "//chromeos/ash/components/install_attributes", "//chromeos/ash/components/login/auth/public:authpublic", "//chromeos/ash/components/network", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/timezone", "//chromeos/ash/experiences/arc:arc_base_utils", "//chromeos/components/onc", @@ -186,6 +187,7 @@ "//chromeos/ash/components/cryptohome", "//chromeos/ash/components/dbus/concierge", "//chromeos/ash/components/dbus/userdataauth", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//chromeos/ash/components/system", "//components/account_id",
diff --git a/chrome/browser/ash/login/users/chrome_user_manager_util.h b/chrome/browser/ash/login/users/chrome_user_manager_util.h index 144e6dd..c87c8758 100644 --- a/chrome/browser/ash/login/users/chrome_user_manager_util.h +++ b/chrome/browser/ash/login/users/chrome_user_manager_util.h
@@ -7,7 +7,7 @@ #include <optional> -#include "components/policy/core/common/device_local_account_type.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/user_manager/user.h" #include "components/user_manager/user_type.h"
diff --git a/chrome/browser/ash/login/users/user_manager_delegate_impl.cc b/chrome/browser/ash/login/users/user_manager_delegate_impl.cc index fc81208..c5dcb7c 100644 --- a/chrome/browser/ash/login/users/user_manager_delegate_impl.cc +++ b/chrome/browser/ash/login/users/user_manager_delegate_impl.cc
@@ -22,7 +22,7 @@ #include "chromeos/ash/components/cryptohome/cryptohome_parameters.h" #include "chromeos/ash/components/dbus/cryptohome/UserDataAuth.pb.h" #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h" -#include "components/policy/core/common/device_local_account_type.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/user_manager/user.h" #include "components/user_manager/user_type.h" #include "content/public/common/content_switches.h"
diff --git a/chrome/browser/ash/login/users/user_manager_unittest.cc b/chrome/browser/ash/login/users/user_manager_unittest.cc index abace54..38ebd9a 100644 --- a/chrome/browser/ash/login/users/user_manager_unittest.cc +++ b/chrome/browser/ash/login/users/user_manager_unittest.cc
@@ -40,10 +40,10 @@ #include "chromeos/ash/components/dbus/concierge/concierge_client.h" #include "chromeos/ash/components/dbus/userdataauth/fake_userdataauth_client.h" #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/system/fake_statistics_provider.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/user_manager/known_user.h"
diff --git a/chrome/browser/ash/main_parts/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/main_parts/chrome_browser_main_parts_ash.cc index 4a4e49a..72fe47b 100644 --- a/chrome/browser/ash/main_parts/chrome_browser_main_parts_ash.cc +++ b/chrome/browser/ash/main_parts/chrome_browser_main_parts_ash.cc
@@ -229,6 +229,7 @@ #include "chromeos/ash/components/network/system_token_cert_db_storage.h" #include "chromeos/ash/components/network/traffic_counters_handler.h" #include "chromeos/ash/components/peripheral_notification/peripheral_notification_manager.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/power/dark_resume_controller.h" #include "chromeos/ash/components/report/device_metrics/use_case/real_psm_client_manager.h" #include "chromeos/ash/components/report/device_metrics/use_case/use_case.h" @@ -256,7 +257,6 @@ #include "components/metrics/metrics_service.h" #include "components/ownership/owner_key_util.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/pref_service.h" #include "components/quirks/quirks_manager.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
diff --git a/chrome/browser/ash/policy/core/BUILD.gn b/chrome/browser/ash/policy/core/BUILD.gn index d9eac2b..1b1215609e 100644 --- a/chrome/browser/ash/policy/core/BUILD.gn +++ b/chrome/browser/ash/policy/core/BUILD.gn
@@ -102,6 +102,7 @@ "//chromeos/ash/components/dbus/userdataauth:userdataauth_proto", "//chromeos/ash/components/install_attributes", "//chromeos/ash/components/network", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//chromeos/ash/components/system", "//chromeos/ash/experiences/arc:arc_features", @@ -257,6 +258,7 @@ "//chromeos/ash/components/dbus/userdataauth", "//chromeos/ash/components/install_attributes", "//chromeos/ash/components/install_attributes:test_support", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/policy/weekly_time", "//chromeos/ash/components/settings", "//chromeos/ash/components/system",
diff --git a/chrome/browser/ash/policy/core/device_local_account.h b/chrome/browser/ash/policy/core/device_local_account.h index 72f94083..07622d97 100644 --- a/chrome/browser/ash/policy/core/device_local_account.h +++ b/chrome/browser/ash/policy/core/device_local_account.h
@@ -8,7 +8,7 @@ #include <string> #include <vector> -#include "components/policy/core/common/device_local_account_type.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" namespace ash { class CrosSettings;
diff --git a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc index 08ca786..8076762 100644 --- a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc +++ b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
@@ -120,6 +120,7 @@ #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/ash/components/login/auth/public/user_context.h" #include "chromeos/ash/components/network/policy_certificate_provider.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/timezone_settings.h" #include "chromeos/components/mgs/managed_guest_session_utils.h" #include "components/crx_file/crx_verifier.h" @@ -129,7 +130,6 @@ #include "components/policy/core/common/cloud/cloud_policy_core.h" #include "components/policy/core/common/cloud/cloud_policy_store.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/external_data_fetcher.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_namespace.h"
diff --git a/chrome/browser/ash/policy/core/device_local_account_policy_provider.h b/chrome/browser/ash/policy/core/device_local_account_policy_provider.h index 08d31ef..134c8d2 100644 --- a/chrome/browser/ash/policy/core/device_local_account_policy_provider.h +++ b/chrome/browser/ash/policy/core/device_local_account_policy_provider.h
@@ -14,8 +14,8 @@ #include "chrome/browser/ash/policy/core/device_local_account.h" #include "chrome/browser/ash/policy/core/device_local_account_policy_service.h" #include "chrome/browser/ash/policy/external_data/device_local_account_external_data_manager.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/policy/core/common/configuration_policy_provider.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/policy_types.h" namespace policy {
diff --git a/chrome/browser/ash/policy/core/device_local_account_policy_service_unittest.cc b/chrome/browser/ash/policy/core/device_local_account_policy_service_unittest.cc index 6337572..f85d626 100644 --- a/chrome/browser/ash/policy/core/device_local_account_policy_service_unittest.cc +++ b/chrome/browser/ash/policy/core/device_local_account_policy_service_unittest.cc
@@ -34,6 +34,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/dbus/power/power_policy_controller.h" #include "components/invalidation/test_support/fake_invalidation_listener.h" @@ -42,7 +43,6 @@ #include "components/policy/core/common/cloud/cloud_policy_service.h" #include "components/policy/core/common/cloud/mock_device_management_service.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/external_data_fetcher.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_bundle.h"
diff --git a/chrome/browser/ash/policy/core/device_local_account_unittest.cc b/chrome/browser/ash/policy/core/device_local_account_unittest.cc index 1cd1e7f..1f2d4d4f 100644 --- a/chrome/browser/ash/policy/core/device_local_account_unittest.cc +++ b/chrome/browser/ash/policy/core/device_local_account_unittest.cc
@@ -9,10 +9,10 @@ #include "base/values.h" #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" #include "chrome/browser/ash/settings/stub_cros_settings_provider.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/settings/cros_settings_provider.h" -#include "components/policy/core/common/device_local_account_type.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ash/policy/core/device_policy_decoder.cc b/chrome/browser/ash/policy/core/device_policy_decoder.cc index a86cf97..5796a55 100644 --- a/chrome/browser/ash/policy/core/device_policy_decoder.cc +++ b/chrome/browser/ash/policy/core/device_policy_decoder.cc
@@ -11,6 +11,7 @@ #include <string_view> #include <utility> +#include "ash/constants/ash_features.h" #include "ash/system/privacy_hub/privacy_hub_controller.h" #include "base/containers/fixed_flat_map.h" #include "base/functional/callback.h" @@ -26,13 +27,12 @@ #include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chromeos/ash/components/dbus/dbus_thread_manager.h" #include "chromeos/ash/components/dbus/update_engine/update_engine_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/policy/core/browser/policy_error_map.h" #include "components/policy/core/common/chrome_schema.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/external_data_fetcher.h" #include "components/policy/core/common/external_data_manager.h" -#include "components/policy/core/common/features.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_types.h" #include "components/policy/core/common/schema.h" @@ -753,7 +753,7 @@ entry.isolated_kiosk_app().allow_downgrades()); } } - if (policy::features::IsHeliumArcvmKioskEnabled()) { + if (ash::features::IsHeliumArcvmKioskEnabled()) { if (entry.arcvm_kiosk_app().has_package_name()) { entry_dict.Set(ash::kAccountsPrefDeviceLocalAccountsKeyArcvmKioskPackage, entry.arcvm_kiosk_app().package_name());
diff --git a/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc b/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc index e1aab4f..0f18bc91 100644 --- a/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc +++ b/chrome/browser/ash/policy/core/device_policy_decoder_unittest.cc
@@ -13,10 +13,10 @@ #include "base/time/time.h" #include "base/values.h" #include "chrome/browser/ash/policy/core/device_local_account.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/policy/weekly_time/weekly_time.h" #include "chromeos/ash/components/policy/weekly_time/weekly_time_interval.h" #include "chromeos/ash/components/settings/cros_settings_names.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/policy_bundle.h" #include "components/policy/policy_constants.h" #include "components/policy/proto/chrome_device_policy.pb.h"
diff --git a/chrome/browser/ash/policy/external_data/BUILD.gn b/chrome/browser/ash/policy/external_data/BUILD.gn index 4c21a38..d40ff45 100644 --- a/chrome/browser/ash/policy/external_data/BUILD.gn +++ b/chrome/browser/ash/policy/external_data/BUILD.gn
@@ -34,6 +34,7 @@ "//chrome/browser/ash/policy/handlers", "//chrome/browser/ash/profiles", "//chrome/browser/profiles:profile", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//components/policy:generated", "//components/policy/core/browser",
diff --git a/chrome/browser/ash/policy/external_data/cloud_external_data_policy_observer.cc b/chrome/browser/ash/policy/external_data/cloud_external_data_policy_observer.cc index 8ceef4a..0beb6d4 100644 --- a/chrome/browser/ash/policy/external_data/cloud_external_data_policy_observer.cc +++ b/chrome/browser/ash/policy/external_data/cloud_external_data_policy_observer.cc
@@ -20,12 +20,12 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/profiles/profile.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/settings/cros_settings_provider.h" #include "components/policy/core/browser/policy_error_map.h" #include "components/policy/core/common/cloud/cloud_policy_core.h" #include "components/policy/core/common/cloud/cloud_policy_store.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/external_data_fetcher.h" #include "components/policy/core/common/policy_namespace.h" #include "components/policy/core/common/policy_service.h"
diff --git a/chrome/browser/ash/policy/external_data/cloud_external_data_policy_observer_unittest.cc b/chrome/browser/ash/policy/external_data/cloud_external_data_policy_observer_unittest.cc index 1316168a..69352eb 100644 --- a/chrome/browser/ash/policy/external_data/cloud_external_data_policy_observer_unittest.cc +++ b/chrome/browser/ash/policy/external_data/cloud_external_data_policy_observer_unittest.cc
@@ -33,12 +33,12 @@ #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "components/policy/core/common/cloud/cloud_policy_core.h" #include "components/policy/core/common/cloud/cloud_policy_store.h" #include "components/policy/core/common/cloud/mock_cloud_external_data_manager.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/external_data_fetcher.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_map.h"
diff --git a/chrome/browser/ash/policy/fuzzer/BUILD.gn b/chrome/browser/ash/policy/fuzzer/BUILD.gn index b254005..463d37a 100644 --- a/chrome/browser/ash/policy/fuzzer/BUILD.gn +++ b/chrome/browser/ash/policy/fuzzer/BUILD.gn
@@ -28,7 +28,6 @@ "//chrome/common:constants", "//chromeos/ash/components/attestation", "//chromeos/ash/components/install_attributes", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", "//components/policy:generated", "//components/policy/core/browser",
diff --git a/chrome/browser/ash/policy/networking/policy_certs_browsertest.cc b/chrome/browser/ash/policy/networking/policy_certs_browsertest.cc index 306769b..ea23dca1 100644 --- a/chrome/browser/ash/policy/networking/policy_certs_browsertest.cc +++ b/chrome/browser/ash/policy/networking/policy_certs_browsertest.cc
@@ -49,12 +49,12 @@ #include "chromeos/ash/components/network/onc/onc_certificate_importer.h" #include "chromeos/ash/components/network/onc/onc_certificate_importer_impl.h" #include "chromeos/ash/components/network/policy_certificate_provider.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/components/onc/onc_test_utils.h" #include "chromeos/test/chromeos_test_utils.h" #include "components/onc/onc_constants.h" #include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_switches.h" #include "components/policy/policy_constants.h"
diff --git a/chrome/browser/ash/policy/remote_commands/BUILD.gn b/chrome/browser/ash/policy/remote_commands/BUILD.gn index a30228f7f..bbcbb969 100644 --- a/chrome/browser/ash/policy/remote_commands/BUILD.gn +++ b/chrome/browser/ash/policy/remote_commands/BUILD.gn
@@ -282,7 +282,6 @@ "//chrome/browser", "//chrome/browser/ash/policy/remote_commands/crd", "//chrome/browser/ash/policy/remote_commands/crd:test_support", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", "//components/policy/proto", ]
diff --git a/chrome/browser/ash/policy/reporting/BUILD.gn b/chrome/browser/ash/policy/reporting/BUILD.gn index eaddf0b..3297599 100644 --- a/chrome/browser/ash/policy/reporting/BUILD.gn +++ b/chrome/browser/ash/policy/reporting/BUILD.gn
@@ -192,7 +192,6 @@ # TODO(crbug.com/335294371): Remove dependency on //chrome/browser to # implement the proper fix. "//chrome/browser", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", ] }
diff --git a/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_browsertest.cc b/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_browsertest.cc index dd60753d..aeb4735 100644 --- a/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_browsertest.cc +++ b/chrome/browser/ash/policy/reporting/user_added_removed/user_added_removed_reporter_browsertest.cc
@@ -34,12 +34,12 @@ #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/ash/components/login/auth/public/user_context.h" #include "chromeos/ash/components/login/login_state/login_state.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/dbus/missive/missive_client.h" #include "chromeos/dbus/missive/missive_client_test_observer.h" #include "components/account_id/account_id.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/reporting/proto/synced/record.pb.h"
diff --git a/chrome/browser/ash/policy/reporting/user_session_activity/BUILD.gn b/chrome/browser/ash/policy/reporting/user_session_activity/BUILD.gn index 5bb3fb07..0821766 100644 --- a/chrome/browser/ash/policy/reporting/user_session_activity/BUILD.gn +++ b/chrome/browser/ash/policy/reporting/user_session_activity/BUILD.gn
@@ -23,6 +23,7 @@ "//chrome/browser/ash/power/ml", "//chrome/browser/ash/profiles", "//chrome/browser/policy/messaging_layer/proto:user_session_activity_proto", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//components/viz/host", ]
diff --git a/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter.cc b/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter.cc index da6d7d63..5edab83f 100644 --- a/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter.cc +++ b/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter.cc
@@ -20,9 +20,9 @@ #include "chrome/browser/ash/policy/reporting/user_event_reporter_helper.h" #include "chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate.h" #include "chrome/browser/policy/messaging_layer/proto/synced/user_session_activity.pb.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate.cc b/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate.cc index 938ea67..5215ed8 100644 --- a/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate.cc +++ b/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate.cc
@@ -19,8 +19,8 @@ #include "chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter.h" #include "chrome/browser/ash/power/ml/idle_event_notifier.h" #include "chrome/browser/policy/messaging_layer/proto/synced/user_session_activity.pb.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "components/user_manager/user_names.h"
diff --git a/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate_unittest.cc b/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate_unittest.cc index d65e1a1..30a8b71 100644 --- a/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate_unittest.cc +++ b/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_delegate_unittest.cc
@@ -18,8 +18,8 @@ #include "chrome/browser/ash/policy/reporting/user_event_reporter_helper_testing.h" #include "chrome/browser/ash/power/ml/idle_event_notifier.h" #include "chrome/browser/policy/messaging_layer/proto/synced/user_session_activity.pb.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/reporting/client/mock_report_queue.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h"
diff --git a/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_unittest.cc b/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_unittest.cc index 2c14535..69b8c055 100644 --- a/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_unittest.cc +++ b/chrome/browser/ash/policy/reporting/user_session_activity/user_session_activity_reporter_unittest.cc
@@ -25,8 +25,8 @@ #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/policy/device_local_account/device_local_account_type.h" #include "chromeos/dbus/power/fake_power_manager_client.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/reporting/client/mock_report_queue.h" #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/session_manager/core/session_manager.h"
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector.cc b/chrome/browser/ash/policy/status_collector/device_status_collector.cc index 3524c1cd..0ca8db2 100644 --- a/chrome/browser/ash/policy/status_collector/device_status_collector.cc +++ b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
@@ -25,6 +25,7 @@ #include <string_view> #include <utility> +#include "ash/constants/ash_features.h" #include "base/check.h" #include "base/check_op.h" #include "base/files/file_enumerator.h" @@ -78,6 +79,7 @@ #include "chromeos/ash/components/network/network_handler.h" #include "chromeos/ash/components/network/network_state.h" #include "chromeos/ash/components/network/network_state_handler.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/settings/timezone_settings.h" @@ -93,8 +95,6 @@ #include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/cloud_policy_util.h" -#include "components/policy/core/common/device_local_account_type.h" -#include "components/policy/core/common/features.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_registry_simple.h" @@ -662,7 +662,7 @@ return em::ActiveTimePeriod::SESSION_IWA_KIOSK; case DeviceLocalAccountType::kArcvmKioskApp: - if (policy::features::IsHeliumArcvmKioskEnabled()) { + if (ash::features::IsHeliumArcvmKioskEnabled()) { return em::ActiveTimePeriod::SESSION_ARC_KIOSK; } break; @@ -2725,7 +2725,7 @@ running_kiosk_app->set_app_id(account->kiosk_iwa_info.web_bundle_id()); break; case DeviceLocalAccountType::kArcvmKioskApp: - if (policy::features::IsHeliumArcvmKioskEnabled()) { + if (ash::features::IsHeliumArcvmKioskEnabled()) { // Use package name as app ID for ARC Kiosks. running_kiosk_app->set_app_id( account->arcvm_kiosk_app_info.package_name()); @@ -3024,7 +3024,7 @@ app_status->set_app_id(account->kiosk_iwa_info.web_bundle_id()); break; case DeviceLocalAccountType::kArcvmKioskApp: - if (policy::features::IsHeliumArcvmKioskEnabled()) { + if (ash::features::IsHeliumArcvmKioskEnabled()) { // Use package name as app ID for ARC Kiosks. app_status->set_app_id(account->arcvm_kiosk_app_info.package_name()); }
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc index 8b455180..9f09d551 100644 --- a/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc +++ b/chrome/browser/ash/policy/status_collector/device_status_collector_browsertest.cc
@@ -100,6 +100,7 @@ #include "chromeos/ash/components/network/network_handler_test_helper.h" #include "chromeos/ash/components/network/network_state.h" #include "chromeos/ash/components/network/network_state_handler.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/settings/timezone_settings.h" #include "chromeos/ash/components/system/fake_statistics_provider.h" @@ -110,7 +111,6 @@ #include "chromeos/dbus/tpm_manager/tpm_manager_client.h" #include "components/account_id/account_id.h" #include "components/ownership/mock_owner_key_util.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/policy/uploading/status_uploader_unittest.cc b/chrome/browser/ash/policy/uploading/status_uploader_unittest.cc index c309f11..9b802ec 100644 --- a/chrome/browser/ash/policy/uploading/status_uploader_unittest.cc +++ b/chrome/browser/ash/policy/uploading/status_uploader_unittest.cc
@@ -21,12 +21,12 @@ #include "chrome/browser/ash/policy/status_collector/device_status_collector.h" #include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" #include "chrome/browser/ash/settings/stub_cros_settings_provider.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/dbus/power/power_manager_client.h" #include "chromeos/dbus/tpm_manager/tpm_manager_client.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/testing_pref_service.h" #include "components/session_manager/core/session_manager.h" #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ash/printing/BUILD.gn b/chrome/browser/ash/printing/BUILD.gn index fa575b3..2d5cd22 100644 --- a/chrome/browser/ash/printing/BUILD.gn +++ b/chrome/browser/ash/printing/BUILD.gn
@@ -258,7 +258,6 @@ "//base", "//base/test:test_support", "//chrome/browser", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", ] }
diff --git a/chrome/browser/ash/settings/device_settings_provider.cc b/chrome/browser/ash/settings/device_settings_provider.cc index add301c5..b03703b7 100644 --- a/chrome/browser/ash/settings/device_settings_provider.cc +++ b/chrome/browser/ash/settings/device_settings_provider.cc
@@ -433,7 +433,7 @@ entry_dict.Set(kAccountsPrefDeviceLocalAccountsKeyKioskAppUpdateURL, entry.kiosk_app().update_url()); } - if (policy::features::IsHeliumArcvmKioskEnabled()) { + if (ash::features::IsHeliumArcvmKioskEnabled()) { if (entry.arcvm_kiosk_app().has_package_name()) { entry_dict.Set(kAccountsPrefDeviceLocalAccountsKeyArcvmKioskPackage, entry.arcvm_kiosk_app().package_name());
diff --git a/chrome/browser/ash/settings/device_settings_provider_unittest.cc b/chrome/browser/ash/settings/device_settings_provider_unittest.cc index f708b95..1d6903d 100644 --- a/chrome/browser/ash/settings/device_settings_provider_unittest.cc +++ b/chrome/browser/ash/settings/device_settings_provider_unittest.cc
@@ -22,9 +22,9 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/install_attributes/stub_install_attributes.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/policy/proto/device_management_backend.pb.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/ash/test/BUILD.gn b/chrome/browser/ash/test/BUILD.gn index 9cea795..bf987a3 100644 --- a/chrome/browser/ash/test/BUILD.gn +++ b/chrome/browser/ash/test/BUILD.gn
@@ -26,6 +26,7 @@ "//ash/constants", "//base", "//chrome/test:test_support_ui", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//chromeos/ash/components/settings:test_support", "//components/account_id",
diff --git a/chrome/browser/ash/test/kiosk_app_logged_in_browser_test_mixin.cc b/chrome/browser/ash/test/kiosk_app_logged_in_browser_test_mixin.cc index daa5d1f..95e43a5 100644 --- a/chrome/browser/ash/test/kiosk_app_logged_in_browser_test_mixin.cc +++ b/chrome/browser/ash/test/kiosk_app_logged_in_browser_test_mixin.cc
@@ -9,9 +9,9 @@ #include "ash/constants/ash_switches.h" #include "base/check.h" #include "base/values.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/device_settings_cache_test_support.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/test/public_account_logged_in_browser_test_mixin.cc b/chrome/browser/ash/test/public_account_logged_in_browser_test_mixin.cc index 2dcf5e218..5abbb43 100644 --- a/chrome/browser/ash/test/public_account_logged_in_browser_test_mixin.cc +++ b/chrome/browser/ash/test/public_account_logged_in_browser_test_mixin.cc
@@ -9,10 +9,10 @@ #include "ash/constants/ash_switches.h" #include "base/check.h" #include "base/values.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/settings/device_settings_cache_test_support.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/ash/test/web_kiosk_app_logged_in_browser_test_mixin.cc b/chrome/browser/ash/test/web_kiosk_app_logged_in_browser_test_mixin.cc index b848b998..03fd3fd8 100644 --- a/chrome/browser/ash/test/web_kiosk_app_logged_in_browser_test_mixin.cc +++ b/chrome/browser/ash/test/web_kiosk_app_logged_in_browser_test_mixin.cc
@@ -9,9 +9,9 @@ #include "ash/constants/ash_switches.h" #include "base/check.h" #include "base/values.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/device_settings_cache_test_support.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/policy/proto/device_management_backend.pb.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/auxiliary_search/BUILD.gn b/chrome/browser/auxiliary_search/BUILD.gn index b61e6ea2..0061088 100644 --- a/chrome/browser/auxiliary_search/BUILD.gn +++ b/chrome/browser/auxiliary_search/BUILD.gn
@@ -25,6 +25,7 @@ "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMetrics.java", "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImpl.java", "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java", + "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridge.java", "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchUtils.java", "java/src/org/chromium/chrome/browser/auxiliary_search/FetchAndRankHelper.java", "java/src/org/chromium/chrome/browser/auxiliary_search/module/AuxiliarySearchModuleBuilder.java", @@ -81,6 +82,7 @@ generate_jni("jni_headers") { sources = [ "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridge.java", + "java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridge.java", "java/src/org/chromium/chrome/browser/auxiliary_search/FetchAndRankHelper.java", ] } @@ -112,6 +114,7 @@ "junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImplUnitTest.java", "junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProviderUnitTest.java", "junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTestHelper.java", + "junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridgeUnitTest.java", "junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchUtilsUnitTest.java", "junit/src/org/chromium/chrome/browser/auxiliary_search/module/AuxiliarySearchModuleBuilderUnitTest.java", "junit/src/org/chromium/chrome/browser/auxiliary_search/module/AuxiliarySearchModuleMediatorUnitTest.java",
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_provider.cc b/chrome/browser/auxiliary_search/auxiliary_search_provider.cc index b99cc61ae..5f6abba 100644 --- a/chrome/browser/auxiliary_search/auxiliary_search_provider.cc +++ b/chrome/browser/auxiliary_search/auxiliary_search_provider.cc
@@ -21,7 +21,6 @@ #include "chrome/browser/auxiliary_search/fetch_and_rank_helper.h" #include "chrome/browser/auxiliary_search/proto/auxiliary_search_group.pb.h" #include "chrome/browser/flags/android/chrome_feature_list.h" -#include "chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_keyed_service_factory.h" #include "chrome/browser/visited_url_ranking/visited_url_ranking_service_factory.h" @@ -50,13 +49,6 @@ using visited_url_ranking::VisitedURLRankingServiceFactory; namespace { -// Must match Java Tab.INVALID_TAB_ID. -static constexpr int kInvalidTabId = -1; -// The next id to assign. -static int kIdCounter = 0; - -constexpr int kMaxNumMostVisitedSites = 4; - using BackToJavaCallback = base::OnceCallback<void( std::unique_ptr<std::vector<base::WeakPtr<TabAndroid>>>)>; @@ -94,10 +86,9 @@ if (base::FeatureList::IsEnabled( chrome::android::kAndroidAppIntegrationMultiDataSource)) { return std::make_unique<AuxiliarySearchProvider>( - VisitedURLRankingServiceFactory::GetForProfile(profile), - ChromeMostVisitedSitesFactory::NewForProfile(profile)); + VisitedURLRankingServiceFactory::GetForProfile(profile)); } - return std::make_unique<AuxiliarySearchProvider>(nullptr, nullptr); + return std::make_unique<AuxiliarySearchProvider>(nullptr); } }; @@ -144,31 +135,14 @@ Java_AuxiliarySearchBridge_onDataReady(env, entries, j_callback); } -// Converts the score to be an integer. Usually the score is between 0 and 1.0. -int convertSiteSuggestionScore(double score) { - return std::max(0, static_cast<int>(score * 100)); -} - } // namespace AuxiliarySearchProvider::AuxiliarySearchProvider( - VisitedURLRankingService* ranking_service, - std::unique_ptr<ntp_tiles::MostVisitedSites> most_visited_sites) - : ranking_service_(ranking_service), - most_visited_sites_(std::move(most_visited_sites)) {} + VisitedURLRankingService* ranking_service) + : ranking_service_(ranking_service) {} AuxiliarySearchProvider::~AuxiliarySearchProvider() = default; -void AuxiliarySearchProvider::Shutdown() { - if (most_visited_sites_) { - if (!observers_map_.empty()) { - most_visited_sites_->RemoveMostVisitedURLsObserver(this); - } - most_visited_sites_.reset(); - } - observers_map_.clear(); -} - void AuxiliarySearchProvider::GetNonSensitiveTabs( JNIEnv* env, const base::android::JavaParamRef<jobjectArray>& j_tabs_android, @@ -198,91 +172,6 @@ helper->StartFetching(); } -int AuxiliarySearchProvider::SetObserverAndTrigger( - JNIEnv* env, - const base::android::JavaRef<jobject>& j_ref_obj) { - auto j_ref = jni_zero::ScopedJavaGlobalRef<jobject>(j_ref_obj); - int id = kIdCounter++; - observers_map_[id] = j_ref; - - // AuxiliarySearchProvider registers itself as an observer of the - // |most_visited_sites_|. Don't register again if it has registered before. - if (observers_map_.size() > 1) { - return id; - } - - CHECK(most_visited_sites_); - most_visited_sites_->AddMostVisitedURLsObserver(this, - kMaxNumMostVisitedSites); - return id; -} - -void AuxiliarySearchProvider::RemoveObserver(JNIEnv* env, jint id) { - CHECK(observers_map_.contains(id)); - observers_map_.erase(id); - - if (observers_map_.size() == 0) { - most_visited_sites_->RemoveMostVisitedURLsObserver(this); - } -} - -void AuxiliarySearchProvider::GetMostVisitedSites(JNIEnv* env) const { - CHECK(most_visited_sites_); - - most_visited_sites_->RefreshTiles(); -} - -void AuxiliarySearchProvider::OnURLsAvailable( - const std::map<ntp_tiles::SectionType, ntp_tiles::NTPTilesVector>& - sections) { - CHECK(most_visited_sites_); - if (observers_map_.empty()) { - return; - } - - JNIEnv* env = base::android::AttachCurrentThread(); - std::vector<jni_zero::ScopedJavaLocalRef<jobject>> entries; - // Uses only personalized tiles for auxiliary search. - auto it = sections.find(ntp_tiles::SectionType::PERSONALIZED); - if (it == sections.end()) { - return; - } - - for (const ntp_tiles::NTPTile& tile : it->second) { - // Filters the tile list to include only TOP_SITES and CUSTOM_LINKS tiles. - if (tile.source != ntp_tiles::TileSource::TOP_SITES && - tile.source != ntp_tiles::TileSource::CUSTOM_LINKS) { - continue; - } - - entries.push_back(Java_AuxiliarySearchBridge_addDataEntry( - env, static_cast<int>(AuxiliarySearchEntryType::kTopSite), - url::GURLAndroid::FromNativeGURL(env, tile.url), - base::android::ConvertUTF16ToJavaString(env, tile.title), - tile.last_visit_time.InMillisecondsSinceUnixEpoch(), kInvalidTabId, - /* appId= */ nullptr, - std::abs(static_cast<int>( - base::Hash(tile.url.spec() + base::UTF16ToUTF8(tile.title)))), - convertSiteSuggestionScore(tile.score))); - } - - for (auto const& [id, observer] : observers_map_) { - Java_AuxiliarySearchBridge_onMostVisitedSitesURLsAvailable(env, observer, - entries); - } -} - -void AuxiliarySearchProvider::OnIconMadeAvailable(const GURL& site_url) { - if (observers_map_.empty()) { - return; - } - - JNIEnv* env = base::android::AttachCurrentThread(); - for (auto const& [id, observer] : observers_map_) { - Java_AuxiliarySearchBridge_onIconMadeAvailable(env, observer, site_url); - } -} - // static void AuxiliarySearchProvider::FilterTabsByScheme( std::vector<raw_ptr<TabAndroid, VectorExperimental>>& tabs) {
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_provider.h b/chrome/browser/auxiliary_search/auxiliary_search_provider.h index de74a86..dd19629 100644 --- a/chrome/browser/auxiliary_search/auxiliary_search_provider.h +++ b/chrome/browser/auxiliary_search/auxiliary_search_provider.h
@@ -15,8 +15,6 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "components/keyed_service/core/keyed_service.h" -#include "components/ntp_tiles/most_visited_sites.h" -#include "components/ntp_tiles/ntp_tile.h" namespace visited_url_ranking { class VisitedURLRankingService; @@ -35,12 +33,10 @@ // AuxiliarySearchProvider is responsible for providing the necessary // information for the auxiliary search. -class AuxiliarySearchProvider : public KeyedService, - public ntp_tiles::MostVisitedSites::Observer { +class AuxiliarySearchProvider : public KeyedService { public: AuxiliarySearchProvider( - visited_url_ranking::VisitedURLRankingService* ranking_service, - std::unique_ptr<ntp_tiles::MostVisitedSites> most_visited_sites); + visited_url_ranking::VisitedURLRankingService* ranking_service); ~AuxiliarySearchProvider() override; @@ -53,18 +49,6 @@ JNIEnv* env, const base::android::JavaParamRef<jobject>& j_callback_obj) const; - // Sets an observer and immediately fetches the current most visited sites - // suggestions. Returns the ID of the observer. - int SetObserverAndTrigger(JNIEnv* env, - const base::android::JavaRef<jobject>& j_ref_obj); - - // Removes the observer with the given ID from the observers list, and stops - // observing the most visited sites if all observers are removed. - void RemoveObserver(JNIEnv* env, jint observerId); - - // Starts a fetch of the current most visited sites suggestions. - void GetMostVisitedSites(JNIEnv* env) const; - static void EnsureFactoryBuilt(); private: @@ -78,20 +62,10 @@ QueryEmptyTabList); FRIEND_TEST_ALL_PREFIXES(AuxiliarySearchProviderBrowserTest, NativeTabTest); FRIEND_TEST_ALL_PREFIXES(AuxiliarySearchProviderBrowserTest, FilterTabsTest); - FRIEND_TEST_ALL_PREFIXES(AuxiliarySearchProviderTest, AddAndRemoveObservers); using NonSensitiveTabsCallback = base::OnceCallback<void(std::vector<base::WeakPtr<TabAndroid>>)>; - // KeyedService: - void Shutdown() override; - - // ntp_tiles::MostVisitedSites::Observer implementation. - void OnURLsAvailable( - const std::map<ntp_tiles::SectionType, ntp_tiles::NTPTilesVector>& - sections) override; - void OnIconMadeAvailable(const GURL& site_url) override; - static void FilterTabsByScheme( std::vector<raw_ptr<TabAndroid, VectorExperimental>>& tabs); @@ -99,10 +73,7 @@ std::vector<raw_ptr<TabAndroid, VectorExperimental>> all_tabs, NonSensitiveTabsCallback callback) const; - std::map<int, jni_zero::ScopedJavaGlobalRef<jobject>> observers_map_; - const raw_ptr<visited_url_ranking::VisitedURLRankingService> ranking_service_; - std::unique_ptr<ntp_tiles::MostVisitedSites> most_visited_sites_; }; #endif // CHROME_BROWSER_AUXILIARY_SEARCH_AUXILIARY_SEARCH_PROVIDER_H_
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_provider_browsertest.cc b/chrome/browser/auxiliary_search/auxiliary_search_provider_browsertest.cc index f957c5d..8b8d0301 100644 --- a/chrome/browser/auxiliary_search/auxiliary_search_provider_browsertest.cc +++ b/chrome/browser/auxiliary_search/auxiliary_search_provider_browsertest.cc
@@ -45,7 +45,7 @@ web_contents(), embedded_test_server()->GetURL("/android/google.html"))); auxiliary_search_provider_ = - std::make_unique<AuxiliarySearchProvider>(nullptr, nullptr); + std::make_unique<AuxiliarySearchProvider>(nullptr); PersistedTabDataAndroid::OnDeferredStartup(); content::RunAllTasksUntilIdle(); }
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_provider_unittest.cc b/chrome/browser/auxiliary_search/auxiliary_search_provider_unittest.cc deleted file mode 100644 index cd07761a..0000000 --- a/chrome/browser/auxiliary_search/auxiliary_search_provider_unittest.cc +++ /dev/null
@@ -1,104 +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 "chrome/browser/auxiliary_search/auxiliary_search_provider.h" - -#include <memory> - -#include "components/ntp_tiles/icon_cacher.h" -#include "components/ntp_tiles/most_visited_sites.h" -#include "components/prefs/testing_pref_service.h" -#include "components/visited_url_ranking/public/testing/mock_visited_url_ranking_service.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { -constexpr size_t kMaxNumMostVisitedSites = 4; -} // namespace - -class MockMostVisitedSites : public ntp_tiles::MostVisitedSites { - public: - explicit MockMostVisitedSites(PrefService* prefs) - : ntp_tiles::MostVisitedSites(prefs, - /*identity_manager*/ nullptr, - /*supervised_user_service*/ nullptr, - /*top_sites*/ nullptr, - /*popular_sites*/ nullptr, - /*custom_links*/ nullptr, - /*icon_cacher*/ nullptr, - /*is_default_chrome_app_migrated*/ true, - /*is_custom_links_mixable*/ false) {} - - MockMostVisitedSites(const MockMostVisitedSites&) = delete; - MockMostVisitedSites& operator=(const MockMostVisitedSites&) = delete; - - ~MockMostVisitedSites() override = default; - - MOCK_METHOD2(AddMostVisitedURLsObserver, - void(Observer* observer, size_t max_num_sites)); - MOCK_METHOD1(RemoveMostVisitedURLsObserver, void(Observer* observer)); -}; - -// Unit tests for AuxiliarySearchProvider. -class AuxiliarySearchProviderTest : public ::testing::Test { - public: - AuxiliarySearchProviderTest() { - auto mock_most_visited_sites = - std::make_unique<MockMostVisitedSites>(&testing_prefs_); - auxiliary_search_provider_ = std::make_unique<AuxiliarySearchProvider>( - &mock_visited_url_ranking_service_, std::move(mock_most_visited_sites)); - } - - AuxiliarySearchProviderTest(const AuxiliarySearchProviderTest&) = delete; - AuxiliarySearchProviderTest& operator=(const AuxiliarySearchProviderTest&) = - delete; - - protected: - TestingPrefServiceSimple testing_prefs_; - visited_url_ranking::MockVisitedURLRankingService - mock_visited_url_ranking_service_; - std::unique_ptr<AuxiliarySearchProvider> auxiliary_search_provider_; -}; - -TEST_F(AuxiliarySearchProviderTest, AddAndRemoveObservers) { - auto j_ref = base::android::JavaRef<jobject>(); - MockMostVisitedSites* mock_most_visited_sites = - static_cast<MockMostVisitedSites*>( - auxiliary_search_provider_->most_visited_sites_.get()); - - // Verifies to start observing most visited sites when the first observer is - // added. - EXPECT_CALL(*mock_most_visited_sites, - AddMostVisitedURLsObserver(testing::_, kMaxNumMostVisitedSites)) - .Times(1); - int id1 = auxiliary_search_provider_->SetObserverAndTrigger(nullptr, j_ref); - EXPECT_EQ(0, id1); - EXPECT_EQ(1u, auxiliary_search_provider_->observers_map_.size()); - - // Verifies not to call AddMostVisitedURLsObserver() again when more observer - // is added. - EXPECT_CALL(*mock_most_visited_sites, - AddMostVisitedURLsObserver(testing::_, kMaxNumMostVisitedSites)) - .Times(0); - auto j_ref_1 = base::android::JavaRef<jobject>(); - int id2 = auxiliary_search_provider_->SetObserverAndTrigger(nullptr, j_ref_1); - EXPECT_EQ(1, id2); - EXPECT_EQ(2u, auxiliary_search_provider_->observers_map_.size()); - - // Verifies still observing the most visited sites when an observer is - // removed. - EXPECT_CALL(*mock_most_visited_sites, - RemoveMostVisitedURLsObserver(testing::_)) - .Times(0); - auxiliary_search_provider_->RemoveObserver(nullptr, id2); - EXPECT_EQ(1u, auxiliary_search_provider_->observers_map_.size()); - - // Verifies not to observe most visited sites after the last observer is - // removed. - EXPECT_CALL(*mock_most_visited_sites, - RemoveMostVisitedURLsObserver(testing::_)) - .Times(1); - auxiliary_search_provider_->RemoveObserver(nullptr, id1); - EXPECT_TRUE(auxiliary_search_provider_->observers_map_.empty()); -}
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge.cc b/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge.cc new file mode 100644 index 0000000..71e8545 --- /dev/null +++ b/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge.cc
@@ -0,0 +1,120 @@ +// 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 "auxiliary_search_top_site_provider_bridge.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/hash/hash.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/auxiliary_search/auxiliary_search_provider.h" +#include "chrome/browser/flags/android/chrome_feature_list.h" +#include "chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "components/ntp_tiles/constants.h" +#include "url/android/gurl_android.h" +#include "url/url_constants.h" + +// Must come after all headers that specialize FromJniType() / ToJniType(). +#include "chrome/browser/auxiliary_search/jni_headers/AuxiliarySearchTopSiteProviderBridge_jni.h" + +namespace { +// Must match Java Tab.INVALID_TAB_ID. +static constexpr int kInvalidTabId = -1; + +constexpr int kMaxNumMostVisitedSites = 4; + +// Converts the score to be an integer. Usually the score is between 0 and 1.0. +int convertSiteSuggestionScore(double score) { + return std::max(0, static_cast<int>(score * 100)); +} + +} // namespace + +AuxiliarySearchTopSiteProviderBridge::AuxiliarySearchTopSiteProviderBridge( + std::unique_ptr<ntp_tiles::MostVisitedSites> most_visited_sites) + : most_visited_sites_(std::move(most_visited_sites)) {} + +AuxiliarySearchTopSiteProviderBridge::~AuxiliarySearchTopSiteProviderBridge() = + default; + +void AuxiliarySearchTopSiteProviderBridge::SetObserverAndTrigger( + JNIEnv* env, + const base::android::JavaRef<jobject>& j_ref_obj) { + observer_ = jni_zero::ScopedJavaGlobalRef<jobject>(j_ref_obj); + + CHECK(most_visited_sites_); + most_visited_sites_->AddMostVisitedURLsObserver(this, + kMaxNumMostVisitedSites); +} + +void AuxiliarySearchTopSiteProviderBridge::Destroy(JNIEnv* env) { + RemoveObserver(); + delete this; +} + +void AuxiliarySearchTopSiteProviderBridge::GetMostVisitedSites( + JNIEnv* env) const { + CHECK(most_visited_sites_); + + most_visited_sites_->RefreshTiles(); +} + +void AuxiliarySearchTopSiteProviderBridge::RemoveObserver() { + most_visited_sites_->RemoveMostVisitedURLsObserver(this); + observer_ = nullptr; +} + +void AuxiliarySearchTopSiteProviderBridge::OnURLsAvailable( + const std::map<ntp_tiles::SectionType, ntp_tiles::NTPTilesVector>& + sections) { + CHECK(most_visited_sites_); + + JNIEnv* env = base::android::AttachCurrentThread(); + std::vector<jni_zero::ScopedJavaLocalRef<jobject>> entries; + // Uses only personalized tiles for auxiliary search. + auto it = sections.find(ntp_tiles::SectionType::PERSONALIZED); + if (it == sections.end()) { + return; + } + + for (const ntp_tiles::NTPTile& tile : it->second) { + // Filters the tile list to include only TOP_SITES and CUSTOM_LINKS tiles. + if (tile.source != ntp_tiles::TileSource::TOP_SITES && + tile.source != ntp_tiles::TileSource::CUSTOM_LINKS) { + continue; + } + + entries.push_back(Java_AuxiliarySearchTopSiteProviderBridge_addDataEntry( + env, static_cast<int>(AuxiliarySearchEntryType::kTopSite), + url::GURLAndroid::FromNativeGURL(env, tile.url), + base::android::ConvertUTF16ToJavaString(env, tile.title), + tile.last_visit_time.InMillisecondsSinceUnixEpoch(), kInvalidTabId, + /* appId= */ nullptr, + std::abs(static_cast<int>( + base::Hash(tile.url.spec() + base::UTF16ToUTF8(tile.title)))), + convertSiteSuggestionScore(tile.score))); + } + + Java_AuxiliarySearchTopSiteProviderBridge_onMostVisitedSitesURLsAvailable( + env, observer_, entries); +} + +void AuxiliarySearchTopSiteProviderBridge::OnIconMadeAvailable( + const GURL& site_url) { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_AuxiliarySearchTopSiteProviderBridge_onIconMadeAvailable(env, observer_, + site_url); +} + +static jlong JNI_AuxiliarySearchTopSiteProviderBridge_Init( + JNIEnv* env, + const jni_zero::JavaParamRef<jobject>& obj, + Profile* profile) { + DCHECK(profile); + + return reinterpret_cast<intptr_t>(new AuxiliarySearchTopSiteProviderBridge( + ChromeMostVisitedSitesFactory::NewForProfile(profile))); +}
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge.h b/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge.h new file mode 100644 index 0000000..071c78a --- /dev/null +++ b/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge.h
@@ -0,0 +1,59 @@ +// 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_AUXILIARY_SEARCH_AUXILIARY_SEARCH_TOP_SITE_PROVIDER_BRIDGE_H_ +#define CHROME_BROWSER_AUXILIARY_SEARCH_AUXILIARY_SEARCH_TOP_SITE_PROVIDER_BRIDGE_H_ + +#include <jni.h> + +#include <memory> + +#include "base/android/scoped_java_ref.h" +#include "components/ntp_tiles/most_visited_sites.h" +#include "components/ntp_tiles/ntp_tile.h" + +// AuxiliarySearchTopSiteProviderBridge is responsible for providing top sites +// information for the auxiliary search. +class AuxiliarySearchTopSiteProviderBridge + : public ntp_tiles::MostVisitedSites::Observer { + public: + explicit AuxiliarySearchTopSiteProviderBridge( + std::unique_ptr<ntp_tiles::MostVisitedSites>); + + AuxiliarySearchTopSiteProviderBridge( + const AuxiliarySearchTopSiteProviderBridge&) = delete; + AuxiliarySearchTopSiteProviderBridge& operator=( + const AuxiliarySearchTopSiteProviderBridge&) = delete; + + ~AuxiliarySearchTopSiteProviderBridge() override; + + // Sets an observer and immediately fetches the current most visited sites + // suggestions. + void SetObserverAndTrigger(JNIEnv* env, + const base::android::JavaRef<jobject>& j_ref_obj); + + // Removes the observer and destroys the bridge. + void Destroy(JNIEnv* env); + + // Starts a fetch of the current most visited sites suggestions. + void GetMostVisitedSites(JNIEnv* env) const; + + private: + FRIEND_TEST_ALL_PREFIXES(AuxiliarySearchTopSiteProviderBridgeTest, + AddAndRemoveObservers); + + void RemoveObserver(); + + // ntp_tiles::MostVisitedSites::Observer implementation. + void OnURLsAvailable( + const std::map<ntp_tiles::SectionType, ntp_tiles::NTPTilesVector>& + sections) override; + void OnIconMadeAvailable(const GURL& site_url) override; + + jni_zero::ScopedJavaGlobalRef<jobject> observer_; + + std::unique_ptr<ntp_tiles::MostVisitedSites> most_visited_sites_; +}; + +#endif // CHROME_BROWSER_AUXILIARY_SEARCH_AUXILIARY_SEARCH_TOP_SITE_PROVIDER_BRIDGE_H_
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge_unittest.cc b/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge_unittest.cc new file mode 100644 index 0000000..8d10fca7 --- /dev/null +++ b/chrome/browser/auxiliary_search/auxiliary_search_top_site_provider_bridge_unittest.cc
@@ -0,0 +1,85 @@ +// 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/auxiliary_search/auxiliary_search_top_site_provider_bridge.h" + +#include <memory> + +#include "components/ntp_tiles/icon_cacher.h" +#include "components/ntp_tiles/most_visited_sites.h" +#include "components/prefs/testing_pref_service.h" +#include "components/visited_url_ranking/public/testing/mock_visited_url_ranking_service.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +constexpr size_t kMaxNumMostVisitedSites = 4; +} // namespace + +class MockMostVisitedSites : public ntp_tiles::MostVisitedSites { + public: + explicit MockMostVisitedSites(PrefService* prefs) + : ntp_tiles::MostVisitedSites(prefs, + /*identity_manager*/ nullptr, + /*supervised_user_service*/ nullptr, + /*top_sites*/ nullptr, + /*popular_sites*/ nullptr, + /*custom_links*/ nullptr, + /*icon_cacher*/ nullptr, + /*is_default_chrome_app_migrated*/ true, + /*is_custom_links_mixable*/ false) {} + + MockMostVisitedSites(const MockMostVisitedSites&) = delete; + MockMostVisitedSites& operator=(const MockMostVisitedSites&) = delete; + + ~MockMostVisitedSites() override = default; + + MOCK_METHOD2(AddMostVisitedURLsObserver, + void(Observer* observer, size_t max_num_sites)); + MOCK_METHOD1(RemoveMostVisitedURLsObserver, void(Observer* observer)); +}; + +// Unit tests for AuxiliarySearchTopSiteProviderBridge. +class AuxiliarySearchTopSiteProviderBridgeTest : public ::testing::Test { + public: + AuxiliarySearchTopSiteProviderBridgeTest() { + auto mock_most_visited_sites = + std::make_unique<MockMostVisitedSites>(&testing_prefs_); + auxiliary_search_top_site_provider_bridge_ = + std::make_unique<AuxiliarySearchTopSiteProviderBridge>( + std::move(mock_most_visited_sites)); + } + + AuxiliarySearchTopSiteProviderBridgeTest( + const AuxiliarySearchTopSiteProviderBridgeTest&) = delete; + AuxiliarySearchTopSiteProviderBridgeTest& operator=( + const AuxiliarySearchTopSiteProviderBridgeTest&) = delete; + + protected: + TestingPrefServiceSimple testing_prefs_; + std::unique_ptr<AuxiliarySearchTopSiteProviderBridge> + auxiliary_search_top_site_provider_bridge_; +}; + +TEST_F(AuxiliarySearchTopSiteProviderBridgeTest, AddAndRemoveObservers) { + auto j_ref = base::android::JavaRef<jobject>(); + MockMostVisitedSites* mock_most_visited_sites = + static_cast<MockMostVisitedSites*>( + auxiliary_search_top_site_provider_bridge_->most_visited_sites_ + .get()); + + // Verifies to start observing most visited sites when the first observer is + // added. + EXPECT_CALL(*mock_most_visited_sites, + AddMostVisitedURLsObserver(testing::_, kMaxNumMostVisitedSites)) + .Times(1); + auxiliary_search_top_site_provider_bridge_->SetObserverAndTrigger(nullptr, + j_ref); + + // Verifies stop observing most visited sites after destroy. + EXPECT_CALL(*mock_most_visited_sites, + RemoveMostVisitedURLsObserver(testing::_)) + .Times(1); + auxiliary_search_top_site_provider_bridge_->RemoveObserver(); +}
diff --git a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridge.java b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridge.java index c9a6af1..46d038c 100644 --- a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridge.java +++ b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridge.java
@@ -15,11 +15,9 @@ import org.chromium.base.task.TaskTraits; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.chrome.browser.auxiliary_search.AuxiliarySearchProvider.Observer; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.url.GURL; import java.util.ArrayList; import java.util.List; @@ -28,8 +26,6 @@ @NullMarked public class AuxiliarySearchBridge { private long mNativeBridge; - private @Nullable Observer mObserver; - private int mObserverId; /** * Constructs a bridge for the auxiliary search provider. @@ -95,36 +91,6 @@ } /** - * Assigns {@link #mObserver}, possibly to null. If non-null {@param observer} is passed, - * requires {@link #mObserver} initially null, then fetches the current most visited site - * suggestions. - * - * @param observer The observer to receive suggestions when they are ready. - */ - public void setObserver(@Nullable Observer observer) { - if (observer == null) { - mObserver = null; - AuxiliarySearchBridgeJni.get().removeObserver(mNativeBridge, mObserverId); - return; - } - - mObserver = observer; - mObserverId = AuxiliarySearchBridgeJni.get().setObserverAndTrigger(mNativeBridge, this); - } - - /** Starts a fetch of the current most visited sites suggestions. */ - public void getMostVisitedSites() { - if (mNativeBridge == 0) { - if (mObserver != null) { - mObserver.onSiteSuggestionsAvailable(null); - } - return; - } - - AuxiliarySearchBridgeJni.get().getMostVisitedSites(mNativeBridge); - } - - /** * Helper to call previously injected callback to pass suggestion results. * * @param entries The list of fetched entries. @@ -138,43 +104,6 @@ callback.onResult(entries); } - @CalledByNative - @VisibleForTesting - static AuxiliarySearchDataEntry addDataEntry( - @AuxiliarySearchEntryType int type, - GURL url, - String title, - long lastActiveTime, - int tabId, - @Nullable String appId, - int visitId, - int score) { - return new AuxiliarySearchDataEntry( - type, url, title, lastActiveTime, tabId, appId, visitId, score); - } - - @CalledByNative - @VisibleForTesting - void onMostVisitedSitesURLsAvailable( - @JniType("std::vector") List<AuxiliarySearchDataEntry> entries) { - if (mObserver == null) return; - mObserver.onSiteSuggestionsAvailable(entries); - } - - @CalledByNative - void onIconMadeAvailable(@JniType("GURL") GURL siteUrl) { - if (mObserver == null) return; - mObserver.onIconMadeAvailable(siteUrl); - } - - @Nullable Observer getObserverForTesting() { - return mObserver; - } - - int getObserverIdForTesting() { - return mObserverId; - } - @NativeMethods @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public interface Natives { @@ -186,11 +115,5 @@ void getNonSensitiveHistoryData( long nativeAuxiliarySearchProvider, Callback<@Nullable List<AuxiliarySearchDataEntry>> callback); - - int setObserverAndTrigger(long nativeAuxiliarySearchProvider, AuxiliarySearchBridge self); - - void removeObserver(long nativeAuxiliarySearchProvider, int id); - - void getMostVisitedSites(long nativeAuxiliarySearchProvider); } }
diff --git a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchControllerImpl.java b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchControllerImpl.java index 6bae180..05352b5d 100644 --- a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchControllerImpl.java +++ b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchControllerImpl.java
@@ -37,9 +37,9 @@ AuxiliarySearchConfigManager.ShareTabsWithOsStateListener { protected final @AuxiliarySearchHostType int mHostType; protected final AuxiliarySearchProvider mAuxiliarySearchProvider; + protected final Profile mProfile; private final Context mContext; - private final Profile mProfile; private final FaviconHelper mFaviconHelper; private final AuxiliarySearchDonor mDonor; private final boolean mIsFaviconEnabled;
diff --git a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImpl.java b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImpl.java index 1a939a5..1dbaf0c 100644 --- a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImpl.java +++ b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImpl.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.auxiliary_search; +import static org.chromium.build.NullUtil.assumeNonNull; import static org.chromium.chrome.browser.flags.ChromeFeatureList.sAndroidAppIntegrationMultiDataSourceHistoryContentTtlHours; import android.content.Context; @@ -31,7 +32,7 @@ */ @NullMarked public class AuxiliarySearchMultiDataControllerImpl extends AuxiliarySearchControllerImpl - implements AuxiliarySearchProvider.Observer { + implements AuxiliarySearchTopSiteProviderBridge.Observer { private final long mHistoryTtlMillis; // Whether this controller is observing most visited sites. @@ -46,6 +47,8 @@ // A set of ActivityLifecycleDispatcher that this controller tracks. private Set<ActivityLifecycleDispatcher> mActivityLifecycleDispatcherSet; + // It is null when the controller doesn't observe top sites changes. + private @Nullable AuxiliarySearchTopSiteProviderBridge mAuxiliarySearchTopSiteProviderBridge; private @Nullable List<AuxiliarySearchDataEntry> mCurrentSiteSuggestionEntries; /** @@ -62,7 +65,8 @@ context, profile, /* tabModelSelector= */ null, hostType), AuxiliarySearchDonor.getInstance(), new FaviconHelper(), - hostType); + hostType, + new AuxiliarySearchTopSiteProviderBridge(profile)); } @VisibleForTesting @@ -72,7 +76,8 @@ AuxiliarySearchProvider auxiliarySearchProvider, AuxiliarySearchDonor auxiliarySearchDonor, FaviconHelper faviconHelper, - @AuxiliarySearchHostType int hostType) { + @AuxiliarySearchHostType int hostType, + AuxiliarySearchTopSiteProviderBridge auxiliarySearchTopSiteProviderBridge) { super( context, profile, @@ -81,6 +86,7 @@ faviconHelper, hostType); + mAuxiliarySearchTopSiteProviderBridge = auxiliarySearchTopSiteProviderBridge; mExpectDonating = true; mHistoryTtlMillis = TimeUnit.HOURS.toMillis( @@ -129,7 +135,11 @@ public void onDeferredStartup() { if (mHostType == AuxiliarySearchHostType.CTA && !mIsObservingTopSites) { mIsObservingTopSites = true; - mAuxiliarySearchProvider.setObserver(this); + if (mAuxiliarySearchTopSiteProviderBridge == null) { + mAuxiliarySearchTopSiteProviderBridge = + new AuxiliarySearchTopSiteProviderBridge(mProfile); + } + mAuxiliarySearchTopSiteProviderBridge.setObserver(this); } } @@ -142,7 +152,9 @@ if (mActivityLifecycleDispatcherSet.isEmpty()) { if (mIsObservingTopSites) { - mAuxiliarySearchProvider.setObserver(null); + assumeNonNull(mAuxiliarySearchTopSiteProviderBridge); + mAuxiliarySearchTopSiteProviderBridge.destroy(); + mAuxiliarySearchTopSiteProviderBridge = null; mIsObservingTopSites = false; } } @@ -227,4 +239,9 @@ boolean getExpectDonatingForTesting() { return mExpectDonating; } + + @Nullable + AuxiliarySearchTopSiteProviderBridge getAuxiliarySearchTopSiteProviderBridgeForTesting() { + return mAuxiliarySearchTopSiteProviderBridge; + } }
diff --git a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java index 392c9d7..a14456f 100644 --- a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java +++ b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProvider.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.auxiliary_search; -import static org.chromium.build.NullUtil.assertNonNull; - import android.content.Context; import android.os.PersistableBundle; import android.text.TextUtils; @@ -56,20 +54,6 @@ int NUM_ENTRIES = 2; } - /** An interface to handle events in {@link MostVisitedSites}. */ - interface Observer { - /** This is called when the list of most visited URLs is initially available or updated. */ - void onSiteSuggestionsAvailable(@Nullable List<AuxiliarySearchDataEntry> entries); - - /** - * This is called when a previously uncached icon has been fetched. Parameters guaranteed to - * be non-null. - * - * @param siteUrl URL of site with newly-cached icon. - */ - void onIconMadeAvailable(GURL siteUrl); - } - /* Only donate the recent 7 days accessed tabs.*/ @VisibleForTesting static final String TAB_AGE_HOURS_PARAM = "tabs_max_hours"; @VisibleForTesting static final String TASK_CREATED_TIME = "TaskCreatedTime"; @@ -141,15 +125,6 @@ mAuxiliarySearchBridge.getNonSensitiveHistoryData(callback); } - /** - * Sets an observer and immediately fetches the current most visited sites suggestions. - * - * @param observer The observer to receive suggestions when they are ready. - */ - public void setObserver(@Nullable Observer observer) { - assertNonNull(mAuxiliarySearchBridge).setObserver(observer); - } - @VisibleForTesting static @Nullable AuxiliarySearchEntry createAuxiliarySearchEntry( int id, String title, String url, long timestamp) {
diff --git a/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridge.java b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridge.java new file mode 100644 index 0000000..80044680 --- /dev/null +++ b/chrome/browser/auxiliary_search/java/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridge.java
@@ -0,0 +1,134 @@ +// 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.auxiliary_search; + +import androidx.annotation.VisibleForTesting; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JniType; +import org.jni_zero.NativeMethods; + +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.url.GURL; + +import java.util.List; + +/** Java bridge to provide information of top sites for the auxiliary search. */ +@NullMarked +public class AuxiliarySearchTopSiteProviderBridge { + /** An interface to handle events in {@link MostVisitedSites}. */ + interface Observer { + /** This is called when the list of most visited URLs is initially available or updated. */ + void onSiteSuggestionsAvailable(@Nullable List<AuxiliarySearchDataEntry> entries); + + /** + * This is called when a previously uncached icon has been fetched. Parameters guaranteed to + * be non-null. + * + * @param siteUrl URL of site with newly-cached icon. + */ + void onIconMadeAvailable(GURL siteUrl); + } + + private long mNativeBridge; + private @Nullable Observer mObserver; + + /** + * Constructs a bridge for the auxiliary search top sites provider. + * + * @param profile The Profile to retrieve the corresponding information. + */ + public AuxiliarySearchTopSiteProviderBridge(Profile profile) { + if ((!ChromeFeatureList.sAndroidAppIntegration.isEnabled() + && !ChromeFeatureList.sAndroidAppIntegrationV2.isEnabled()) + || profile.isOffTheRecord()) { + mNativeBridge = 0; + } else { + mNativeBridge = AuxiliarySearchTopSiteProviderBridgeJni.get().init(this, profile); + } + } + + /** + * Assigns {@link #mObserver}. Requires {@link #mObserver} initially null, then fetches the + * current most visited site suggestions. + * + * @param observer The observer to receive suggestions when they are ready. + */ + public void setObserver(Observer observer) { + assert mNativeBridge != 0; + + mObserver = observer; + AuxiliarySearchTopSiteProviderBridgeJni.get().setObserverAndTrigger(mNativeBridge, this); + } + + /** Destroys the native bridge and remove observer. */ + public void destroy() { + AuxiliarySearchTopSiteProviderBridgeJni.get().destroy(mNativeBridge); + mObserver = null; + mNativeBridge = 0; + } + + /** Starts a fetch of the current most visited sites suggestions. */ + public void getMostVisitedSites() { + if (mNativeBridge == 0) { + if (mObserver != null) { + mObserver.onSiteSuggestionsAvailable(null); + } + return; + } + + AuxiliarySearchTopSiteProviderBridgeJni.get().getMostVisitedSites(mNativeBridge); + } + + @CalledByNative + @VisibleForTesting + static AuxiliarySearchDataEntry addDataEntry( + @AuxiliarySearchEntryType int type, + GURL url, + String title, + long lastActiveTime, + int tabId, + @Nullable String appId, + int visitId, + int score) { + return new AuxiliarySearchDataEntry( + type, url, title, lastActiveTime, tabId, appId, visitId, score); + } + + @CalledByNative + @VisibleForTesting + void onMostVisitedSitesURLsAvailable( + @JniType("std::vector") List<AuxiliarySearchDataEntry> entries) { + if (mObserver == null) return; + mObserver.onSiteSuggestionsAvailable(entries); + } + + @CalledByNative + void onIconMadeAvailable(@JniType("GURL") GURL siteUrl) { + if (mObserver == null) return; + mObserver.onIconMadeAvailable(siteUrl); + } + + @Nullable Observer getObserverForTesting() { + return mObserver; + } + + @NativeMethods + @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) + public interface Natives { + long init(AuxiliarySearchTopSiteProviderBridge self, @JniType("Profile*") Profile profile); + + void setObserverAndTrigger( + long nativeAuxiliarySearchTopSiteProviderBridge, + AuxiliarySearchTopSiteProviderBridge self); + + void destroy(long nativeAuxiliarySearchTopSiteProviderBridge); + + void getMostVisitedSites(long nativeAuxiliarySearchTopSiteProviderBridge); + } +}
diff --git a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridgeUnitTest.java b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridgeUnitTest.java index 27db9ee9..ffff039b 100644 --- a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridgeUnitTest.java +++ b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchBridgeUnitTest.java
@@ -6,7 +6,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -23,7 +22,6 @@ 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.annotation.Config; @@ -37,7 +35,6 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; import java.util.ArrayList; @@ -147,54 +144,6 @@ .getNonSensitiveHistoryData(eq(NATIVE_BRIDGE), eq(callback)); } - @Test - @SmallTest - public void testSetObserver() { - AuxiliarySearchProvider.Observer observer = mock(AuxiliarySearchProvider.Observer.class); - - int id = 100; - when(mMockAuxiliarySearchBridgeJni.setObserverAndTrigger(eq(NATIVE_BRIDGE), eq(mBridge))) - .thenReturn(id); - mBridge.setObserver(observer); - assertEquals(observer, mBridge.getObserverForTesting()); - assertEquals(id, mBridge.getObserverIdForTesting()); - verify(mMockAuxiliarySearchBridgeJni).setObserverAndTrigger(eq(NATIVE_BRIDGE), eq(mBridge)); - - Mockito.reset(mMockAuxiliarySearchBridgeJni); - mBridge.setObserver(null); - verify(mMockAuxiliarySearchBridgeJni).removeObserver(eq(NATIVE_BRIDGE), eq(id)); - assertNull(mBridge.getObserverForTesting()); - } - - @Test - @SmallTest - public void testGetMostVisitedSites() { - mBridge.getMostVisitedSites(); - verify(mMockAuxiliarySearchBridgeJni).getMostVisitedSites(eq(NATIVE_BRIDGE)); - } - - @Test - @SmallTest - public void testOnMostVisitedSitesURLsAvailable() { - AuxiliarySearchProvider.Observer observer = mock(AuxiliarySearchProvider.Observer.class); - mBridge.setObserver(observer); - - List<AuxiliarySearchDataEntry> entryList = createEntryList(); - mBridge.onMostVisitedSitesURLsAvailable(entryList); - verify(observer).onSiteSuggestionsAvailable(eq(entryList)); - } - - @Test - @SmallTest - public void testOnIconMadeAvailable() { - AuxiliarySearchProvider.Observer observer = mock(AuxiliarySearchProvider.Observer.class); - mBridge.setObserver(observer); - - GURL url = JUnitTestGURLs.URL_1; - mBridge.onIconMadeAvailable(url); - verify(observer).onIconMadeAvailable(eq(url)); - } - List<AuxiliarySearchDataEntry> createEntryList() { List<AuxiliarySearchDataEntry> entryList = new ArrayList<>();
diff --git a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchControllerFactoryUnitTest.java b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchControllerFactoryUnitTest.java index eeba8bf9..4b43ab0 100644 --- a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchControllerFactoryUnitTest.java +++ b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchControllerFactoryUnitTest.java
@@ -45,6 +45,11 @@ @Mock private Profile mProfile; @Mock private TabModelSelector mTabModelSelector; @Mock private AuxiliarySearchBridge.Natives mMockAuxiliarySearchBridgeJni; + + @Mock + private AuxiliarySearchTopSiteProviderBridge.Natives + mMockAuxiliarySearchTopSiteProviderBridgeJni; + @Mock private FaviconHelper.Natives mMockFaviconHelperJni; @Mock private AuxiliarySearchHooks mHooks; @@ -56,6 +61,8 @@ when(mContext.getResources()).thenReturn(mResources); AuxiliarySearchBridgeJni.setInstanceForTesting(mMockAuxiliarySearchBridgeJni); + AuxiliarySearchTopSiteProviderBridgeJni.setInstanceForTesting( + mMockAuxiliarySearchTopSiteProviderBridgeJni); when(mMockFaviconHelperJni.init()).thenReturn(1L); FaviconHelperJni.setInstanceForTesting(mMockFaviconHelperJni); AuxiliarySearchDonor.setSkipInitializationForTesting(true);
diff --git a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImplUnitTest.java b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImplUnitTest.java index f8c098c..ed54b1a 100644 --- a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImplUnitTest.java +++ b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchMultiDataControllerImplUnitTest.java
@@ -66,6 +66,7 @@ @Mock private FaviconHelper mFaviconHelper; @Mock private ActivityLifecycleDispatcher mActivityLifecycleDispatcher; @Mock private AuxiliarySearchHooks mHooks; + @Mock private AuxiliarySearchTopSiteProviderBridge mAuxiliarySearchTopSiteProviderBridge; @Captor private ArgumentCaptor<Callback<List<AuxiliarySearchDataEntry>>> mEntryReadyCallbackCaptor; @@ -216,12 +217,13 @@ @Test public void testOnDeferredStartup() { mAuxiliarySearchMultiDataControllerImpl.onDeferredStartup(); - verify(mAuxiliarySearchProvider).setObserver(eq(mAuxiliarySearchMultiDataControllerImpl)); - - Mockito.reset(mAuxiliarySearchProvider); - mAuxiliarySearchMultiDataControllerImpl.onDeferredStartup(); - verify(mAuxiliarySearchProvider, never()) + verify(mAuxiliarySearchTopSiteProviderBridge) .setObserver(eq(mAuxiliarySearchMultiDataControllerImpl)); + + Mockito.reset(mAuxiliarySearchTopSiteProviderBridge); + mAuxiliarySearchMultiDataControllerImpl.onDeferredStartup(); + verify(mAuxiliarySearchTopSiteProviderBridge, never()) + .setObserver(any(AuxiliarySearchTopSiteProviderBridge.Observer.class)); } @Test @@ -236,11 +238,19 @@ @Test public void testOnDestroy() { mAuxiliarySearchMultiDataControllerImpl.onDeferredStartup(); - verify(mAuxiliarySearchProvider).setObserver(eq(mAuxiliarySearchMultiDataControllerImpl)); + assertEquals( + mAuxiliarySearchTopSiteProviderBridge, + mAuxiliarySearchMultiDataControllerImpl + .getAuxiliarySearchTopSiteProviderBridgeForTesting()); + verify(mAuxiliarySearchTopSiteProviderBridge) + .setObserver(eq(mAuxiliarySearchMultiDataControllerImpl)); mAuxiliarySearchMultiDataControllerImpl.destroy(mActivityLifecycleDispatcher); verify(mActivityLifecycleDispatcher).unregister(mAuxiliarySearchMultiDataControllerImpl); - verify(mAuxiliarySearchProvider).setObserver(eq(null)); + verify(mAuxiliarySearchTopSiteProviderBridge).destroy(); + assertNull( + mAuxiliarySearchMultiDataControllerImpl + .getAuxiliarySearchTopSiteProviderBridgeForTesting()); } @Test @@ -249,17 +259,18 @@ mAuxiliarySearchMultiDataControllerImpl.register(mActivityLifecycleDispatcher); mAuxiliarySearchMultiDataControllerImpl.register(dispatcher); mAuxiliarySearchMultiDataControllerImpl.onDeferredStartup(); - verify(mAuxiliarySearchProvider).setObserver(eq(mAuxiliarySearchMultiDataControllerImpl)); + verify(mAuxiliarySearchTopSiteProviderBridge) + .setObserver(eq(mAuxiliarySearchMultiDataControllerImpl)); - // Verifies that the controller doesn't stop observing most visited sites when there is - // reference to it. + // Verifies that the controller doesn't destroy the native bridge when there is reference + // to it. mAuxiliarySearchMultiDataControllerImpl.destroy(dispatcher); - verify(mAuxiliarySearchProvider, never()).setObserver(eq(null)); + verify(mAuxiliarySearchTopSiteProviderBridge, never()).destroy(); - // Verifies that the controller will stop observing most visited sites when there isn't any + // Verifies that the controller will destroy the native bridge when there isn't any // reference to it. mAuxiliarySearchMultiDataControllerImpl.destroy(mActivityLifecycleDispatcher); - verify(mAuxiliarySearchProvider).setObserver(eq(null)); + verify(mAuxiliarySearchTopSiteProviderBridge).destroy(); } private void createController() { @@ -270,7 +281,8 @@ mAuxiliarySearchProvider, mAuxiliarySearchDonor, mFaviconHelper, - AuxiliarySearchController.AuxiliarySearchHostType.CTA); + AuxiliarySearchController.AuxiliarySearchHostType.CTA, + mAuxiliarySearchTopSiteProviderBridge); assertTrue(mAuxiliarySearchMultiDataControllerImpl.getExpectDonatingForTesting()); mAuxiliarySearchMultiDataControllerImpl.register(mActivityLifecycleDispatcher); }
diff --git a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProviderUnitTest.java b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProviderUnitTest.java index 2a3d157..3b5c74b 100644 --- a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProviderUnitTest.java +++ b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchProviderUnitTest.java
@@ -10,11 +10,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -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.verify; import static org.mockito.Mockito.when; import android.content.Context; @@ -294,16 +290,6 @@ @Test @SmallTest - public void testSetObserver() { - AuxiliarySearchProvider.Observer observer = mock(AuxiliarySearchProvider.Observer.class); - mAuxiliarySearchProvider.setObserver(observer); - - verify(mMockAuxiliarySearchBridgeJni) - .setObserverAndTrigger(eq(FAKE_NATIVE_PROVIDER), any(AuxiliarySearchBridge.class)); - } - - @Test - @SmallTest public void testCreationViaCTABackgroundTask() { mAuxiliarySearchProvider = new AuxiliarySearchProvider(
diff --git a/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridgeUnitTest.java b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridgeUnitTest.java new file mode 100644 index 0000000..d5658b2 --- /dev/null +++ b/chrome/browser/auxiliary_search/junit/src/org/chromium/chrome/browser/auxiliary_search/AuxiliarySearchTopSiteProviderBridgeUnitTest.java
@@ -0,0 +1,120 @@ +// 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.auxiliary_search; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +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.annotation.Config; + +import org.chromium.base.TimeUtils; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Features; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.url.GURL; +import org.chromium.url.JUnitTestGURLs; + +import java.util.List; + +/** Unit tests for {@link AuxiliarySearchTopSiteProviderBridge} */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +@Features.EnableFeatures({ChromeFeatureList.ANDROID_APP_INTEGRATION}) +public class AuxiliarySearchTopSiteProviderBridgeUnitTest { + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + // Arbitrary non-0 value. + private static final long NATIVE_BRIDGE = 10L; + + @Mock + private AuxiliarySearchTopSiteProviderBridge.Natives + mMockAuxiliarySearchTopSiteProviderBridgeJni; + + @Mock private Profile mProfile; + + private AuxiliarySearchTopSiteProviderBridge mBridge; + + @Before + public void setUp() { + when(mProfile.isOffTheRecord()).thenReturn(false); + AuxiliarySearchTopSiteProviderBridgeJni.setInstanceForTesting( + mMockAuxiliarySearchTopSiteProviderBridgeJni); + when(mMockAuxiliarySearchTopSiteProviderBridgeJni.init(any(), eq(mProfile))) + .thenReturn(NATIVE_BRIDGE); + + mBridge = new AuxiliarySearchTopSiteProviderBridge(mProfile); + assertNotNull(mBridge); + } + + @Test + public void testSetObserver() { + AuxiliarySearchTopSiteProviderBridge.Observer observer = + mock(AuxiliarySearchTopSiteProviderBridge.Observer.class); + + mBridge.setObserver(observer); + assertEquals(observer, mBridge.getObserverForTesting()); + verify(mMockAuxiliarySearchTopSiteProviderBridgeJni) + .setObserverAndTrigger(eq(NATIVE_BRIDGE), eq(mBridge)); + } + + @Test + public void testDestroy() { + AuxiliarySearchTopSiteProviderBridge.Observer observer = + mock(AuxiliarySearchTopSiteProviderBridge.Observer.class); + + mBridge.setObserver(observer); + assertNotNull(mBridge.getObserverForTesting()); + + Mockito.reset(mMockAuxiliarySearchTopSiteProviderBridgeJni); + mBridge.destroy(); + verify(mMockAuxiliarySearchTopSiteProviderBridgeJni).destroy(eq(NATIVE_BRIDGE)); + assertNull(mBridge.getObserverForTesting()); + } + + @Test + public void testGetMostVisitedSites() { + mBridge.getMostVisitedSites(); + verify(mMockAuxiliarySearchTopSiteProviderBridgeJni).getMostVisitedSites(eq(NATIVE_BRIDGE)); + } + + @Test + public void testOnMostVisitedSitesURLsAvailable() { + AuxiliarySearchTopSiteProviderBridge.Observer observer = + mock(AuxiliarySearchTopSiteProviderBridge.Observer.class); + mBridge.setObserver(observer); + + List<AuxiliarySearchDataEntry> entryList = + AuxiliarySearchTestHelper.createAuxiliarySearchDataEntries_TopSite( + TimeUtils.uptimeMillis()); + mBridge.onMostVisitedSitesURLsAvailable(entryList); + verify(observer).onSiteSuggestionsAvailable(eq(entryList)); + } + + @Test + public void testOnIconMadeAvailable() { + AuxiliarySearchTopSiteProviderBridge.Observer observer = + mock(AuxiliarySearchTopSiteProviderBridge.Observer.class); + mBridge.setObserver(observer); + + GURL url = JUnitTestGURLs.URL_1; + mBridge.onIconMadeAvailable(url); + verify(observer).onIconMadeAvailable(eq(url)); + } +}
diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarButton.java b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarButton.java index 44282d64..61d85795 100644 --- a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarButton.java +++ b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarButton.java
@@ -25,8 +25,7 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.bookmarks.R; - -import java.util.function.IntConsumer; +import org.chromium.ui.util.ClickWithMetaStateCallback; /** * View for a button in the bookmark bar which provides users with bookmark access from top chrome. @@ -78,8 +77,9 @@ * * @param callback the callback to notify. */ - public void setClickCallback(@Nullable IntConsumer callback) { - setOnClickListener(callback != null ? (v) -> callback.accept(mLastEventMetaState) : null); + public void setClickCallback(@Nullable ClickWithMetaStateCallback callback) { + setOnClickListener( + callback != null ? (v) -> callback.onClickWithMeta(mLastEventMetaState) : null); } /**
diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarButtonProperties.java b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarButtonProperties.java index d4254ee..c8aa61c 100644 --- a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarButtonProperties.java +++ b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarButtonProperties.java
@@ -11,8 +11,7 @@ import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; - -import java.util.function.IntConsumer; +import org.chromium.ui.util.ClickWithMetaStateCallback; /** * Properties for a button in the bookmark bar which provides users with bookmark access from top @@ -25,7 +24,7 @@ * The callback to notify of bookmark bar button click events. The callback is provided the meta * state of the most recent key/touch event. */ - public static final WritableObjectPropertyKey<IntConsumer> CLICK_CALLBACK = + public static final WritableObjectPropertyKey<ClickWithMetaStateCallback> CLICK_CALLBACK = new WritableObjectPropertyKey<>(); /** The supplier for the icon to render in the bookmark bar button. */
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 17918fb7..0a2664d 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -5395,8 +5395,7 @@ } } -std::vector<std::unique_ptr<content::NavigationThrottle>> -ChromeContentBrowserClient::CreateThrottlesForNavigation( +void ChromeContentBrowserClient::CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) { // MetricsNavigationThrottle requires that it runs before NavigationThrottles // that may delay or cancel navigations, so only NavigationThrottles that @@ -5767,8 +5766,6 @@ registry.MaybeAddThrottle( web_app::IsolatedWebAppThrottle::MaybeCreateThrottleFor(&handle)); #endif // !BUILDFLAG(IS_ANDROID) - - return {}; } std::vector<std::unique_ptr<content::CommitDeferringCondition>>
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 48fd2e3..4d28838 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -635,8 +635,7 @@ content::WebContents* web_contents) override; void RemovePresentationObserver(content::PresentationObserver* observer, content::WebContents* web_contents) override; - std::vector<std::unique_ptr<content::NavigationThrottle>> - CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override; std::vector<std::unique_ptr<content::CommitDeferringCondition>> CreateCommitDeferringConditionsForNavigation(
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 d30694e8..bf3a198 100644 --- a/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc +++ b/chrome/browser/chromeos/app_mode/kiosk_browser_session_unittest.cc
@@ -55,9 +55,9 @@ #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/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/policy/core/common/device_local_account_type.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h" #include "content/public/common/webplugininfo.h"
diff --git a/chrome/browser/collaboration/BUILD.gn b/chrome/browser/collaboration/BUILD.gn index 3ddeefe6..c9e3511 100644 --- a/chrome/browser/collaboration/BUILD.gn +++ b/chrome/browser/collaboration/BUILD.gn
@@ -23,6 +23,8 @@ "//chrome/browser/settings:factory_java", "//chrome/browser/signin/services/android:java", "//chrome/browser/tab_group_sync:factory_java", + "//chrome/browser/tab_ui/android:java", + "//chrome/browser/tabmodel:java", "//chrome/browser/ui/android/signin:java", "//chrome/browser/ui/android/strings:ui_strings_grd", "//components/browser_ui/settings/android:java",
diff --git a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java index 9e6d902..6c536e8 100644 --- a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java +++ b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImpl.java
@@ -8,6 +8,7 @@ import android.app.Activity; import android.content.Intent; +import android.text.TextUtils; import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; @@ -22,6 +23,9 @@ import org.chromium.chrome.browser.settings.SettingsNavigationFactory; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninManager; +import org.chromium.chrome.browser.tab_ui.ActionConfirmationManager; +import org.chromium.chrome.browser.tab_ui.ActionConfirmationManager.MaybeBlockingResult; +import org.chromium.chrome.browser.tabmodel.TabGroupTitleUtils; import org.chromium.chrome.browser.ui.signin.BottomSheetSigninAndHistorySyncConfig; import org.chromium.chrome.browser.ui.signin.BottomSheetSigninAndHistorySyncConfig.NoAccountSigninMode; import org.chromium.chrome.browser.ui.signin.BottomSheetSigninAndHistorySyncConfig.WithAccountSigninMode; @@ -30,6 +34,7 @@ import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetStrings; import org.chromium.chrome.browser.ui.signin.history_sync.HistorySyncConfig; import org.chromium.components.browser_ui.settings.SettingsNavigation; +import org.chromium.components.browser_ui.widget.ActionConfirmationResult; import org.chromium.components.browser_ui.widget.loading.LoadingFullscreenCoordinator; import org.chromium.components.collaboration.CollaborationControllerDelegate; import org.chromium.components.collaboration.FlowType; @@ -581,6 +586,32 @@ }; } + private Callback<MaybeBlockingResult> getActionConfirmationCallback(long resultCallback) { + return (MaybeBlockingResult maybeBlockingResult) -> { + boolean accept = + maybeBlockingResult.result != ActionConfirmationResult.CONFIRMATION_NEGATIVE; + + if (maybeBlockingResult.finishBlocking != null) { + mCloseScreenRunnable = maybeBlockingResult.finishBlocking; + } + + if (accept) { + CollaborationControllerDelegateImplJni.get() + .runResultCallback(Outcome.SUCCESS, resultCallback); + } else { + CollaborationControllerDelegateImplJni.get() + .runResultCallback(Outcome.CANCEL, resultCallback); + } + }; + } + + private ActionConfirmationManager getActionConfirmationManager() { + return new ActionConfirmationManager( + assumeNonNull(mDataSharingTabManager.getProfile()), + mActivity, + assumeNonNull(mDataSharingTabManager.getWindowAndroid().getModalDialogManager())); + } + /** * Show the leave dialog screen. * @@ -590,8 +621,13 @@ */ @CalledByNative void showLeaveDialog(String syncId, LocalTabGroupId localId, long resultCallback) { - CollaborationControllerDelegateImplJni.get() - .runResultCallback(Outcome.FAILURE, resultCallback); + SavedTabGroup existingGroup = + mDataSharingTabManager.getSavedTabGroupForEitherId(syncId, localId); + + getActionConfirmationManager() + .processLeaveGroupAttempt( + getSavedTabGroupTitle(existingGroup), + getActionConfirmationCallback(resultCallback)); } /** @@ -603,8 +639,19 @@ */ @CalledByNative void showDeleteDialog(String syncId, LocalTabGroupId localId, long resultCallback) { - CollaborationControllerDelegateImplJni.get() - .runResultCallback(Outcome.FAILURE, resultCallback); + SavedTabGroup existingGroup = + mDataSharingTabManager.getSavedTabGroupForEitherId(syncId, localId); + + getActionConfirmationManager() + .processDeleteSharedGroupAttempt( + getSavedTabGroupTitle(existingGroup), + getActionConfirmationCallback(resultCallback)); + } + + private String getSavedTabGroupTitle(SavedTabGroup tabGroup) { + return TextUtils.isEmpty(tabGroup.title) + ? TabGroupTitleUtils.getDefaultTitle(mActivity, tabGroup.savedTabs.size()) + : tabGroup.title; } /**
diff --git a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java index d868501..e4e3059 100644 --- a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java +++ b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationControllerDelegateImplUnitTest.java
@@ -479,4 +479,56 @@ verify(mCollaborationControllerDelegateImplNativeMock) .runResultCallback(eq(Outcome.SUCCESS), eq(resultCallback)); } + + @Test + public void testLeaveSharedTabGroup() { + createDelegate(FlowType.LEAVE_OR_DELETE); + long resultCallback = 1; + LocalTabGroupId localId = new LocalTabGroupId(new Token(1L, 2L)); + String title = "title"; + + SavedTabGroup savedGroup = new SavedTabGroup(); + savedGroup.localId = localId; + savedGroup.title = title; + doReturn(savedGroup) + .when(mDataSharingTabManager) + .getSavedTabGroupForEitherId(null, localId); + + mCollaborationControllerDelegateImpl.showLeaveDialog(null, localId, resultCallback); + ArgumentCaptor<PropertyModel> propertyModelCaptor = + ArgumentCaptor.forClass(PropertyModel.class); + verify(mModalDialogManager).showDialog(propertyModelCaptor.capture(), anyInt()); + + ModalDialogProperties.Controller controller = + propertyModelCaptor.getValue().get(ModalDialogProperties.CONTROLLER); + controller.onClick(propertyModelCaptor.getValue(), ButtonType.NEGATIVE); + verify(mCollaborationControllerDelegateImplNativeMock) + .runResultCallback(eq(Outcome.CANCEL), eq(resultCallback)); + } + + @Test + public void testDeleteSharedTabGroup() { + createDelegate(FlowType.LEAVE_OR_DELETE); + long resultCallback = 1; + LocalTabGroupId localId = new LocalTabGroupId(new Token(1L, 2L)); + String title = "title"; + + SavedTabGroup savedGroup = new SavedTabGroup(); + savedGroup.localId = localId; + savedGroup.title = title; + doReturn(savedGroup) + .when(mDataSharingTabManager) + .getSavedTabGroupForEitherId(null, localId); + + mCollaborationControllerDelegateImpl.showLeaveDialog(null, localId, resultCallback); + ArgumentCaptor<PropertyModel> propertyModelCaptor = + ArgumentCaptor.forClass(PropertyModel.class); + verify(mModalDialogManager).showDialog(propertyModelCaptor.capture(), anyInt()); + + ModalDialogProperties.Controller controller = + propertyModelCaptor.getValue().get(ModalDialogProperties.CONTROLLER); + controller.onClick(propertyModelCaptor.getValue(), ButtonType.POSITIVE); + verify(mCollaborationControllerDelegateImplNativeMock) + .runResultCallback(eq(Outcome.SUCCESS), eq(resultCallback)); + } }
diff --git a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationServiceFactoryTest.java b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationServiceFactoryTest.java index 730238d..135789b 100644 --- a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationServiceFactoryTest.java +++ b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationServiceFactoryTest.java
@@ -28,6 +28,7 @@ import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.components.collaboration.CollaborationControllerDelegate; import org.chromium.components.collaboration.CollaborationService; +import org.chromium.components.collaboration.CollaborationServiceLeaveOrDeleteEntryPoint; import org.chromium.components.collaboration.CollaborationServiceShareOrManageEntryPoint; import org.chromium.components.collaboration.CollaborationStatus; import org.chromium.components.collaboration.ServiceStatus; @@ -67,6 +68,12 @@ @CollaborationServiceShareOrManageEntryPoint int entry) {} @Override + public void startLeaveOrDeleteFlow( + CollaborationControllerDelegate delegate, + String syncId, + @CollaborationServiceLeaveOrDeleteEntryPoint int entry) {} + + @Override public ServiceStatus getServiceStatus() { return new ServiceStatus( SigninStatus.NOT_SIGNED_IN,
diff --git a/chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.cc b/chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.cc index e282615..5638dd2 100644 --- a/chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.cc +++ b/chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.cc
@@ -11,7 +11,6 @@ #include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.h" #include "chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.h" -#include "chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h" #include "components/collaboration/public/collaboration_service.h" #include "components/data_sharing/public/data_sharing_service.h" #include "url/gurl.h"
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 97bb4be6..ec4b6904 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -1297,6 +1297,8 @@ if (glic::GlicEnabling::IsEnabledByFlags()) { (*s_allowlist)[glic::prefs::kGlicLauncherEnabled] = settings_api::PrefType::kBoolean; + (*s_allowlist)[glic::prefs::kGlicClosedCaptioningEnabled] = + settings_api::PrefType::kBoolean; (*s_allowlist)[glic::prefs::kGlicGeolocationEnabled] = settings_api::PrefType::kBoolean; (*s_allowlist)[glic::prefs::kGlicMicrophoneEnabled] =
diff --git a/chrome/browser/extensions/api/storage/managed_value_store_cache_unittest.cc b/chrome/browser/extensions/api/storage/managed_value_store_cache_unittest.cc index cdcc21d..cb1923d 100644 --- a/chrome/browser/extensions/api/storage/managed_value_store_cache_unittest.cc +++ b/chrome/browser/extensions/api/storage/managed_value_store_cache_unittest.cc
@@ -18,12 +18,15 @@ #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_utils.h" #include "extensions/browser/api/storage/backend_task_runner.h" +#include "extensions/buildflags/buildflags.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "extensions/common/extension_id.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + namespace extensions { namespace {
diff --git a/chrome/browser/extensions/api/storage/settings_apitest.cc b/chrome/browser/extensions/api/storage/settings_apitest.cc index 329ade5..9a9f3f3 100644 --- a/chrome/browser/extensions/api/storage/settings_apitest.cc +++ b/chrome/browser/extensions/api/storage/settings_apitest.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/policy/schema_registry_service.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/browser.h" #include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_bundle.h" @@ -37,6 +36,7 @@ #include "extensions/browser/api/storage/storage_area_namespace.h" #include "extensions/browser/api/storage/storage_frontend.h" #include "extensions/browser/extension_system.h" +#include "extensions/buildflags/buildflags.h" #include "extensions/common/extension_id.h" #include "extensions/common/features/feature_channel.h" #include "extensions/test/extension_test_message_listener.h" @@ -44,6 +44,8 @@ #include "extensions/test/test_extension_dir.h" #include "testing/gmock/include/gmock/gmock.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + namespace extensions { using testing::NiceMock; @@ -290,9 +292,9 @@ // regular and incognito mode. ResultCatcher catcher; ResultCatcher catcher_incognito; - catcher.RestrictToBrowserContext(browser()->profile()); + catcher.RestrictToBrowserContext(profile()); catcher_incognito.RestrictToBrowserContext( - browser()->profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); + profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); // Sync, local and managed follow the same storage flow (RunWithStorage), // whereas session follows a separate flow (RunWithSession). For the purpose @@ -330,9 +332,9 @@ // regular and incognito mode. ResultCatcher catcher; ResultCatcher catcher_incognito; - catcher.RestrictToBrowserContext(browser()->profile()); + catcher.RestrictToBrowserContext(profile()); catcher_incognito.RestrictToBrowserContext( - browser()->profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); + profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); StorageAreaNamespace storage_areas[2] = {StorageAreaNamespace::kSync, StorageAreaNamespace::kSession}; @@ -378,9 +380,9 @@ // regular and incognito mode. ResultCatcher catcher; ResultCatcher catcher_incognito; - catcher.RestrictToBrowserContext(browser()->profile()); + catcher.RestrictToBrowserContext(profile()); catcher_incognito.RestrictToBrowserContext( - browser()->profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); + profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); LoadAndReplyWhenSatisfied(StorageAreaNamespace::kSync, "assertNoNotifications", "assertNoNotifications", @@ -490,9 +492,9 @@ // We need 2 ResultCatchers because we'll be running the same test in both // regular and incognito mode. ResultCatcher catcher, catcher_incognito; - catcher.RestrictToBrowserContext(browser()->profile()); + catcher.RestrictToBrowserContext(profile()); catcher_incognito.RestrictToBrowserContext( - browser()->profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); + profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); const Extension* extension = LoadAndReplyWhenSatisfied( StorageAreaNamespace::kSync, "assertNoNotifications", @@ -535,9 +537,9 @@ // We need 2 ResultCatchers because we'll be running the same test in both // regular and incognito mode. ResultCatcher catcher, catcher_incognito; - catcher.RestrictToBrowserContext(browser()->profile()); + catcher.RestrictToBrowserContext(profile()); catcher_incognito.RestrictToBrowserContext( - browser()->profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); + profile()->GetPrimaryOTRProfile(/*create_if_needed=*/true)); const Extension* extension = LoadAndReplyWhenSatisfied( StorageAreaNamespace::kLocal, "assertNoNotifications", @@ -571,7 +573,7 @@ } IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, IsStorageEnabled) { - StorageFrontend* frontend = StorageFrontend::Get(browser()->profile()); + StorageFrontend* frontend = StorageFrontend::Get(profile()); EXPECT_TRUE(frontend->IsStorageEnabled(settings_namespace::LOCAL)); EXPECT_TRUE(frontend->IsStorageEnabled(settings_namespace::SYNC)); @@ -602,9 +604,12 @@ ResultCatcher events_result_catcher_; }; +// Desktop Android supports only service worker, not persistent background. +#if BUILDFLAG(ENABLE_EXTENSIONS) INSTANTIATE_TEST_SUITE_P(PersistentBackground, ExtensionSettingsManagedStorageApiTest, ::testing::Values(ContextType::kPersistentBackground)); +#endif INSTANTIATE_TEST_SUITE_P(ServiceWorker, ExtensionSettingsManagedStorageApiTest, @@ -613,8 +618,7 @@ IN_PROC_BROWSER_TEST_P(ExtensionSettingsManagedStorageApiTest, ExtensionsSchemas) { // Verifies that the Schemas for the extensions domain are created on startup. - Profile* profile = browser()->profile(); - ExtensionSystem* extension_system = ExtensionSystem::Get(profile); + ExtensionSystem* extension_system = ExtensionSystem::Get(profile()); if (!extension_system->ready().is_signaled()) { // Wait until the extension system is ready. base::RunLoop run_loop; @@ -628,7 +632,7 @@ message_.clear(); policy::SchemaRegistry* registry = - profile->GetPolicySchemaRegistryService()->registry(); + profile()->GetPolicySchemaRegistryService()->registry(); ASSERT_TRUE(registry); EXPECT_FALSE(registry->schema_map()->GetSchema(policy::PolicyNamespace( policy::POLICY_DOMAIN_EXTENSIONS, kManagedStorageExtensionId))); @@ -721,6 +725,10 @@ ASSERT_TRUE(RunExtensionTest("settings/managed_storage")) << message_; } +// TODO(crbug.com/40200835): PRE_ test does not work on android_browsertest, +// therefore, disabled the following tests until the PRE_ test issue is +// resolved. +#if BUILDFLAG(ENABLE_EXTENSIONS) // TODO(crbug.com/40789870): This test should be rewritten. See the bug for more // details. IN_PROC_BROWSER_TEST_P(ExtensionSettingsManagedStorageApiTest, @@ -775,11 +783,12 @@ EXPECT_TRUE(events_result_catcher_.GetNextResult()) << events_result_catcher_.message(); } +#endif // BUILDFLAG(ENABLE_EXTENSIONS) IN_PROC_BROWSER_TEST_P(ExtensionSettingsManagedStorageApiTest, ManagedStorageDisabled) { // Disable the 'managed' namespace. - StorageFrontend* frontend = StorageFrontend::Get(browser()->profile()); + StorageFrontend* frontend = StorageFrontend::Get(profile()); frontend->DisableStorageForTesting(settings_namespace::MANAGED); EXPECT_FALSE(frontend->IsStorageEnabled(settings_namespace::MANAGED)); // Now run the extension.
diff --git a/chrome/browser/extensions/api/storage/settings_sync_unittest.cc b/chrome/browser/extensions/api/storage/settings_sync_unittest.cc index 765c532..6218df9 100644 --- a/chrome/browser/extensions/api/storage/settings_sync_unittest.cc +++ b/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
@@ -34,10 +34,13 @@ #include "extensions/browser/event_router_factory.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/mock_extension_system.h" +#include "extensions/buildflags/buildflags.h" #include "extensions/common/extension_id.h" #include "extensions/common/manifest.h" #include "testing/gtest/include/gtest/gtest.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + using value_store::ValueStore; namespace extensions {
diff --git a/chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.cc b/chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.cc index 407bef1d..83a0936a 100644 --- a/chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.cc +++ b/chrome/browser/extensions/desktop_android/desktop_android_extensions_browser_client.cc
@@ -10,6 +10,8 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/api/management/chrome_management_api_delegate.h" #include "chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h" +#include "chrome/browser/extensions/api/storage/managed_value_store_cache.h" +#include "chrome/browser/extensions/api/storage/sync_value_store_cache.h" #include "chrome/browser/extensions/chrome_extension_system_factory.h" #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" #include "chrome/browser/extensions/chrome_extensions_browser_api_provider.h" @@ -20,6 +22,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_selections.h" #include "components/update_client/update_client.h" +#include "components/value_store/value_store_factory.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -82,6 +85,24 @@ return new ChromeManagementAPIDelegate; } + // The following code is used to support chrome.storage api for sync + // and managed mode, until ChromeExtensionAPIClient is ported for + // desktop android. + void AddAdditionalValueStoreCaches( + content::BrowserContext* context, + const scoped_refptr<value_store::ValueStoreFactory>& factory, + SettingsChangedCallback observer, + std::map<settings_namespace::Namespace, + raw_ptr<ValueStoreCache, CtnExperimental>>* caches) override { + // Add support for chrome.storage.sync. + (*caches)[settings_namespace::SYNC] = + new SyncValueStoreCache(factory, observer, context->GetPath()); + + // Add support for chrome.storage.managed. + (*caches)[settings_namespace::MANAGED] = new ManagedValueStoreCache( + *Profile::FromBrowserContext(context), factory, observer); + } + private: std::unique_ptr<MessagingDelegate> messaging_delegate_; };
diff --git a/chrome/browser/extensions/extension_navigation_throttle_unittest.cc b/chrome/browser/extensions/extension_navigation_throttle_unittest.cc index f0f03d1..806a514c 100644 --- a/chrome/browser/extensions/extension_navigation_throttle_unittest.cc +++ b/chrome/browser/extensions/extension_navigation_throttle_unittest.cc
@@ -46,11 +46,10 @@ // Only construct an ExtensionNavigationThrottle so that we can test it in // isolation. - std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override { registry.AddThrottle(std::make_unique<ExtensionNavigationThrottle>( ®istry.GetNavigationHandle())); - return {}; } };
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc index e0b2293..70682c0 100644 --- a/chrome/browser/extensions/external_provider_impl.cc +++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -74,7 +74,7 @@ #include "chromeos/components/kiosk/kiosk_utils.h" #include "chromeos/components/mgs/managed_guest_session_utils.h" #else -#include "components/policy/core/common/device_local_account_type.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #endif #if BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc index 35148645..5b543e8 100644 --- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc +++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
@@ -18,6 +18,7 @@ #include "base/files/file_util.h" #include "base/json/values_util.h" #include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/notreached.h" #include "base/path_service.h" @@ -265,111 +266,6 @@ // the struct below. constexpr const int kNoBasePathKey = -1; -using BlockType = ChromeFileSystemAccessPermissionContext::BlockType; - -std::vector<ChromeFileSystemAccessPermissionContext::BlockedPath> -GenerateBlockedPath() { - return { - // Don't allow users to share their entire home directory, entire desktop - // or entire documents folder, but do allow sharing anything inside those - // directories not otherwise blocked. - {base::DIR_HOME, nullptr, BlockType::kDontBlockChildren}, - {base::DIR_USER_DESKTOP, nullptr, BlockType::kDontBlockChildren}, - {chrome::DIR_USER_DOCUMENTS, nullptr, BlockType::kDontBlockChildren}, - // Similar restrictions for the downloads directory. - {chrome::DIR_DEFAULT_DOWNLOADS, nullptr, BlockType::kDontBlockChildren}, - {chrome::DIR_DEFAULT_DOWNLOADS_SAFE, nullptr, - BlockType::kDontBlockChildren}, - // The Chrome installation itself should not be modified by the web. - {base::DIR_EXE, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_MODULE, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_ASSETS, nullptr, BlockType::kBlockAllChildren}, - // And neither should the configuration of at least the currently running - // Chrome instance (note that this does not take --user-data-dir command - // line overrides into account). - {chrome::DIR_USER_DATA, nullptr, BlockType::kBlockAllChildren}, - // ~/.ssh is pretty sensitive on all platforms, so block access to that. - {base::DIR_HOME, FILE_PATH_LITERAL(".ssh"), BlockType::kBlockAllChildren}, - // And limit access to ~/.gnupg as well. - {base::DIR_HOME, FILE_PATH_LITERAL(".gnupg"), - BlockType::kBlockAllChildren}, -#if BUILDFLAG(IS_WIN) - // Some Windows specific directories to block, basically all apps, the - // operating system itself, as well as configuration data for apps. - {base::DIR_PROGRAM_FILES, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_PROGRAM_FILESX86, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_PROGRAM_FILES6432, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_WINDOWS, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_ROAMING_APP_DATA, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_LOCAL_APP_DATA, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_COMMON_APP_DATA, nullptr, BlockType::kBlockAllChildren}, - // Opening a file from an MTP device, such as a smartphone or a camera, is - // implemented by Windows as opening a file in the temporary internet - // files directory. To support that, allow opening files in that - // directory, but not whole directories. - {base::DIR_IE_INTERNET_CACHE, nullptr, - BlockType::kBlockNestedDirectories}, -#endif -#if BUILDFLAG(IS_MAC) - // Similar Mac specific blocks. - {base::DIR_APP_DATA, nullptr, BlockType::kBlockAllChildren}, - // Block access to the current bundle directory. - {chrome::DIR_OUTER_BUNDLE, nullptr, BlockType::kBlockAllChildren}, - // Block access to the user's Applications directory. - {base::DIR_HOME, FILE_PATH_LITERAL("Applications"), - BlockType::kBlockAllChildren}, - // Block access to the root Applications directory. - {kNoBasePathKey, FILE_PATH_LITERAL("/Applications"), - BlockType::kBlockAllChildren}, - {base::DIR_HOME, FILE_PATH_LITERAL("Library"), - BlockType::kBlockAllChildren}, - // Allow access to other cloud files, such as Google Drive. - {base::DIR_HOME, FILE_PATH_LITERAL("Library/CloudStorage"), - BlockType::kDontBlockChildren}, - // Allow the site to interact with data from its corresponding natively - // installed (sandboxed) application. It would be nice to limit a site to - // access only _its_ corresponding natively installed application, but - // unfortunately there's no straightforward way to do that. See - // https://crbug.com/984641#c22. - {base::DIR_HOME, FILE_PATH_LITERAL("Library/Containers"), - BlockType::kDontBlockChildren}, - // Allow access to iCloud files... - {base::DIR_HOME, FILE_PATH_LITERAL("Library/Mobile Documents"), - BlockType::kDontBlockChildren}, - // ... which may also appear at this directory. - {base::DIR_HOME, - FILE_PATH_LITERAL("Library/Mobile Documents/com~apple~CloudDocs"), - BlockType::kDontBlockChildren}, -#endif -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) - // On Linux also block access to devices via /dev. - {kNoBasePathKey, FILE_PATH_LITERAL("/dev"), BlockType::kBlockAllChildren}, - // And security sensitive data in /proc and /sys. - {kNoBasePathKey, FILE_PATH_LITERAL("/proc"), - BlockType::kBlockAllChildren}, - {kNoBasePathKey, FILE_PATH_LITERAL("/sys"), BlockType::kBlockAllChildren}, - // And system files in /boot and /etc. - {kNoBasePathKey, FILE_PATH_LITERAL("/boot"), - BlockType::kBlockAllChildren}, - {kNoBasePathKey, FILE_PATH_LITERAL("/etc"), BlockType::kBlockAllChildren}, - // And block all of ~/.config, matching the similar restrictions on mac - // and windows. - {base::DIR_HOME, FILE_PATH_LITERAL(".config"), - BlockType::kBlockAllChildren}, - // Block ~/.dbus as well, just in case, although there probably isn't much - // a website can do with access to that directory and its contents. - {base::DIR_HOME, FILE_PATH_LITERAL(".dbus"), - BlockType::kBlockAllChildren}, -#endif -#if BUILDFLAG(IS_ANDROID) - {base::DIR_ANDROID_APP_DATA, nullptr, BlockType::kBlockAllChildren}, - {base::DIR_CACHE, nullptr, BlockType::kBlockAllChildren}, -#endif - // TODO(crbug.com/40095723): Refine this list, for example add - // XDG_CONFIG_HOME when it is not set ~/.config? - }; -} - // A wrapper around `base::NormalizeFilePath` that returns its result instead of // using an out parameter. base::FilePath NormalizeFilePath(const base::FilePath& path) { @@ -385,46 +281,123 @@ return normalized_path; } -// Checks if `path` should be blocked by the `rules`. -// The BlockType of the nearest ancestor of a path to check is what -// ultimately determines if a path is blocked or not. If a blocked path is a -// descendent of another blocked path, then it may override the -// child-blocking policy of its ancestor. For example, if /home blocks all -// children, but /home/downloads does not, then /home/downloads/file.ext -// will *not* be blocked. -bool ShouldBlockAccessToPath( - const base::FilePath& path, - HandleType handle_type, - std::vector<ChromeFileSystemAccessPermissionContext::BlockPathRule> rules, - std::vector<ChromeFileSystemAccessPermissionContext::BlockedPath> - blocked_paths, - const base::FilePath& profile_path) { - DCHECK(!path.empty()); -#if BUILDFLAG(IS_ANDROID) - // The only check for content-URIs is that they are not from an internal - // FileProvider. - if (path.IsContentUri()) { - base::android::BuildInfo* info = base::android::BuildInfo::GetInstance(); - return base::StartsWith( - path.value(), base::StrCat({"content://", info->package_name(), "."}), - base::CompareCase::INSENSITIVE_ASCII); - } -#endif - DCHECK(path.IsAbsolute()); +using BlockType = ChromeFileSystemAccessPermissionContext::BlockType; - bool normalize_file_paths = base::FeatureList::IsEnabled( - features::kFileSystemAccessSymbolicLinkCheck); - - base::FilePath check_path = - normalize_file_paths ? NormalizeFilePath(path) : path; - +std::unique_ptr<ChromeFileSystemAccessPermissionContext::BlockPathRules> +GenerateBlockPaths(bool should_normalize_file_path) { + static constexpr ChromeFileSystemAccessPermissionContext::BlockPath + kBlockPaths[] = { + // Don't allow users to share their entire home directory, entire + // desktop or entire documents folder, but do allow sharing anything + // inside those directories not otherwise blocked. + {base::DIR_HOME, nullptr, BlockType::kDontBlockChildren}, + {base::DIR_USER_DESKTOP, nullptr, BlockType::kDontBlockChildren}, + {chrome::DIR_USER_DOCUMENTS, nullptr, BlockType::kDontBlockChildren}, + // Similar restrictions for the downloads directory. + {chrome::DIR_DEFAULT_DOWNLOADS, nullptr, + BlockType::kDontBlockChildren}, + {chrome::DIR_DEFAULT_DOWNLOADS_SAFE, nullptr, + BlockType::kDontBlockChildren}, + // The Chrome installation itself should not be modified by the web. + {base::DIR_EXE, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_MODULE, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_ASSETS, nullptr, BlockType::kBlockAllChildren}, + // And neither should the configuration of at least the currently + // running + // Chrome instance (note that this does not take --user-data-dir + // command + // line overrides into account). + {chrome::DIR_USER_DATA, nullptr, BlockType::kBlockAllChildren}, + // ~/.ssh is pretty sensitive on all platforms, so block access to + // that. + {base::DIR_HOME, FILE_PATH_LITERAL(".ssh"), + BlockType::kBlockAllChildren}, + // And limit access to ~/.gnupg as well. + {base::DIR_HOME, FILE_PATH_LITERAL(".gnupg"), + BlockType::kBlockAllChildren}, #if BUILDFLAG(IS_WIN) - // On Windows, local UNC paths are rejected, as UNC path can be written in a - // way that can bypass the blocklist. - if (MaybeIsLocalUNCPath(check_path)) { - return true; - } + // Some Windows specific directories to block, basically all apps, the + // operating system itself, as well as configuration data for apps. + {base::DIR_PROGRAM_FILES, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_PROGRAM_FILESX86, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_PROGRAM_FILES6432, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_WINDOWS, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_ROAMING_APP_DATA, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_LOCAL_APP_DATA, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_COMMON_APP_DATA, nullptr, BlockType::kBlockAllChildren}, + // Opening a file from an MTP device, such as a smartphone or a + // camera, is + // implemented by Windows as opening a file in the temporary internet + // files directory. To support that, allow opening files in that + // directory, but not whole directories. + {base::DIR_IE_INTERNET_CACHE, nullptr, + BlockType::kBlockNestedDirectories}, #endif +#if BUILDFLAG(IS_MAC) + // Similar Mac specific blocks. + {base::DIR_APP_DATA, nullptr, BlockType::kBlockAllChildren}, + // Block access to the current bundle directory. + {chrome::DIR_OUTER_BUNDLE, nullptr, BlockType::kBlockAllChildren}, + // Block access to the user's Applications directory. + {base::DIR_HOME, FILE_PATH_LITERAL("Applications"), + BlockType::kBlockAllChildren}, + // Block access to the root Applications directory. + {kNoBasePathKey, FILE_PATH_LITERAL("/Applications"), + BlockType::kBlockAllChildren}, + {base::DIR_HOME, FILE_PATH_LITERAL("Library"), + BlockType::kBlockAllChildren}, + // Allow access to other cloud files, such as Google Drive. + {base::DIR_HOME, FILE_PATH_LITERAL("Library/CloudStorage"), + BlockType::kDontBlockChildren}, + // Allow the site to interact with data from its corresponding + // natively + // installed (sandboxed) application. It would be nice to limit a site + // to + // access only _its_ corresponding natively installed application, but + // unfortunately there's no straightforward way to do that. See + // https://crbug.com/984641#c22. + {base::DIR_HOME, FILE_PATH_LITERAL("Library/Containers"), + BlockType::kDontBlockChildren}, + // Allow access to iCloud files... + {base::DIR_HOME, FILE_PATH_LITERAL("Library/Mobile Documents"), + BlockType::kDontBlockChildren}, + // ... which may also appear at this directory. + {base::DIR_HOME, + FILE_PATH_LITERAL("Library/Mobile Documents/com~apple~CloudDocs"), + BlockType::kDontBlockChildren}, +#endif +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) + // On Linux also block access to devices via /dev. + {kNoBasePathKey, FILE_PATH_LITERAL("/dev"), + BlockType::kBlockAllChildren}, + // And security sensitive data in /proc and /sys. + {kNoBasePathKey, FILE_PATH_LITERAL("/proc"), + BlockType::kBlockAllChildren}, + {kNoBasePathKey, FILE_PATH_LITERAL("/sys"), + BlockType::kBlockAllChildren}, + // And system files in /boot and /etc. + {kNoBasePathKey, FILE_PATH_LITERAL("/boot"), + BlockType::kBlockAllChildren}, + {kNoBasePathKey, FILE_PATH_LITERAL("/etc"), + BlockType::kBlockAllChildren}, + // And block all of ~/.config, matching the similar restrictions on + // mac + // and windows. + {base::DIR_HOME, FILE_PATH_LITERAL(".config"), + BlockType::kBlockAllChildren}, + // Block ~/.dbus as well, just in case, although there probably isn't + // much + // a website can do with access to that directory and its contents. + {base::DIR_HOME, FILE_PATH_LITERAL(".dbus"), + BlockType::kBlockAllChildren}, +#endif +#if BUILDFLAG(IS_ANDROID) + {base::DIR_ANDROID_APP_DATA, nullptr, BlockType::kBlockAllChildren}, + {base::DIR_CACHE, nullptr, BlockType::kBlockAllChildren}, +#endif + // TODO(crbug.com/40095723): Refine this list, for example add + // XDG_CONFIG_HOME when it is not set ~/.config? + }; // ChromeOS supports multi-user sign-in. base::DIR_HOME only returns the // profile path for the primary user, the first user to sign in. We want to @@ -433,42 +406,105 @@ // // TODO(crbug.com/375490221): Improve the ChromeOS blocklist logic. constexpr bool kUseProfilePathForDirHome = BUILDFLAG(IS_CHROMEOS); + // Populate the hard-coded rules. + auto block_path_rules = std::make_unique< + ChromeFileSystemAccessPermissionContext::BlockPathRules>(); - // Add the hard-coded rules to the dynamic rules. - for (const auto& block : blocked_paths) { - base::FilePath blocked_path; - if (block.base_path_key != kNoBasePathKey) { - if (kUseProfilePathForDirHome && block.base_path_key == base::DIR_HOME) { - blocked_path = profile_path; - } else if (!base::PathService::Get(block.base_path_key, &blocked_path)) { + for (const auto& blocked_path : kBlockPaths) { + base::FilePath path; + if (blocked_path.base_path_key != kNoBasePathKey) { + if (kUseProfilePathForDirHome && + blocked_path.base_path_key == base::DIR_HOME) { + block_path_rules->profile_based_block_path_rules_.emplace_back( + blocked_path.path, blocked_path.type); continue; } - if (block.path) { - blocked_path = blocked_path.Append(block.path); + + if (!base::PathService::Get(blocked_path.base_path_key, &path)) { + continue; + } + + if (blocked_path.path) { + path = path.Append(blocked_path.path); } } else { - DCHECK(block.path); - blocked_path = base::FilePath(block.path); + DCHECK(blocked_path.path); + path = base::FilePath(blocked_path.path); } - rules.emplace_back(blocked_path, block.type); + block_path_rules->block_path_rules_.emplace_back( + should_normalize_file_path ? NormalizeFilePath(path) : path, + blocked_path.type); } + return block_path_rules; +} + +// Checks if `path` should be blocked by the `rules`. +// The BlockType of the nearest ancestor of a path to check is what +// ultimately determines if a path is blocked or not. If a blocked path is a +// descendent of another blocked path, then it may override the +// child-blocking policy of its ancestor. For example, if /home blocks all +// children, but /home/downloads does not, then /home/downloads/file.ext +// will *not* be blocked. +bool ShouldBlockAccessToPath( + bool should_normalize_file_path, + base::FilePath path, + HandleType handle_type, + std::vector<ChromeFileSystemAccessPermissionContext::BlockPathRule> + extra_rules, + ChromeFileSystemAccessPermissionContext::BlockPathRules block_path_rules, + base::FilePath profile_path) { + DCHECK(!path.empty()); + DCHECK(path.IsAbsolute()); + + if (should_normalize_file_path) { + path = NormalizeFilePath(path); + profile_path = NormalizeFilePath(profile_path); + for (auto& rule : extra_rules) { + rule.path = NormalizeFilePath(rule.path); + } + } + +#if BUILDFLAG(IS_WIN) + // On Windows, local UNC paths are rejected, as UNC path can be written in a + // way that can bypass the blocklist. + if (MaybeIsLocalUNCPath(path)) { + return true; + } +#endif + base::FilePath nearest_ancestor; BlockType nearest_ancestor_block_type = BlockType::kDontBlockChildren; - for (const auto& block : rules) { - base::FilePath blocked_path = - normalize_file_paths ? NormalizeFilePath(block.path) : block.path; - - if (check_path == blocked_path || check_path.IsParent(blocked_path)) { - VLOG(1) << "Blocking access to " << check_path - << " because it is a parent of " << blocked_path; + auto should_block_with_rule = [&](const base::FilePath& block_path, + BlockType block_type) -> bool { + if (path == block_path || path.IsParent(block_path)) { + VLOG(1) << "Blocking access to " << path << " because it is a parent of " + << block_path; return true; } - if (blocked_path.IsParent(check_path) && - (nearest_ancestor.empty() || nearest_ancestor.IsParent(blocked_path))) { - nearest_ancestor = blocked_path; - nearest_ancestor_block_type = block.type; + if (block_path.IsParent(path) && + (nearest_ancestor.empty() || nearest_ancestor.IsParent(block_path))) { + nearest_ancestor = block_path; + nearest_ancestor_block_type = block_type; + } + return false; + }; + + for (const auto* block_rules_ptr : + {&extra_rules, &block_path_rules.block_path_rules_}) { + for (const auto& block : *block_rules_ptr) { + if (should_block_with_rule(block.path, block.type)) { + return true; + } + } + } + + for (const auto& rule : block_path_rules.profile_based_block_path_rules_) { + if (should_block_with_rule( + rule.path ? profile_path.Append(rule.path) : profile_path, + rule.type)) { + return true; } } @@ -476,6 +512,8 @@ // nearest ancestor does not block access to its children. Grant access. if (nearest_ancestor.empty() || nearest_ancestor_block_type == BlockType::kDontBlockChildren) { + VLOG(1) << "Not blocking access to " << path << " because it is inside " + << nearest_ancestor << " and it's kDontBlockChildren"; return false; } @@ -483,12 +521,14 @@ // access to directories. Grant access. if (handle_type == HandleType::kFile && nearest_ancestor_block_type == BlockType::kBlockNestedDirectories) { + VLOG(1) << "Not blocking access to " << path << " because it is inside " + << nearest_ancestor << " and it's kBlockNestedDirectories"; return false; } // The nearest ancestor blocks access to its children, so block access. - VLOG(1) << "Blocking access to " << check_path << " because it is inside " - << nearest_ancestor; + VLOG(1) << "Blocking access to " << path << " because it is inside " + << nearest_ancestor << " and it's kBlockAllChildren"; return true; } @@ -1221,6 +1261,16 @@ std::unique_ptr<base::RetainingOneShotTimer> cleanup_timer; }; +ChromeFileSystemAccessPermissionContext::BlockPathRules::BlockPathRules() = + default; +ChromeFileSystemAccessPermissionContext::BlockPathRules::~BlockPathRules() = + default; +ChromeFileSystemAccessPermissionContext::BlockPathRules::BlockPathRules( + const BlockPathRules& other) = default; +ChromeFileSystemAccessPermissionContext::BlockPathRules& +ChromeFileSystemAccessPermissionContext::BlockPathRules::operator=( + const BlockPathRules& other) = default; + ChromeFileSystemAccessPermissionContext:: ChromeFileSystemAccessPermissionContext(content::BrowserContext* context, const base::Clock* clock) @@ -1229,7 +1279,9 @@ ContentSettingsType::FILE_SYSTEM_ACCESS_CHOOSER_DATA, HostContentSettingsMapFactory::GetForProfile(context)), profile_(context), - clock_(clock) { + clock_(clock), + should_normalize_file_path_(base::FeatureList::IsEnabled( + features::kFileSystemAccessSymbolicLinkCheck)) { DETACH_FROM_SEQUENCE(sequence_checker_); content_settings_ = base::WrapRefCounted( HostContentSettingsMapFactory::GetForProfile(profile_)); @@ -1264,12 +1316,32 @@ } #endif - blocked_paths_ = GenerateBlockedPath(); + ResetBlockPaths(); } ChromeFileSystemAccessPermissionContext:: ~ChromeFileSystemAccessPermissionContext() = default; +void ChromeFileSystemAccessPermissionContext::ResetBlockPaths() { + is_block_path_rules_init_complete_ = false; + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&GenerateBlockPaths, should_normalize_file_path_), + base::BindOnce(&ChromeFileSystemAccessPermissionContext::UpdateBlockPaths, + weak_factory_.GetWeakPtr())); +} + +void ChromeFileSystemAccessPermissionContext::ResetBlockPathsForTesting() { + ResetBlockPaths(); +} + +void ChromeFileSystemAccessPermissionContext::UpdateBlockPaths( + std::unique_ptr<BlockPathRules> block_path_rules) { + block_path_rules_ = std::move(block_path_rules); + is_block_path_rules_init_complete_ = true; + block_rules_check_callbacks_.Notify(*block_path_rules_.get()); +} + bool ChromeFileSystemAccessPermissionContext::RevokeActiveGrants( const url::Origin& origin, base::FilePath file_path) { @@ -1845,6 +1917,21 @@ #endif // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS) +void ChromeFileSystemAccessPermissionContext:: + CheckShouldBlockAccessToPathAndReply( + base::FilePath path, + HandleType handle_type, + std::vector<BlockPathRule> extra_rules, + base::OnceCallback<void(bool)> callback, + BlockPathRules block_path_rules) { + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&ShouldBlockAccessToPath, should_normalize_file_path_, + path, handle_type, extra_rules, block_path_rules, + profile_path_override_.value_or(profile_->GetPath())), + std::move(callback)); +} + void ChromeFileSystemAccessPermissionContext::CheckPathAgainstBlocklist( const content::PathInfo& path_info, HandleType handle_type, @@ -1860,6 +1947,19 @@ return; } +#if BUILDFLAG(IS_ANDROID) + // The only check for content-URIs is that they are not from an internal + // FileProvider. + if (path_info.path.IsContentUri()) { + base::android::BuildInfo* info = base::android::BuildInfo::GetInstance(); + std::move(callback).Run(base::StartsWith( + path_info.path.value(), + base::StrCat({"content://", info->package_name(), "."}), + base::CompareCase::INSENSITIVE_ASCII)); + return; + } +#endif // BUILDFLAG(IS_ANDROID) + // Unlike the DIR_USER_DATA check, this handles the --user-data-dir override. // We check for the user data dir in two different ways: directly, via the // profile manager, where it exists (it does not in unit tests), and via the @@ -1874,12 +1974,20 @@ BlockType::kBlockAllChildren); } - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, - base::BindOnce(&ShouldBlockAccessToPath, path_info.path, handle_type, - extra_rules, blocked_paths_, - profile_path_override_.value_or(profile_->GetPath())), - std::move(callback)); + if (is_block_path_rules_init_complete_) { + // The rules initialization is completed, we can just post the task to a + // anonymous blocking traits. + CheckShouldBlockAccessToPathAndReply(path_info.path, handle_type, + extra_rules, std::move(callback), + *block_path_rules_.get()); + return; + } + // The check must be performed after the rules initialization is done. + block_rules_check_subscription_.push_back(block_rules_check_callbacks_.Add( + base::BindOnce(&ChromeFileSystemAccessPermissionContext:: + CheckShouldBlockAccessToPathAndReply, + weak_factory_.GetWeakPtr(), path_info.path, handle_type, + extra_rules, std::move(callback)))); } void ChromeFileSystemAccessPermissionContext::PerformAfterWriteChecks(
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.h b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.h index 46a2019..5e1aa12 100644 --- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.h +++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.h
@@ -12,6 +12,7 @@ #include "base/callback_list.h" #include "base/files/file_path.h" #include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "base/sequence_checker.h" #include "base/time/clock.h" @@ -137,14 +138,38 @@ kDontBlockChildren }; - // Describes a rule for blocking a directory, which can be constructed - // dynamically (based on state) or statically (from `kBlockedPaths`). + // Describes a rule for blocking a directory, which can be + // - constructed dynamically based on the profile path + // - provided by the caller + // - or constructed statically during `UpdateBlockPaths()`. struct BlockPathRule { base::FilePath path; BlockType type; }; - struct BlockedPath { + // Describes a rule for blocking a directory, but the file path will be + // determined during the check time when profile path is provided. + struct ProfileBasedBlockPathRule { + // Path that will be appended to the profile path. + const base::FilePath::CharType* path; + BlockType type; + }; + + // Contains two lists of the block rules: one for `BlockPathRule`s which has + // the path set and normalized, and another for `ProfileBasedBlockPathRule`s + // which can only be determined when performing the checks. + class BlockPathRules { + public: + BlockPathRules(); + ~BlockPathRules(); + BlockPathRules(const BlockPathRules& other); + BlockPathRules& operator=(const BlockPathRules& other); + + std::vector<BlockPathRule> block_path_rules_; + std::vector<ProfileBasedBlockPathRule> profile_based_block_path_rules_; + }; + + struct BlockPath { // base::BasePathKey value (or one of the platform specific extensions to // it) for a path that should be blocked. Specify kNoBasePathKey if |path| // should be used instead. @@ -371,6 +396,9 @@ // KeyedService: void Shutdown() override; + // This is needed when updating path with ScopedPathOverride. + void ResetBlockPathsForTesting(); + protected: SEQUENCE_CHECKER(sequence_checker_); @@ -398,6 +426,13 @@ std::vector<bool> allowed); #endif + void CheckShouldBlockAccessToPathAndReply( + base::FilePath path, + HandleType handle_type, + std::vector<BlockPathRule> extra_rules, + base::OnceCallback<void(bool)> callback, + BlockPathRules block_path_rules); + // Checks whether the file or directory at `path` corresponds to a directory // Chrome considers sensitive (i.e. system files). Calls `callback` with // whether the path is on the blocklist. @@ -545,6 +580,9 @@ bool RevokeActiveGrants(const url::Origin& origin, base::FilePath file_path = base::FilePath()); + void ResetBlockPaths(); + void UpdateBlockPaths(std::unique_ptr<BlockPathRules> block_path_rules); + base::WeakPtr<ChromeFileSystemAccessPermissionContext> GetWeakPtr(); const raw_ptr<content::BrowserContext, DanglingUntriaged> profile_; @@ -581,7 +619,18 @@ std::optional<base::FilePath> profile_path_override_; - std::vector<BlockedPath> blocked_paths_; + // The normalization flag should be consistent during the initialization and + // checking, so we store is as a member variable. + bool should_normalize_file_path_ = false; + + // The initialization of `block_path_rules_` needs to be done in a blocking + // sequence so it's asynchronous. When we need to check if a path should be + // blocked, we need to wait until the initialization completes, hence the + // `WaitableEvent` and `OnceCallbackList`. + std::unique_ptr<BlockPathRules> block_path_rules_; + bool is_block_path_rules_init_complete_ = false; + std::vector<base::CallbackListSubscription> block_rules_check_subscription_; + base::OnceCallbackList<void(BlockPathRules)> block_rules_check_callbacks_; base::WeakPtrFactory<ChromeFileSystemAccessPermissionContext> weak_factory_{ this};
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc index f6561fd..01d7f60 100644 --- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc +++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_unittest.cc
@@ -566,6 +566,7 @@ ConfirmSensitiveEntryAccess_DontBlockAllChildren) { base::FilePath home_dir = temp_dir_.GetPath().AppendASCII("home"); ScopedHomeDirOverride home_override = OverrideHomeDir(home_dir); + permission_context_->ResetBlockPathsForTesting(); // The Home directory itself should not be allowed. EXPECT_EQ(ConfirmSensitiveEntryAccessSync( @@ -592,6 +593,7 @@ ConfirmSensitiveEntryAccess_BlockAllChildren) { base::FilePath app_dir = temp_dir_.GetPath().AppendASCII("app"); base::ScopedPathOverride app_override(base::DIR_EXE, app_dir, true, true); + permission_context_->ResetBlockPathsForTesting(); // The App directory itself should not be allowed. EXPECT_TRUE(IsOpenAbort(app_dir, HandleType::kDirectory)); @@ -605,6 +607,7 @@ base::FilePath app_data_dir = temp_dir_.GetPath().AppendASCII("app_data"); base::ScopedPathOverride app_data_override(base::DIR_ANDROID_APP_DATA, app_data_dir, true, true); + permission_context_->ResetBlockPathsForTesting(); // The android app data directory, its parent and paths inside should not be // allowed. @@ -617,6 +620,7 @@ base::FilePath cache_dir = temp_dir_.GetPath().AppendASCII("cache"); base::ScopedPathOverride cache_override(base::DIR_CACHE, cache_dir, true, true); + permission_context_->ResetBlockPathsForTesting(); // The android cache directory, its parent and paths inside should not be // allowed. EXPECT_TRUE(IsOpenAbort(cache_dir, HandleType::kDirectory)); @@ -637,6 +641,7 @@ base::FilePath download_dir = user_data_dir.AppendASCII("downloads"); base::ScopedPathOverride download_override(chrome::DIR_DEFAULT_DOWNLOADS, download_dir, true, true); + permission_context_->ResetBlockPathsForTesting(); // The User Data directory itself should not be allowed. EXPECT_FALSE(IsOpenAllowed(user_data_dir, HandleType::kDirectory)); @@ -662,8 +667,10 @@ base::FilePath download_dir = profile_path.AppendASCII("downloads"); base::ScopedPathOverride download_override(chrome::DIR_DEFAULT_DOWNLOADS, download_dir, true, true); + permission_context_->ResetBlockPathsForTesting(); EXPECT_FALSE(IsOpenAllowed(profile_path, HandleType::kDirectory)); + DLOG(ERROR) << "HERE"; EXPECT_FALSE( IsOpenAllowed(profile_path.AppendASCII("foo"), HandleType::kFile)); EXPECT_FALSE(IsOpenAllowed(profile_path.DirName(), HandleType::kDirectory)); @@ -681,6 +688,7 @@ base::FilePath internet_cache = user_data_dir.AppendASCII("INetCache"); base::ScopedPathOverride internet_cache_override(base::DIR_IE_INTERNET_CACHE, internet_cache, true, true); + permission_context_->ResetBlockPathsForTesting(); // The nested INetCache directory itself should not be allowed. EXPECT_FALSE(IsOpenAllowed(internet_cache, HandleType::kDirectory)); @@ -703,6 +711,7 @@ base::ScopedPathOverride app_override(base::DIR_EXE, temp_dir_.GetPath(), true, true); base::ScopedPathOverride home_override(base::DIR_HOME, home_dir, true, true); + permission_context_->ResetBlockPathsForTesting(); // `base::DIR_HOME` and paths inside of it should not be allowed. EXPECT_FALSE(IsOpenAllowed(home_dir, HandleType::kDirectory)); @@ -727,6 +736,7 @@ ConfirmSensitiveEntryAccess_RelativePathBlock) { base::FilePath home_dir = temp_dir_.GetPath().AppendASCII("home"); ScopedHomeDirOverride home_override = OverrideHomeDir(home_dir); + permission_context_->ResetBlockPathsForTesting(); // ~/.ssh should be blocked. EXPECT_EQ(ConfirmSensitiveEntryAccessSync( @@ -779,6 +789,7 @@ ConfirmSensitiveEntryAccess_DontBlockAllChildren_Overlapping) { base::FilePath home_dir = temp_dir_.GetPath().AppendASCII("home"); ScopedHomeDirOverride home_override = OverrideHomeDir(home_dir); + permission_context_->ResetBlockPathsForTesting(); // The Home directory itself should not be allowed. EXPECT_EQ(ConfirmSensitiveEntryAccessSync( @@ -843,6 +854,7 @@ ConfirmSensitiveEntryAccess_BlockAllChildren_UserApplicationsDir) { base::FilePath home_dir = temp_dir_.GetPath().AppendASCII("home"); ScopedHomeDirOverride home_override = OverrideHomeDir(home_dir); + permission_context_->ResetBlockPathsForTesting(); // User's Applications directory should be blocked. base::FilePath user_applications_dir(home_dir.AppendASCII("Applications")); @@ -866,6 +878,7 @@ ASSERT_FALSE(outer_bundle_path.empty()); base::ScopedPathOverride bundle_override(chrome::DIR_OUTER_BUNDLE, outer_bundle_path, true, true); + permission_context_->ResetBlockPathsForTesting(); EXPECT_EQ(ConfirmSensitiveEntryAccessSync( permission_context(), PathInfo(outer_bundle_path), @@ -980,6 +993,7 @@ ASSERT_TRUE(base::CreateDirectory(app_dir)); base::ScopedPathOverride app_override(base::DIR_EXE, app_dir, true, true); + permission_context_->ResetBlockPathsForTesting(); CreateSymbolicLinkResult result = CreateSymbolicLinkForTesting(app_dir, symlink1); @@ -1026,6 +1040,7 @@ // Set the blocked path to a symbolic link. base::ScopedPathOverride app_override(base::DIR_EXE, symlink1, true, true); + permission_context_->ResetBlockPathsForTesting(); // The target of the blocked symbolic link should be blocked. EXPECT_EQ( @@ -1038,6 +1053,7 @@ ConfirmSensitiveEntryAccess_DangerousFile) { base::FilePath home_dir = temp_dir_.GetPath().AppendASCII("home"); ScopedHomeDirOverride home_override = OverrideHomeDir(home_dir); + permission_context_->ResetBlockPathsForTesting(); // Saving files with a harmless extension should be allowed. EXPECT_EQ( @@ -1327,6 +1343,7 @@ GetWellKnownDirectoryPath_Base_OK) { base::ScopedPathOverride user_desktop_override( base::DIR_USER_DESKTOP, temp_dir_.GetPath(), true, true); + permission_context_->ResetBlockPathsForTesting(); EXPECT_EQ(permission_context()->GetWellKnownDirectoryPath( blink::mojom::WellKnownDirectory::kDirDesktop, kTestOrigin), temp_dir_.GetPath()); @@ -1336,6 +1353,7 @@ GetWellKnownDirectoryPath_Chrome_OK) { base::ScopedPathOverride user_documents_override( chrome::DIR_USER_DOCUMENTS, temp_dir_.GetPath(), true, true); + permission_context_->ResetBlockPathsForTesting(); EXPECT_EQ(permission_context()->GetWellKnownDirectoryPath( blink::mojom::WellKnownDirectory::kDirDocuments, kTestOrigin), temp_dir_.GetPath()); @@ -1348,6 +1366,8 @@ ->SkipSanitizeDownloadTargetPathForTesting(); DownloadPrefs::FromBrowserContext(browser_context()) ->SetDownloadPath(temp_dir_.GetPath()); + permission_context_->ResetBlockPathsForTesting(); + #if BUILDFLAG(IS_ANDROID) // Android always uses the system Download directory (/storage/emulated/...). ASSERT_TRUE(base::android::GetDownloadsDirectory(&expected_downloads));
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 9613d8b..97d2bc3 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -306,13 +306,13 @@ "expiry_milestone": 170 }, { - "name": "android-surface-color-update", - "owners": [ "jtanaristy@google.com", "wenyufu@google.com" ], - "expiry_milestone": 140 + "name": "android-sms-otp-filling", + "owners": ["kazinova@google.com", "vasilii@chromium.org", "chrome-password-manager-team@google.com"], + "expiry_milestone": 145 }, { - "name": "android-tab-declutter", - "owners": [ "wylieb@google.com", "clank-tab-dev@google.com" ], + "name": "android-surface-color-update", + "owners": [ "jtanaristy@google.com", "wenyufu@google.com" ], "expiry_milestone": 140 }, { @@ -331,6 +331,11 @@ "expiry_milestone": 142 }, { + "name": "android-tab-declutter-auto-delete", + "owners": [ "wylieb@google.com", "clank-tab-dev@google.com" ], + "expiry_milestone": 145 + }, + { "name": "android-tab-declutter-performance-improvements", "owners": [ "wylieb@google.com", "clank-tab-dev@google.com" ], "expiry_milestone": 140
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index d8f227c..e43e0f0 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -212,6 +212,12 @@ "Enable the new updated progress bar"; #endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) +const char kAndroidSmsOtpFillingName[] = "Enable SMS OTP filling"; +const char kAndroidSmsOtpFillingDescription[] = + "Enables filling of OTPs received via SMS on Android"; +#endif // BUILDFLAG(IS_ANDROID) + #if BUILDFLAG(IS_CHROMEOS) const char kIgnoreDeviceFlexArcEnabledPolicyName[] = "Ignore VPN Apps Enabling on ChromeOS Flex"; @@ -4530,9 +4536,10 @@ const char kAndroidSurfaceColorUpdateDescription[] = "If enabled, updates the android surface colors for toolbar/omnibox."; -const char kAndroidTabDeclutterName[] = "Android Tab Declutter"; -const char kAndroidTabDeclutterDescription[] = - "Enables auto-archival and deletion of inactive tabs."; +const char kAndroidTabDeclutterAutoDeleteName[] = + "Android Tab Declutter Auto Deletion"; +const char kAndroidTabDeclutterAutoDeleteDescription[] = + "Enables auto-deletion of inactive tabs."; const char kAndroidTabDeclutterArchiveAllButActiveTabName[] = "Archive all tabs except active";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 97080e12..506c53ec 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -146,6 +146,11 @@ extern const char kAndroidProgressBarVisualUpdateDescription[]; #endif // BUILDFLAG(IS_ANDROID) +#if BUILDFLAG(IS_ANDROID) +extern const char kAndroidSmsOtpFillingName[]; +extern const char kAndroidSmsOtpFillingDescription[]; +#endif // BUILDFLAG(IS_ANDROID) + #if BUILDFLAG(IS_CHROMEOS) extern const char kIgnoreDeviceFlexArcEnabledPolicyName[]; extern const char kIgnoreDeviceFlexArcEnabledPolicyDescription[]; @@ -2650,8 +2655,8 @@ extern const char kAndroidSurfaceColorUpdateName[]; extern const char kAndroidSurfaceColorUpdateDescription[]; -extern const char kAndroidTabDeclutterName[]; -extern const char kAndroidTabDeclutterDescription[]; +extern const char kAndroidTabDeclutterAutoDeleteName[]; +extern const char kAndroidTabDeclutterAutoDeleteDescription[]; extern const char kAndroidTabDeclutterArchiveAllButActiveTabName[]; extern const char kAndroidTabDeclutterArchiveAllButActiveTabDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 6f270ca..cbbb38f 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -200,10 +200,10 @@ &kAndroidOpenPdfInlineBackport, &kAndroidPdfAssistContent, &kAndroidSurfaceColorUpdate, - &kAndroidTabDeclutter, &kAndroidTabDeclutterArchiveAllButActiveTab, &kAndroidTabDeclutterArchiveDuplicateTabs, &kAndroidTabDeclutterArchiveTabGroups, + &kAndroidTabDeclutterAutoDelete, &kAndroidTabDeclutterDedupeTabIdsKillSwitch, &kAndroidTabDeclutterRescueKillswitch, &kAndroidTabDeclutterPerformanceImprovements, @@ -311,7 +311,6 @@ &kNativePageTransitionHardwareCapture, &kNavBarColorAnimation, &kNavBarColorMatchesTabBackground, - &kNavigationCaptureRefactorAndroid, &kNewTabSearchEngineUrlAndroid, &kNewTabPageAndroidTriggerForPrerender2, &kNotificationPermissionVariant, @@ -557,16 +556,12 @@ BASE_FEATURE(kAndroidPdfAssistContent, "AndroidPdfAssistContent", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kAndroidSurfaceColorUpdate, "AndroidSurfaceColorUpdate", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kAndroidTabDeclutter, - "AndroidTabDeclutter", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kAndroidTabDeclutterArchiveAllButActiveTab, "AndroidTabDeclutterArchiveAllButActiveTab", base::FEATURE_DISABLED_BY_DEFAULT); @@ -579,6 +574,10 @@ "AndroidTabDeclutterArchiveTabGroups", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kAndroidTabDeclutterAutoDelete, + "AndroidTabDeclutterAutoDelete", + base::FEATURE_ENABLED_BY_DEFAULT); + BASE_FEATURE(kAndroidTabDeclutterDedupeTabIdsKillSwitch, "AndroidTabDeclutterDedupeTabIdsKillSwitch", base::FEATURE_ENABLED_BY_DEFAULT); @@ -1012,10 +1011,6 @@ "NavBarColorMatchesTabBackground", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kNavigationCaptureRefactorAndroid, - "NavigationCaptureRefactorAndroid", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kNewTabSearchEngineUrlAndroid, "NewTabSearchEngineUrlAndroid", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index f41d050..a76bb28 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -9,7 +9,6 @@ #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" -#include "chrome/common/chrome_features.h" namespace chrome { namespace android { @@ -38,10 +37,10 @@ BASE_DECLARE_FEATURE(kAndroidOpenPdfInlineBackport); BASE_DECLARE_FEATURE(kAndroidPdfAssistContent); BASE_DECLARE_FEATURE(kAndroidSurfaceColorUpdate); -BASE_DECLARE_FEATURE(kAndroidTabDeclutter); BASE_DECLARE_FEATURE(kAndroidTabDeclutterArchiveAllButActiveTab); BASE_DECLARE_FEATURE(kAndroidTabDeclutterArchiveDuplicateTabs); BASE_DECLARE_FEATURE(kAndroidTabDeclutterArchiveTabGroups); +BASE_DECLARE_FEATURE(kAndroidTabDeclutterAutoDelete); BASE_DECLARE_FEATURE(kAndroidTabDeclutterRescueKillswitch); BASE_DECLARE_FEATURE(kAndroidTabDeclutterDedupeTabIdsKillSwitch); BASE_DECLARE_FEATURE(kAndroidTabDeclutterPerformanceImprovements); @@ -155,7 +154,6 @@ BASE_DECLARE_FEATURE(kNativePageTransitionHardwareCapture); BASE_DECLARE_FEATURE(kNavBarColorAnimation); BASE_DECLARE_FEATURE(kNavBarColorMatchesTabBackground); -BASE_DECLARE_FEATURE(kNavigationCaptureRefactorAndroid); BASE_DECLARE_FEATURE(kNewTabSearchEngineUrlAndroid); BASE_DECLARE_FEATURE(kNewTabPageAndroidTriggerForPrerender2); BASE_DECLARE_FEATURE(kNotificationPermissionVariant);
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 90fcf99..0ee2fc3 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
@@ -188,13 +188,13 @@ public static final String ANDROID_PDF_ASSIST_CONTENT = "AndroidPdfAssistContent"; public static final String ANDROID_PROGRESS_BAR_VISUAL_UPDATE = "AndroidProgressBarVisualUpdate"; public static final String ANDROID_SURFACE_COLOR_UPDATE = "AndroidSurfaceColorUpdate"; - public static final String ANDROID_TAB_DECLUTTER = "AndroidTabDeclutter"; public static final String ANDROID_TAB_DECLUTTER_ARCHIVE_ALL_BUT_ACTIVE = "AndroidTabDeclutterArchiveAllButActiveTab"; public static final String ANDROID_TAB_DECLUTTER_ARCHIVE_DUPLICATE_TABS = "AndroidTabDeclutterArchiveDuplicateTabs"; public static final String ANDROID_TAB_DECLUTTER_ARCHIVE_TAB_GROUPS = "AndroidTabDeclutterArchiveTabGroups"; + public static final String ANDROID_TAB_DECLUTTER_AUTO_DELETE = "AndroidTabDeclutterAutoDelete"; public static final String ANDROID_TAB_DECLUTTER_DEDUPE_TAB_IDS_KILL_SWITCH = "AndroidTabDeclutterDedupeTabIdsKillSwitch"; public static final String ANDROID_TAB_DECLUTTER_PERFORMANCE_IMPROVEMENTS = @@ -993,14 +993,14 @@ newMutableFlagWithSafeDefault(ANDROID_DUMP_ON_SCROLL_WITHOUT_RESOURCE, false); public static final MutableFlagWithSafeDefault sAndroidNativePagesInNewTab = newMutableFlagWithSafeDefault(ANDROID_NATIVE_PAGES_IN_NEW_TAB, false); - public static final MutableFlagWithSafeDefault sAndroidTabDeclutter = - newMutableFlagWithSafeDefault(ANDROID_TAB_DECLUTTER, true); public static final MutableFlagWithSafeDefault sAndroidTabDeclutterArchiveAllButActiveTab = newMutableFlagWithSafeDefault(ANDROID_TAB_DECLUTTER_ARCHIVE_ALL_BUT_ACTIVE, false); public static final MutableFlagWithSafeDefault sAndroidTabDeclutterArchiveDuplicateTabs = newMutableFlagWithSafeDefault(ANDROID_TAB_DECLUTTER_ARCHIVE_DUPLICATE_TABS, true); public static final MutableFlagWithSafeDefault sAndroidTabDeclutterArchiveTabGroups = newMutableFlagWithSafeDefault(ANDROID_TAB_DECLUTTER_ARCHIVE_TAB_GROUPS, false); + public static final MutableFlagWithSafeDefault sAndroidTabDeclutterAutoDelete = + newMutableFlagWithSafeDefault(ANDROID_TAB_DECLUTTER_AUTO_DELETE, false); public static final MutableFlagWithSafeDefault sAndroidTabDeclutterPerformanceImprovements = newMutableFlagWithSafeDefault(ANDROID_TAB_DECLUTTER_PERFORMANCE_IMPROVEMENTS, false); public static final MutableFlagWithSafeDefault sAndroidTabDeclutterRescueKillSwitch = @@ -1492,30 +1492,15 @@ "android_native_pages_in_new_tab_history_enabled", true); public static final MutableBooleanParamWithSafeDefault sAndroidNativePagesInNewTabRecentTabsEnabled = - sAndroidNativePagesInNewTab.newBooleanParam( - "android_native_pages_in_new_tab_recent_tabs_enabled", true); - public static final MutableBooleanParamWithSafeDefault sAndroidTabDeclutterArchiveEnabled = - sAndroidTabDeclutter.newBooleanParam("android_tab_declutter_archive_enabled", true); - public static final MutableIntParamWithSafeDefault sAndroidTabDeclutterArchiveTimeDeltaHours = - sAndroidTabDeclutter.newIntParam( - "android_tab_declutter_archive_time_delta_hours", 21 * 24); + sAndroidNativePagesInNewTab.newBooleanParam( + "android_native_pages_in_new_tab_recent_tabs_enabled", true); public static final MutableBooleanParamWithSafeDefault sAndroidTabDeclutterAutoDeleteEnabled = - sAndroidTabDeclutter.newBooleanParam( + sAndroidTabDeclutterAutoDelete.newBooleanParam( "android_tab_declutter_auto_delete_enabled", false); public static final MutableIntParamWithSafeDefault sAndroidTabDeclutterAutoDeleteTimeDeltaHours = - sAndroidTabDeclutter.newIntParam( + sAndroidTabDeclutterAutoDelete.newIntParam( "android_tab_declutter_auto_delete_time_delta_hours", 60 * 24); - public static final MutableIntParamWithSafeDefault sAndroidTabDeclutterIntervalTimeDeltaHours = - sAndroidTabDeclutter.newIntParam( - "android_tab_declutter_interval_time_delta_hours", 7 * 24); - public static final MutableIntParamWithSafeDefault sAndroidTabDeclutterMaxSimultaneousArchives = - sAndroidTabDeclutter.newIntParam( - "android_tab_declutter_max_simultaneous_archives", 100); - public static final MutableIntParamWithSafeDefault - sAndroidTabDeclutterIphMessageDismissThreshold = - sAndroidTabDeclutter.newIntParam( - "android_tab_declutter_iph_message_dismiss_threshold", 3); public static final MutableBooleanParamWithSafeDefault sDisableBottomControlsStackerYOffsetDispatching = sBottomBrowserControlsRefactor.newBooleanParam(
diff --git a/chrome/browser/glic/BUILD.gn b/chrome/browser/glic/BUILD.gn index 5f4cbd6d..3a3db741 100644 --- a/chrome/browser/glic/BUILD.gn +++ b/chrome/browser/glic/BUILD.gn
@@ -151,7 +151,8 @@ "widget/glic_widget.h", "widget/glic_window_animator.cc", "widget/glic_window_animator.h", - "widget/glic_window_controller.cc", + "widget/glic_window_controller_impl.cc", + "widget/glic_window_controller_impl.h", "widget/glic_window_hotkey_delegate.cc", "widget/glic_window_resize_animation.cc", "widget/glic_window_resize_animation.h", @@ -236,6 +237,8 @@ "test_support/interactive_glic_test.h", "test_support/interactive_test_util.cc", "test_support/interactive_test_util.h", + "test_support/mock_glic_window_controller.cc", + "test_support/mock_glic_window_controller.h", ] deps = [ ":glic",
diff --git a/chrome/browser/glic/fre/glic_fre_controller_browsertest.cc b/chrome/browser/glic/fre/glic_fre_controller_browsertest.cc index 18623bb..3c4557be 100644 --- a/chrome/browser/glic/fre/glic_fre_controller_browsertest.cc +++ b/chrome/browser/glic/fre/glic_fre_controller_browsertest.cc
@@ -163,10 +163,18 @@ EXPECT_TRUE(glic_fre_controller()->IsShowingDialog()); } +// TODO(crbug.com/402310277): Re-enable this test. +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) +#define MAYBE_FreDialogCloseAndReopenForDifferentTab \ + DISABLED_FreDialogCloseAndReopenForDifferentTab +#else +#define MAYBE_FreDialogCloseAndReopenForDifferentTab \ + FreDialogCloseAndReopenForDifferentTab +#endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) // Tests that, when the FRE dialog is already open in an inactive tab, trying to // show it in the active tab closes the existing dialog and opens a new one. IN_PROC_BROWSER_TEST_F(GlicFreControllerBrowserTest, - FreDialogCloseAndReopenForDifferentTab) { + MAYBE_FreDialogCloseAndReopenForDifferentTab) { // Open the FRE dialog in a tab. chrome::AddTabAt(browser(), GURL("about:blank"), -1, true); browser()->tab_strip_model()->ActivateTabAt(0);
diff --git a/chrome/browser/glic/glic_keyed_service.cc b/chrome/browser/glic/glic_keyed_service.cc index 0a4604d..7f3f6b60 100644 --- a/chrome/browser/glic/glic_keyed_service.cc +++ b/chrome/browser/glic/glic_keyed_service.cc
@@ -33,7 +33,7 @@ #include "chrome/browser/glic/host/host.h" #include "chrome/browser/glic/host/webui_contents_container.h" #include "chrome/browser/glic/widget/glic_widget.h" -#include "chrome/browser/glic/widget/glic_window_controller.h" +#include "chrome/browser/glic/widget/glic_window_controller_impl.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" @@ -85,10 +85,10 @@ metrics_(std::make_unique<GlicMetrics>(profile, enabling_.get())), host_(std::make_unique<Host>(profile)), window_controller_( - std::make_unique<GlicWindowController>(profile, - identity_manager, - this, - enabling_.get())), + std::make_unique<GlicWindowControllerImpl>(profile, + identity_manager, + this, + enabling_.get())), focused_tab_manager_(profile, *window_controller_), screenshot_capturer_(std::make_unique<GlicScreenshotCapturer>()), auth_controller_(std::make_unique<AuthController>(profile, @@ -210,6 +210,11 @@ } } +GlicWindowController& GlicKeyedService::window_controller() { + CHECK(window_controller_); + return *window_controller_.get(); +} + void GlicKeyedService::GuestAdded(content::WebContents* guest_contents) { host().GuestAdded(guest_contents); } @@ -386,6 +391,17 @@ actor_controller_->StopTask(); } +bool GlicKeyedService::IsActorCoordinatorActingOnTab( + const content::WebContents* tab) const { + return actor_controller_ && + actor_controller_->IsActorCoordinatorActingOnTab(tab); +} + +actor::ActorCoordinator& GlicKeyedService::GetActorCoordinatorForTesting() { + CHECK(actor_controller_); + return actor_controller_->GetActorCoordinatorForTesting(); // IN-TEST +} + void GlicKeyedService::CaptureScreenshot( mojom::WebClientHandler::CaptureScreenshotCallback callback) { screenshot_capturer_->CaptureScreenshot(
diff --git a/chrome/browser/glic/glic_keyed_service.h b/chrome/browser/glic/glic_keyed_service.h index 0fc8c24..3431c01 100644 --- a/chrome/browser/glic/glic_keyed_service.h +++ b/chrome/browser/glic/glic_keyed_service.h
@@ -21,6 +21,10 @@ class Profile; class ProfileManager; +namespace actor { +class ActorCoordinator; +} // namespace actor + namespace contextual_cueing { class ContextualCueingService; } // namespace contextual_cueing @@ -37,7 +41,7 @@ class GlicMetrics; class GlicProfileManager; class GlicScreenshotCapturer; -class GlicWindowController; +class GlicWindowControllerImpl; // The GlicKeyedService is created for each eligible (i.e. non-incognito, // non-system, etc.) browser profile if Glic flags are enabled, regardless @@ -89,7 +93,7 @@ GlicEnabling& enabling() { return *enabling_.get(); } GlicMetrics* metrics() { return metrics_.get(); } - GlicWindowController& window_controller() { return *window_controller_; } + GlicWindowController& window_controller(); // Called when a webview guest is created within a chrome://glic WebUI. void GuestAdded(content::WebContents* guest_contents); @@ -196,6 +200,13 @@ void StopActorTask(); + // Returns true if the associated ActorCoordinator is active on the given + // `tab`. This can be used by callers to customize certain behaviour that + // might interfere with the ActorCoordinator. + bool IsActorCoordinatorActingOnTab(const content::WebContents* tab) const; + + actor::ActorCoordinator& GetActorCoordinatorForTesting(); + void CaptureScreenshot( glic::mojom::WebClientHandler::CaptureScreenshotCallback callback); @@ -246,7 +257,7 @@ std::unique_ptr<GlicEnabling> enabling_; std::unique_ptr<GlicMetrics> metrics_; std::unique_ptr<Host> host_; - std::unique_ptr<GlicWindowController> window_controller_; + std::unique_ptr<GlicWindowControllerImpl> window_controller_; GlicFocusedTabManager focused_tab_manager_; std::unique_ptr<GlicScreenshotCapturer> screenshot_capturer_; std::unique_ptr<AuthController> auth_controller_;
diff --git a/chrome/browser/glic/glic_profile_manager.cc b/chrome/browser/glic/glic_profile_manager.cc index 8878639..0eb12b1 100644 --- a/chrome/browser/glic/glic_profile_manager.cc +++ b/chrome/browser/glic/glic_profile_manager.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/glic/glic_keyed_service_factory.h" #include "chrome/browser/global_features.h" #include "chrome/browser/lifetime/termination_notification.h" +#include "chrome/browser/profiles/nuke_profile_directory_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser.h" @@ -147,6 +148,9 @@ void GlicProfileManager::ShouldPreloadForProfile( Profile* profile, ShouldPreloadCallback callback) { + if (IsProfileDirectoryMarkedForDeletion(profile->GetPath())) { + return; + } if (!base::FeatureList::IsEnabled(features::kGlicWarming) || !GlicEnabling::IsReadyForProfile(profile)) { base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
diff --git a/chrome/browser/glic/host/glic_actor_controller.cc b/chrome/browser/glic/host/glic_actor_controller.cc index aab7d5c4..ccdb251 100644 --- a/chrome/browser/glic/host/glic_actor_controller.cc +++ b/chrome/browser/glic/host/glic_actor_controller.cc
@@ -101,6 +101,18 @@ actor_coordinator_->StopTask(); } +bool GlicActorController::IsActorCoordinatorActingOnTab( + const content::WebContents* tab) const { + return actor_coordinator_ && actor_coordinator_->HasTaskForTab(tab); +} + +actor::ActorCoordinator& GlicActorController::GetActorCoordinatorForTesting() { + if (!actor_coordinator_) { + actor_coordinator_ = std::make_unique<actor::ActorCoordinator>(profile_); + } + return *actor_coordinator_; +} + void GlicActorController::OnTaskStarted( const optimization_guide::proto::BrowserAction& action, const mojom::GetTabContextOptions& options,
diff --git a/chrome/browser/glic/host/glic_actor_controller.h b/chrome/browser/glic/host/glic_actor_controller.h index 5a30ae68..9776a1b 100644 --- a/chrome/browser/glic/host/glic_actor_controller.h +++ b/chrome/browser/glic/host/glic_actor_controller.h
@@ -20,6 +20,10 @@ class ActorCoordinator; } +namespace content { +class WebContents; +} // namespace content + namespace tabs { class TabInterface; } // namespace tabs @@ -42,6 +46,10 @@ void StopTask(); + bool IsActorCoordinatorActingOnTab(const content::WebContents* tab) const; + + actor::ActorCoordinator& GetActorCoordinatorForTesting(); + private: // Handles a new task being started, and then performs the action that // initiated the task.
diff --git a/chrome/browser/glic/host/glic_api_uitest.cc b/chrome/browser/glic/host/glic_api_uitest.cc index 020f4a8f..998dba19 100644 --- a/chrome/browser/glic/host/glic_api_uitest.cc +++ b/chrome/browser/glic/host/glic_api_uitest.cc
@@ -1078,56 +1078,51 @@ } IN_PROC_BROWSER_TEST_F(GlicApiTestWithOneTab, testManualResizeChanged) { - window_controller().OnWidgetUserResizeStarted(); + window_controller().GetGlicWidget()->OnNativeWidgetUserResizeStarted(); // Check that the web client is notified of the beginning of the user // initiated resizing event. ExecuteJsTest(); - window_controller().OnWidgetUserResizeEnded(); + window_controller().GetGlicWidget()->OnNativeWidgetUserResizeEnded(); // Check that the web client is notified of the ending of the user // initiated resizing event. ContinueJsTest(); } -// TODO(crbug.com/409712213): Test fails for Windows. -#if BUILDFLAG(IS_WIN) -#define MAYBE_testResizeWindowTooSmall DISABLED_testResizeWindowTooSmall -#else -#define MAYBE_testResizeWindowTooSmall testResizeWindowTooSmall -#endif -IN_PROC_BROWSER_TEST_F(GlicApiTestWithOneTab, MAYBE_testResizeWindowTooSmall) { +IN_PROC_BROWSER_TEST_F(GlicApiTestWithOneTab, testResizeWindowTooSmall) { // Web client requests the window to be resized to 0x0, bellow the minimum // dimensions (see GlicWindowController#GetLastRequestedSizeClamped), so it - // gets discarded in favor of the initial size.≈ + // gets discarded in favor of the initial size. + gfx::Size expected_size = GlicWidget::GetInitialSize(); + GlicWidget* glic_widget = window_controller().GetGlicWidget(); + ASSERT_TRUE(glic_widget); + ExecuteJsTest(); - gfx::Size initial_size = GlicWidget::GetInitialSize(); - gfx::Size min_real_size = window_controller().GetSize(); - ASSERT_EQ(initial_size.width(), min_real_size.width()); - ASSERT_EQ(initial_size.height(), min_real_size.height()); + + gfx::Rect final_widget_bounds = glic_widget->GetWindowBoundsInScreen(); + ASSERT_EQ(expected_size, + glic_widget->WidgetToVisibleBounds(final_widget_bounds).size()); } IN_PROC_BROWSER_TEST_F(GlicApiTestWithOneTab, testResizeWindowTooLarge) { - // Web client requests the window to be resized to 2000x2000, above the + // Web client requests the window to be resized to 20000x20000, above the // maximum dimensions (see GlicWindowController#GetLastRequestedSizeClamped), - // so it gets discarded in favor of the display work area. + // so it gets discarded in favor of the max size. This max size is still + // larger than the display work area so we clamp the dimensions down to fit on + // screen. ExecuteJsTest(); gfx::Rect display_bounds = display::Screen::GetScreen()->GetPrimaryDisplay().work_area(); - gfx::Size max_real_size = window_controller().GetSize(); - ASSERT_EQ(display_bounds.width(), max_real_size.width()); - ASSERT_EQ(display_bounds.height(), max_real_size.height()); + GlicWidget* glic_widget = window_controller().GetGlicWidget(); + ASSERT_TRUE(glic_widget); + gfx::Rect final_widget_bounds = glic_widget->GetWindowBoundsInScreen(); + + ASSERT_TRUE(display_bounds.Contains(final_widget_bounds)); } -// TODO(crbug.com/409712213): Test fails for Windows. -#if BUILDFLAG(IS_WIN) -#define MAYBE_testResizeWindowWithinBounds DISABLED_testResizeWindowWithinBounds -#else -#define MAYBE_testResizeWindowWithinBounds testResizeWindowWithinBounds -#endif -IN_PROC_BROWSER_TEST_F(GlicApiTestWithOneTab, - MAYBE_testResizeWindowWithinBounds) { +IN_PROC_BROWSER_TEST_F(GlicApiTestWithOneTab, testResizeWindowWithinBounds) { // Web client requests the window to be resized to 800x700, which are valid // dimensions. gfx::Size expected_size = gfx::Size(800, 700); @@ -1135,9 +1130,11 @@ {.params = base::Value(base::Value::Dict() .Set("width", expected_size.width()) .Set("height", expected_size.height()))}); - gfx::Size valid_real_size = window_controller().GetSize(); - ASSERT_EQ(expected_size.width(), valid_real_size.width()); - ASSERT_EQ(expected_size.height(), valid_real_size.height()); + GlicWidget* glic_widget = window_controller().GetGlicWidget(); + ASSERT_TRUE(glic_widget); + gfx::Rect final_widget_bounds = glic_widget->GetWindowBoundsInScreen(); + ASSERT_EQ(expected_size, + glic_widget->WidgetToVisibleBounds(final_widget_bounds).size()); } class GlicApiTestPageContextEligibilityTest : public GlicApiTest {
diff --git a/chrome/browser/glic/test_support/mock_glic_window_controller.cc b/chrome/browser/glic/test_support/mock_glic_window_controller.cc new file mode 100644 index 0000000..0c8f9a0f --- /dev/null +++ b/chrome/browser/glic/test_support/mock_glic_window_controller.cc
@@ -0,0 +1,12 @@ +// 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/glic/test_support/mock_glic_window_controller.h" + +namespace glic { + +MockGlicWindowController::MockGlicWindowController() = default; +MockGlicWindowController::~MockGlicWindowController() = default; + +} // namespace glic
diff --git a/chrome/browser/glic/test_support/mock_glic_window_controller.h b/chrome/browser/glic/test_support/mock_glic_window_controller.h new file mode 100644 index 0000000..5950a806 --- /dev/null +++ b/chrome/browser/glic/test_support/mock_glic_window_controller.h
@@ -0,0 +1,85 @@ +// 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_GLIC_TEST_SUPPORT_MOCK_GLIC_WINDOW_CONTROLLER_H_ +#define CHROME_BROWSER_GLIC_TEST_SUPPORT_MOCK_GLIC_WINDOW_CONTROLLER_H_ + +#include "chrome/browser/glic/widget/glic_window_controller.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace glic { + +class MockGlicWindowController + : public testing::NiceMock<GlicWindowController> { + public: + MockGlicWindowController(); + ~MockGlicWindowController(); + + MOCK_METHOD(void, + Toggle, + (BrowserWindowInterface*, bool, mojom::InvocationSource), + (override)); + MOCK_METHOD(void, ShowAfterSignIn, (base::WeakPtr<Browser>), (override)); + MOCK_METHOD(void, + ToggleWhenNotAlwaysDetached, + (Browser*, bool, mojom::InvocationSource), + (override)); + MOCK_METHOD(void, FocusIfOpen, (), (override)); + MOCK_METHOD(void, Attach, (), (override)); + MOCK_METHOD(void, Detach, (), (override)); + MOCK_METHOD(void, Shutdown, (), (override)); + MOCK_METHOD(void, + Resize, + (const gfx::Size&, base::TimeDelta, base::OnceClosure), + (override)); + MOCK_METHOD(void, EnableDragResize, (bool), (override)); + MOCK_METHOD(gfx::Size, GetSize, (), (override)); + MOCK_METHOD(void, + SetDraggableAreas, + (const std::vector<gfx::Rect>&), + (override)); + MOCK_METHOD(void, SetMinimumWidgetSize, (const gfx::Size&), (override)); + MOCK_METHOD(void, Close, (), (override)); + MOCK_METHOD(void, CloseWithReason, (views::Widget::ClosedReason), (override)); + MOCK_METHOD(void, ShowTitleBarContextMenuAt, (gfx::Point), (override)); + MOCK_METHOD(bool, + ShouldStartDrag, + (const gfx::Point&, const gfx::Point&), + (override)); + MOCK_METHOD(void, HandleWindowDragWithOffset, (gfx::Vector2d), (override)); + MOCK_METHOD(const mojom::PanelState&, GetPanelState, (), (const, override)); + MOCK_METHOD(void, AddStateObserver, (StateObserver*), (override)); + MOCK_METHOD(void, RemoveStateObserver, (StateObserver*), (override)); + MOCK_METHOD(bool, IsActive, (), (override)); + MOCK_METHOD(bool, IsShowing, (), (const, override)); + MOCK_METHOD(bool, IsPanelOrFreShowing, (), (const, override)); + MOCK_METHOD(bool, IsAttached, (), (const, override)); + MOCK_METHOD(bool, IsDetached, (), (const, override)); + MOCK_METHOD(base::CallbackListSubscription, + AddWindowActivationChangedCallback, + (WindowActivationChangedCallback), + (override)); + MOCK_METHOD(void, Preload, (), (override)); + MOCK_METHOD(void, PreloadFre, (), (override)); + MOCK_METHOD(void, Reload, (), (override)); + MOCK_METHOD(bool, IsWarmed, (), (const, override)); + MOCK_METHOD(base::WeakPtr<GlicWindowController>, GetWeakPtr, (), (override)); + MOCK_METHOD(GlicView*, GetGlicView, (), (override)); + MOCK_METHOD(GlicWidget*, GetGlicWidget, (), (override)); + MOCK_METHOD(content::WebContents*, GetFreWebContents, (), (override)); + MOCK_METHOD(Browser*, attached_browser, (), (override)); + MOCK_METHOD(State, state, (), (const, override)); + MOCK_METHOD(GlicFreController*, fre_controller, (), (override)); + MOCK_METHOD(GlicWindowAnimator*, window_animator, (), (override)); + MOCK_METHOD(Profile*, profile, (), (override)); + MOCK_METHOD(bool, IsDragging, (), (override)); + MOCK_METHOD(void, ShowGlicModal, (std::u16string), (override)); + MOCK_METHOD(gfx::Rect, GetInitialBounds, (Browser*), (override)); + MOCK_METHOD(void, ShowDetachedForTesting, (), (override)); + MOCK_METHOD(void, SetPreviousPositionForTesting, (gfx::Point), (override)); +}; +} // namespace glic + +#endif // CHROME_BROWSER_GLIC_TEST_SUPPORT_MOCK_GLIC_WINDOW_CONTROLLER_H_
diff --git a/chrome/browser/glic/widget/glic_widget.cc b/chrome/browser/glic/widget/glic_widget.cc index 9b541a92..bd99a36 100644 --- a/chrome/browser/glic/widget/glic_widget.cc +++ b/chrome/browser/glic/widget/glic_widget.cc
@@ -45,7 +45,7 @@ gfx::Outsets outsets; #if BUILDFLAG(IS_WIN) RECT bounds_rect = bounds.ToRECT(); - int frame_thickness = ui::GetResizeFrameOnlyThickness( + int frame_thickness = ui::GetFrameThickness( MonitorFromRect(&bounds_rect, MONITOR_DEFAULTTONEAREST)); // On Windows, the presence of a frame means that we need to adjust both the // width and height of the widget by 2*frame thickness, and center the content
diff --git a/chrome/browser/glic/widget/glic_window_controller.h b/chrome/browser/glic/widget/glic_window_controller.h index f388e2c3..ad9d3a2d 100644 --- a/chrome/browser/glic/widget/glic_window_controller.h +++ b/chrome/browser/glic/widget/glic_window_controller.h
@@ -25,37 +25,32 @@ #include "chrome/browser/glic/widget/local_hotkey_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_window/public/browser_window_interface.h" +#include "chrome/common/chrome_features.h" #include "content/public/browser/web_contents.h" #include "ui/base/interaction/element_tracker.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" class Browser; -class WindowFinder; namespace gfx { class Size; class Point; } // namespace gfx namespace glic { - // Distance the detached window should be from the top and the right of the // display when opened unassociated to a browser. inline constexpr static int kDefaultDetachedTopRightDistance = 48; DECLARE_CUSTOM_ELEMENT_EVENT_TYPE(kGlicWidgetAttached); -class GlicEnabling; class GlicWidget; class GlicKeyedService; class GlicView; class GlicWindowAnimator; -class ScopedGlicButtonIndicator; class GlicFreController; -class GlicButton; class Host; enum class AttachChangeReason; -class GlicModalManager; // This class owns and manages the glic window. This class has the same lifetime // as the GlicKeyedService, so it exists if and only if the profile exists. @@ -63,9 +58,7 @@ // See the |State| enum below for the lifecycle of the window. When the glic // window is open |attached_browser_| indicates if the window is attached or // standalone. See |IsAttached| -class GlicWindowController : public views::WidgetObserver, - public Host::Observer, - public Host::Delegate { +class GlicWindowController : public Host::Delegate { public: // Observes the state of the glic window. class StateObserver : public base::CheckedObserver { @@ -76,160 +69,141 @@ GlicWindowController(const GlicWindowController&) = delete; GlicWindowController& operator=(const GlicWindowController&) = delete; - - GlicWindowController(Profile* profile, - signin::IdentityManager* identity_manager, - GlicKeyedService* service, - GlicEnabling* enabling); - ~GlicWindowController() override; + GlicWindowController() = default; + ~GlicWindowController() = default; // Show, summon, or activate the panel if needed, or close it if it's already // active and prevent_close is false. - void Toggle(BrowserWindowInterface* browser, - bool prevent_close, - mojom::InvocationSource source); + virtual void Toggle(BrowserWindowInterface* browser, + bool prevent_close, + mojom::InvocationSource source) = 0; // If the panel is opened, but sign-in is required, we provide a sign-in // button which closes the panel. This is called after the user signs in to // open the panel again. - void ShowAfterSignIn(base::WeakPtr<Browser> browser); + virtual void ShowAfterSignIn(base::WeakPtr<Browser> browser) = 0; // Handle Toggle when AlwaysDetached is true. - void ToggleWhenNotAlwaysDetached(Browser* new_attached_browser, - bool prevent_close, - mojom::InvocationSource source); + virtual void ToggleWhenNotAlwaysDetached(Browser* new_attached_browser, + bool prevent_close, + mojom::InvocationSource source) = 0; - void FocusIfOpen(); + virtual void FocusIfOpen() = 0; // Attaches glic to the last focused Chrome window. - void Attach(); + virtual void Attach() = 0; // Detaches glic if attached and moves it to the top right of the current // display. - void Detach(); + virtual void Detach() = 0; // Destroy the glic panel and its web contents. - void Shutdown(); + virtual void Shutdown() = 0; // Sets the size of the glic window to the specified dimensions. Callback runs // when the animation finishes or is destroyed, or soon if the window // doesn't exist yet. In this last case `size` will be used for the initial // size when creating the widget later. - void Resize(const gfx::Size& size, - base::TimeDelta duration, - base::OnceClosure callback); + virtual void Resize(const gfx::Size& size, + base::TimeDelta duration, + base::OnceClosure callback) = 0; // Allows the user to manually resize the widget by dragging. If the widget // hasn't been created yet, apply this setting when it is created. No effect // if the widget doesn't exist or the feature flag is disabled. - void EnableDragResize(bool enabled); + virtual void EnableDragResize(bool enabled) = 0; // Returns the current size of the glic window. - gfx::Size GetSize(); + virtual gfx::Size GetSize() = 0; // Sets the areas of the view from which it should be draggable. - void SetDraggableAreas(const std::vector<gfx::Rect>& draggable_areas); + virtual void SetDraggableAreas( + const std::vector<gfx::Rect>& draggable_areas) = 0; // Sets the minimum widget size that the widget will allow the user to resize // to. - void SetMinimumWidgetSize(const gfx::Size& size); + virtual void SetMinimumWidgetSize(const gfx::Size& size) = 0; // Close the panel but keep the glic WebContents alive in the background. - void Close(); + virtual void Close() = 0; // Used when the native window is closed directly. - void CloseWithReason(views::Widget::ClosedReason reason); - - // Sets the audio ducking status. Returns true if the operation succeeded. - bool SetAudioDucking(bool enabled); + virtual void CloseWithReason(views::Widget::ClosedReason reason) = 0; // Displays a context menu when the user right clicks on the title bar. // This is probably Windows only. - void ShowTitleBarContextMenuAt(gfx::Point event_loc); + virtual void ShowTitleBarContextMenuAt(gfx::Point event_loc) = 0; // Returns true if the mouse has been dragged more than a minimum distance // from `initial_press_loc`, so a mouse down followed by a move of less than // the minimum number of pixels doesn't start a window drag. - bool ShouldStartDrag(const gfx::Point& initial_press_loc, - const gfx::Point& mouse_location); + virtual bool ShouldStartDrag(const gfx::Point& initial_press_loc, + const gfx::Point& mouse_location) = 0; // Drags the glic window following the current mouse location with the given // `mouse_offset` and checks if the glic window is at a position where it // could attach to a browser window when a drag ends. - void HandleWindowDragWithOffset(gfx::Vector2d mouse_offset); + virtual void HandleWindowDragWithOffset(gfx::Vector2d mouse_offset) = 0; // Host::Delegate implementation. - const mojom::PanelState& GetPanelState() const override; + const mojom::PanelState& GetPanelState() const override = 0; - void AddStateObserver(StateObserver* observer); - void RemoveStateObserver(StateObserver* observer); + virtual void AddStateObserver(StateObserver* observer) = 0; + virtual void RemoveStateObserver(StateObserver* observer) = 0; // Returns whether the views::Widget associated with the glic window is active // (e.g. will receive keyboard events). - bool IsActive(); + virtual bool IsActive() = 0; // Returns true if the state is anything other than kClosed. - // Virtual for testing. - virtual bool IsShowing() const; + virtual bool IsShowing() const = 0; // Returns true if either the glic panel or the FRE are showing. - virtual bool IsPanelOrFreShowing() const; + virtual bool IsPanelOrFreShowing() const = 0; // Returns whether or not the glic window is currently attached to a browser. // Virtual for testing. - virtual bool IsAttached() const; + virtual bool IsAttached() const = 0; // Returns wehether or not the glic window is currently showing detached. - bool IsDetached() const; + virtual bool IsDetached() const = 0; using WindowActivationChangedCallback = base::RepeatingCallback<void(bool active)>; // Registers |callback| to be called whenever the window activation changes. - base::CallbackListSubscription AddWindowActivationChangedCallback( - WindowActivationChangedCallback callback); + virtual base::CallbackListSubscription AddWindowActivationChangedCallback( + WindowActivationChangedCallback callback) = 0; // Warms the glic web contents. - void Preload(); + virtual void Preload() = 0; // Warms the fre web contents. - void PreloadFre(); + virtual void PreloadFre() = 0; // Reloads the glic web contents or the FRE's web contents (depending on // which is currently visible). - void Reload(); + virtual void Reload() = 0; // Returns whether or not the glic web contents are loaded (this can also be // true if `IsActive()` (i.e., if the contents are loaded in the glic window). - bool IsWarmed() const; + virtual bool IsWarmed() const = 0; // Returns a WeakPtr to this instance. It can be destroyed at any time if the // profile is deleted or if the browser shuts down. - base::WeakPtr<GlicWindowController> GetWeakPtr(); + virtual base::WeakPtr<GlicWindowController> GetWeakPtr() = 0; - // views::WidgetObserver implementation, monitoring the glic window widget. - void OnWidgetActivationChanged(views::Widget* widget, bool active) override; - void OnWidgetDestroyed(views::Widget* widget) override; - void OnWidgetBoundsChanged(views::Widget* widget, - const gfx::Rect& new_bounds) override; - void OnWidgetUserResizeStarted() override; - void OnWidgetUserResizeEnded() override; - - GlicView* GetGlicView(); - - // Called when the programmatic resize has finished. Public for use by - // GlicWindowResizeAnimation. - void ResizeFinished(); + virtual GlicView* GetGlicView() = 0; // Returns the widget that backs the glic window. - GlicWidget* GetGlicWidget(); + virtual GlicWidget* GetGlicWidget() = 0; // Returns the WebContents used for the first-run experience, or nullptr if // none. - content::WebContents* GetFreWebContents(); + virtual content::WebContents* GetFreWebContents() = 0; // Return the Browser to which the panel is attached, or null if detached. - Browser* attached_browser() { return attached_browser_; } + virtual Browser* attached_browser() = 0; // Possible states for the glic window. Public for testing. // * Closed (aka hidden, invisible) @@ -249,242 +223,27 @@ kClosingToReopenDetached, kCloseAnimation, }; - State state() const { return state_; } + virtual State state() const = 0; - void ShowDetachedForTesting(); + virtual GlicFreController* fre_controller() = 0; - GlicFreController* fre_controller() { return fre_controller_.get(); } + virtual GlicWindowAnimator* window_animator() = 0; - GlicWindowAnimator* window_animator() { return glic_window_animator_.get(); } + virtual Profile* profile() = 0; - Profile* profile() { return profile_; } + virtual bool IsDragging() = 0; + + virtual void ShowGlicModal(std::u16string label) = 0; + + virtual gfx::Rect GetInitialBounds(Browser* browser) = 0; + + virtual void ShowDetachedForTesting() = 0; + virtual void SetPreviousPositionForTesting(gfx::Point position) = 0; // Helper function to get the always detached flag. - static bool AlwaysDetached(); - - bool IsDragging() { return in_move_loop_; } - - void ShowGlicModal(std::u16string label); - - private: - FRIEND_TEST_ALL_PREFIXES(GlicWindowControllerUiTest, TestInitialBounds); - FRIEND_TEST_ALL_PREFIXES(GlicWindowControllerWithPreviousPostionUiTest, - TestInitialBounds); - - Host& host() const; - - // Sets the floating attributes of the glic window. - // - // When set to true, the glic window is set to have a `kFloatingWindow` - // z-order, and on the Mac is set to be "activation independent" (to allow the - // user to interact with it without causing Chromium to be activated), and - // visible on every space (including fullscreen ones). - // - // When set to false, the glic window is set to have a `kNormal` z-order, and - // on the Mac, all special activation and visibility properties are cleared. - void SetGlicWindowToFloatingMode(bool floating); - - gfx::Rect GetInitialBounds(Browser* browser); - - // Return the default detached bounds which are just below the tab strip - // button on the active browser. - std::optional<gfx::Rect> GetInitialDetachedBoundsFromBrowser( - Browser* browser, - const gfx::Size& target_size); - - // Return the default detached bounds when there is no active browser. The - // position is relative to the top right of the current display. - gfx::Rect GetInitialDetachedBoundsNoBrowser(const gfx::Size& target_size); - - // Return the default bounds when attached to the browser which cover the tab - // strip button on the active browser. - gfx::Rect GetInitialAttachedBounds(Browser& browser); - - // Creates the glic view, waits for the web client to initialize, and then - // shows the glic window. If `browser` is non-nullptr then glic will be - // attached to the browser. Otherwise glic will be detached. - void Show(Browser* browser, mojom::InvocationSource source); - - // Close the widget and reopen in detached mode. - void CloseAndReopenDetached(mojom::InvocationSource source); - - void SetupGlicWidget(Browser* browser); - void SetupGlicWidgetAccessibilityText(); - - // Host::Observer implementation. - void WebClientInitializeFailed() override; - void LoginPageCommitted() override; - void ClientReadyToShow(const mojom::OpenPanelInfo& open_info) override; - - // Called once glic is completely loaded and any animations have finished. - // This is the end of the opening process and |state_| will be set to kOpen. - void GlicLoadedAndReadyToDisplay(); - - void SetDraggingAreasAndWatchForMouseEvents(); - - // Internal closing implementation. reopen_detached_source must be set - // if and only if the internal state is kClosingToReopenDetached. - void CloseInternal( - std::optional<mojom::InvocationSource> reopen_detached_source); - - // Finishes closing off the widget after running the closing animation. - void CloseFinish( - bool reopen_detached, - std::optional<mojom::InvocationSource> reopen_detached_source); - - // Called when the Detach() animation ends. - void DetachFinished(); - - // Causes an immediate close (eg, for during shutdown). - void ForceClose(); - - // Save the top-right corner position for re-opening. - void SaveWidgetPosition(); - - // Clear the previous position if the widget would not be on an existing - // display when shown. - void MaybeResetPreviousPosition(const gfx::Size& target_size); - - // Determines the correct position for the glic window when attached to a - // browser window. The top right of the widget should be placed here. - gfx::Point GetTopRightPositionForAttachedGlicWindow(GlicButton* glic_button); - - // Runs an animation to move glic to its target position. - // TODO(crbug.com/410629338): Reimplement attachment. - void AttachToBrowser(Browser& browser, AttachChangeReason reason); - - // Keep part of glic window within the visible region. - void AdjustPositionIfNeeded(); - - // Handles end-of-drag: - // - If glic is within attachment distance of a browser window's glic button, - // attach the glic window to the button's position. - // - If glic is still detached and has moved to a display with a different - // work area size, possibly resize the window. - void OnDragComplete(); - - // Finds a browser within attachment distance of glic to toggle the attachment - // indicator. - void HandleGlicButtonIndicator(); - - // Find and return a browser within attachment distance. Returns nullptr if no - // browsers are within attachment distance. - Browser* FindBrowserForAttachment(); - - // Updates the position of the glic window to that of the glic button of - // `browser`'s window. This position change is animated if `animate` is true. - void MovePositionToBrowserGlicButton(const Browser& browser, bool animate); - - // Called when the move animation finishes when attaching. - void AttachAnimationFinished(); - - // This method should be called anytime: - // * state_ transitions to or from kClosed. - // * attached_browser_ changes. - void NotifyIfPanelStateChanged(); - mojom::PanelState ComputePanelState() const; - - // When the attached browser is closed, this is invoked so we can clean up. - void AttachedBrowserDidClose(BrowserWindowInterface* browser); - - // Returns true if a browser is occluded at point in screen coordinates. - bool IsBrowserOccludedAtPoint(Browser* browser, gfx::Point point); - - // Return the last size Resize() was called with, or the default initial size - // if Resize() hasn't been called. The return value is clamped to fit between - // the minimum and maximum sizes. - gfx::Size GetLastRequestedSizeClamped() const; - - // Possibly adjusts the size of the window appropriate for the current - // display workspace, but only if it's different than the current target size. - void MaybeAdjustSizeForDisplay(bool animate); - - // Modifies `state_` to the given new state. - void SetWindowState(State new_state); - - // Returns true of the window is showing and the content is loaded. - bool IsWindowOpenAndReady(); - - // Observes the glic widget. - base::ScopedObservation<views::Widget, views::WidgetObserver> - glic_widget_observation_{this}; - - // Used for observing closing of the pinned browser. - std::optional<base::CallbackListSubscription> browser_close_subscription_; - - // List of callbacks to be notified when window activation has changed. - base::RepeatingCallbackList<void(bool)> window_activation_callback_list_; - - const raw_ptr<Profile> profile_; - - // Contains the glic webview. - std::unique_ptr<GlicWidget> glic_widget_; - - std::unique_ptr<GlicWindowAnimator> glic_window_animator_; - - // True if we've hit a login page (and have not yet shown). - bool login_page_committed_ = false; - - // This member contains the last size that glic requested. This should be - // reset every time glic is closed but is currently cached. - std::optional<gfx::Size> glic_size_; - - // Whether the widget should be user resizable, kept here in case it's - // specified before the widget is created. - bool user_resizable_ = true; - - // Used to monitor key and mouse events from native window. - class WindowEventObserver; - std::unique_ptr<WindowEventObserver> window_event_observer_; - - // True while RunMoveLoop() has been called on a widget. - bool in_move_loop_ = false; - - // This is the last panel state sent to observers. It should only be updated - // in `NotifyIfPanelStateChanged`. - mojom::PanelState panel_state_; - - raw_ptr<GlicWebClientAccess> web_client_; - - // Modified only by calling `SetWindowState`. - State state_ = State::kClosed; - - // If State != kClosed, then the UI must either be associated with a browser - // window, or standalone. That is tracked by this member. - raw_ptr<Browser> attached_browser_ = nullptr; - - base::ObserverList<StateObserver> state_observers_; - - // The announcement should happen the first time focus is lost after the FRE. - bool do_focus_loss_announcement_ = false; - - // Whether the user is currently drag-resizing the widget. - bool user_resizing_ = false; - - // The invocation source requesting the opening of the web client. Note that - // this value is retained until it is consumed by the web client. Because - // opening the glic window may not actually load the client, there's no - // guarantee that this value is sent to the web client. - std::optional<mojom::InvocationSource> opening_source_; - - std::optional<gfx::Point> previous_position_ = std::nullopt; - - std::unique_ptr<ScopedGlicButtonIndicator> scoped_glic_button_indicator_; - - std::unique_ptr<GlicFreController> fre_controller_; - - std::unique_ptr<WindowFinder> window_finder_; - - std::unique_ptr<GlicModalManager> glic_modal_manager_; - - std::unique_ptr<LocalHotkeyManager> application_hotkey_manager_; - std::unique_ptr<LocalHotkeyManager> glic_window_hotkey_manager_; - - raw_ptr<GlicKeyedService> glic_service_; // Owns this. - raw_ptr<GlicEnabling> enabling_; - base::ScopedObservation<Host, Host::Observer> host_observation_{this}; - - base::WeakPtrFactory<GlicWindowController> weak_ptr_factory_{this}; + static bool AlwaysDetached() { + return base::FeatureList::IsEnabled(features::kGlicDetached); + } }; } // namespace glic
diff --git a/chrome/browser/glic/widget/glic_window_controller.cc b/chrome/browser/glic/widget/glic_window_controller_impl.cc similarity index 86% rename from chrome/browser/glic/widget/glic_window_controller.cc rename to chrome/browser/glic/widget/glic_window_controller_impl.cc index 54b8d25..d32eb26 100644 --- a/chrome/browser/glic/widget/glic_window_controller.cc +++ b/chrome/browser/glic/widget/glic_window_controller_impl.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 "chrome/browser/glic/widget/glic_window_controller.h" +#include "chrome/browser/glic/widget/glic_window_controller_impl.h" #include <algorithm> @@ -168,7 +168,7 @@ } // namespace // Helper class for observing mouse and key events from native window. -class GlicWindowController::WindowEventObserver : public ui::EventObserver { +class GlicWindowControllerImpl::WindowEventObserver : public ui::EventObserver { public: WindowEventObserver(glic::GlicWindowController* glic_window_controller, glic::GlicView* glic_view) @@ -287,7 +287,7 @@ gfx::Point initial_press_loc_; }; -GlicWindowController::GlicWindowController( +GlicWindowControllerImpl::GlicWindowControllerImpl( Profile* profile, signin::IdentityManager* identity_manager, GlicKeyedService* glic_service, @@ -304,9 +304,9 @@ host_observation_.Observe(&glic_service_->host()); } -GlicWindowController::~GlicWindowController() = default; +GlicWindowControllerImpl::~GlicWindowControllerImpl() = default; -void GlicWindowController::WebClientInitializeFailed() { +void GlicWindowControllerImpl::WebClientInitializeFailed() { if (state_ == State::kWaitingForGlicToLoad) { // TODO(crbug.com/388328847): The web client failed to initialize. Decide // what the fallback behavior is. Additionally, we probably need some kind @@ -319,7 +319,7 @@ } } -void GlicWindowController::LoginPageCommitted() { +void GlicWindowControllerImpl::LoginPageCommitted() { login_page_committed_ = true; if (state_ == State::kWaitingForGlicToLoad && !host().IsReady()) { // TODO(crbug.com/388328847): Temporarily allow showing the UI when a login @@ -330,8 +330,8 @@ } // Monitoring the glic widget. -void GlicWindowController::OnWidgetActivationChanged(views::Widget* widget, - bool active) { +void GlicWindowControllerImpl::OnWidgetActivationChanged(views::Widget* widget, + bool active) { if (GetGlicWidget() != widget) { return; } @@ -350,20 +350,21 @@ } // Monitoring the glic widget. -void GlicWindowController::OnWidgetDestroyed(views::Widget* widget) { +void GlicWindowControllerImpl::OnWidgetDestroyed(views::Widget* widget) { // This is used to handle the case where the native window is closed // directly (e.g., Windows context menu close on the title bar). // Conceptually this should synchronously call Close(), but the Widget // implementation currently does not support this. if (GetGlicWidget() == widget) { base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&GlicWindowController::Close, + FROM_HERE, base::BindOnce(&GlicWindowControllerImpl::Close, weak_ptr_factory_.GetWeakPtr())); } } -void GlicWindowController::OnWidgetBoundsChanged(views::Widget* widget, - const gfx::Rect& new_bounds) { +void GlicWindowControllerImpl::OnWidgetBoundsChanged( + views::Widget* widget, + const gfx::Rect& new_bounds) { if (in_move_loop_ && !AlwaysDetached()) { // While in a move loop, look for nearby browsers to toggle the drop to // attach indicator. @@ -371,7 +372,7 @@ } } -void GlicWindowController::OnWidgetUserResizeStarted() { +void GlicWindowControllerImpl::OnWidgetUserResizeStarted() { user_resizing_ = true; glic_service_->metrics()->OnWidgetUserResizeStarted(); if (GlicWebClientAccess* client = host().GetPrimaryWebClient()) { @@ -379,7 +380,7 @@ } } -void GlicWindowController::OnWidgetUserResizeEnded() { +void GlicWindowControllerImpl::OnWidgetUserResizeEnded() { glic_service_->metrics()->OnWidgetUserResizeEnded(); if (GlicWebClientAccess* client = host().GetPrimaryWebClient()) { client->ManualResizeChanged(false); @@ -397,16 +398,16 @@ user_resizing_ = false; } -void GlicWindowController::ShowAfterSignIn(base::WeakPtr<Browser> browser) { +void GlicWindowControllerImpl::ShowAfterSignIn(base::WeakPtr<Browser> browser) { Toggle(browser.get(), true, // Prefer the source that triggered the sign-in, but if that's not // available, report it as coming from the sign-in flow. opening_source_.value_or(mojom::InvocationSource::kAfterSignIn)); } -void GlicWindowController::Toggle(BrowserWindowInterface* bwi, - bool prevent_close, - mojom::InvocationSource source) { +void GlicWindowControllerImpl::Toggle(BrowserWindowInterface* bwi, + bool prevent_close, + mojom::InvocationSource source) { // If `bwi` is non-null, the glic button was clicked on a specific window and // glic should be attached to that window. Otherwise glic was invoked from the // hotkey or other OS-level entrypoint. @@ -479,7 +480,7 @@ } } -void GlicWindowController::ToggleWhenNotAlwaysDetached( +void GlicWindowControllerImpl::ToggleWhenNotAlwaysDetached( Browser* new_attached_browser, bool prevent_close, mojom::InvocationSource source) { @@ -566,30 +567,36 @@ } } -void GlicWindowController::FocusIfOpen() { +void GlicWindowControllerImpl::FocusIfOpen() { if (IsShowing() && !IsActive()) { GetGlicWidget()->Activate(); GetGlicView()->web_view()->GetWebContents()->Focus(); } } -void GlicWindowController::ShowDetachedForTesting() { +void GlicWindowControllerImpl::ShowDetachedForTesting() { glic::GlicProfileManager::GetInstance()->SetActiveGlic(glic_service_); Show(nullptr, mojom::InvocationSource::kOsHotkey); } -Host& GlicWindowController::host() const { +void GlicWindowControllerImpl::SetPreviousPositionForTesting( + gfx::Point position) { + previous_position_ = position; +} + +Host& GlicWindowControllerImpl::host() const { return glic_service_->host(); } -void GlicWindowController::Show(Browser* browser, - mojom::InvocationSource source) { +void GlicWindowControllerImpl::Show(Browser* browser, + mojom::InvocationSource source) { // At this point State must be kClosed, and all glic window state must be // unset. CHECK(!attached_browser_); opening_source_ = source; if (!glic_service_->GetAuthController().CheckAuthBeforeShowSync( - base::BindOnce(&GlicWindowController::ShowAfterSignIn, GetWeakPtr(), + base::BindOnce(&GlicWindowControllerImpl::ShowAfterSignIn, + weak_ptr_factory_.GetWeakPtr(), browser ? browser->AsWeakPtr() : nullptr))) { return; } @@ -626,16 +633,11 @@ glic_service_->metrics()->OnGlicWindowShown(); } -// static -bool GlicWindowController::AlwaysDetached() { - return base::FeatureList::IsEnabled(features::kGlicDetached); -} - -void GlicWindowController::ShowGlicModal(std::u16string label) { +void GlicWindowControllerImpl::ShowGlicModal(std::u16string label) { glic_modal_manager_->ShowModal(std::move(label), glic_widget_.get()); } -void GlicWindowController::SetupGlicWidget(Browser* browser) { +void GlicWindowControllerImpl::SetupGlicWidget(Browser* browser) { auto initial_bounds = GetInitialBounds(browser); glic_window_hotkey_manager_ = MakeGlicWindowHotkeyManager(GetWeakPtr()); glic_widget_ = GlicWidget::Create(profile_, initial_bounds, @@ -668,13 +670,13 @@ // bug where the window position was not restored after closing with the // context menu close menu item. GetGlicWidget()->MakeCloseSynchronous(base::BindOnce( - &GlicWindowController::CloseWithReason, base::Unretained(this))); + &GlicWindowControllerImpl::CloseWithReason, base::Unretained(this))); // Immediately hook up the WebView to the WebContents. GetGlicView()->SetWebContents(host().webui_contents()); } -void GlicWindowController::SetupGlicWidgetAccessibilityText() { +void GlicWindowControllerImpl::SetupGlicWidgetAccessibilityText() { auto* widget_delegate = glic_widget_->widget_delegate(); if (opening_source_ == mojom::InvocationSource::kFre) { widget_delegate->SetAccessibleTitle( @@ -689,7 +691,7 @@ } } -void GlicWindowController::SetGlicWindowToFloatingMode(bool floating) { +void GlicWindowControllerImpl::SetGlicWindowToFloatingMode(bool floating) { GetGlicWidget()->SetZOrderLevel(floating ? ui::ZOrderLevel::kFloatingWindow : ui::ZOrderLevel::kNormal); #if BUILDFLAG(IS_MAC) @@ -699,7 +701,7 @@ #endif } -gfx::Rect GlicWindowController::GetInitialBounds(Browser* browser) { +gfx::Rect GlicWindowControllerImpl::GetInitialBounds(Browser* browser) { if (browser && !AlwaysDetached()) { return GetInitialAttachedBounds(*browser); } @@ -721,7 +723,7 @@ GetInitialDetachedBoundsNoBrowser(target_size)); } -gfx::Rect GlicWindowController::GetInitialDetachedBoundsNoBrowser( +gfx::Rect GlicWindowControllerImpl::GetInitialDetachedBoundsNoBrowser( const gfx::Size& target_size) { // Get the default position offset equal distances from the top right corner // of the work area (which excludes system UI such as the taskbar). @@ -733,7 +735,7 @@ return {{initial_x, initial_y}, target_size}; } -gfx::Rect GlicWindowController::GetInitialAttachedBounds(Browser& browser) { +gfx::Rect GlicWindowControllerImpl::GetInitialAttachedBounds(Browser& browser) { GlicButton* glic_button = GetGlicButton(browser); CHECK(glic_button); @@ -754,7 +756,7 @@ } std::optional<gfx::Rect> -GlicWindowController::GetInitialDetachedBoundsFromBrowser( +GlicWindowControllerImpl::GetInitialDetachedBoundsFromBrowser( Browser* browser, const gfx::Size& target_size) { if (!browser) { @@ -776,7 +778,7 @@ : std::nullopt; } -void GlicWindowController::ClientReadyToShow( +void GlicWindowControllerImpl::ClientReadyToShow( const mojom::OpenPanelInfo& open_info) { DVLOG(1) << "Glic client ready to show " << open_info.web_client_mode; glic_service_->metrics()->set_starting_mode(open_info.web_client_mode); @@ -791,7 +793,7 @@ } } -void GlicWindowController::GlicLoadedAndReadyToDisplay() { +void GlicWindowControllerImpl::GlicLoadedAndReadyToDisplay() { login_page_committed_ = false; if (state_ == State::kClosed || state_ == State::kOpen) { return; @@ -817,7 +819,7 @@ NotifyIfPanelStateChanged(); } -void GlicWindowController::SetDraggingAreasAndWatchForMouseEvents() { +void GlicWindowControllerImpl::SetDraggingAreasAndWatchForMouseEvents() { if (window_event_observer_) { return; } @@ -830,34 +832,34 @@ {{0, 0, GetGlicView()->width(), GlicWidget::GetInitialSize().height()}}); } -GlicView* GlicWindowController::GetGlicView() { +GlicView* GlicWindowControllerImpl::GetGlicView() { if (!GetGlicWidget()) { return nullptr; } return static_cast<GlicView*>(GetGlicWidget()->GetContentsView()); } -GlicWidget* GlicWindowController::GetGlicWidget() { +GlicWidget* GlicWindowControllerImpl::GetGlicWidget() { return glic_widget_.get(); } -content::WebContents* GlicWindowController::GetFreWebContents() { +content::WebContents* GlicWindowControllerImpl::GetFreWebContents() { return fre_controller_->GetWebContents(); } -gfx::Point GlicWindowController::GetTopRightPositionForAttachedGlicWindow( +gfx::Point GlicWindowControllerImpl::GetTopRightPositionForAttachedGlicWindow( GlicButton* glic_button) { // The widget should be placed so its top right corner matches the visible top // right corner of the glic button. return glic_button->GetBoundsWithInset().top_right(); } -void GlicWindowController::AttachedBrowserDidClose( +void GlicWindowControllerImpl::AttachedBrowserDidClose( BrowserWindowInterface* browser) { ForceClose(); } -void GlicWindowController::Attach() { +void GlicWindowControllerImpl::Attach() { if (!GetGlicWidget()) { return; } @@ -873,7 +875,7 @@ AttachToBrowser(*browser, AttachChangeReason::kMenu); } -void GlicWindowController::Detach() { +void GlicWindowControllerImpl::Detach() { if (state_ != State::kOpen || !attached_browser_) { return; } @@ -888,15 +890,16 @@ glic_window_animator_->AnimatePosition( new_position, kAnimationDuration, - base::BindOnce(&GlicWindowController::DetachFinished, GetWeakPtr())); + base::BindOnce(&GlicWindowControllerImpl::DetachFinished, + weak_ptr_factory_.GetWeakPtr())); } -void GlicWindowController::DetachFinished() { +void GlicWindowControllerImpl::DetachFinished() { SetWindowState(State::kOpen); } -void GlicWindowController::AttachToBrowser(Browser& browser, - AttachChangeReason reason) { +void GlicWindowControllerImpl::AttachToBrowser(Browser& browser, + AttachChangeReason reason) { CHECK(!AlwaysDetached()); CHECK(GetGlicWidget()); attached_browser_ = &browser; @@ -915,7 +918,7 @@ SetGlicWindowToFloatingMode(false); browser_close_subscription_ = browser.RegisterBrowserDidClose( - base::BindRepeating(&GlicWindowController::AttachedBrowserDidClose, + base::BindRepeating(&GlicWindowControllerImpl::AttachedBrowserDidClose, base::Unretained(this))); // Trigger custom event for testing. @@ -923,9 +926,9 @@ kGlicWidgetAttached, GetGlicButton(browser)); } -void GlicWindowController::Resize(const gfx::Size& size, - base::TimeDelta duration, - base::OnceClosure callback) { +void GlicWindowControllerImpl::Resize(const gfx::Size& size, + base::TimeDelta duration, + base::OnceClosure callback) { glic_size_ = size; glic_service_->metrics()->OnGlicWindowResize(); @@ -950,7 +953,7 @@ } } -void GlicWindowController::EnableDragResize(bool enabled) { +void GlicWindowControllerImpl::EnableDragResize(bool enabled) { user_resizable_ = enabled; if (!GetGlicWidget()) { return; @@ -968,7 +971,7 @@ } } -gfx::Size GlicWindowController::GetSize() { +gfx::Size GlicWindowControllerImpl::GetSize() { if (!GetGlicWidget()) { return gfx::Size(); } @@ -976,7 +979,7 @@ return GetGlicWidget()->GetSize(); } -void GlicWindowController::SetDraggableAreas( +void GlicWindowControllerImpl::SetDraggableAreas( const std::vector<gfx::Rect>& draggable_areas) { GlicView* glic_view = GetGlicView(); if (!glic_view) { @@ -986,7 +989,7 @@ glic_view->SetDraggableAreas(draggable_areas); } -void GlicWindowController::SetMinimumWidgetSize(const gfx::Size& size) { +void GlicWindowControllerImpl::SetMinimumWidgetSize(const gfx::Size& size) { if (!GetGlicWidget()) { return; } @@ -994,15 +997,16 @@ glic_widget_->SetMinimumSize(size); } -void GlicWindowController::CloseWithReason(views::Widget::ClosedReason reason) { +void GlicWindowControllerImpl::CloseWithReason( + views::Widget::ClosedReason reason) { Close(); } -void GlicWindowController::Close() { - GlicWindowController::CloseInternal(std::nullopt); +void GlicWindowControllerImpl::Close() { + GlicWindowControllerImpl::CloseInternal(std::nullopt); } -void GlicWindowController::CloseInternal( +void GlicWindowControllerImpl::CloseInternal( std::optional<mojom::InvocationSource> reopen_detached_source) { if (state_ == State::kCloseAnimation || state_ == State::kClosed) { return; @@ -1023,15 +1027,15 @@ SetWindowState(State::kCloseAnimation); GlicButton* glic_button = GetGlicButton(*attached_browser_); glic_window_animator_->RunCloseAnimation( - glic_button, - base::BindOnce(&GlicWindowController::CloseFinish, GetWeakPtr(), - reopen_detached, reopen_detached_source)); + glic_button, base::BindOnce(&GlicWindowControllerImpl::CloseFinish, + weak_ptr_factory_.GetWeakPtr(), + reopen_detached, reopen_detached_source)); } else { CloseFinish(reopen_detached, reopen_detached_source); } } -void GlicWindowController::CloseFinish( +void GlicWindowControllerImpl::CloseFinish( bool reopen_detached, std::optional<mojom::InvocationSource> reopen_detached_source) { if (state_ == State::kClosed) { @@ -1060,12 +1064,12 @@ } } -void GlicWindowController::ForceClose() { +void GlicWindowControllerImpl::ForceClose() { CloseFinish(/*reopen_detached=*/false, /*reopen_detached_source=*/std::nullopt); } -void GlicWindowController::CloseAndReopenDetached( +void GlicWindowControllerImpl::CloseAndReopenDetached( mojom::InvocationSource source) { if (state_ != State::kOpen) { return; @@ -1075,7 +1079,7 @@ CloseInternal(source); } -void GlicWindowController::SaveWidgetPosition() { +void GlicWindowControllerImpl::SaveWidgetPosition() { if (GetGlicWidget() && GetGlicWidget()->IsVisible()) { previous_position_ = GetGlicWidget()->GetWindowBoundsInScreen().origin(); profile_->GetPrefs()->SetInteger(prefs::kGlicPreviousPositionX, @@ -1085,7 +1089,7 @@ } } -void GlicWindowController::ShowTitleBarContextMenuAt(gfx::Point event_loc) { +void GlicWindowControllerImpl::ShowTitleBarContextMenuAt(gfx::Point event_loc) { #if BUILDFLAG(IS_WIN) views::View::ConvertPointToScreen(GetGlicView(), &event_loc); event_loc = display::win::GetScreenWin()->DIPToScreenPoint(event_loc); @@ -1094,8 +1098,9 @@ #endif // BUILDFLAG(IS_WIN) } -bool GlicWindowController::ShouldStartDrag(const gfx::Point& initial_press_loc, - const gfx::Point& mouse_location) { +bool GlicWindowControllerImpl::ShouldStartDrag( + const gfx::Point& initial_press_loc, + const gfx::Point& mouse_location) { // Determine if the mouse has moved beyond a minimum elasticity distance // in any direction from the starting point. static const int kMinimumDragDistance = 10; @@ -1105,7 +1110,7 @@ pow(static_cast<float>(y_offset), 2)) > kMinimumDragDistance; } -void GlicWindowController::HandleWindowDragWithOffset( +void GlicWindowControllerImpl::HandleWindowDragWithOffset( gfx::Vector2d mouse_offset) { // This code isn't set up to handle nested run loops. Nested run loops will // lead to crashes. @@ -1140,11 +1145,11 @@ } } -const mojom::PanelState& GlicWindowController::GetPanelState() const { +const mojom::PanelState& GlicWindowControllerImpl::GetPanelState() const { return panel_state_; } -void GlicWindowController::AdjustPositionIfNeeded() { +void GlicWindowControllerImpl::AdjustPositionIfNeeded() { // Always have at least `kMinimumVisible` px visible from glic window in // both vertical and horizontal directions. constexpr int kMinimumVisible = 40; @@ -1162,7 +1167,7 @@ GetGlicWidget()->SetBounds(rect); } -void GlicWindowController::OnDragComplete() { +void GlicWindowControllerImpl::OnDragComplete() { Browser* browser = FindBrowserForAttachment(); // No browser within attachment range. if (!browser) { @@ -1173,7 +1178,7 @@ AttachToBrowser(*browser, AttachChangeReason::kDrag); } -void GlicWindowController::HandleGlicButtonIndicator() { +void GlicWindowControllerImpl::HandleGlicButtonIndicator() { Browser* browser = FindBrowserForAttachment(); // No browser within attachment range so reset indicators if (!browser) { @@ -1191,7 +1196,7 @@ } } -Browser* GlicWindowController::FindBrowserForAttachment() { +Browser* GlicWindowControllerImpl::FindBrowserForAttachment() { // The profile must have started off as Glic enabled since a Glic widget is // open but it may have been disabled at runtime by policy. In this edge-case, // prevent reattaching back to a window (as it no longer has a GlicButton). @@ -1241,7 +1246,7 @@ return nullptr; } -void GlicWindowController::MovePositionToBrowserGlicButton( +void GlicWindowControllerImpl::MovePositionToBrowserGlicButton( const Browser& browser, bool animate) { if (!GetGlicWidget()) { @@ -1290,15 +1295,15 @@ NotifyIfPanelStateChanged(); } -void GlicWindowController::AddStateObserver(StateObserver* observer) { +void GlicWindowControllerImpl::AddStateObserver(StateObserver* observer) { state_observers_.AddObserver(observer); } -void GlicWindowController::RemoveStateObserver(StateObserver* observer) { +void GlicWindowControllerImpl::RemoveStateObserver(StateObserver* observer) { state_observers_.RemoveObserver(observer); } -void GlicWindowController::NotifyIfPanelStateChanged() { +void GlicWindowControllerImpl::NotifyIfPanelStateChanged() { auto new_state = ComputePanelState(); if (new_state != panel_state_) { panel_state_ = new_state; @@ -1307,50 +1312,50 @@ } } -mojom::PanelState GlicWindowController::ComputePanelState() const { +mojom::PanelState GlicWindowControllerImpl::ComputePanelState() const { return CreatePanelState(IsShowing(), attached_browser_); } -bool GlicWindowController::IsActive() { +bool GlicWindowControllerImpl::IsActive() { return IsShowing() && GetGlicWidget() && GetGlicWidget()->IsActive(); } -bool GlicWindowController::IsShowing() const { +bool GlicWindowControllerImpl::IsShowing() const { return !(state_ == State::kClosed || state_ == State::kCloseAnimation); } -bool GlicWindowController::IsPanelOrFreShowing() const { +bool GlicWindowControllerImpl::IsPanelOrFreShowing() const { return IsShowing() || fre_controller_->IsShowingDialog(); } -bool GlicWindowController::IsAttached() const { +bool GlicWindowControllerImpl::IsAttached() const { return attached_browser_ != nullptr; } -bool GlicWindowController::IsDetached() const { +bool GlicWindowControllerImpl::IsDetached() const { return IsShowing() && !IsAttached(); } base::CallbackListSubscription -GlicWindowController::AddWindowActivationChangedCallback( +GlicWindowControllerImpl::AddWindowActivationChangedCallback( WindowActivationChangedCallback callback) { return window_activation_callback_list_.Add(std::move(callback)); } -void GlicWindowController::Preload() { +void GlicWindowControllerImpl::Preload() { if (!host().contents_container()) { host().CreateContents(); host().webui_contents()->Resize(GetInitialBounds(nullptr)); } } -void GlicWindowController::PreloadFre() { +void GlicWindowControllerImpl::PreloadFre() { if (fre_controller_->ShouldShowFreDialog()) { fre_controller_->TryPreload(); } } -void GlicWindowController::Reload() { +void GlicWindowControllerImpl::Reload() { if (GetFreWebContents()) { GetFreWebContents()->ReloadFocusedFrame(); } @@ -1360,23 +1365,23 @@ } } -bool GlicWindowController::IsWarmed() const { +bool GlicWindowControllerImpl::IsWarmed() const { return !!host().contents_container(); } -base::WeakPtr<GlicWindowController> GlicWindowController::GetWeakPtr() { +base::WeakPtr<GlicWindowController> GlicWindowControllerImpl::GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } -void GlicWindowController::Shutdown() { +void GlicWindowControllerImpl::Shutdown() { // Hide first, then clean up (but do not animate). ForceClose(); fre_controller_->Shutdown(); window_activation_callback_list_.Notify(false); } -bool GlicWindowController::IsBrowserOccludedAtPoint(Browser* browser, - gfx::Point point) { +bool GlicWindowControllerImpl::IsBrowserOccludedAtPoint(Browser* browser, + gfx::Point point) { std::set<gfx::NativeWindow> exclude = { GetGlicView()->GetWidget()->GetNativeWindow()}; gfx::NativeWindow window = @@ -1387,7 +1392,7 @@ return false; } -gfx::Size GlicWindowController::GetLastRequestedSizeClamped() const { +gfx::Size GlicWindowControllerImpl::GetLastRequestedSizeClamped() const { gfx::Size min = GlicWidget::GetInitialSize(); if (glic_widget_) { gfx::Size widget_min = glic_widget_->GetMinimumSize(); @@ -1404,7 +1409,7 @@ return result; } -void GlicWindowController::MaybeAdjustSizeForDisplay(bool animate) { +void GlicWindowControllerImpl::MaybeAdjustSizeForDisplay(bool animate) { if (state_ == State::kOpen || state_ == State::kWaitingForGlicToLoad || state_ == State::kDetaching) { const auto target_size = GetLastRequestedSizeClamped(); @@ -1416,7 +1421,7 @@ } } -void GlicWindowController::SetWindowState(State new_state) { +void GlicWindowControllerImpl::SetWindowState(State new_state) { if (state_ == new_state) { return; } @@ -1427,8 +1432,33 @@ } } -bool GlicWindowController::IsWindowOpenAndReady() { +bool GlicWindowControllerImpl::IsWindowOpenAndReady() { return host().IsReady() && state_ == State::kOpen; } +GlicWindowController::State GlicWindowControllerImpl::state() const { + return state_; +} + +bool GlicWindowControllerImpl::IsDragging() { + return in_move_loop_; +} + +Profile* GlicWindowControllerImpl::profile() { + return profile_; +} + +GlicWindowAnimator* GlicWindowControllerImpl::window_animator() { + return glic_window_animator_.get(); +} + +GlicFreController* GlicWindowControllerImpl::fre_controller() { + return fre_controller_.get(); +} + +// Return the Browser to which the panel is attached, or null if detached. +Browser* GlicWindowControllerImpl::attached_browser() { + return attached_browser_; +} + } // namespace glic
diff --git a/chrome/browser/glic/widget/glic_window_controller_impl.h b/chrome/browser/glic/widget/glic_window_controller_impl.h new file mode 100644 index 0000000..4084eb296 --- /dev/null +++ b/chrome/browser/glic/widget/glic_window_controller_impl.h
@@ -0,0 +1,351 @@ +// 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. + +#ifndef CHROME_BROWSER_GLIC_WIDGET_GLIC_WINDOW_CONTROLLER_IMPL_H_ +#define CHROME_BROWSER_GLIC_WIDGET_GLIC_WINDOW_CONTROLLER_IMPL_H_ + +#include <optional> +#include <vector> + +#include "base/callback_list.h" +#include "base/functional/callback_forward.h" +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/observer_list_types.h" +#include "base/scoped_observation.h" +#include "base/scoped_observation_traits.h" +#include "chrome/browser/glic/glic_enabling.h" +#include "chrome/browser/glic/host/glic.mojom.h" +#include "chrome/browser/glic/host/glic_web_client_access.h" +#include "chrome/browser/glic/host/host.h" +#include "chrome/browser/glic/widget/application_hotkey_delegate.h" +#include "chrome/browser/glic/widget/glic_modal_manager.h" +#include "chrome/browser/glic/widget/glic_window_controller.h" +#include "chrome/browser/glic/widget/glic_window_hotkey_delegate.h" +#include "chrome/browser/glic/widget/local_hotkey_manager.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_window/public/browser_window_interface.h" +#include "content/public/browser/web_contents.h" +#include "ui/base/interaction/element_tracker.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_observer.h" + +class Browser; +class WindowFinder; +namespace gfx { +class Size; +class Point; +} // namespace gfx + +namespace glic { + +class GlicEnabling; +class ScopedGlicButtonIndicator; +class GlicButton; +class GlicModalManager; + +// This class owns and manages the glic window. This class has the same lifetime +// as the GlicKeyedService, so it exists if and only if the profile exists. +// +// See the |State| enum below for the lifecycle of the window. When the glic +// window is open |attached_browser_| indicates if the window is attached or +// standalone. See |IsAttached| +class GlicWindowControllerImpl : public GlicWindowController, + public views::WidgetObserver, + public Host::Observer { + public: + GlicWindowControllerImpl(const GlicWindowControllerImpl&) = delete; + GlicWindowControllerImpl& operator=(const GlicWindowControllerImpl&) = delete; + + GlicWindowControllerImpl(Profile* profile, + signin::IdentityManager* identity_manager, + GlicKeyedService* service, + GlicEnabling* enabling); + ~GlicWindowControllerImpl() override; + + // GlicWindowController implementation + void Toggle(BrowserWindowInterface* browser, + bool prevent_close, + mojom::InvocationSource source) override; + void ShowAfterSignIn(base::WeakPtr<Browser> browser) override; + void ToggleWhenNotAlwaysDetached(Browser* new_attached_browser, + bool prevent_close, + mojom::InvocationSource source) override; + void FocusIfOpen() override; + void Attach() override; + void Detach() override; + void Shutdown() override; + void Resize(const gfx::Size& size, + base::TimeDelta duration, + base::OnceClosure callback) override; + void EnableDragResize(bool enabled) override; + gfx::Size GetSize() override; + void SetDraggableAreas( + const std::vector<gfx::Rect>& draggable_areas) override; + void SetMinimumWidgetSize(const gfx::Size& size) override; + void Close() override; + void CloseWithReason(views::Widget::ClosedReason reason) override; + void ShowTitleBarContextMenuAt(gfx::Point event_loc) override; + bool ShouldStartDrag(const gfx::Point& initial_press_loc, + const gfx::Point& mouse_location) override; + void HandleWindowDragWithOffset(gfx::Vector2d mouse_offset) override; + const mojom::PanelState& GetPanelState() const override; + + void AddStateObserver(StateObserver* observer) override; + void RemoveStateObserver(StateObserver* observer) override; + + bool IsActive() override; + bool IsShowing() const override; + bool IsPanelOrFreShowing() const override; + bool IsAttached() const override; + bool IsDetached() const override; + base::CallbackListSubscription AddWindowActivationChangedCallback( + WindowActivationChangedCallback callback) override; + void Preload() override; + void PreloadFre() override; + void Reload() override; + bool IsWarmed() const override; + base::WeakPtr<GlicWindowController> GetWeakPtr() override; + + GlicView* GetGlicView() override; + GlicWidget* GetGlicWidget() override; + content::WebContents* GetFreWebContents() override; + + Browser* attached_browser() override; + State state() const override; + GlicFreController* fre_controller() override; + GlicWindowAnimator* window_animator() override; + Profile* profile() override; + bool IsDragging() override; + void ShowGlicModal(std::u16string label) override; + gfx::Rect GetInitialBounds(Browser* browser) override; + void ShowDetachedForTesting() override; + void SetPreviousPositionForTesting(gfx::Point position) override; + + // views::WidgetObserver implementation, monitoring the glic window widget. + void OnWidgetActivationChanged(views::Widget* widget, bool active) override; + void OnWidgetDestroyed(views::Widget* widget) override; + void OnWidgetBoundsChanged(views::Widget* widget, + const gfx::Rect& new_bounds) override; + void OnWidgetUserResizeStarted() override; + void OnWidgetUserResizeEnded() override; + + private: + Host& host() const; + + // Sets the floating attributes of the glic window. + // + // When set to true, the glic window is set to have a `kFloatingWindow` + // z-order, and on the Mac is set to be "activation independent" (to allow the + // user to interact with it without causing Chromium to be activated), and + // visible on every space (including fullscreen ones). + // + // When set to false, the glic window is set to have a `kNormal` z-order, and + // on the Mac, all special activation and visibility properties are cleared. + void SetGlicWindowToFloatingMode(bool floating); + + // Return the default detached bounds which are just below the tab strip + // button on the active browser. + std::optional<gfx::Rect> GetInitialDetachedBoundsFromBrowser( + Browser* browser, + const gfx::Size& target_size); + + // Return the default detached bounds when there is no active browser. The + // position is relative to the top right of the current display. + gfx::Rect GetInitialDetachedBoundsNoBrowser(const gfx::Size& target_size); + + // Return the default bounds when attached to the browser which cover the tab + // strip button on the active browser. + gfx::Rect GetInitialAttachedBounds(Browser& browser); + + // Creates the glic view, waits for the web client to initialize, and then + // shows the glic window. If `browser` is non-nullptr then glic will be + // attached to the browser. Otherwise glic will be detached. + void Show(Browser* browser, mojom::InvocationSource source); + + // Close the widget and reopen in detached mode. + void CloseAndReopenDetached(mojom::InvocationSource source); + + void SetupGlicWidget(Browser* browser); + void SetupGlicWidgetAccessibilityText(); + + // Host::Observer implementation. + void WebClientInitializeFailed() override; + void LoginPageCommitted() override; + void ClientReadyToShow(const mojom::OpenPanelInfo& open_info) override; + + // Called once glic is completely loaded and any animations have finished. + // This is the end of the opening process and |state_| will be set to kOpen. + void GlicLoadedAndReadyToDisplay(); + + void SetDraggingAreasAndWatchForMouseEvents(); + + // Internal closing implementation. reopen_detached_source must be set + // if and only if the internal state is kClosingToReopenDetached. + void CloseInternal( + std::optional<mojom::InvocationSource> reopen_detached_source); + + // Finishes closing off the widget after running the closing animation. + void CloseFinish( + bool reopen_detached, + std::optional<mojom::InvocationSource> reopen_detached_source); + + // Called when the Detach() animation ends. + void DetachFinished(); + + // Causes an immediate close (eg, for during shutdown). + void ForceClose(); + + // Save the top-right corner position for re-opening. + void SaveWidgetPosition(); + + // Clear the previous position if the widget would not be on an existing + // display when shown. + void MaybeResetPreviousPosition(const gfx::Size& target_size); + + // Determines the correct position for the glic window when attached to a + // browser window. The top right of the widget should be placed here. + gfx::Point GetTopRightPositionForAttachedGlicWindow(GlicButton* glic_button); + + // Runs an animation to move glic to its target position. + // TODO(crbug.com/410629338): Reimplement attachment. + void AttachToBrowser(Browser& browser, AttachChangeReason reason); + + // Keep part of glic window within the visible region. + void AdjustPositionIfNeeded(); + + // Handles end-of-drag: + // - If glic is within attachment distance of a browser window's glic button, + // attach the glic window to the button's position. + // - If glic is still detached and has moved to a display with a different + // work area size, possibly resize the window. + void OnDragComplete(); + + // Finds a browser within attachment distance of glic to toggle the attachment + // indicator. + void HandleGlicButtonIndicator(); + + // Find and return a browser within attachment distance. Returns nullptr if no + // browsers are within attachment distance. + Browser* FindBrowserForAttachment(); + + // Updates the position of the glic window to that of the glic button of + // `browser`'s window. This position change is animated if `animate` is true. + void MovePositionToBrowserGlicButton(const Browser& browser, bool animate); + + // Called when the move animation finishes when attaching. + void AttachAnimationFinished(); + + // This method should be called anytime: + // * state_ transitions to or from kClosed. + // * attached_browser_ changes. + void NotifyIfPanelStateChanged(); + mojom::PanelState ComputePanelState() const; + + // When the attached browser is closed, this is invoked so we can clean up. + void AttachedBrowserDidClose(BrowserWindowInterface* browser); + + // Returns true if a browser is occluded at point in screen coordinates. + bool IsBrowserOccludedAtPoint(Browser* browser, gfx::Point point); + + // Return the last size Resize() was called with, or the default initial size + // if Resize() hasn't been called. The return value is clamped to fit between + // the minimum and maximum sizes. + gfx::Size GetLastRequestedSizeClamped() const; + + // Possibly adjusts the size of the window appropriate for the current + // display workspace, but only if it's different than the current target size. + void MaybeAdjustSizeForDisplay(bool animate); + + // Modifies `state_` to the given new state. + void SetWindowState(State new_state); + + // Returns true of the window is showing and the content is loaded. + bool IsWindowOpenAndReady(); + + // Observes the glic widget. + base::ScopedObservation<views::Widget, views::WidgetObserver> + glic_widget_observation_{this}; + + // Used for observing closing of the pinned browser. + std::optional<base::CallbackListSubscription> browser_close_subscription_; + + // List of callbacks to be notified when window activation has changed. + base::RepeatingCallbackList<void(bool)> window_activation_callback_list_; + + const raw_ptr<Profile> profile_; + + // Contains the glic webview. + std::unique_ptr<GlicWidget> glic_widget_; + + std::unique_ptr<GlicWindowAnimator> glic_window_animator_; + + // True if we've hit a login page (and have not yet shown). + bool login_page_committed_ = false; + + // This member contains the last size that glic requested. This should be + // reset every time glic is closed but is currently cached. + std::optional<gfx::Size> glic_size_; + + // Whether the widget should be user resizable, kept here in case it's + // specified before the widget is created. + bool user_resizable_ = true; + + // Used to monitor key and mouse events from native window. + class WindowEventObserver; + std::unique_ptr<WindowEventObserver> window_event_observer_; + + // True while RunMoveLoop() has been called on a widget. + bool in_move_loop_ = false; + + // This is the last panel state sent to observers. It should only be updated + // in `NotifyIfPanelStateChanged`. + mojom::PanelState panel_state_; + + raw_ptr<GlicWebClientAccess> web_client_; + + // Modified only by calling `SetWindowState`. + State state_ = State::kClosed; + + // If State != kClosed, then the UI must either be associated with a browser + // window, or standalone. That is tracked by this member. + raw_ptr<Browser> attached_browser_ = nullptr; + + base::ObserverList<StateObserver> state_observers_; + + // The announcement should happen the first time focus is lost after the FRE. + bool do_focus_loss_announcement_ = false; + + // Whether the user is currently drag-resizing the widget. + bool user_resizing_ = false; + + // The invocation source requesting the opening of the web client. Note that + // this value is retained until it is consumed by the web client. Because + // opening the glic window may not actually load the client, there's no + // guarantee that this value is sent to the web client. + std::optional<mojom::InvocationSource> opening_source_; + + std::optional<gfx::Point> previous_position_ = std::nullopt; + + std::unique_ptr<ScopedGlicButtonIndicator> scoped_glic_button_indicator_; + + std::unique_ptr<GlicFreController> fre_controller_; + + std::unique_ptr<WindowFinder> window_finder_; + + std::unique_ptr<GlicModalManager> glic_modal_manager_; + + std::unique_ptr<LocalHotkeyManager> application_hotkey_manager_; + std::unique_ptr<LocalHotkeyManager> glic_window_hotkey_manager_; + + raw_ptr<GlicKeyedService> glic_service_; // Owns this. + raw_ptr<GlicEnabling> enabling_; + base::ScopedObservation<Host, Host::Observer> host_observation_{this}; + + base::WeakPtrFactory<GlicWindowControllerImpl> weak_ptr_factory_{this}; +}; + +} // namespace glic + +#endif // CHROME_BROWSER_GLIC_WIDGET_GLIC_WINDOW_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/glic/widget/glic_window_controller_interactive_uitest.cc b/chrome/browser/glic/widget/glic_window_controller_interactive_uitest.cc index ee3f8c41..b3f3b66 100644 --- a/chrome/browser/glic/widget/glic_window_controller_interactive_uitest.cc +++ b/chrome/browser/glic/widget/glic_window_controller_interactive_uitest.cc
@@ -566,7 +566,7 @@ }; for (auto& t : test_points) { - window_controller().previous_position_ = t.test; + window_controller().SetPreviousPositionForTesting(t.test); initial_bounds = window_controller().GetInitialBounds(nullptr); EXPECT_EQ(initial_bounds.origin(), t.expected) << t.msg; }
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc index 617b84c1..bfa5420 100644 --- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc +++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
@@ -459,12 +459,13 @@ const url::Origin& origin = web_view_guest()->owner_rfh()->GetLastCommittedOrigin(); // chrome://glic requires additional permissions, and webview's - // permissionrequest API does not handle clipboard access. + // permissionrequest API does not handle clipboard access or screen wake lock. if (origin.scheme() == content::kChromeUIScheme && origin.host() == chrome::kChromeUIGlicHost) { switch (type) { case ContentSettingsType::CLIPBOARD_READ_WRITE: case ContentSettingsType::CLIPBOARD_SANITIZED_WRITE: + case ContentSettingsType::WAKE_LOCK_SCREEN: return content::PermissionResult( content::PermissionStatus::GRANTED, content::PermissionStatusSource::UNSPECIFIED);
diff --git a/chrome/browser/headless/headless_mode_protocol_browsertest.cc b/chrome/browser/headless/headless_mode_protocol_browsertest.cc index b8ef6dd..2ccaec9 100644 --- a/chrome/browser/headless/headless_mode_protocol_browsertest.cc +++ b/chrome/browser/headless/headless_mode_protocol_browsertest.cc
@@ -348,6 +348,8 @@ "--ozone-override-screen-size=1234,5678") #endif +// --screen-info switch is only supported on Linux and Windows at this time. +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) // This currently results in an unexpected screen orientation type, // see http://crbug.com/398150465. HEADLESS_MODE_PROTOCOL_TEST_WITH_COMMAND_LINE_EXTRAS( @@ -370,4 +372,6 @@ "sanity/create-target-secondary-screen.js", "--screen-info={label='#1'}{label='#2'}") +#endif + } // namespace headless
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/AlwaysTranslateListFragment.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/AlwaysTranslateListFragment.java index d2a8332..42d6cda 100644 --- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/AlwaysTranslateListFragment.java +++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/AlwaysTranslateListFragment.java
@@ -69,6 +69,11 @@ TranslateBridge.setLanguageAlwaysTranslateState(getProfile(), code, false); } + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } + /** * Helper class to populate the LanguageItem list and used by {@link LanguageItemListPreference} * to make the summary text and launch an Intent to this Fragment.
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java index c376401b..374bd14 100644 --- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java +++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
@@ -398,4 +398,9 @@ PrefService getPrefService() { return UserPrefs.get(getProfile()); } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/NeverTranslateListFragment.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/NeverTranslateListFragment.java index c2267bc7..4d422b6 100644 --- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/NeverTranslateListFragment.java +++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/NeverTranslateListFragment.java
@@ -70,6 +70,11 @@ TranslateBridge.setLanguageBlockedState(getProfile(), code, false); } + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } + /** * Helper class to populate the LanguageItem list and used by {@link LanguageItemListPreference} * to make the summary text and launch an Intent to this Fragment.
diff --git a/chrome/browser/lens/core/mojom/lens_side_panel.mojom b/chrome/browser/lens/core/mojom/lens_side_panel.mojom index 56b9e39..7fcc165 100644 --- a/chrome/browser/lens/core/mojom/lens_side_panel.mojom +++ b/chrome/browser/lens/core/mojom/lens_side_panel.mojom
@@ -30,6 +30,9 @@ // file:// URL being tracked on the browser. If the latest contextualized // local file:// URL is not open on the main tab, then it opens in a new tab. OnScrollToMessage(array<string> text_fragments, uint32 pdf_page_number); + + // Request the browser to open the feedback dialog. + RequestSendFeedback(); }; // Enumerates the semantic events that can be logged by the Lens Overlay.
diff --git a/chrome/browser/metrics/k12_age_classification_metrics_provider_browsertest.cc b/chrome/browser/metrics/k12_age_classification_metrics_provider_browsertest.cc index 56adac5f..462ebea 100644 --- a/chrome/browser/metrics/k12_age_classification_metrics_provider_browsertest.cc +++ b/chrome/browser/metrics/k12_age_classification_metrics_provider_browsertest.cc
@@ -22,11 +22,11 @@ #include "chrome/common/chrome_features.h" #include "chrome/test/base/fake_gaia_mixin.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/metrics/metrics_service.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/device_management_backend.pb.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/metrics/structured/metadata_processor_ash_browsertest.cc b/chrome/browser/metrics/structured/metadata_processor_ash_browsertest.cc index eb03ffcf..81c20744 100644 --- a/chrome/browser/metrics/structured/metadata_processor_ash_browsertest.cc +++ b/chrome/browser/metrics/structured/metadata_processor_ash_browsertest.cc
@@ -34,6 +34,7 @@ #include "chrome/browser/metrics/structured/test/structured_metrics_mixin.h" #include "chrome/test/base/fake_gaia_mixin.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/metrics/metrics_service.h" #include "components/metrics/structured/structured_events.h" #include "components/metrics/structured/structured_metrics_client.h" @@ -42,7 +43,6 @@ #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/device_management_backend.pb.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h"
diff --git a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc index f9dde2e9..1e863915 100644 --- a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc +++ b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
@@ -31,11 +31,11 @@ #include "chrome/browser/browser_process_platform_part_ash.h" #include "chrome/test/base/fake_gaia_mixin.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/metrics/metrics_service.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/device_management_backend.pb.h" #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java index 5fabde8..30da11e 100644 --- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java +++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationCoordinator.java
@@ -25,7 +25,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.ntp_customization.feed.FeedSettingsCoordinator; import org.chromium.chrome.browser.ntp_customization.ntp_cards.NtpCardsCoordinator; -import org.chromium.chrome.browser.profiles.ProfileProvider; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -44,7 +44,7 @@ private final BottomSheetDelegate mDelegate; private final Context mContext; - private final Supplier<ProfileProvider> mProfileSupplier; + private final Supplier<Profile> mProfileSupplier; private NtpCustomizationMediator mMediator; private @MonotonicNonNull NtpCardsCoordinator mNtpCardsCoordinator; private @Nullable FeedSettingsCoordinator mFeedSettingsCoordinator; @@ -70,7 +70,7 @@ public NtpCustomizationCoordinator( Context context, BottomSheetController bottomSheetController, - Supplier<ProfileProvider> profileSupplier) { + Supplier<Profile> profileSupplier) { mContext = context; mProfileSupplier = profileSupplier; View contentView =
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java index a1bf46b..969b387 100644 --- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java +++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediator.java
@@ -24,7 +24,6 @@ import org.chromium.chrome.browser.feed.FeedFeatures; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.profiles.ProfileProvider; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; @@ -57,7 +56,7 @@ private final PropertyModel mViewFlipperPropertyModel; private List<Integer> mListContent; private final PropertyModel mContainerPropertyModel; - private final Supplier<ProfileProvider> mProfileSupplier; + private final Supplier<Profile> mProfileSupplier; private @Nullable Profile mProfile; private @Nullable Integer mCurrentBottomSheet; private static @Nullable PrefService sPrefServiceForTest; @@ -67,7 +66,7 @@ NtpCustomizationBottomSheetContent bottomSheetContent, PropertyModel viewFlipperPropertyModel, PropertyModel containerPropertyModel, - Supplier<ProfileProvider> profileSupplier) { + Supplier<Profile> profileSupplier) { mBottomSheetController = bottomSheetController; mBottomSheetContent = bottomSheetContent; mViewFlipperPropertyModel = viewFlipperPropertyModel;
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java index 364d25b..9a04b8f 100644 --- a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java +++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationMediatorUnitTest.java
@@ -39,7 +39,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import org.chromium.base.supplier.OneshotSupplierImpl; +import org.chromium.base.supplier.Supplier; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.chrome.browser.feed.FeedFeatures; @@ -48,7 +48,6 @@ import org.chromium.chrome.browser.ntp_customization.NtpCustomizationCoordinator.BottomSheetType; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.profiles.ProfileProvider; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; @@ -70,20 +69,17 @@ @Mock private PrefService mPrefService; @Mock private FeedServiceBridge.Natives mFeedServiceBridgeJniMock; @Mock private Profile mProfile; - @Mock private ProfileProvider mProfileProvider; private NtpCustomizationMediator mMediator; private Map<Integer, Integer> mViewFlipperMap; private ListContainerViewDelegate mListDelegate; private Context mContext; - private OneshotSupplierImpl<ProfileProvider> mSupplier; + private Supplier<Profile> mProfileSupplier; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); - mSupplier = new OneshotSupplierImpl<>(); - mSupplier.set(mProfileProvider); - when(mProfileProvider.getOriginalProfile()).thenReturn(mProfile); + mProfileSupplier = () -> mProfile; NtpCustomizationMediator.setPrefForTesting(mPrefService); FeedServiceBridgeJni.setInstanceForTesting(mFeedServiceBridgeJniMock); FeedFeatures.setFakePrefsForTest(mPrefService); @@ -93,7 +89,7 @@ mBottomSheetContent, mViewFlipperPropertyModel, mContainerPropertyModel, - mSupplier); + mProfileSupplier); mViewFlipperMap = mMediator.getViewFlipperMapForTesting(); mListDelegate = mMediator.createListDelegate(); }
diff --git a/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.cc index 00b11d0..ef6237697 100644 --- a/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/lcp_critical_path_predictor_page_load_metrics_observer.cc
@@ -624,6 +624,7 @@ navigation_handle->GetLCPPNavigationHint(); if (hint) { if (!hint->lcp_element_locators.empty() || + !hint->lcp_element_locators_all.empty() || !hint->lcp_influencer_scripts.empty() || !hint->preconnect_origins.empty()) { is_lcpp_hinted_navigation_ = true;
diff --git a/chrome/browser/policy/system_features_disable_list_policy_handler.cc b/chrome/browser/policy/system_features_disable_list_policy_handler.cc index 30d3c0b..93edf4b 100644 --- a/chrome/browser/policy/system_features_disable_list_policy_handler.cc +++ b/chrome/browser/policy/system_features_disable_list_policy_handler.cc
@@ -12,7 +12,6 @@ #include "base/values.h" #include "build/build_config.h" #include "components/policy/core/common/policy_pref_names.h" -#include "components/policy/core/common/system_features_disable_list_constants.h" #include "components/policy/policy_constants.h" #include "components/prefs/pref_registry_simple.h" @@ -56,13 +55,6 @@ SystemFeaturesDisableListPolicyHandler:: ~SystemFeaturesDisableListPolicyHandler() = default; -void SystemFeaturesDisableListPolicyHandler::RegisterPrefs( - PrefRegistrySimple* registry) { - registry->RegisterListPref(policy_prefs::kSystemFeaturesDisableList); - registry->RegisterStringPref(policy_prefs::kSystemFeaturesDisableMode, - kSystemFeaturesDisableModeBlocked); -} - SystemFeature SystemFeaturesDisableListPolicyHandler::GetSystemFeatureFromAppId( const std::string& app_id) { if (app_id == ash::kCanvasAppId) {
diff --git a/chrome/browser/policy/system_features_disable_list_policy_handler.h b/chrome/browser/policy/system_features_disable_list_policy_handler.h index 34f195f..b9792f1 100644 --- a/chrome/browser/policy/system_features_disable_list_policy_handler.h +++ b/chrome/browser/policy/system_features_disable_list_policy_handler.h
@@ -12,7 +12,6 @@ #include "components/prefs/pref_service.h" class PrefValueMap; -class PrefRegistrySimple; namespace policy { @@ -96,7 +95,6 @@ SystemFeaturesDisableListPolicyHandler(); ~SystemFeaturesDisableListPolicyHandler() override; - static void RegisterPrefs(PrefRegistrySimple* registry); static SystemFeature GetSystemFeatureFromAppId(const std::string& app_id); static bool IsSystemFeatureDisabled(SystemFeature feature, PrefService* const pref_service);
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc index ad692e2fa..fe1cb448 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.cc
@@ -816,6 +816,8 @@ std::vector<std::string> lcp_element_locators = PredictLcpElementLocators(lcpp_stat.lcp_element_locator_stat(), kConfidenceThreshold, kTotalFrequencyThreshold); + std::vector<std::string> lcp_element_locators_all = + PredictLcpElementLocators(lcpp_stat.lcp_element_locator_stat_all()); std::vector<GURL> lcp_influencer_scripts = PredictLcpInfluencerScripts(lcpp_stat); std::vector<GURL> fetched_fonts = PredictFetchedFontUrls(lcpp_stat); @@ -823,13 +825,13 @@ PredictPreconnectableOrigins(lcpp_stat); std::vector<GURL> unused_preloads = PredictUnusedPreloads(lcpp_stat); - if (!lcp_element_locators.empty() || !lcp_influencer_scripts.empty() || - !fetched_fonts.empty() || !preconnect_origins.empty() || - !unused_preloads.empty()) { + if (!lcp_element_locators.empty() || !lcp_element_locators_all.empty() || + !lcp_influencer_scripts.empty() || !fetched_fonts.empty() || + !preconnect_origins.empty() || !unused_preloads.empty()) { return blink::mojom::LCPCriticalPathPredictorNavigationTimeHint( - std::move(lcp_element_locators), std::move(lcp_influencer_scripts), - std::move(fetched_fonts), std::move(preconnect_origins), - std::move(unused_preloads), false); + std::move(lcp_element_locators), std::move(lcp_element_locators_all), + std::move(lcp_influencer_scripts), std::move(fetched_fonts), + std::move(preconnect_origins), std::move(unused_preloads), false); } return std::nullopt; } @@ -850,9 +852,10 @@ std::vector<std::string> PredictLcpElementLocators( const predictors::LcpElementLocatorStat& stat, - const double confidence_threshold, - const double total_frequency_threshold) { - if (SumOfFrequency(stat) < total_frequency_threshold) { + const std::optional<double>& confidence_threshold, + const std::optional<double>& total_frequency_threshold) { + if (total_frequency_threshold && + SumOfFrequency(stat) < *total_frequency_threshold) { return {}; } std::vector<std::pair<double, std::string>> @@ -862,7 +865,7 @@ lcp_element_locators.reserve(lcp_element_locators_with_confidence.size()); for (auto& [confidence, lcp_element_locator] : lcp_element_locators_with_confidence) { - if (confidence < confidence_threshold) { + if (confidence_threshold && confidence < *confidence_threshold) { break; } lcp_element_locators.push_back(std::move(lcp_element_locator));
diff --git a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h index 3063f44..9bd39946 100644 --- a/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h +++ b/chrome/browser/predictors/lcp_critical_path_predictor/lcp_critical_path_predictor_util.h
@@ -62,8 +62,8 @@ // data, it returns an empty vector. std::vector<std::string> PredictLcpElementLocators( const predictors::LcpElementLocatorStat& stat, - const double confidence_threshold, - const double total_frequency_threshold); + const std::optional<double>& confidence_threshold = std::nullopt, + const std::optional<double>& total_frequency_threshold = std::nullopt); // Returns possible fonts from past loads for a given `stat`. // The returned urls are ordered by descending frequency (the most
diff --git a/chrome/browser/predictors/loading_predictor_browsertest.cc b/chrome/browser/predictors/loading_predictor_browsertest.cc index 82bad5d94..10e776e0 100644 --- a/chrome/browser/predictors/loading_predictor_browsertest.cc +++ b/chrome/browser/predictors/loading_predictor_browsertest.cc
@@ -1339,7 +1339,7 @@ NavigateAndWaitForLcpElement(kUrl, /*expected_events=*/"LCP@IMG, LCP@DIV, Onload", /*expected_lcp_count=*/2u, - /*expected_lcp_index=*/0u, // =IMG + /*expected_lcp_index=*/1u, // =DIV from_here); } @@ -1359,6 +1359,40 @@ TestPrediction(); } +class LCPPTimingPredictorBrowserFlagTest + : public LCPPTimingPredictorBrowserTest, + public ::testing::WithParamInterface<std::string> { + public: + LCPPTimingPredictorBrowserFlagTest() { + scoped_feature_list_.InitWithFeaturesAndParameters( + /*enabled_features=*/ + {{blink::features::kLCPCriticalPathPredictor, + {{blink::features::kLCPCriticalPathPredictorRecordedLcpElementTypes + .name, + GetParam()}}}}, + /*disabled_features=*/{}); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// kLCPCriticalPathPredictorRecordedLcpElementTypes should not affect. +// TODO(crbug.com/413192370): Flaky on win-rel. +#if BUILDFLAG(IS_WIN) +#define MAYBE_WithKCriticalPathFlag DISABLED_WithKCriticalPathFlag +#else +#define MAYBE_WithKCriticalPathFlag WithKCriticalPathFlag +#endif +IN_PROC_BROWSER_TEST_P(LCPPTimingPredictorBrowserFlagTest, + MAYBE_WithKCriticalPathFlag) { + TestPrediction(); +} + +INSTANTIATE_TEST_SUITE_P(Flags, + LCPPTimingPredictorBrowserFlagTest, + ::testing::Values("all", "image_only")); + class SuppressesLoadingPredictorOnSlowNetworkBrowserTest : public LoadingPredictorBrowserTest { public:
diff --git a/chrome/browser/predictors/loading_predictor_tab_helper.cc b/chrome/browser/predictors/loading_predictor_tab_helper.cc index e18fbad..b2ee3909 100644 --- a/chrome/browser/predictors/loading_predictor_tab_helper.cc +++ b/chrome/browser/predictors/loading_predictor_tab_helper.cc
@@ -215,7 +215,7 @@ CHECK_IS_TEST(); if (!hint) { hint = blink::mojom::LCPCriticalPathPredictorNavigationTimeHint( - {}, {}, {}, {}, {}, /*for_testing=*/false); + {}, {}, {}, {}, {}, {}, /*for_testing=*/false); } hint->for_testing = true; }
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java index f61908d..dee2ddb4 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -873,12 +873,12 @@ "org.chromium.chrome.browser.tab.TabIdManager.NEXT_ID"; // Start timestamp of 1-day period for measuring the number of times the max-instance toast is - // shown when tab tearing fails. - public static final String TAB_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS = - "Chrome.TabTearing.MaxInstancesFailureStartTimeMs"; - // Number of times in a day the max-instance toast is shown when tab tearing fails. - public static final String TAB_TEARING_MAX_INSTANCES_FAILURE_COUNT = - "Chrome.TabTearing.MaxInstancesFailureCount"; + // shown when tab or group tearing fails. + public static final String TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS = + "Chrome.TabOrGroupTearing.MaxInstancesFailureStartTimeMs"; + // Number of times in a day the max-instance toast is shown when tab or group tearing fails. + public static final String TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_COUNT = + "Chrome.TabOrGroupTearing.MaxInstancesFailureCount"; // If the toolbar should be shown on top. public static final String TOOLBAR_TOP_ANCHORED = "Chrome.Toolbar.TopAnchored"; @@ -1130,8 +1130,8 @@ TAB_DECLUTTER_AUTO_DELETE_ENABLED, TAB_DECLUTTER_AUTO_DELETE_TIME_DELTA_HOURS, TAB_DECLUTTER_DIALOG_IPH_DISMISS_COUNT, - TAB_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, - TAB_TEARING_MAX_INSTANCES_FAILURE_COUNT, + TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_START_TIME_MS, + TAB_OR_GROUP_TEARING_MAX_INSTANCES_FAILURE_COUNT, TOOLBAR_TOP_ANCHORED, TWA_DISCLOSURE_SEEN_PACKAGES, UMA_ON_POSTCREATE_COUNTER,
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/DeprecatedChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/DeprecatedChromePreferenceKeys.java index 67702b8..dfcdd21 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/DeprecatedChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/DeprecatedChromePreferenceKeys.java
@@ -70,6 +70,8 @@ "Chrome.Tab.ArchiveIphShowing", "Chrome.Tab.ShowArchiveTabDialogIPH", "Chrome.Tab.ShowTabGroupCreationDialog", + "Chrome.TabTearing.MaxInstancesFailureCount", + "Chrome.TabTearing.MaxInstancesFailureStartTimeMs", "Chrome.UMA.OnPreCreateCounter", "Chrome.UMA.OnResumeCounter", "Chrome.VideoTutorials.ShareUrls",
diff --git a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/ExtendedPreloadingSettingsFragment.java b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/ExtendedPreloadingSettingsFragment.java index 0fc13087..033a860 100644 --- a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/ExtendedPreloadingSettingsFragment.java +++ b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/ExtendedPreloadingSettingsFragment.java
@@ -13,4 +13,9 @@ protected int getPreferenceResource() { return R.xml.extended_preloading_preferences; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java index ad1478f..76335bf 100644 --- a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java +++ b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java
@@ -101,4 +101,9 @@ PreloadPagesSettingsBridge.setState(getProfile(), newState); return true; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/StandardPreloadingSettingsFragment.java b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/StandardPreloadingSettingsFragment.java index cc8abd8..df675e166 100644 --- a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/StandardPreloadingSettingsFragment.java +++ b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/StandardPreloadingSettingsFragment.java
@@ -13,4 +13,9 @@ protected int getPreferenceResource() { return R.xml.standard_preloading_preferences; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 93d3420d..8a39797e 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -428,7 +428,6 @@ #include "chrome/browser/memory/oom_kills_monitor.h" #include "chrome/browser/metrics/chromeos_metrics_provider.h" #include "chrome/browser/policy/annotations/blocklist_handler.h" -#include "chrome/browser/policy/system_features_disable_list_policy_handler.h" #include "chrome/browser/ui/ash/shelf/chrome_shelf_prefs.h" #include "chrome/browser/ui/webui/ash/login/enable_debugging_screen_handler.h" #include "chrome/browser/ui/webui/ash/settings/os_settings_ui.h" @@ -447,6 +446,7 @@ #include "chromeos/ash/components/network/network_metadata_store.h" #include "chromeos/ash/components/network/proxy/proxy_config_handler.h" #include "chromeos/ash/components/policy/restriction_schedule/device_restriction_schedule_controller.h" +#include "chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.h" #include "chromeos/ash/components/quickoffice/quickoffice_prefs.h" #include "chromeos/ash/components/report/report_controller.h" #include "chromeos/ash/components/scheduler_config/scheduler_configuration_manager.h" @@ -1769,7 +1769,7 @@ RegisterNearbySharingLocalPrefs(registry); chromeos::echo_offer::RegisterPrefs(registry); memory::OOMKillsMonitor::RegisterPrefs(registry); - policy::SystemFeaturesDisableListPolicyHandler::RegisterPrefs(registry); + policy::RegisterDisabledSystemFeaturesPrefs(registry); policy::DlpRulesManagerImpl::RegisterPrefs(registry); #endif // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/preloading/chrome_preloading.cc b/chrome/browser/preloading/chrome_preloading.cc index 5d8645a7..a18a1bc 100644 --- a/chrome/browser/preloading/chrome_preloading.cc +++ b/chrome/browser/preloading/chrome_preloading.cc
@@ -36,7 +36,8 @@ bool HasCanonicalPreloadingOmniboxSearchURL( const GURL& preloading_url, content::BrowserContext* browser_context, - GURL* canonical_url) { + GURL* canonical_url, + std::u16string* search_terms) { const TemplateURLService* const template_url_service = GetTemplateURLServiceFromBrowserContext(browser_context); if (!template_url_service) { @@ -52,7 +53,7 @@ return default_search_provider->KeepSearchTermsInURL( preloading_url, template_url_service->search_terms_data(), /*keep_search_intent_params=*/true, - /*normalize_search_terms=*/true, canonical_url); + /*normalize_search_terms=*/true, canonical_url, search_terms); } bool IsSearchDestinationMatch(const GURL& canonical_preloading_search_url,
diff --git a/chrome/browser/preloading/chrome_preloading.h b/chrome/browser/preloading/chrome_preloading.h index d882b649..155e458 100644 --- a/chrome/browser/preloading/chrome_preloading.h +++ b/chrome/browser/preloading/chrome_preloading.h
@@ -216,13 +216,15 @@ content::BrowserContext* browser_context, const GURL& url); -// Returns true if a canonical URL representation of a |preloading_url| can be -// generated. |canonical_url| is set to the canonical URL representation when -// this method returns |true|. +// Returns true if a canonical URL representation of a `preloading_url` can be +// generated. `canonical_url` is set to the canonical URL representation when +// this method returns `true`. The search query is returned in `search_terms` if +// the passing `search_terms` is not nullptr. bool HasCanonicalPreloadingOmniboxSearchURL( const GURL& preloading_url, content::BrowserContext* browser_context, - GURL* canonical_url); + GURL* canonical_url, + std::u16string* search_terms = nullptr); // Returns true when |navigation_url| is considered as navigating to the same // omnibox search results page as |canonical_preloading_search_url|.
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.cc b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.cc index 26a550e5..1bd7e64 100644 --- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.cc +++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.cc
@@ -238,18 +238,29 @@ struct SearchPrefetchService::SearchPrefetchServingReasonRecorder { public: - explicit SearchPrefetchServingReasonRecorder(bool for_prerender) - : for_prerender_(for_prerender) {} + // Passing the SearchPrefetchService pointer is optional. If it is passed, + // the recorder will ask the service to track the search terms it in its dtor. + explicit SearchPrefetchServingReasonRecorder( + bool for_prerender, + SearchPrefetchService* service = nullptr) + : for_prerender_(for_prerender), service_(service) {} ~SearchPrefetchServingReasonRecorder() { base::UmaHistogramEnumeration( for_prerender_ ? "Omnibox.SearchPrefetch.PrefetchServingReason2.Prerender" : "Omnibox.SearchPrefetch.PrefetchServingReason2", reason_); + if (service_) { + service_->RecordInterceptionMetrics(search_terms_, reason_); + } } - SearchPrefetchServingReason reason_ = SearchPrefetchServingReason::kServed; const bool for_prerender_ = false; + // A method of SearchPrefetchService holds this instance, so it is safe to + // refer to it with pointer. + raw_ptr<SearchPrefetchService> service_; + SearchPrefetchServingReason reason_ = SearchPrefetchServingReason::kServed; + std::u16string search_terms_; }; // static @@ -542,7 +553,12 @@ SearchPrefetchService::TakePrefetchResponseFromMemoryCache( const network::ResourceRequest& tentative_resource_request) { const GURL& navigation_url = tentative_resource_request.url; - SearchPrefetchServingReasonRecorder recorder(/*for_prerender=*/false); + SearchPrefetchServingReasonRecorder recorder( + /*for_prerender=*/false, + // Not to track back/forward style navigation. + tentative_resource_request.load_flags & net::LOAD_SKIP_CACHE_VALIDATION + ? nullptr + : this); auto iter = RetrieveSearchTermsInMemoryCache(tentative_resource_request, recorder); @@ -756,20 +772,13 @@ } GURL canonical_search_url; + std::u16string search_terms; if (!HasCanonicalPreloadingOmniboxSearchURL(match.destination_url, profile_, - &canonical_search_url)) { + &canonical_search_url, + &search_terms)) { return false; } - - // Parse the search terms from the match URL to verify this is a valid search - // query. - std::u16string search_terms; - template_url_service->GetDefaultSearchProvider()->ExtractSearchTermsFromURL( - match.destination_url, template_url_service->search_terms_data(), - &search_terms); - - if (search_terms.size() == 0) - return false; + CHECK(!search_terms.empty()); // Search history suggestions (those that are not also server suggestions) // don't have search term args. If search history suggestions are enabled, @@ -1083,14 +1092,16 @@ } GURL canonical_search_url; - if (!HasCanonicalPreloadingOmniboxSearchURL(navigation_url, profile_, - &canonical_search_url) || - !IsSearchDestinationMatch(canonical_search_url, profile_, - navigation_url)) { + std::u16string search_terms; + if (!HasCanonicalPreloadingOmniboxSearchURL( + navigation_url, profile_, &canonical_search_url, &search_terms)) { recorder.reason_ = SearchPrefetchServingReason::kNotDefaultSearchWithTerms; return prefetches_.end(); } - + // `HasCanonicalPreloadingOmniboxSearchURL` should return false if + // search_terms is empty. + CHECK(!search_terms.empty()); + recorder.search_terms_ = search_terms; const auto& iter = prefetches_.find(canonical_search_url); // Return early if there is no prefetch found before checking for other @@ -1248,3 +1259,36 @@ void SearchPrefetchService::DeletePreloadedDictionaries() { preloaded_shared_dictionaries_handle_.reset(); } + +void SearchPrefetchService::RecordInterceptionMetrics( + const std::u16string& search_terms, + SearchPrefetchServingReason serving_status) { + // Do not track empty search terms. + if (search_terms.empty()) { + return; + } + switch (serving_status) { + // Do not track non-DSE navigations. + case SearchPrefetchServingReason::kSearchEngineNotValid: + case SearchPrefetchServingReason::kJavascriptDisabled: + case SearchPrefetchServingReason::kNotDefaultSearchWithTerms: + return; + case SearchPrefetchServingReason::kServed: + case SearchPrefetchServingReason::kNoPrefetch: + case SearchPrefetchServingReason::kPrefetchWasForDifferentOrigin: + case SearchPrefetchServingReason::kRequestFailed: + case SearchPrefetchServingReason::kNotServedOtherReason: + case SearchPrefetchServingReason::kPostReloadFormOrLink: + break; + case SearchPrefetchServingReason::kRequestInFlightNotReady: + NOTREACHED(); + } + auto iter = search_terms_cache_.Get(search_terms); + if (iter != search_terms_cache_.end()) { + base::UmaHistogramCustomTimes( + "Omnibox.SearchPrefetch.DuplicateSearchTermsAge", + base::Time::Now() - iter->second, base::Milliseconds(1), + base::Hours(10), 100); + } + search_terms_cache_.Put(search_terms, base::Time::Now()); +}
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.h b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.h index 9bb7faae..6f2ca1aa 100644 --- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.h +++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service.h
@@ -10,6 +10,7 @@ #include <optional> #include <utility> +#include "base/containers/lru_cache.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" @@ -271,6 +272,9 @@ void MaybePreloadDictionary(const AutocompleteResult& result); void DeletePreloadedDictionaries(); + void RecordInterceptionMetrics(const std::u16string& search_terms, + SearchPrefetchServingReason serving_status); + // Prefetches that are started are stored using search terms as a key. Only // one prefetch should be started for a given search term until the old // prefetch expires. @@ -295,6 +299,8 @@ // serving time of the response. std::map<GURL, std::pair<GURL, base::Time>> prefetch_cache_; + base::LRUCache<std::u16string, base::Time> search_terms_cache_{50}; + mojo::PendingRemote<network::mojom::PreloadedSharedDictionaryInfoHandle> preloaded_shared_dictionaries_handle_; base::OneShotTimer preloaded_shared_dictionaries_expiry_timer_;
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc index 21b7a2b..23cef01 100644 --- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc +++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -1327,6 +1327,35 @@ } } +IN_PROC_BROWSER_TEST_F(SearchPrefetchServiceEnabledBrowserTest, + DuplicateSearchTermMetricsAreRecorded) { + base::HistogramTester histogram_tester; + auto* search_prefetch_service = + SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); + EXPECT_NE(nullptr, search_prefetch_service); + + std::string search_terms = "prefetch_content"; + + auto [prefetch_url, search_url] = + GetSearchPrefetchAndNonPrefetch(search_terms); + GURL canonical_search_url = GetCanonicalSearchURL(prefetch_url); + + EXPECT_TRUE(search_prefetch_service->MaybePrefetchURL(prefetch_url, + GetWebContents())); + histogram_tester.ExpectUniqueSample( + "Omnibox.SearchPrefetch.PrefetchEligibilityReason2.SuggestionPrefetch", + SearchPrefetchEligibilityReason::kPrefetchStarted, 1); + WaitUntilStatusChangesTo(canonical_search_url, + SearchPrefetchStatus::kComplete); + + ASSERT_TRUE(content::NavigateToURL(GetWebContents(), search_url)); + histogram_tester.ExpectTotalCount( + "Omnibox.SearchPrefetch.DuplicateSearchTermsAge", 0); + ASSERT_TRUE(content::NavigateToURL(GetWebContents(), search_url)); + histogram_tester.ExpectTotalCount( + "Omnibox.SearchPrefetch.DuplicateSearchTermsAge", 1); +} + // Tests used for integrating to No-Vary-Search Disk Cache. class SearchPrefetchServiceEnabledWithNVSBrowserTest : public testing::WithParamInterface<bool>, @@ -1456,6 +1485,8 @@ histogram_tester.ExpectTotalCount( "Omnibox.SearchPrefetch.NavigationInterceptedToForwardingComplete", expected_count); + histogram_tester.ExpectTotalCount( + "Omnibox.SearchPrefetch.DuplicateSearchTermsAge", 0); } IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledWithNVSBrowserTest,
diff --git a/chrome/browser/preloading/search_preload/search_preload_browsertest.cc b/chrome/browser/preloading/search_preload/search_preload_browsertest.cc index ffcfd9d..8f48a1f0 100644 --- a/chrome/browser/preloading/search_preload/search_preload_browsertest.cc +++ b/chrome/browser/preloading/search_preload/search_preload_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" +#include "chrome/browser/preloading/chrome_preloading.h" #include "chrome/browser/preloading/prefetch/search_prefetch/search_preload_test_response_utils.h" #include "chrome/browser/preloading/search_preload/search_preload_features.h" #include "chrome/browser/preloading/search_preload/search_preload_service.h" @@ -19,8 +20,10 @@ #include "chrome/test/base/search_test_utils.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_result.h" +#include "components/omnibox/browser/omnibox.mojom.h" #include "components/search_engines/template_url_data.h" #include "components/search_engines/template_url_service.h" +#include "content/public/browser/preload_pipeline_info.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" @@ -100,7 +103,14 @@ scoped_feature_list_.InitWithFeaturesAndParameters( { {features::kPrefetchPrerenderIntegration, {}}, - {features::kDsePreload2, {}}, + { + features::kDsePreload2, + { + {"kDsePreload2PredictorMouseDown", "true"}, + {"kDsePreload2PredictorUpOrDownArrowButton", "true"}, + {"kDsePreload2PredictorTouchDown", "true"}, + }, + }, }, /*disabled_features=*/{}); @@ -136,13 +146,15 @@ base::BindRepeating(&SearchPreloadBrowserTest::HandleSearchRequest, base::Unretained(this))); ASSERT_TRUE(https_server_->Start()); + } - // Set up `TemplateURLService`. + void SetUpTemplateURLService(bool prefetch_likely_navigations = true) { TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(&GetProfile()); ASSERT_TRUE(model); search_test_utils::WaitForTemplateURLServiceToLoad(model); ASSERT_TRUE(model->loaded()); + TemplateURLData data; data.SetShortName(kSearchDomain16); data.SetKeyword(data.short_name()); @@ -154,6 +166,8 @@ .spec()); data.suggestions_url = https_server_->GetURL(kSearchDomain, "/?q={searchTerms}").spec(); + data.prefetch_likely_navigations = prefetch_likely_navigations; + TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data)); ASSERT_TRUE(template_url); model->SetUserSelectedDefaultSearchProvider(template_url); @@ -184,31 +198,35 @@ kReal, // For URLs that will be used for prefetch requests. kPrefetch, + // For URLs that will be used for prefetch requests for + // `OnNavigationLikely()`. + kPrefetchOnNavigationLikely, // For URLs that will be used for prerender requests. kPrerender }; GURL GetSearchUrl(const std::string& search_terms, UrlType url_type) { - // $1: the search terms that will be retrieved. - // $2: parameter for prefetch request. Should be &pf=cs if the url is - // expected to declare itself as a prefetch request. Otherwise it should be - // an empty string. - std::string url_template = "/search_page.html?q=$1$2&type=test"; - bool attach_prefetch_flag; + const char* pf; switch (url_type) { case UrlType::kReal: case UrlType::kPrerender: - attach_prefetch_flag = false; + pf = ""; break; case UrlType::kPrefetch: - attach_prefetch_flag = true; + pf = "&pf=cs"; + break; + case UrlType::kPrefetchOnNavigationLikely: + pf = "&pf=op"; break; } - return https_server_->GetURL( - kSearchDomain, - base::ReplaceStringPlaceholders( - url_template, {search_terms, attach_prefetch_flag ? "&pf=cs" : ""}, - nullptr)); + std::string path = base::StrCat({ + "/search_page.html", + "?q=", + search_terms, + pf, + "&type=test", + }); + return https_server_->GetURL(kSearchDomain, path); } void ChangeAutocompleteResult(const std::string& original_query, @@ -309,6 +327,8 @@ // - Prefetch is used. IN_PROC_BROWSER_TEST_F(SearchPreloadBrowserTest, OnAutocompleteResultChanged_TriggersPrefetch) { + SetUpTemplateURLService(); + ASSERT_TRUE(content::NavigateToURL( &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); @@ -358,6 +378,8 @@ // - Prefetch is used. IN_PROC_BROWSER_TEST_F(SearchPreloadBrowserTest, OnAutocompleteResultChanged_TriggeredPrefetchIsHeld) { + SetUpTemplateURLService(); + ASSERT_TRUE(content::NavigateToURL( &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); @@ -412,6 +434,8 @@ IN_PROC_BROWSER_TEST_F( SearchPreloadBrowserTest, OnAutocompleteResultChanged_TriggersPrefetchAndPrerender) { + SetUpTemplateURLService(); + ASSERT_TRUE(content::NavigateToURL( &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); @@ -472,6 +496,8 @@ IN_PROC_BROWSER_TEST_F( SearchPreloadBrowserTest, OnAutocompleteResultChanged_TriggersPrefetchThenPrerender) { + SetUpTemplateURLService(); + ASSERT_TRUE(content::NavigateToURL( &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); @@ -525,4 +551,132 @@ alternative_content::PrerenderFinalStatus::kActivated, 1); } +// Scenario: +// +// - A user inputs "he". +// - A user clicks a suggestion "hello". +// - `SearchPreloadService` starts prefetch with query "?q=hello&pf=op...". +// - A user navigates to a page with query "?q=hello&..." +// - Prefetch is used. +IN_PROC_BROWSER_TEST_F(SearchPreloadBrowserTest, + OnNavigationLikely_TriggersPrefetch) { + SetUpTemplateURLService(/*prefetch_likely_navigations=*/true); + + ASSERT_TRUE(content::NavigateToURL( + &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); + + std::string original_query = "he"; + std::string search_terms = "hello"; + GURL prefetch_url_on_navigation_likely = + GetSearchUrl(search_terms, UrlType::kPrefetchOnNavigationLikely); + GURL navigation_url = GetSearchUrl(search_terms, UrlType::kReal); + + { + content::test::TestPrefetchWatcher watcher; + + AutocompleteMatch autocomplete_match = CreateSearchSuggestionMatch( + original_query, search_terms, PrefetchHint::kEnabled, + PrerenderHint::kDisabled); + + const bool is_triggered_prefetch = + GetSearchPreloadService().OnNavigationLikely( + 1, autocomplete_match, + omnibox::mojom::NavigationPredictor::kMouseDown, &GetWebContents()); + ASSERT_TRUE(is_triggered_prefetch); + + watcher.WaitUntilPrefetchResponseCompleted( + std::nullopt, prefetch_url_on_navigation_likely); + } + + EXPECT_EQ(1, + request_collector().CountByPath(prefetch_url_on_navigation_likely)); + + // Navigate. + ASSERT_TRUE(content::NavigateToURL(&GetWebContents(), navigation_url)); + + // Prefetch is used. + EXPECT_EQ(1, + request_collector().CountByPath(prefetch_url_on_navigation_likely)); + EXPECT_EQ(0, request_collector().CountByPath(navigation_url)); +} + +// `OnNavigationLikely()` doesn't trigger prefetch if default search provider +// doesn't opt in. +IN_PROC_BROWSER_TEST_F( + SearchPreloadBrowserTest, + OnNavigationLikely_DoesntTriggerPrefetchIfDefaultSearchProviderDoesntOptIn) { + SetUpTemplateURLService(/*prefetch_likely_navigations=*/false); + + ASSERT_TRUE(content::NavigateToURL( + &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); + + std::string original_query = "he"; + std::string search_terms = "hello"; + + AutocompleteMatch autocomplete_match = CreateSearchSuggestionMatch( + original_query, search_terms, PrefetchHint::kEnabled, + PrerenderHint::kDisabled); + + const bool is_triggered_prefetch = + GetSearchPreloadService().OnNavigationLikely( + 1, autocomplete_match, + omnibox::mojom::NavigationPredictor::kMouseDown, &GetWebContents()); + ASSERT_FALSE(is_triggered_prefetch); +} + +// Scenario: +// +// - A user inputs "he". +// - Autocomplete suggests to prefetch "hello". +// - `SearchPreloadService` starts prefetch with query "?q=hello&pf=cs...". +// - A user clicks a suggestion "hello". +// - Prefetch is not triggered with query "?q=hello&pf=op..." as prefetch is +// already triggered. +// - A user navigates to a page with query "?q=hello&..." +// - Prefetch is used. +IN_PROC_BROWSER_TEST_F(SearchPreloadBrowserTest, + OnAutocompleteResultChanged_Then_OnNavigationLikely) { + SetUpTemplateURLService(/*prefetch_likely_navigations=*/true); + + ASSERT_TRUE(content::NavigateToURL( + &GetWebContents(), embedded_test_server()->GetURL("/empty.html"))); + + std::string original_query = "he"; + std::string search_terms = "hello"; + GURL prefetch_url = GetSearchUrl(search_terms, UrlType::kPrefetch); + GURL prefetch_url_on_navigation_likely = + GetSearchUrl(search_terms, UrlType::kPrefetchOnNavigationLikely); + GURL navigation_url = GetSearchUrl(search_terms, UrlType::kReal); + + { + content::test::TestPrefetchWatcher watcher; + + ChangeAutocompleteResult(original_query, search_terms, + PrefetchHint::kEnabled, PrerenderHint::kDisabled); + + watcher.WaitUntilPrefetchResponseCompleted(std::nullopt, prefetch_url); + } + + EXPECT_EQ(1, request_collector().CountByPath(prefetch_url)); + + AutocompleteMatch autocomplete_match = CreateSearchSuggestionMatch( + original_query, search_terms, PrefetchHint::kEnabled, + PrerenderHint::kDisabled); + + const bool is_triggered_prefetch = + GetSearchPreloadService().OnNavigationLikely( + 1, autocomplete_match, + omnibox::mojom::NavigationPredictor::kMouseDown, &GetWebContents()); + ASSERT_FALSE(is_triggered_prefetch); + + // Navigate. + ASSERT_TRUE(content::NavigateToURL(&GetWebContents(), navigation_url)); + + // Prefetch is used. + EXPECT_EQ(1, request_collector().CountByPath(prefetch_url)); + EXPECT_EQ(0, + request_collector().CountByPath(prefetch_url_on_navigation_likely)); + EXPECT_EQ(0, request_collector().CountByPath(navigation_url)); +} + } // namespace
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline.cc b/chrome/browser/preloading/search_preload/search_preload_pipeline.cc index 24c698f..e72a9c7 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline.cc +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline.cc
@@ -55,13 +55,19 @@ /*vary_on_key_order=*/true); } -void SearchPreloadPipeline::StartPrefetch( +bool SearchPreloadPipeline::StartPrefetch( content::WebContents& web_contents, const GURL& prefetch_url, content::PreloadingPredictor predictor) { - // Don't trigger prefetch if already triggered. + // Don't trigger prefetch if already triggered and is alive. + // + // TODO(crbug.com/394213503): Reconsider the behavior when prefetch is already + // triggered but not alive. Currently, the main reason that a triggered + // prefetch fails for DSE (embedder trigger, no TTL) is the failure of the + // load of the prefetch. (There should be no other timeouts nor expiration.) + // In general, retriggering may be useful. if (prefetch_handle_) { - return; + return false; } auto* preloading_data = @@ -93,6 +99,8 @@ /*referring_origin=*/std::nullopt, std::move(no_vary_search_hint), pipeline_info_, attempt->GetWeakPtr(), /*holdback_status_override=*/std::nullopt); + + return true; } void SearchPreloadPipeline::StartPrerender(
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline.h b/chrome/browser/preloading/search_preload/search_preload_pipeline.h index 10667927..10980b51 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline.h +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline.h
@@ -29,7 +29,10 @@ void UpdateConfidence(content::WebContents& web_contents, int confidence); // Starts prefetch if not triggered yet. - void StartPrefetch(content::WebContents& web_contents, + // + // Returns true iff prefetch is triggered, i.e. `WebContents::StartPrefetch()` + // is called. + bool StartPrefetch(content::WebContents& web_contents, const GURL& prefetch_url, content::PreloadingPredictor predictor); // Starts prerender if not triggered yet and prefetch is alive.
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.cc b/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.cc index 0b3c7d8..8844593c 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.cc +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.cc
@@ -33,6 +33,20 @@ return std::nullopt; } +// Ergonomic wrapper of `ExtractSearchTermsFromURL()` +std::optional<std::u16string> ExtractSearchTermsFromUrl( + TemplateURLService& template_url_service, + const AutocompleteMatch& match) { + std::u16string search_terms; + if (template_url_service.GetDefaultSearchProvider() + ->ExtractSearchTermsFromURL(match.destination_url, + template_url_service.search_terms_data(), + &search_terms)) { + return search_terms; + } + return std::nullopt; +} + } // namespace WEB_CONTENTS_USER_DATA_KEY_IMPL(SearchPreloadPipelineManager); @@ -120,3 +134,81 @@ chrome_preloading_predictor::kDefaultSearchEngine); } } + +bool SearchPreloadPipelineManager::OnNavigationLikely( + Profile& profile, + const AutocompleteMatch& match, + omnibox::mojom::NavigationPredictor navigation_predictor) { + if (!features::DsePreload2IsPredictorEnabled(navigation_predictor)) { + return false; + } + + if (!AutocompleteMatch::IsSearchType(match.type)) { + return false; + } + + auto* template_url_service = + TemplateURLServiceFactory::GetForProfile(&profile); + CHECK(template_url_service); + bool does_search_provider_opt_in = + template_url_service->GetDefaultSearchProvider() && + template_url_service->GetDefaultSearchProvider() + ->data() + .prefetch_likely_navigations; + if (!does_search_provider_opt_in) { + return false; + } + + const std::optional<GURL> maybe_canonical_url = + GetCanonicalUrlForSearchPreload(profile, match.destination_url); + if (!maybe_canonical_url.has_value()) { + return false; + } + const GURL& canonical_url = maybe_canonical_url.value(); + + const std::optional<std::u16string> maybe_search_terms = + ExtractSearchTermsFromUrl(*template_url_service, match); + if (!maybe_search_terms.has_value()) { + return false; + } + const std::u16string& search_terms = maybe_search_terms.value(); + + GURL prefetch_url; + if (match.search_terms_args) { + auto& search_terms_args = *match.search_terms_args.get(); + prefetch_url = + GetPrefetchUrlFromMatch(search_terms_args, *template_url_service, + /*is_navigation_likely=*/true); + } else { + // Search history suggestions (those that are not also server suggestions) + // don't have search term args. Generate search term args instead. + + auto search_terms_args_for_history_suggestion = + std::make_unique<TemplateURLRef::SearchTermsArgs>(search_terms); + auto& search_terms_args = *search_terms_args_for_history_suggestion.get(); + prefetch_url = + GetPrefetchUrlFromMatch(search_terms_args, *template_url_service, + /*is_navigation_likely=*/true); + } + + auto predictor = + [](omnibox::mojom::NavigationPredictor navigation_predictor) { + switch (navigation_predictor) { + case omnibox::mojom::NavigationPredictor::kMouseDown: + return chrome_preloading_predictor::kOmniboxMousePredictor; + case omnibox::mojom::NavigationPredictor::kUpOrDownArrowButton: + return chrome_preloading_predictor::kOmniboxSearchPredictor; + case omnibox::mojom::NavigationPredictor::kTouchDown: + return chrome_preloading_predictor::kOmniboxTouchDownPredictor; + } + }(navigation_predictor); + + // TODO(crbug.com/403198750): Limit the number of active pipelines. + if (!pipelines_.contains(canonical_url)) { + pipelines_.insert_or_assign( + canonical_url, std::make_unique<SearchPreloadPipeline>(canonical_url)); + } + pipelines_[canonical_url]->UpdateConfidence(GetWebContents(), 100); + return pipelines_[canonical_url]->StartPrefetch(GetWebContents(), + prefetch_url, predictor); +}
diff --git a/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.h b/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.h index cf0bf44..612f7d1 100644 --- a/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.h +++ b/chrome/browser/preloading/search_preload/search_preload_pipeline_manager.h
@@ -13,6 +13,7 @@ class Profile; class AutocompleteResult; +struct AutocompleteMatch; namespace content { class WebContents; @@ -50,6 +51,16 @@ void OnAutocompleteResultChanged(Profile& profile, const AutocompleteResult& result); + // Called when a user is likely to navigate to the match. + // + // Returns true iff a new prefetch is triggered by this call. Note that it + // returns false if a prefetch for the same canonical URL has already + // triggered. + bool OnNavigationLikely( + Profile& profile, + const AutocompleteMatch& match, + omnibox::mojom::NavigationPredictor navigation_predictor); + private: friend content::WebContentsUserData<SearchPreloadPipelineManager>; WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/preloading/search_preload/search_preload_service.cc b/chrome/browser/preloading/search_preload/search_preload_service.cc index 5b039fe..955b7dc7 100644 --- a/chrome/browser/preloading/search_preload/search_preload_service.cc +++ b/chrome/browser/preloading/search_preload/search_preload_service.cc
@@ -87,5 +87,10 @@ const AutocompleteMatch& match, omnibox::mojom::NavigationPredictor navigation_predictor, content::WebContents* web_contents) { - NOTREACHED(); + if (!web_contents) { + return false; + } + + return GetOrCreatePipelineManagerWithLimit(*web_contents) + .OnNavigationLikely(*profile_, match, navigation_predictor); }
diff --git a/chrome/browser/printing/print_backend_service_manager.cc b/chrome/browser/printing/print_backend_service_manager.cc index 8e75f8b..43dadbf 100644 --- a/chrome/browser/printing/print_backend_service_manager.cc +++ b/chrome/browser/printing/print_backend_service_manager.cc
@@ -38,6 +38,7 @@ #if BUILDFLAG(IS_LINUX) #include "content/public/common/content_switches.h" +#include "ui/linux/linux_ui.h" #endif #if BUILDFLAG(IS_WIN) @@ -878,14 +879,19 @@ << (sandboxed ? "sandboxed" : "unsandboxed") << " for `" << remote_id << "`"; + std::vector<std::string> extra_switches; +#if BUILDFLAG(IS_LINUX) + if (auto* linux_ui = ui::LinuxUi::instance()) { + extra_switches = linux_ui->GetCmdLineFlagsForCopy(); + } + extra_switches.push_back(switches::kMessageLoopTypeUi); +#endif mojo::Remote<T>& host = bundle->host; content::ServiceProcessHost::Launch( host.BindNewPipeAndPassReceiver(), content::ServiceProcessHost::Options() .WithDisplayName(IDS_UTILITY_PROCESS_PRINT_BACKEND_SERVICE_NAME) -#if BUILDFLAG(IS_LINUX) - .WithExtraCommandLineSwitches({switches::kMessageLoopTypeUi}) -#endif + .WithExtraCommandLineSwitches(std::move(extra_switches)) .Pass()); host->BindBackend(service.BindNewPipeAndPassReceiver());
diff --git a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_welcome.xml b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_welcome.xml index 1effa2d..eb72fa1 100644 --- a/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_welcome.xml +++ b/chrome/browser/privacy_guide/android/java/res/layout/privacy_guide_welcome.xml
@@ -8,7 +8,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:id="@+id/privacy_guide_welcome_scrollview"> <LinearLayout android:layout_width="match_parent"
diff --git a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/PrivacyGuideFragment.java b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/PrivacyGuideFragment.java index 716ded7..e60f2e4 100644 --- a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/PrivacyGuideFragment.java +++ b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/PrivacyGuideFragment.java
@@ -19,6 +19,7 @@ import androidx.annotation.IntDef; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager2.widget.ViewPager2; import com.google.android.material.tabs.TabLayout; @@ -129,6 +130,14 @@ mViewPager.setPageTransformer(new PrivacyGuidePageTransformer()); mViewPager.setUserInputEnabled(false); + // Workaround for ViewPager2 bug: https://issuetracker.google.com/issues/284429851. + for (int i = 0; i < mViewPager.getChildCount(); i++) { + var child = mViewPager.getChildAt(i); + if (child instanceof RecyclerView) { + child.setFocusable(false); + } + } + mOnPageChangeCallback = new ViewPager2.OnPageChangeCallback() { @Override @@ -154,10 +163,12 @@ mViewPager.registerOnPageChangeCallback(mOnPageChangeCallback); mTabLayout = mView.findViewById(R.id.tab_layout); + mTabLayout.setFocusable(false); new TabLayoutMediator( mTabLayout, mViewPager, (tab, position) -> { + tab.view.setFocusable(false); tab.view.setClickable(false); tab.view.setImportantForAccessibility( View.IMPORTANT_FOR_ACCESSIBILITY_NO);
diff --git a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/WelcomeFragment.java b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/WelcomeFragment.java index cd8913b..706e0f5 100644 --- a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/WelcomeFragment.java +++ b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/WelcomeFragment.java
@@ -22,4 +22,12 @@ @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.privacy_guide_welcome, container, false); } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + // ScrollView sets focusable to true during construction. So setting focusable to false in + // xml file doesn't work. It has to be set after the construction of ScrollView. + view.findViewById(R.id.privacy_guide_welcome_scrollview).setFocusable(false); + } }
diff --git a/chrome/browser/privacy_sandbox/BUILD.gn b/chrome/browser/privacy_sandbox/BUILD.gn index 79998f3..ed2b0215 100644 --- a/chrome/browser/privacy_sandbox/BUILD.gn +++ b/chrome/browser/privacy_sandbox/BUILD.gn
@@ -288,13 +288,58 @@ ] } +source_set("survey_desktop_controller_unittest") { + testonly = true + if (!is_android) { + sources = [ "privacy_sandbox_survey_desktop_controller_unittest.cc" ] + deps = [ + "//base/test:test_support", + "//base/version_info:channel", + "//chrome/browser/profiles:profile", + "//chrome/browser/ui/hats", + "//chrome/browser/ui/hats:test_support", + "//chrome/common:channel_info", + "//chrome/test:test_support", + "//components/prefs", + "//components/prefs:test_support", + "//components/privacy_sandbox:features", + "//components/privacy_sandbox:privacy_sandbox_prefs", + "//components/privacy_sandbox:privacy_sandbox_survey_service", + "//components/signin/public/base", + "//components/signin/public/identity_manager:test_support", + "//components/version_info", + "//content/test:test_support", + ] + } +} + +source_set("activity_types_service_unittest") { + testonly = true + if (is_android) { + sources = [ "privacy_sandbox_activity_types_service_unittest.cc" ] + deps = [ + "//base/test:test_support", + "//chrome/browser/preferences:java_pref_names_srcjar", + "//chrome/browser/privacy_sandbox/android:privacy_sandbox_enums", + "//chrome/test:test_support", + "//components/metrics:metrics_pref_names", + "//components/prefs:test_support", + "//components/privacy_sandbox:features", + "//components/privacy_sandbox:privacy_sandbox_prefs", + "//content/test:test_support", + ] + } +} + group("unit_tests") { testonly = true deps = [ + ":activity_types_service_unittest", ":policy_handler_unittest", ":profile_bucket_metrics_unittest", ":service_impl_unittest", ":settings_delegate_unittest", + ":survey_desktop_controller_unittest", ":utils_unittest", "notice:unit_tests", ]
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 f86596f..fdbca07 100644 --- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc +++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -231,6 +231,7 @@ #include "chrome/browser/visited_url_ranking/group_suggestions_service_factory.h" #include "chrome/browser/visited_url_ranking/visited_url_ranking_service_factory.h" #include "chrome/browser/webauthn/enclave_manager_factory.h" +#include "chrome/browser/webauthn/immediate_request_rate_limiter_factory.h" #include "chrome/browser/webdata_services/web_data_service_factory.h" #include "chrome/browser/webid/federated_identity_api_permission_context_factory.h" #include "chrome/browser/webid/federated_identity_auto_reauthn_permission_context_factory.h" @@ -956,6 +957,9 @@ HttpsEngagementServiceFactory::GetInstance(); HttpsFirstModeServiceFactory::GetInstance(); IdentityManagerFactory::EnsureFactoryAndDependeeFactoriesBuilt(); +#if !BUILDFLAG(IS_ANDROID) + ImmediateRequestRateLimiterFactory::GetInstance(); +#endif // !BUILDFLAG(IS_ANDROID) InMemoryURLIndexFactory::GetInstance(); visited_url_ranking::VisitedURLRankingServiceFactory::GetInstance(); #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/autoclick/autoclick_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/autoclick/autoclick_test.js index 02398a807..90f2167 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/autoclick/autoclick_test.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/autoclick/autoclick_test.js
@@ -38,6 +38,7 @@ #include "base/functional/bind.h" #include "base/functional/callback.h" #include "chrome/browser/ash/accessibility/accessibility_manager.h" +#include "ui/accessibility/accessibility_features.h" `); } @@ -52,6 +53,13 @@ super.testGenPreambleCommon('kAccessibilityCommonExtensionId'); } + /** @override */ + get featureList() { + return { + disabled: ['features::kAccessibilityManifestV3AccessibilityCommon'] + }; + } + /** * Asserts that two rects are the same. * @param {!chrome.accessibilityPrivate.ScreenRect} first
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/dictation/dictation_test_base.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/dictation/dictation_test_base.js index 3150eff..e336897 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/dictation/dictation_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/dictation/dictation_test_base.js
@@ -159,6 +159,13 @@ ]); } + /** @override */ + get featureList() { + return { + disabled: ['features::kAccessibilityManifestV3AccessibilityCommon'] + }; + } + /** Turns on Dictation and checks IME and Speech Recognition state. */ toggleDictationOn() { this.mockAccessibilityPrivate.callOnToggleDictation(true);
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/facegaze/facegaze_test_base.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/facegaze/facegaze_test_base.js index 23b47d7..6aae0f3 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/facegaze/facegaze_test_base.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/facegaze/facegaze_test_base.js
@@ -284,7 +284,10 @@ /** @override */ get featureList() { - return {enabled: ['features::kAccessibilityFaceGaze']}; + return { + enabled: ['features::kAccessibilityFaceGaze'], + disabled: ['features::kAccessibilityManifestV3AccessibilityCommon'] + }; } /** @return {!FaceGaze} */
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/magnifier/magnifier_test.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/magnifier/magnifier_test.js index 305e712..10f8cf7 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/magnifier/magnifier_test.js +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv2/magnifier/magnifier_test.js
@@ -53,6 +53,7 @@ enabled: [ 'features::kAccessibilityMagnifierFollowsChromeVox', ], + disabled: ['features::kAccessibilityManifestV3AccessibilityCommon'] }; } };
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/BUILD.gn index ad0fec9..8a1b6f0c 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/BUILD.gn
@@ -53,6 +53,7 @@ "dictation/ui_controller.ts", "dictation/macros/list_commands_macro.ts", "dictation/offscreen_audio.ts", + "dictation/offscreen_pumpkin_worker.ts", "dictation/parse/input_text_strategy.ts", "dictation/parse/parse_strategy.ts", "dictation/parse/pumpkin_parse_strategy.ts",
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/offscreen.html b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/offscreen.html index cb6ee3a8..ef0b9824 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/offscreen.html +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/offscreen.html
@@ -6,4 +6,5 @@ <body> <script type="module" src="offscreen_audio.js"></script> + <script type="module" src="offscreen_pumpkin_worker.js"></script> </body>
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/offscreen_pumpkin_worker.ts b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/offscreen_pumpkin_worker.ts new file mode 100644 index 0000000..85be4581 --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/offscreen_pumpkin_worker.ts
@@ -0,0 +1,62 @@ +// 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 {OffscreenCommandType} from '../offscreen_command_type.js'; + +import * as PumpkinConstants from './parse/pumpkin/pumpkin_constants.js'; + +const SANDBOXED_PUMPKIN_TAGGER_JS_FILE = 'parse/sandboxed_pumpkin_tagger.js'; + +/** + * Offscreen way to communicate to pumpkin via worker. + */ +class OffscreenPumpkinWorker { + private worker_: Worker|null = null; + + static instance?: OffscreenPumpkinWorker; + + static init(): void { + if (OffscreenPumpkinWorker.instance) { + throw 'Error: trying to create two instances of singleton ' + + 'OffscreenPumpkinWorker.'; + } + OffscreenPumpkinWorker.instance = new OffscreenPumpkinWorker(); + } + + constructor() { + chrome.runtime.onMessage.addListener( + (message: any|undefined, _sender: chrome.runtime.MessageSender) => + this.handleMessageFromServiceWorker_(message)); + } + + private handleMessageFromServiceWorker_(message: any|undefined): boolean { + switch (message['command']) { + case OffscreenCommandType.DICTATION_PUMPKIN_INSTALL: + this.worker_ = + new Worker(SANDBOXED_PUMPKIN_TAGGER_JS_FILE, {type: 'module'}); + this.worker_.onmessage = (message) => + chrome.runtime.sendMessage(undefined, { + command: OffscreenCommandType.DICTATION_PUMPKIN_RECEIVE, + fromPumpkinTagger: message.data + }); + break; + case OffscreenCommandType.DICTATION_PUMPKIN_SEND: + this.sendToSandboxedPumpkinTagger_(message['toPumpkinTagger']) + break; + } + return false; + } + + private sendToSandboxedPumpkinTagger_( + command: PumpkinConstants.ToPumpkinTagger): void { + if (!this.worker_) { + throw new Error( + `Worker not ready, cannot send command to SandboxedPumpkinTagger: ${ + command.type}`); + } + this.worker_.postMessage(command); + } +} + +OffscreenPumpkinWorker.init();
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/parse/pumpkin/pumpkin_constants.ts b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/parse/pumpkin/pumpkin_constants.ts index be65875..aff3fe36 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/parse/pumpkin/pumpkin_constants.ts +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/parse/pumpkin/pumpkin_constants.ts
@@ -141,7 +141,4 @@ END_PHRASE = 'END_PHRASE', } -export const SANDBOXED_PUMPKIN_TAGGER_JS_FILE = - 'dictation/parse/sandboxed_pumpkin_tagger.js'; - TestImportManager.exportForTesting(['SUPPORTED_LOCALES', SUPPORTED_LOCALES]);
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/parse/pumpkin_parse_strategy.ts b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/parse/pumpkin_parse_strategy.ts index f5e07dd..bc8ac70 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/parse/pumpkin_parse_strategy.ts +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/dictation/parse/pumpkin_parse_strategy.ts
@@ -21,6 +21,7 @@ import {SmartSelectBetweenMacro} from '/common/action_fulfillment/macros/smart_select_between_macro.js'; import {ToggleDictationMacro} from '/common/action_fulfillment/macros/toggle_dictation_macro.js'; +import {OffscreenCommandType} from '../../offscreen_command_type.js'; import {LocaleInfo} from '../locale_info.js'; import {ListCommandsMacro} from '../macros/list_commands_macro.js'; @@ -39,7 +40,6 @@ private pumpkinTaggerReady_ = false; private tagResolver_: ( (results: proto.speech.pumpkin.PumpkinTaggerResults) => void)|null = null; - private worker_: Worker|null = null; private locale_: PumpkinConstants.PumpkinLocale|null = null; private requestedPumpkinInstall_ = false; private onPumpkinTaggerReadyChangedForTesting_: VoidFunction|null = null; @@ -50,6 +50,11 @@ return; } + chrome.runtime.onMessage.addListener( + (message: any|undefined, _sender: chrome.runtime.MessageSender, + _sendResponse: (value: any) => void) => + this.handleMessageFromOffscreen_(message)); + this.requestedPumpkinInstall_ = true; chrome.accessibilityPrivate.installPumpkinForDictation(data => { // TODO(crbug.com/259352407): Consider retrying installation at a later @@ -79,17 +84,23 @@ this.setPumpkinTaggerReady_(false); this.pumpkinData_ = data; - this.worker_ = new Worker( - PumpkinConstants.SANDBOXED_PUMPKIN_TAGGER_JS_FILE, {type: 'module'}); - this.worker_.onmessage = (message) => this.onMessage_(message); + this.sendToOffscreen_(OffscreenCommandType.DICTATION_PUMPKIN_INSTALL); + } + + private handleMessageFromOffscreen_(message: any|undefined) { + switch (message['command']) { + case OffscreenCommandType.DICTATION_PUMPKIN_RECEIVE: + this.onMessage_(message['fromPumpkinTagger']); + break; + } + return false; } /** * Called when the SandboxedPumpkinTagger posts a message to the background * context. */ - private onMessage_(message: MessageEvent): void { - const command: PumpkinConstants.FromPumpkinTagger = message.data; + private onMessage_(command: PumpkinConstants.FromPumpkinTagger): void { switch (command.type) { case PumpkinConstants.FromPumpkinTaggerCommand.READY: this.refreshLocale_(); @@ -128,14 +139,9 @@ } private sendToSandboxedPumpkinTagger_( - command: PumpkinConstants.ToPumpkinTagger): void { - if (!this.worker_) { - throw new Error( - `Worker not ready, cannot send command to SandboxedPumpkinTagger: ${ - command.type}`); - } - - this.worker_.postMessage(command); + toPumpkinTagger: PumpkinConstants.ToPumpkinTagger): void { + this.sendToOffscreen_( + OffscreenCommandType.DICTATION_PUMPKIN_SEND, {toPumpkinTagger}); } /** @@ -356,4 +362,8 @@ this.onPumpkinTaggerReadyChangedForTesting_(); } } + + private sendToOffscreen_(command: OffscreenCommandType, data = {}): void { + chrome.runtime.sendMessage(undefined, Object.assign({command}, data)); + } }
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/offscreen_command_type.ts b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/offscreen_command_type.ts index 415eaa2..232f942 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/offscreen_command_type.ts +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/offscreen_command_type.ts
@@ -10,4 +10,7 @@ DICTATION_PLAY_CANCEL = 'DictationPlayCancel', DICTATION_PLAY_START = 'DictationPlayStart', DICTATION_PLAY_END = 'DictationPlayEnd', + DICTATION_PUMPKIN_INSTALL = 'DictationPumpkinInstall', + DICTATION_PUMPKIN_RECEIVE = 'DictationPumpkinReceive', + DICTATION_PUMPKIN_SEND = 'DictationPumpkinSend', }
diff --git a/chrome/browser/resources/glic/webview.ts b/chrome/browser/resources/glic/webview.ts index ba735d8..b68fcf55 100644 --- a/chrome/browser/resources/glic/webview.ts +++ b/chrome/browser/resources/glic/webview.ts
@@ -222,6 +222,7 @@ return; } } + console.warn(`Webview permission request was denied: ${e.permission}`); e.request.deny(); }
diff --git a/chrome/browser/resources/lens/overlay/BUILD.gn b/chrome/browser/resources/lens/overlay/BUILD.gn index fd1b5c3..34314cd 100644 --- a/chrome/browser/resources/lens/overlay/BUILD.gn +++ b/chrome/browser/resources/lens/overlay/BUILD.gn
@@ -77,6 +77,8 @@ "selection_utils.ts", "side_panel/side_panel_browser_proxy.ts", "side_panel/side_panel_error_page.ts", + "side_panel/feedback_toast.ts", + "side_panel/feedback_toast.html.ts", "side_panel/side_panel_error_page.html.ts", "side_panel/post_message_communication.ts", "simplified_text_layer.html.ts", @@ -91,6 +93,7 @@ css_files = [ "simplified_text_layer.css", "side_panel/side_panel_error_page.css", + "side_panel/feedback_toast.css", ] ts_deps = [
diff --git a/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.css b/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.css new file mode 100644 index 0000000..1cc113c --- /dev/null +++ b/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.css
@@ -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. */ + +/* #css_wrapper_metadata_start + * #type=style-lit + * #scheme=relative + * #css_wrapper_metadata_end */ + +#closeFeedbackToastButton { + margin-block-end: 8px; + margin-block-start: 8px; + margin-inline-end: 0; + margin-inline-start: 0; +} + +#feedbackButtonContainer { + align-items: center; + display: flex; + justify-content: center; + margin-inline-start: auto; +} + +#feedbackToast { + --color-toast-background: white; + --color-toast-button: #1558D6; + --color-toast-foreground: #474747; + --cr-icon-button-fill-color: #5E5E5E; + box-shadow: 0px 2px 6px 0px rgba(23, 23, 23, 0.32); + display: flex; + height: 48px; + left: 0; + margin: auto auto 16px; + min-height: 48px; + padding: 0; + right: 0; + width: 336px; + white-space: nowrap; +} + +:host([dark-mode]) #feedbackToast { + --color-toast-background: #303134; + --color-toast-button: #99C3FF6; + --color-toast-foreground: #BFBFBF; + --cr-icon-button-fill-color: #9E9E9E; +} + +#feedbackToastMessage { + margin-inline-start: 16px; +} + +#sendFeedbackButton { + background-color: transparent; + border: none; + margin-block-end: 6px; + margin-block-start: 6px; + padding: 0; +} \ No newline at end of file
diff --git a/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.html.ts b/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.html.ts new file mode 100644 index 0000000..1815e107 --- /dev/null +++ b/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.html.ts
@@ -0,0 +1,28 @@ +// 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 '//resources/cr_elements/cr_button/cr_button.js'; +import '//resources/cr_elements/cr_icon_button/cr_icon_button.js'; +import '//resources/cr_elements/cr_toast/cr_toast.js'; + +import {loadTimeData} from '//resources/js/load_time_data.js'; +import {html} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {FeedbackToastElement} from './feedback_toast.js'; + +export function getHtml(this: FeedbackToastElement) { + return html` +<cr-toast id="feedbackToast" duration="0"> + <div id="feedbackToastMessage">${ + loadTimeData.getString('feedbackToastMessage')}</div> + <div id="feedbackButtonContainer"> + <cr-button id="sendFeedbackButton" @click="${this.onSendFeedbackClick}"> + ${loadTimeData.getString('sendFeedbackButtonText')} + </cr-button> + <cr-icon-button id="closeFeedbackToastButton" iron-icon="cr:close" + @click="${this.onHideFeedbackToastClick}"> + </cr-icon-button> + </div> +</cr-toast>`; +}
diff --git a/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.ts b/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.ts new file mode 100644 index 0000000..0346fd3 --- /dev/null +++ b/chrome/browser/resources/lens/overlay/side_panel/feedback_toast.ts
@@ -0,0 +1,88 @@ +// 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 '//resources/cr_elements/cr_button/cr_button.js'; +import '//resources/cr_elements/cr_icon_button/cr_icon_button.js'; +import '//resources/cr_elements/cr_toast/cr_toast.js'; +import '/strings.m.js'; + +import type {CrButtonElement} from '//resources/cr_elements/cr_button/cr_button.js'; +import type {CrToastElement} from '//resources/cr_elements/cr_toast/cr_toast.js'; +import {loadTimeData} from '//resources/js/load_time_data.js'; +import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js'; + +import {getCss} from './feedback_toast.css.js'; +import {getHtml} from './feedback_toast.html.js'; +import {SidePanelBrowserProxyImpl} from './side_panel_browser_proxy.js'; +import type {SidePanelBrowserProxy} from './side_panel_browser_proxy.js'; + +export interface FeedbackToastElement { + $: { + closeFeedbackToastButton: CrButtonElement, + feedbackToast: CrToastElement, + }; +} + +export class FeedbackToastElement extends CrLitElement { + static get is() { + return 'feedback-toast'; + } + + static override get styles() { + return getCss(); + } + + override render() { + return getHtml.bind(this)(); + } + + static override get properties() { + return { + darkMode: { + type: Boolean, + reflect: true, + }, + }; + } + + // Whether to render the feedback toast in dark mode. + protected accessor darkMode: boolean = loadTimeData.getBoolean('darkMode'); + + private browserProxy: SidePanelBrowserProxy = + SidePanelBrowserProxyImpl.getInstance(); + + show() { + if (this.$.feedbackToast.open) { + // If toast already open, wait after hiding so that animation is + // smoother. + this.hide(); + setTimeout(() => { + this.$.feedbackToast.show(); + }, 100); + return; + } + this.$.feedbackToast.show(); + } + + hide() { + this.$.feedbackToast.hide(); + } + + protected onSendFeedbackClick() { + this.browserProxy.handler.requestSendFeedback(); + this.hide(); + } + + protected onHideFeedbackToastClick() { + this.hide(); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'feedback-toast': FeedbackToastElement; + } +} + +customElements.define(FeedbackToastElement.is, FeedbackToastElement);
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 ca52348..2865f6e9 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
@@ -28,48 +28,6 @@ background-color: #101218; } - #closeFeedbackToastButton { - margin-block-end: 8px; - margin-block-start: 8px; - margin-inline-end: 0; - margin-inline-start: 0; - } - - #feedbackButtonContainer { - align-items: center; - display: flex; - justify-content: center; - margin-inline-start: auto; - } - - #feedbackToast { - --color-toast-background: white; - --color-toast-button: #1558D6; - --color-toast-foreground: #474747; - --cr-icon-button-fill-color: #5E5E5E; - box-shadow: 0px 2px 6px 0px rgba(23, 23, 23, 0.32); - display: flex; - height: 48px; - left: 0; - margin: auto auto 16px; - min-height: 48px; - padding: 0; - right: 0; - width: 336px; - white-space: nowrap; - } - - :host([dark-mode]) #feedbackToast { - --color-toast-background: #303134; - --color-toast-button: #99C3FF6; - --color-toast-foreground: #BFBFBF; - --cr-icon-button-fill-color: #9E9E9E; - } - - #feedbackToastMessage { - margin-inline-start: 16px; - } - /* Set z-index to hide results to prevent ghost frames when reshowing. */ :host([is-loading-results]) #results { z-index: 0; @@ -154,14 +112,6 @@ --color-searchbox-background: var(--color-searchbox-results-background); } - #sendFeedbackButton { - background-color: transparent; - border: none; - margin-block-end: 6px; - margin-block-start: 6px; - padding: 0; - } - #toast { justify-content: space-between; } @@ -268,17 +218,7 @@ allow="cross-origin-isolated; display-capture; geolocation; microphone;" frameBorder="0"> </iframe> -<cr-toast id="feedbackToast" duration="0"> - <div id="feedbackToastMessage">$i18n{feedbackToastMessage}</div> - <div id="feedbackButtonContainer"> - <cr-button id="sendFeedbackButton" on-click="onSendFeedbackClick"> - $i18n{sendFeedbackButtonText} - </cr-button> - <cr-icon-button id="closeFeedbackToastButton" iron-icon="cr:close" - on-click="onHideFeedbackToastClick"> - </cr-icon-button> - </div> -</cr-toast> +<feedback-toast id="feedbackToast"></feedback-toast> <cr-toast id="messageToast" duration="4000"> <div>[[toastMessage]]</div>
diff --git a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts index 6a02e0e..69ad781 100644 --- a/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts +++ b/chrome/browser/resources/lens/overlay/side_panel/side_panel_app.ts
@@ -4,6 +4,7 @@ import './side_panel_ghost_loader.js'; import './side_panel_error_page.js'; +import './feedback_toast.js'; import '/strings.m.js'; import '/lens/shared/searchbox_ghost_loader.js'; import '/lens/shared/searchbox_shared_style.css.js'; @@ -13,7 +14,6 @@ import {ColorChangeUpdater} from '//resources/cr_components/color_change_listener/colors_css_updater.js'; import {HelpBubbleMixin} from '//resources/cr_components/help_bubble/help_bubble_mixin.js'; import type {SearchboxElement} from '//resources/cr_components/searchbox/searchbox.js'; -import type {CrButtonElement} from '//resources/cr_elements/cr_button/cr_button.js'; import type {CrToastElement} from '//resources/cr_elements/cr_toast/cr_toast.js'; import {I18nMixin} from '//resources/cr_elements/i18n_mixin.js'; import {assert} from '//resources/js/assert.js'; @@ -28,6 +28,8 @@ import {PageContentType} from '../page_content_type.mojom-webui.js'; import {handleEscapeSearchbox} from '../searchbox_utils.js'; +import type {FeedbackToastElement} from './feedback_toast.js'; + import {PostMessageReceiver} from './post_message_communication.js'; import {getTemplate} from './side_panel_app.html.js'; import {SidePanelBrowserProxyImpl} from './side_panel_browser_proxy.js'; @@ -41,8 +43,7 @@ export interface LensSidePanelAppElement { $: { - closeFeedbackToastButton: CrButtonElement, - feedbackToast: CrToastElement, + feedbackToast: FeedbackToastElement, ghostLoader: SidePanelGhostLoaderElement, messageToast: CrToastElement, errorPage: SidePanelErrorPageElement, @@ -304,6 +305,8 @@ this.uploadProgressPercentage = 0; }; + // Show the feedback on every result load by showing it as soon as the + // result load animation is complete. this.showFeedbackToast(); } } @@ -465,11 +468,11 @@ } await this.$.messageToast.hide(); - await this.showToast(this.$.feedbackToast); + this.$.feedbackToast.show(); } private async showMessageToast(message: string) { - await this.$.feedbackToast.hide(); + this.$.feedbackToast.hide(); await this.showToast(this.$.messageToast, message); } @@ -489,14 +492,6 @@ toast.show(); } - private onSendFeedbackClick() { - // TODO(crbug.com/408057740): Clicking button should open form. - } - - private onHideFeedbackToastClick() { - this.$.feedbackToast.hide(); - } - private onHideMessageToastClick() { this.$.messageToast.hide(); }
diff --git a/chrome/browser/resources/on_device_internals/tools.ts b/chrome/browser/resources/on_device_internals/tools.ts index 9ba1cfe8..ee5f33f0 100644 --- a/chrome/browser/resources/on_device_internals/tools.ts +++ b/chrome/browser/resources/on_device_internals/tools.ts
@@ -289,6 +289,7 @@ this.session_.append( { maxTokens: 0, + // TODO(crbug.com/416009528): This field is deprecated. Remove it. tokenOffset: 0, input: {pieces: textToInputPieces(this.contextText_)}, }, @@ -407,6 +408,7 @@ clonedSession.append( { maxTokens: 0, + // TODO(crbug.com/416009528): This field is deprecated. Remove it. tokenOffset: 0, input: {pieces: pieces}, },
diff --git a/chrome/browser/resources/settings/glic_page/glic_page.html b/chrome/browser/resources/settings/glic_page/glic_page.html index 09ec2fb..a535dc0 100644 --- a/chrome/browser/resources/settings/glic_page/glic_page.html +++ b/chrome/browser/resources/settings/glic_page/glic_page.html
@@ -139,6 +139,13 @@ on-shortcut-updated="onFocusToggleShortcutUpdated_"> </cr-shortcut-input> </div> + <settings-toggle-button + id="closedCaptionsToggle" + pref="{{prefs.glic.closed_captioning_enabled}}" + label="$i18n{glicClosedCaptionsToggle}" + sub-label="$i18n{glicClosedCaptionsToggleSublabel}" + on-settings-boolean-control-change="onClosedCaptionsToggleChange_"> + </settings-toggle-button> </template> </div> <div class="section">
diff --git a/chrome/browser/resources/settings/glic_page/glic_page.ts b/chrome/browser/resources/settings/glic_page/glic_page.ts index 8367233..355029dd 100644 --- a/chrome/browser/resources/settings/glic_page/glic_page.ts +++ b/chrome/browser/resources/settings/glic_page/glic_page.ts
@@ -33,6 +33,7 @@ import {getTemplate} from './glic_page.html.js'; export enum SettingsGlicPageFeaturePrefName { + CLOSED_CAPTIONS_ENABLED = 'glic.closed_captioning_enabled', GEOLOCATION_ENABLED = 'glic.geolocation_enabled', LAUNCHER_ENABLED = 'glic.launcher_enabled', MICROPHONE_ENABLED = 'glic.microphone_enabled', @@ -265,6 +266,12 @@ private disallowedByAdminChanged_(disallowed: boolean) { this.disallowedByAdmin_ = disallowed; } + + private onClosedCaptionsToggleChange_(event: Event) { + const enabled = (event.target as SettingsToggleButtonElement).checked; + this.metricsBrowserProxy_.recordAction( + 'Glic.Settings.ClosedCaptions.' + (enabled ? 'Enabled' : 'Disabled')); + } } declare global {
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts index beddbd29..d2f4dd3 100644 --- a/chrome/browser/resources/side_panel/read_anything/app.ts +++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -28,6 +28,7 @@ import {PauseActionSource, SpeechEngineState} from './read_aloud/speech_model.js'; import type {SpeechPlayingState} from './read_aloud/speech_model.js'; import {VoicePackController} from './read_aloud/voice_pack_controller.js'; +import type {VoiceLanguageListener} from './read_aloud/voice_pack_controller.js'; import {WordBoundaries} from './read_aloud/word_boundaries.js'; import type {WordBoundaryState} from './read_aloud/word_boundaries.js'; import {ReadAnythingLogger, TimeFrom} from './read_anything_logger.js'; @@ -56,7 +57,8 @@ }; } -export class AppElement extends AppElementBase implements SpeechListener { +export class AppElement extends AppElementBase implements + SpeechListener, VoiceLanguageListener { static get is() { return 'read-anything-app'; } @@ -213,6 +215,7 @@ if (this.isReadAloudEnabled_) { this.speechController_.addListener(this); + this.voicePackController_.addListener(this); this.notificationManager_.addListener(this.$.languageToast); // Clear state. We don't do this in disconnectedCallback because that's @@ -816,9 +819,8 @@ // Update application state this.updateApplicationState(lang, newVoicePackStatus); - if (isVoicePackStatusError(newVoicePackStatus) && - this.voicePackController_.disableLangIfNoVoices(lang)) { - this.enabledLangs_ = this.voicePackController_.getEnabledLangs(); + if (isVoicePackStatusError(newVoicePackStatus)) { + this.voicePackController_.disableLangIfNoVoices(lang); } } @@ -840,7 +842,8 @@ case VoicePackServerStatusSuccessCode.INSTALLED: // Force a refresh of the voices list since we might not get an update // the voices have changed. - this.getVoices_(/*forceRefresh=*/ true); + this.voicePackController_.refreshAvailableVoices( + /*forceRefresh=*/ true); this.autoSwitchVoice_(lang); // Some languages may require a download from the voice pack @@ -906,7 +909,7 @@ onVoicesChanged() { if (this.waitingForNewEngine_) { - this.enabledLangs_.forEach(lang => { + this.voicePackController_.getEnabledLangs().forEach(lang => { this.installVoicePackIfPossible( lang, /* onlyInstallExactGoogleLocaleMatch=*/ true, @@ -919,15 +922,13 @@ const hadAvailableVoices = this.voicePackController_.hasAvailableVoices(); // Get a new list of voices. This should be done before we call // refreshVoicePackStatuses(); - this.getVoices_(/*forceRefresh=*/ true); + this.voicePackController_.refreshAvailableVoices(/*forceRefresh=*/ true); // TODO: crbug.com/390435037 - Simplify logic around loading voices and // language availability, especially around the new TTS engine. // <if expr="not is_chromeos"> - if (this.voicePackController_.enableNowAvailableLangs()) { - this.enabledLangs_ = this.voicePackController_.getEnabledLangs(); - } + this.voicePackController_.enableNowAvailableLangs(); // </if> if (!hadAvailableVoices && this.voicePackController_.hasAvailableVoices()) { @@ -1060,12 +1061,8 @@ } private getVoices_(forceRefresh: boolean = false): SpeechSynthesisVoice[] { - if (this.voicePackController_.refreshAvailableVoices(forceRefresh)) { - this.availableVoices_ = this.voicePackController_.getAvailableVoices(); - this.localeToDisplayName_ = - this.voicePackController_.getDisplayNamesForLocaleCodes(); - } - return this.availableVoices_; + this.voicePackController_.refreshAvailableVoices(forceRefresh); + return this.voicePackController_.getAvailableVoices(); } protected onPreviewVoice_( @@ -1126,6 +1123,16 @@ } } + onEnabledLangsChange(): void { + this.enabledLangs_ = this.voicePackController_.getEnabledLangs(); + } + + onAvailableVoicesChange(): void { + this.availableVoices_ = this.voicePackController_.getAvailableVoices(); + this.localeToDisplayName_ = + this.voicePackController_.getDisplayNamesForLocaleCodes(); + } + private logSpeechPlaySession_() { // Don't log a playback session just in case something has gotten out of // sync and we call stopSpeech before playSpeech. @@ -1683,15 +1690,10 @@ this.installVoicePackIfPossible( toggledLanguage, /* onlyInstallExactGoogleLocaleMatch=*/ true, /* retryIfPreviousInstallFailed= */ true); + this.voicePackController_.enableLang(toggledLanguage); } else { this.voicePackController_.uninstall(toggledLanguage); - } - - const updateEnabledLangs = currentlyEnabled ? - this.voicePackController_.disableLang(toggledLanguage) : - this.voicePackController_.enableLang(toggledLanguage); - if (updateEnabledLangs) { - this.enabledLangs_ = this.voicePackController_.getEnabledLangs(); + this.voicePackController_.disableLang(toggledLanguage); } chrome.readingMode.onLanguagePrefChange(toggledLanguage, !currentlyEnabled); @@ -1746,17 +1748,10 @@ } restoreEnabledLanguagesFromPref() { - // We need to make sure the languages we choose correspond to voices, so - // refresh the list of voices and available langs - this.getVoices_(); + this.voicePackController_.restoreEnabledLanguagesFromPref( + this.defaultVoice()?.lang); - this.voicePackController_.setCurrentLanguage( - chrome.readingMode.baseLanguageForSpeech); - this.enabledLangs_ = - this.voicePackController_.getInitialListOfEnabledLanguages( - this.defaultVoice()?.lang); - - for (const lang of this.enabledLangs_) { + for (const lang of this.voicePackController_.getEnabledLangs()) { this.installVoicePackIfPossible( lang, /* onlyInstallExactGoogleLocaleMatch=*/ true, /* retryIfPreviousInstallFailed= */ false); @@ -1798,9 +1793,7 @@ this.defaultVoice(); // Enable the locale for the preferred voice for this language. - if (this.voicePackController_.enableLang(this.selectedVoice_?.lang)) { - this.enabledLangs_ = this.voicePackController_.getEnabledLangs(); - } + this.voicePackController_.enableLang(this.selectedVoice_?.lang); } protected onLineSpacingChange_() { @@ -1922,9 +1915,7 @@ // Enable the locales so we can select a voice for the given language and // show it in the voice menu. - if (this.voicePackController_.enableLang(localeToEnable)) { - this.enabledLangs_ = this.voicePackController_.getEnabledLangs(); - } + this.voicePackController_.enableLang(localeToEnable); this.selectPreferredVoice(); }
diff --git a/chrome/browser/resources/side_panel/read_anything/read_aloud/voice_pack_controller.ts b/chrome/browser/resources/side_panel/read_anything/read_aloud/voice_pack_controller.ts index 7cff1b1..a16a2e7 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_aloud/voice_pack_controller.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_aloud/voice_pack_controller.ts
@@ -16,12 +16,17 @@ import {VoicePackModel} from './voice_pack_model.js'; +export interface VoiceLanguageListener { + onEnabledLangsChange(): void; + onAvailableVoicesChange(): void; +} export class VoicePackController { private notificationManager_: VoiceNotificationManager = VoiceNotificationManager.getInstance(); private model_: VoicePackModel = new VoicePackModel(); private speech_: SpeechBrowserProxy = SpeechBrowserProxyImpl.getInstance(); + private listeners_: VoiceLanguageListener[] = []; // The extension is responsible for installing the Natural voices. If the // extension is not being responsive, the extension is probably not @@ -29,6 +34,10 @@ // if the extension does not respond in a timely manner. private speechExtensionResponseCallbackHandle_?: number; + addListener(listener: VoiceLanguageListener) { + this.listeners_.push(listener); + } + getCurrentLanguage(): string { return this.model_.getCurrentLanguage(); } @@ -45,6 +54,11 @@ return [...this.model_.getAvailableLangs()]; } + setAvailableVoices(voices: SpeechSynthesisVoice[]): void { + this.model_.setAvailableVoices(voices); + this.listeners_.forEach(l => l.onAvailableVoicesChange()); + } + getAvailableVoices(): SpeechSynthesisVoice[] { return this.model_.getAvailableVoices(); } @@ -67,7 +81,7 @@ } } - disableLangIfNoVoices(lang: string): boolean { + disableLangIfNoVoices(lang: string): void { const lowerLang = lang.toLowerCase(); this.refreshAvailableVoices(); const availableVoicesForLang = this.getAvailableVoicesForLang_(lowerLang); @@ -88,28 +102,26 @@ } }); } - - return disableLang; } - // Returns whether lang was enabled before disabling it. - disableLang(lang?: string): boolean { + disableLang(lang?: string): void { if (!lang) { - return false; + return; } - return this.model_.disableLang(lang); + if (this.isLangEnabled(lang)) { + this.model_.disableLang(lang); + this.listeners_.forEach(l => l.onEnabledLangsChange()); + } } - // Returns whether lang was disabled before enabling it. - enableLang(lang?: string): boolean { + enableLang(lang?: string): void { if (!lang) { - return false; + return; } if (!this.isLangEnabled(lang)) { this.model_.enableLang(lang.toLowerCase()); - return true; + this.listeners_.forEach(l => l.onEnabledLangsChange()); } - return false; } isLangEnabled(lang: string): boolean { @@ -122,7 +134,7 @@ // happen on non-ChromeOS, since we're only installing the new engine // outside of ChromeOS. // <if expr="not is_chromeos"> - enableNowAvailableLangs(): boolean { + enableNowAvailableLangs(): void { const nowAvailableLangs = [...this.model_.getPossiblyDisabledLangs()].filter( (lang: string) => this.isLangAvailable_(lang)); @@ -132,7 +144,6 @@ chrome.readingMode.onLanguagePrefChange(lowerLang, true); this.model_.removePossiblyDisabledLang(lowerLang); }); - return nowAvailableLangs.length > 0; } private isLangAvailable_(lang: string) { @@ -140,24 +151,25 @@ } // </if> - getInitialListOfEnabledLanguages(langOfDefaultVoice?: string): string[] { + restoreEnabledLanguagesFromPref(langOfDefaultVoice?: string): void { + // We need to make sure the languages we choose correspond to voices, so + // refresh the list of voices and available langs + this.refreshAvailableVoices(); + this.setCurrentLanguage(chrome.readingMode.baseLanguageForSpeech); const storedLanguagesPref = chrome.readingMode.getLanguagesEnabledInPref(); const langs = createInitialListOfEnabledLanguages( chrome.readingMode.baseLanguageForSpeech, storedLanguagesPref, this.getAvailableLangs(), langOfDefaultVoice); this.alignPreferencesWithEnabledLangs_(storedLanguagesPref); langs.forEach((l: string) => this.enableLang(l)); - return langs; } - refreshAvailableVoices(forceRefresh: boolean = false): boolean { + refreshAvailableVoices(forceRefresh: boolean = false): void { if (!this.hasAvailableVoices() || forceRefresh) { const availableVoices = getFilteredVoiceList(this.speech_.getVoices()); - this.model_.setAvailableVoices(availableVoices); + this.setAvailableVoices(availableVoices); this.model_.setAvailableLangs(availableVoices.map(({lang}) => lang)); - return true; } - return false; } getDisplayNamesForLocaleCodes(): {[locale: string]: string} {
diff --git a/chrome/browser/resources/side_panel/read_anything/read_aloud/voice_pack_model.ts b/chrome/browser/resources/side_panel/read_anything/read_aloud/voice_pack_model.ts index c528013..c2f6656 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_aloud/voice_pack_model.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_aloud/voice_pack_model.ts
@@ -63,8 +63,8 @@ this.enabledLangs_.add(lang); } - disableLang(lang: string): boolean { - return this.enabledLangs_.delete(lang); + disableLang(lang: string): void { + this.enabledLangs_.delete(lang); } getAvailableLangs(): Set<string> {
diff --git a/chrome/browser/resources/side_panel/read_anything/read_anything.ts b/chrome/browser/resources/side_panel/read_anything/read_anything.ts index f7a0fc5..152287ef 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_anything.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_anything.ts
@@ -26,7 +26,7 @@ export {currentReadHighlightClass, previousReadHighlightClass, ReadAloudHighlighter} from './read_aloud/highlighter.js'; export {SpeechController, SpeechListener} from './read_aloud/speech_controller.js'; export {PauseActionSource, SpeechEngineState, SpeechModel} from './read_aloud/speech_model.js'; -export {VoicePackController} from './read_aloud/voice_pack_controller.js'; +export {VoiceLanguageListener, VoicePackController} from './read_aloud/voice_pack_controller.js'; export {VoicePackModel} from './read_aloud/voice_pack_model.js'; export type {WordBoundaryState} from './read_aloud/word_boundaries.js'; export {WordBoundaries} from './read_aloud/word_boundaries.js';
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/EnhancedProtectionSettingsFragment.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/EnhancedProtectionSettingsFragment.java index 672894e..efab943 100644 --- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/EnhancedProtectionSettingsFragment.java +++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/EnhancedProtectionSettingsFragment.java
@@ -46,4 +46,9 @@ private void onLearnMoreClicked(View view) { getCustomTabLauncher().openUrlInCct(getContext(), SAFE_BROWSING_IN_CHROME_URL); } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java index e5ec9c6..ec9611a 100644 --- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java +++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java
@@ -282,4 +282,9 @@ } RecordUserAction.record("SafeBrowsing.Settings." + userActionSuffix); } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragment.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragment.java index 41e26f47..468e218 100644 --- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragment.java +++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragment.java
@@ -96,4 +96,9 @@ } }; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/safety_hub/android/BUILD.gn b/chrome/browser/safety_hub/android/BUILD.gn index 542c338..709fa7d 100644 --- a/chrome/browser/safety_hub/android/BUILD.gn +++ b/chrome/browser/safety_hub/android/BUILD.gn
@@ -77,6 +77,7 @@ "java/src/org/chromium/chrome/browser/safety_hub/SafetyHubReusedPasswordsModuleHelper.java", "java/src/org/chromium/chrome/browser/safety_hub/SafetyHubSafeBrowsingModuleMediator.java", "java/src/org/chromium/chrome/browser/safety_hub/SafetyHubSubpageFragment.java", + "java/src/org/chromium/chrome/browser/safety_hub/SafetyHubUnavailablePasswordsModuleHelper.java", "java/src/org/chromium/chrome/browser/safety_hub/SafetyHubUpdateCheckModuleMediator.java", "java/src/org/chromium/chrome/browser/safety_hub/SafetyHubUtils.java", "java/src/org/chromium/chrome/browser/safety_hub/SafetyHubWeakPasswordsModuleHelper.java",
diff --git a/chrome/browser/safety_hub/android/java/res/layout/safety_hub_expandable_preference.xml b/chrome/browser/safety_hub/android/java/res/layout/safety_hub_expandable_preference.xml index d74937d..0725cca 100644 --- a/chrome/browser/safety_hub/android/java/res/layout/safety_hub_expandable_preference.xml +++ b/chrome/browser/safety_hub/android/java/res/layout/safety_hub_expandable_preference.xml
@@ -68,7 +68,7 @@ android:layout_marginTop="4dp" android:layout_alignStart="@android:id/title" android:scrollbars="none" - android:focusable="true" + android:screenReaderFocusable="true" style="@style/PreferenceSummary" /> </RelativeLayout>
diff --git a/chrome/browser/safety_hub/android/java/res/xml/safety_hub_preferences.xml b/chrome/browser/safety_hub/android/java/res/xml/safety_hub_preferences.xml index 8be3af0..5f2cf7a 100644 --- a/chrome/browser/safety_hub/android/java/res/xml/safety_hub_preferences.xml +++ b/chrome/browser/safety_hub/android/java/res/xml/safety_hub_preferences.xml
@@ -16,7 +16,8 @@ <org.chromium.components.browser_ui.settings.TextMessagePreference android:key="safety_hub_description" android:summary="@string/safety_hub_description" - app:allowDividerAbove="false" /> + app:allowDividerAbove="false" + android:screenReaderFocusable="true" /> <PreferenceCategory android:key="safety_modules"
diff --git a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubExpandablePreference.java b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubExpandablePreference.java index acafe8e..4edec3d6 100644 --- a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubExpandablePreference.java +++ b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubExpandablePreference.java
@@ -13,6 +13,7 @@ import android.view.View; import android.view.View.AccessibilityDelegate; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.ProgressBar; import android.widget.TextView; @@ -179,11 +180,14 @@ String description = getContext() .getString( - R.string.concat_two_strings_with_periods, + R.string.concat_two_strings_with_comma, getTitle(), collapseOrExpandedText); view.setContentDescription(description); + if (view.isAccessibilityFocused()) { + view.sendAccessibilityEvent(AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION); + } } private AccessibilityDelegate createButtonAccessibilityDelegate(View labelView) {
diff --git a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubPasswordsModuleMediator.java b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubPasswordsModuleMediator.java index 35dcebd..90db06e6 100644 --- a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubPasswordsModuleMediator.java +++ b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubPasswordsModuleMediator.java
@@ -87,7 +87,6 @@ @SafetyHubLocalPasswordsDataSource.ModuleType int localModuleType) { Context context = mPreference.getContext(); - // TODO(crbug.com/407930886): Add all states for account and local passwords. if (accountModuleType == SafetyHubAccountPasswordsDataSource.ModuleType.HAS_COMPROMISED_PASSWORDS || localModuleType @@ -100,6 +99,16 @@ /* unifiedModule= */ true); } + if (accountModuleType + == SafetyHubAccountPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS + || accountModuleType + == SafetyHubAccountPasswordsDataSource.ModuleType + .UNAVAILABLE_COMPROMISED_NO_WEAK_REUSED_PASSWORDS + || localModuleType + == SafetyHubLocalPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS) { + return new SafetyHubUnavailablePasswordsModuleHelper(context, mModuleDelegate); + } + if (accountModuleType == SafetyHubAccountPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS || localModuleType == SafetyHubLocalPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS) { @@ -133,6 +142,7 @@ /* unifiedModule= */ true); } + // TODO(crbug.com/407930886): Add no password state for account and local passwords. return new SafetyHubAccountPasswordsUnavailableAllPasswordsModuleHelper( context, mModuleDelegate); }
diff --git a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubUnavailablePasswordsModuleHelper.java b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubUnavailablePasswordsModuleHelper.java new file mode 100644 index 0000000..50efc94 --- /dev/null +++ b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubUnavailablePasswordsModuleHelper.java
@@ -0,0 +1,66 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.safety_hub; + +import android.content.Context; +import android.view.View; + +import androidx.annotation.Nullable; + +import org.chromium.build.annotations.NullMarked; +import org.chromium.chrome.browser.safety_hub.SafetyHubModuleMediator.ModuleState; + +/** + * Helper for the {@link SafetyHubPasswordsModule} for when passwords counts are unavailable module. + */ +@NullMarked +public class SafetyHubUnavailablePasswordsModuleHelper implements SafetyHubModuleHelper { + private final Context mContext; + private final SafetyHubModuleDelegate mModuleDelegate; + + SafetyHubUnavailablePasswordsModuleHelper( + Context context, SafetyHubModuleDelegate moduleDelegate) { + mContext = context; + mModuleDelegate = moduleDelegate; + } + + @Override + public String getTitle() { + return mContext.getString(R.string.safety_hub_password_check_unavailable_title); + } + + @Override + public String getSummary() { + return mContext.getString(R.string.safety_hub_unavailable_summary); + } + + @Override + public @Nullable String getPrimaryButtonText() { + return null; + } + + @Override + public @Nullable View.OnClickListener getPrimaryButtonListener() { + return null; + } + + @Override + public String getSecondaryButtonText() { + return mContext.getString(R.string.safety_hub_password_subpage_navigation_button); + } + + @Override + public View.OnClickListener getSecondaryButtonListener() { + return v -> { + // TODO(crbug.com/407931779): Change to open the SH passwords page. + mModuleDelegate.showLocalPasswordCheckUi(mContext); + }; + } + + @Override + public @ModuleState int getModuleState() { + return ModuleState.UNAVAILABLE; + } +}
diff --git a/chrome/browser/safety_hub/android/javatests/src/org/chromium/chrome/browser/safety_hub/SafetyHubTest.java b/chrome/browser/safety_hub/android/javatests/src/org/chromium/chrome/browser/safety_hub/SafetyHubTest.java index d938f0f5..b11bbf0 100644 --- a/chrome/browser/safety_hub/android/javatests/src/org/chromium/chrome/browser/safety_hub/SafetyHubTest.java +++ b/chrome/browser/safety_hub/android/javatests/src/org/chromium/chrome/browser/safety_hub/SafetyHubTest.java
@@ -1512,6 +1512,7 @@ verifyButtonsNextToTextVisibility(safeBrowsingTitle, true); clearLocalCompromisedPasswordsCount(); + clearAccountCompromisedPasswordsCount(); setLocalPasswordCheckTimestamp(0); } @@ -1553,6 +1554,7 @@ verifyButtonsNextToTextVisibility(safeBrowsingTitle, true); clearLocalCompromisedPasswordsCount(); + clearAccountCompromisedPasswordsCount(); setLocalPasswordCheckTimestamp(0); } @@ -1593,6 +1595,7 @@ verifyButtonsNextToTextVisibility(safeBrowsingTitle, true); clearLocalCompromisedPasswordsCount(); + clearAccountCompromisedPasswordsCount(); setLocalPasswordCheckTimestamp(0); } @@ -1605,7 +1608,7 @@ ChromeFeatureList.SAFETY_HUB_LOCAL_PASSWORDS_MODULE, ChromeFeatureList.SAFETY_HUB_UNIFIED_PASSWORDS_MODULE }) - public void testUnifiedPasswordsModule_NoCompromisedPasswords() { + public void testUnifiedPasswordsModule_NoAccountAndLocalCompromisedPasswords() { setAccountCompromisedPasswordsCount(0); setLocalCompromisedPasswordsCount(0); setAccountReusedPasswordsCount(0); @@ -1619,8 +1622,7 @@ mSafetyHubFragmentTestRule.startSettingsActivity(); SafetyHubFragment safetyHubFragment = mSafetyHubFragmentTestRule.getFragment(); - // Verify that unified passwords module which is in the safe state is collapsed by - // default. + // Verify that unified passwords module which is in the safe state is collapsed by default. String noCompromisedPasswordsTitle = safetyHubFragment.getString(R.string.safety_hub_no_compromised_passwords_title); scrollToExpandedPreference(noCompromisedPasswordsTitle); @@ -1633,6 +1635,42 @@ verifyButtonsNextToTextVisibility(safeBrowsingTitle, true); clearLocalCompromisedPasswordsCount(); + clearAccountCompromisedPasswordsCount(); + setLocalPasswordCheckTimestamp(0); + } + + @Test + @MediumTest + @Policies.Add({@Policies.Item(key = "SafeBrowsingEnabled", string = "false")}) + @Restriction(GmsCoreVersionRestriction.RESTRICTION_TYPE_VERSION_GE_24W15) + @Features.EnableFeatures({ + ChromeFeatureList.SAFETY_HUB_WEAK_AND_REUSED_PASSWORDS, + ChromeFeatureList.SAFETY_HUB_LOCAL_PASSWORDS_MODULE, + ChromeFeatureList.SAFETY_HUB_UNIFIED_PASSWORDS_MODULE + }) + public void testUnifiedPasswordsModule_AccountAndLocalPasswordsUnavailable() { + clearLocalCompromisedPasswordsCount(); + clearAccountCompromisedPasswordsCount(); + addCredentialToProfileStore(); + addCredentialToAccountStore(); + + mSafetyHubFragmentTestRule.startSettingsActivity(); + SafetyHubFragment safetyHubFragment = mSafetyHubFragmentTestRule.getFragment(); + + // Verify that unified passwords module which is in the unavailable state is expanded by + // default. + String unavailablePasswordsTitle = + safetyHubFragment.getString(R.string.safety_hub_password_check_unavailable_title); + scrollToExpandedPreference(unavailablePasswordsTitle); + verifyButtonsNextToTextVisibility(unavailablePasswordsTitle, true); + + // Verify the information module is expanded. + String safeBrowsingTitle = + safetyHubFragment.getString(R.string.prefs_safe_browsing_no_protection_summary); + scrollToPreference(withText(safeBrowsingTitle)); + verifyButtonsNextToTextVisibility(safeBrowsingTitle, true); + + clearLocalCompromisedPasswordsCount(); setLocalPasswordCheckTimestamp(0); }
diff --git a/chrome/browser/safety_hub/android/junit/src/org/chromium/chrome/browser/safety_hub/SafetyHubPasswordsModuleMediatorTest.java b/chrome/browser/safety_hub/android/junit/src/org/chromium/chrome/browser/safety_hub/SafetyHubPasswordsModuleMediatorTest.java index 7894f74b..fbb3a3a 100644 --- a/chrome/browser/safety_hub/android/junit/src/org/chromium/chrome/browser/safety_hub/SafetyHubPasswordsModuleMediatorTest.java +++ b/chrome/browser/safety_hub/android/junit/src/org/chromium/chrome/browser/safety_hub/SafetyHubPasswordsModuleMediatorTest.java
@@ -143,7 +143,7 @@ } @Test - public void compromisedAccountPasswordsExist() { + public void compromisedAccountPasswordsExist_weakAndReuseExist() { int compromisedAccountPasswordsCount = 5; mockAccountPasswordCounts(compromisedAccountPasswordsCount, /* reused= */ 2, /* weak= */ 1); mockLocalPasswordCounts(/* compromised= */ 0, /* reused= */ 2, /* weak= */ 1); @@ -152,10 +152,9 @@ SafetyHubAccountPasswordsDataSource.ModuleType.HAS_COMPROMISED_PASSWORDS); mModuleMediator.accountPasswordsStateChanged( SafetyHubAccountPasswordsDataSource.ModuleType.HAS_COMPROMISED_PASSWORDS); - mockLocalPasswordState( - SafetyHubLocalPasswordsDataSource.ModuleType.NO_COMPROMISED_PASSWORDS); + mockLocalPasswordState(SafetyHubLocalPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS); mModuleMediator.localPasswordsStateChanged( - SafetyHubLocalPasswordsDataSource.ModuleType.NO_COMPROMISED_PASSWORDS); + SafetyHubLocalPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS); verify(mMediatorDelegateMock, times(1)).onUpdateNeeded(); @@ -186,15 +185,100 @@ } @Test - public void compromisedLocalPasswordsExist() { + public void compromisedAccountPasswordsExist_unavailableLocalPasswords() { + int compromisedAccountPasswordsCount = 5; + mockAccountPasswordCounts(compromisedAccountPasswordsCount, /* reused= */ 2, /* weak= */ 1); + mockLocalPasswordCounts(/* compromised= */ -1, /* reused= */ -1, /* weak= */ -1); + + mockAccountPasswordState( + SafetyHubAccountPasswordsDataSource.ModuleType.HAS_COMPROMISED_PASSWORDS); + mModuleMediator.accountPasswordsStateChanged( + SafetyHubAccountPasswordsDataSource.ModuleType.HAS_COMPROMISED_PASSWORDS); + mockLocalPasswordState(SafetyHubLocalPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + mModuleMediator.localPasswordsStateChanged( + SafetyHubLocalPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + + verify(mMediatorDelegateMock, times(1)).onUpdateNeeded(); + + String expectedTitle = + mActivity + .getResources() + .getQuantityString( + R.plurals.safety_hub_account_passwords_compromised_exist, + compromisedAccountPasswordsCount, + compromisedAccountPasswordsCount); + String expectedSummary = + mActivity + .getResources() + .getQuantityString( + R.plurals.safety_hub_compromised_passwords_summary, + compromisedAccountPasswordsCount, + compromisedAccountPasswordsCount); + String expectedPrimaryButtonText = + mActivity.getString(R.string.safety_hub_passwords_navigation_button); + String expectedSecondaryButtonText = + mActivity.getString(R.string.safety_hub_password_subpage_navigation_button); + + assertEquals(expectedTitle, mPreference.getTitle().toString()); + assertEquals(expectedSummary, mPreference.getSummary().toString()); + assertEquals(WARNING_ICON, shadowOf(mPreference.getIcon()).getCreatedFromResId()); + assertEquals(expectedPrimaryButtonText, mPreference.getPrimaryButtonText()); + assertEquals(expectedSecondaryButtonText, mPreference.getSecondaryButtonText()); + } + + @Test + public void compromisedLocalPasswordsExist_weakAndReuseExist() { int compromisedLocalPasswordsCount = 5; mockAccountPasswordCounts(/* compromised= */ 0, /* reused= */ 2, /* weak= */ 1); mockLocalPasswordCounts(compromisedLocalPasswordsCount, /* reused= */ 2, /* weak= */ 1); mockAccountPasswordState( - SafetyHubAccountPasswordsDataSource.ModuleType.NO_COMPROMISED_PASSWORDS); + SafetyHubAccountPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS); mModuleMediator.accountPasswordsStateChanged( - SafetyHubAccountPasswordsDataSource.ModuleType.NO_COMPROMISED_PASSWORDS); + SafetyHubAccountPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS); + mockLocalPasswordState( + SafetyHubLocalPasswordsDataSource.ModuleType.HAS_COMPROMISED_PASSWORDS); + mModuleMediator.localPasswordsStateChanged( + SafetyHubLocalPasswordsDataSource.ModuleType.HAS_COMPROMISED_PASSWORDS); + + verify(mMediatorDelegateMock, times(1)).onUpdateNeeded(); + + String expectedTitle = + mActivity + .getResources() + .getQuantityString( + R.plurals.safety_hub_local_passwords_compromised_title, + compromisedLocalPasswordsCount, + compromisedLocalPasswordsCount); + String expectedSummary = + mActivity + .getResources() + .getQuantityString( + R.plurals.safety_hub_compromised_passwords_summary, + compromisedLocalPasswordsCount, + compromisedLocalPasswordsCount); + String expectedPrimaryButtonText = + mActivity.getString(R.string.safety_hub_passwords_navigation_button); + String expectedSecondaryButtonText = + mActivity.getString(R.string.safety_hub_password_subpage_navigation_button); + + assertEquals(expectedTitle, mPreference.getTitle().toString()); + assertEquals(expectedSummary, mPreference.getSummary().toString()); + assertEquals(WARNING_ICON, shadowOf(mPreference.getIcon()).getCreatedFromResId()); + assertEquals(expectedPrimaryButtonText, mPreference.getPrimaryButtonText()); + assertEquals(expectedSecondaryButtonText, mPreference.getSecondaryButtonText()); + } + + @Test + public void compromisedLocalPasswordsExist_unavailableAccountPasswords() { + int compromisedLocalPasswordsCount = 5; + mockAccountPasswordCounts(/* compromised= */ -1, /* reused= */ -1, /* weak= */ -1); + mockLocalPasswordCounts(compromisedLocalPasswordsCount, /* reused= */ 2, /* weak= */ 1); + + mockAccountPasswordState( + SafetyHubAccountPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + mModuleMediator.accountPasswordsStateChanged( + SafetyHubAccountPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); mockLocalPasswordState( SafetyHubLocalPasswordsDataSource.ModuleType.HAS_COMPROMISED_PASSWORDS); mModuleMediator.localPasswordsStateChanged( @@ -477,4 +561,79 @@ assertEquals(expectedPrimaryButtonText, mPreference.getPrimaryButtonText()); assertEquals(expectedSecondaryButtonText, mPreference.getSecondaryButtonText()); } + + @Test + public void unavailableLocalPasswords_reusedAccountPasswordsExists() { + mockAccountPasswordState( + SafetyHubAccountPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS); + mockLocalPasswordState(SafetyHubLocalPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + mModuleMediator.accountPasswordsStateChanged( + SafetyHubAccountPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS); + mModuleMediator.localPasswordsStateChanged( + SafetyHubLocalPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + + verify(mMediatorDelegateMock, times(1)).onUpdateNeeded(); + + String expectedTitle = + mActivity.getString(R.string.safety_hub_password_check_unavailable_title); + String expectedSummary = mActivity.getString(R.string.safety_hub_unavailable_summary); + String expectedSecondaryButtonText = + mActivity.getString(R.string.safety_hub_password_subpage_navigation_button); + + assertEquals(expectedTitle, mPreference.getTitle().toString()); + assertEquals(expectedSummary, mPreference.getSummary().toString()); + assertEquals(INFO_ICON, shadowOf(mPreference.getIcon()).getCreatedFromResId()); + assertNull(mPreference.getPrimaryButtonText()); + assertEquals(expectedSecondaryButtonText, mPreference.getSecondaryButtonText()); + } + + @Test + public void unavailableAccountPasswords_reusedLocalPasswordsExists() { + mockAccountPasswordState( + SafetyHubAccountPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + mockLocalPasswordState(SafetyHubLocalPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS); + mModuleMediator.accountPasswordsStateChanged( + SafetyHubAccountPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + mModuleMediator.localPasswordsStateChanged( + SafetyHubLocalPasswordsDataSource.ModuleType.HAS_REUSED_PASSWORDS); + + verify(mMediatorDelegateMock, times(1)).onUpdateNeeded(); + + String expectedTitle = + mActivity.getString(R.string.safety_hub_password_check_unavailable_title); + String expectedSummary = mActivity.getString(R.string.safety_hub_unavailable_summary); + String expectedSecondaryButtonText = + mActivity.getString(R.string.safety_hub_password_subpage_navigation_button); + + assertEquals(expectedTitle, mPreference.getTitle().toString()); + assertEquals(expectedSummary, mPreference.getSummary().toString()); + assertEquals(INFO_ICON, shadowOf(mPreference.getIcon()).getCreatedFromResId()); + assertNull(mPreference.getPrimaryButtonText()); + assertEquals(expectedSecondaryButtonText, mPreference.getSecondaryButtonText()); + } + + @Test + public void unavailableAccountAndLocalPasswords() { + mockAccountPasswordState( + SafetyHubAccountPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + mockLocalPasswordState(SafetyHubLocalPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + mModuleMediator.accountPasswordsStateChanged( + SafetyHubAccountPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + mModuleMediator.localPasswordsStateChanged( + SafetyHubLocalPasswordsDataSource.ModuleType.UNAVAILABLE_PASSWORDS); + + verify(mMediatorDelegateMock, times(1)).onUpdateNeeded(); + + String expectedTitle = + mActivity.getString(R.string.safety_hub_password_check_unavailable_title); + String expectedSummary = mActivity.getString(R.string.safety_hub_unavailable_summary); + String expectedSecondaryButtonText = + mActivity.getString(R.string.safety_hub_password_subpage_navigation_button); + + assertEquals(expectedTitle, mPreference.getTitle().toString()); + assertEquals(expectedSummary, mPreference.getSummary().toString()); + assertEquals(INFO_ICON, shadowOf(mPreference.getIcon()).getCreatedFromResId()); + assertNull(mPreference.getPrimaryButtonText()); + assertEquals(expectedSecondaryButtonText, mPreference.getSecondaryButtonText()); + } }
diff --git a/chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc b/chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc index 38dd0d32..998cdd11 100644 --- a/chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc +++ b/chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc
@@ -371,12 +371,6 @@ histograms.ExpectBucketCount("Accessibility.ScreenAI.OCR.LinesCount", expected_lines_count, expected_calls); - histograms.ExpectTotalCount("Accessibility.ScreenAI.OCR.ImageSize10M", - expected_calls); - histograms.ExpectBucketCount("Accessibility.ScreenAI.OCR.ImageSize10M", - bitmap.width() * bitmap.height(), - expected_calls); - // Expect measured latency, but we don't know how long it taskes to process. // So we just check the total count of the expected bucket determined by the // image dimensions, with threshold 2048 for each dimension. @@ -386,6 +380,8 @@ "Accessibility.ScreenAI.OCR.Latency.NotDownsampled", expected_calls); histograms.ExpectTotalCount("Accessibility.ScreenAI.OCR.Latency.Downsampled", 0); + histograms.ExpectTotalCount( + "Accessibility.ScreenAI.OCR.Downsampled.ClientType", 0); // PDF Specific metrics should not be recorded as the client type is test. histograms.ExpectTotalCount("Accessibility.ScreenAI.OCR.LinesCount.PDF", 0); @@ -663,6 +659,8 @@ #endif IN_PROC_BROWSER_TEST_F(OpticalCharacterRecognizerResultsTest, MAYBE_PerformOCRLargeImage) { + base::HistogramTester histograms; + base::ScopedAllowBlockingForTesting allow_blocking; ASSERT_TRUE(CreateAndInitOCR()); @@ -679,6 +677,10 @@ // Since OCR downsamples large images, the content of this image becomes quite // small and unreadable, hence nothing is recognized. EXPECT_FALSE(results->lines.size()); + + metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting(); + histograms.ExpectTotalCount( + "Accessibility.ScreenAI.OCR.Downsampled.ClientType", 1); } IN_PROC_BROWSER_TEST_F(OpticalCharacterRecognizerResultsTest,
diff --git a/chrome/browser/search_engines/template_url_service_sync_unittest.cc b/chrome/browser/search_engines/template_url_service_sync_unittest.cc index 1815361..7b0e68b 100644 --- a/chrome/browser/search_engines/template_url_service_sync_unittest.cc +++ b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
@@ -1295,29 +1295,6 @@ model()->GetTemplateURLForKeyword(kCommonKeyword)); } -TEST_F(TemplateURLServiceSyncTest, SyncMergeDeletesDefault) { - // If the value from Sync is a duplicate of the local default and is newer, it - // should safely replace the local value and set as the new default. - TemplateURL* default_turl = model()->Add( - CreateTestTemplateURL(u"key1", "http://key1.com/{searchTerms}", - "whateverguid", base::Time::FromTimeT(10))); - model()->SetUserSelectedDefaultSearchProvider(default_turl); - - syncer::SyncDataList initial_data = CreateInitialSyncData(); - // The guid1 entry should be a duplicate of the default. - std::unique_ptr<TemplateURL> turl( - CreateTestTemplateURL(u"key1", "http://key1.com/{searchTerms}", "guid1", - base::Time::FromTimeT(90))); - initial_data[0] = - TemplateURLService::CreateSyncDataFromTemplateURLData(turl->data()); - MergeAndExpectNotify(initial_data, 1); - - EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size()); - EXPECT_FALSE(model()->GetTemplateURLForGUID("whateverguid")); - EXPECT_EQ(model()->GetDefaultSearchProvider(), - model()->GetTemplateURLForGUID("guid1")); -} - TEST_F(TemplateURLServiceSyncTest, DeleteBogusData) { // Create a couple of bogus entries to sync. syncer::SyncDataList initial_data; @@ -3605,6 +3582,30 @@ "localkey3"); } +TEST_F(TemplateURLServiceSyncTestWithoutSeparateLocalAndAccountSearchEngines, + SyncMergeDeletesDefault) { + // If the value from Sync is a duplicate of the local default and is newer, it + // should safely replace the local value and set as the new default. + TemplateURL* default_turl = model()->Add( + CreateTestTemplateURL(u"key1", "http://key1.com/{searchTerms}", + "whateverguid", base::Time::FromTimeT(10))); + model()->SetUserSelectedDefaultSearchProvider(default_turl); + + syncer::SyncDataList initial_data = CreateInitialSyncData(); + // The guid1 entry should be a duplicate of the default. + std::unique_ptr<TemplateURL> turl( + CreateTestTemplateURL(u"key1", "http://key1.com/{searchTerms}", "guid1", + base::Time::FromTimeT(90))); + initial_data[0] = + TemplateURLService::CreateSyncDataFromTemplateURLData(turl->data()); + MergeAndExpectNotify(initial_data, 1); + + EXPECT_EQ(3U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size()); + EXPECT_FALSE(model()->GetTemplateURLForGUID("whateverguid")); + EXPECT_EQ(model()->GetDefaultSearchProvider(), + model()->GetTemplateURLForGUID("guid1")); +} + class TemplateURLServiceSyncTestWithSeparateLocalAndAccountSearchEngines : public TemplateURLServiceSyncTest { public:
diff --git a/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc b/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc index b43c217..997d9a6 100644 --- a/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc +++ b/chrome/browser/sync_file_system/local/syncable_file_system_unittest.cc
@@ -28,7 +28,6 @@ #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "third_party/leveldatabase/leveldb_chrome.h" -using blink::mojom::StorageType; using storage::FileSystemContext; using storage::FileSystemOperationContext; using storage::FileSystemURL;
diff --git a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/ActionConfirmationManager.java b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/ActionConfirmationManager.java index 0357f4d..af52d16a 100644 --- a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/ActionConfirmationManager.java +++ b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/ActionConfirmationManager.java
@@ -80,7 +80,6 @@ this.finishBlocking = finishBlocking; } } - ; /** * @param profile The profile to access shared services with.
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderControllerImpl.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderControllerImpl.java index ea051a4..aaf82baa 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderControllerImpl.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelOrderControllerImpl.java
@@ -163,8 +163,13 @@ && type != TabLaunchType.FROM_BOOKMARK_BAR_BACKGROUND && type != TabLaunchType.FROM_REPARENTING_BACKGROUND && type != TabLaunchType.FROM_HISTORY_NAVIGATION_BACKGROUND) - || (!mTabModelSelector.isIncognitoBrandedModelSelected() - && isNewTabIncognitoBranded); + || isDifferentModel(isNewTabIncognitoBranded); + } + + private boolean isDifferentModel(boolean isNewTabIncognitoBranded) { + return mTabModelSelector.isIncognitoBrandedModelSelected() + ? !isNewTabIncognitoBranded + : isNewTabIncognitoBranded; } /**
diff --git a/chrome/browser/themes/theme_syncable_service_unittest.cc b/chrome/browser/themes/theme_syncable_service_unittest.cc index 43f4f69a..935a85d 100644 --- a/chrome/browser/themes/theme_syncable_service_unittest.cc +++ b/chrome/browser/themes/theme_syncable_service_unittest.cc
@@ -525,73 +525,6 @@ EXPECT_FALSE(fake_theme_service_->is_dirty()); } -TEST_F(ThemeSyncableServiceTest, UpdateThemeSpecifics_CurrentTheme_Extension) { - // Set up theme service to use custom theme. - fake_theme_service_->SetTheme(theme_extension_.get()); - - std::optional<syncer::ModelError> error = - theme_sync_service_->MergeDataAndStartSyncing( - syncer::THEMES, syncer::SyncDataList(), - std::unique_ptr<syncer::SyncChangeProcessor>( - new syncer::SyncChangeProcessorWrapperForTest( - fake_change_processor_.get()))); - EXPECT_FALSE(error.has_value()) << error.value().message(); - const syncer::SyncChangeList& changes = fake_change_processor_->changes(); - ASSERT_EQ(1u, changes.size()); - EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type()); - EXPECT_EQ(syncer::THEMES, changes[0].sync_data().GetDataType()); - - const sync_pb::ThemeSpecifics& theme_specifics = - changes[0].sync_data().GetSpecifics().theme(); - EXPECT_TRUE(theme_specifics.use_custom_theme()); - EXPECT_EQ(theme_extension_->id(), theme_specifics.custom_theme_id()); - EXPECT_EQ(theme_extension_->name(), theme_specifics.custom_theme_name()); - EXPECT_EQ( - extensions::ManifestURL::GetUpdateURL(theme_extension_.get()).spec(), - theme_specifics.custom_theme_update_url()); -} - -TEST_F(ThemeSyncableServiceTest, - UpdateThemeSpecifics_CurrentTheme_Autogenerated) { - // Set up theme service to use autogenerated theme. - fake_theme_service_->BuildAutogeneratedThemeFromColor( - SkColorSetRGB(0, 0, 100)); - - std::optional<syncer::ModelError> error = - theme_sync_service_->MergeDataAndStartSyncing( - syncer::THEMES, syncer::SyncDataList(), - std::unique_ptr<syncer::SyncChangeProcessor>( - new syncer::SyncChangeProcessorWrapperForTest( - fake_change_processor_.get()))); - EXPECT_FALSE(error.has_value()) << error.value().message(); - const syncer::SyncChangeList& changes = fake_change_processor_->changes(); - ASSERT_EQ(1u, changes.size()); - EXPECT_EQ(syncer::SyncChange::ACTION_ADD, changes[0].change_type()); - EXPECT_EQ(syncer::THEMES, changes[0].sync_data().GetDataType()); - - const sync_pb::ThemeSpecifics& theme_specifics = - changes[0].sync_data().GetSpecifics().theme(); - EXPECT_FALSE(theme_specifics.use_custom_theme()); - EXPECT_EQ(fake_theme_service_->GetAutogeneratedThemeColor(), - theme_specifics.autogenerated_color_theme().color()); -} - -TEST_F(ThemeSyncableServiceTest, UpdateThemeSpecifics_CurrentTheme_Policy) { - // Set up theme service to use policy theme. - fake_theme_service_->BuildAutogeneratedPolicyTheme(); - - std::optional<syncer::ModelError> error = - theme_sync_service_->MergeDataAndStartSyncing( - syncer::THEMES, syncer::SyncDataList(), - std::unique_ptr<syncer::SyncChangeProcessor>( - new syncer::SyncChangeProcessorWrapperForTest( - fake_change_processor_.get()))); - EXPECT_FALSE(error.has_value()) << error.value().message(); - // Applying policy theme doesn't trigger sync changes. - const syncer::SyncChangeList& changes = fake_change_processor_->changes(); - ASSERT_EQ(0u, changes.size()); -} - TEST_F(ThemeSyncableServiceTest, GetAllSyncDataForTesting_Extension) { // Set up theme service to use custom theme. fake_theme_service_->SetTheme(theme_extension_.get()); @@ -1034,6 +967,84 @@ EXPECT_TRUE(registrar()->IsExtensionEnabled(theme_extension()->id())); } +TEST_F(RealThemeSyncableServiceTest, + UpdateThemeSpecifics_CurrentTheme_Extension) { + std::optional<syncer::ModelError> error = + theme_sync_service()->MergeDataAndStartSyncing( + syncer::THEMES, syncer::SyncDataList(), + std::unique_ptr<syncer::SyncChangeProcessor>( + new syncer::SyncChangeProcessorWrapperForTest( + fake_change_processor()))); + EXPECT_FALSE(error.has_value()) << error.value().message(); + + fake_change_processor()->changes().clear(); + // Set up theme service to use custom theme. + { + test::ThemeServiceChangedWaiter waiter(theme_service()); + theme_service()->SetTheme(theme_extension()); + waiter.WaitForThemeChanged(); + } + + const syncer::SyncChangeList& changes = fake_change_processor()->changes(); + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type()); + EXPECT_EQ(syncer::THEMES, changes[0].sync_data().GetDataType()); + + const sync_pb::ThemeSpecifics& theme_specifics = + changes[0].sync_data().GetSpecifics().theme(); + EXPECT_TRUE(theme_specifics.use_custom_theme()); + EXPECT_EQ(theme_extension()->id(), theme_specifics.custom_theme_id()); + EXPECT_EQ(theme_extension()->name(), theme_specifics.custom_theme_name()); + EXPECT_EQ(extensions::ManifestURL::GetUpdateURL(theme_extension()).spec(), + theme_specifics.custom_theme_update_url()); +} + +TEST_F(RealThemeSyncableServiceTest, + UpdateThemeSpecifics_CurrentTheme_Autogenerated) { + std::optional<syncer::ModelError> error = + theme_sync_service()->MergeDataAndStartSyncing( + syncer::THEMES, syncer::SyncDataList(), + std::unique_ptr<syncer::SyncChangeProcessor>( + new syncer::SyncChangeProcessorWrapperForTest( + fake_change_processor()))); + EXPECT_FALSE(error.has_value()) << error.value().message(); + + fake_change_processor()->changes().clear(); + // Set up theme service to use autogenerated theme. + theme_service()->BuildAutogeneratedThemeFromColor(SkColorSetRGB(0, 0, 100)); + + const syncer::SyncChangeList& changes = fake_change_processor()->changes(); + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ(syncer::SyncChange::ACTION_UPDATE, changes[0].change_type()); + EXPECT_EQ(syncer::THEMES, changes[0].sync_data().GetDataType()); + + const sync_pb::ThemeSpecifics& theme_specifics = + changes[0].sync_data().GetSpecifics().theme(); + EXPECT_FALSE(theme_specifics.use_custom_theme()); + EXPECT_EQ(theme_service()->GetAutogeneratedThemeColor(), + theme_specifics.autogenerated_color_theme().color()); +} + +TEST_F(RealThemeSyncableServiceTest, UpdateThemeSpecifics_CurrentTheme_Policy) { + std::optional<syncer::ModelError> error = + theme_sync_service()->MergeDataAndStartSyncing( + syncer::THEMES, syncer::SyncDataList(), + std::unique_ptr<syncer::SyncChangeProcessor>( + new syncer::SyncChangeProcessorWrapperForTest( + fake_change_processor()))); + EXPECT_FALSE(error.has_value()) << error.value().message(); + + fake_change_processor()->changes().clear(); + // Set up theme service to use policy theme. + profile_->GetTestingPrefService()->SetManagedPref( + prefs::kPolicyThemeColor, std::make_unique<base::Value>(100)); + + ASSERT_TRUE(theme_service()->UsingPolicyTheme()); + // Applying policy theme doesn't trigger sync changes. + const syncer::SyncChangeList& changes = fake_change_processor()->changes(); + ASSERT_EQ(0u, changes.size()); +} + TEST_F(RealThemeSyncableServiceTest, ShouldDownloadUserColorTheme) { sync_pb::ThemeSpecifics theme_specifics; sync_pb::ThemeSpecifics::UserColorTheme* user_color_theme = @@ -2191,14 +2202,11 @@ prefs::kNonSyncingNtpCustomBackgroundDictDoNotUse), new_value); - // The local theme should be committed to the server. - const syncer::SyncChangeList& changes = fake_change_processor()->changes(); - ASSERT_EQ(changes.size(), 1u); - const sync_pb::ThemeSpecifics& change_specifics = - changes.back().sync_data().GetSpecifics().theme(); - ASSERT_TRUE(change_specifics.has_browser_color_scheme()); - ASSERT_TRUE(change_specifics.has_ntp_background()); - EXPECT_EQ(change_specifics.ntp_background().url(), kTestUrl); + sync_pb::ThemeSpecifics current_specifics = + theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting(); + ASSERT_TRUE(current_specifics.has_browser_color_scheme()); + ASSERT_TRUE(current_specifics.has_ntp_background()); + EXPECT_EQ(current_specifics.ntp_background().url(), kTestUrl); } // Regression test for crbug.com/389026436. @@ -2285,14 +2293,11 @@ prefs::kNonSyncingNtpCustomBackgroundDictDoNotUse), new_value); - // The local theme should be committed to the server. - const syncer::SyncChangeList& changes = fake_change_processor()->changes(); - ASSERT_EQ(changes.size(), 1u); - const sync_pb::ThemeSpecifics& change_specifics = - changes.back().sync_data().GetSpecifics().theme(); - ASSERT_TRUE(change_specifics.has_browser_color_scheme()); - ASSERT_TRUE(change_specifics.has_ntp_background()); - EXPECT_EQ(change_specifics.ntp_background().url(), kTestUrl); + sync_pb::ThemeSpecifics current_specifics = + theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting(); + ASSERT_TRUE(current_specifics.has_browser_color_scheme()); + ASSERT_TRUE(current_specifics.has_ntp_background()); + EXPECT_EQ(current_specifics.ntp_background().url(), kTestUrl); } TEST_F(RealThemeSyncableServiceTest, @@ -2351,15 +2356,12 @@ EXPECT_EQ(theme_service()->GetThemeID(), ThemeService::kUserColorThemeID); EXPECT_EQ(theme_service()->GetUserColor(), SK_ColorBLUE); - // The local theme should be committed to the server. - const syncer::SyncChangeList& changes = fake_change_processor()->changes(); - ASSERT_EQ(changes.size(), 1u); - const sync_pb::ThemeSpecifics& change_specifics = - changes.back().sync_data().GetSpecifics().theme(); - ASSERT_TRUE(change_specifics.has_browser_color_scheme()); - ASSERT_TRUE(change_specifics.has_user_color_theme()); - EXPECT_EQ(change_specifics.user_color_theme().color(), SK_ColorBLUE); - EXPECT_EQ(change_specifics.user_color_theme().browser_color_variant(), + sync_pb::ThemeSpecifics current_specifics = + theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting(); + ASSERT_TRUE(current_specifics.has_browser_color_scheme()); + ASSERT_TRUE(current_specifics.has_user_color_theme()); + EXPECT_EQ(current_specifics.user_color_theme().color(), SK_ColorBLUE); + EXPECT_EQ(current_specifics.user_color_theme().browser_color_variant(), sync_pb::ThemeSpecifics_UserColorTheme_BrowserColorVariant_NEUTRAL); } @@ -2426,15 +2428,12 @@ EXPECT_EQ(theme_service()->GetThemeID(), ThemeService::kUserColorThemeID); EXPECT_EQ(theme_service()->GetUserColor(), SK_ColorBLUE); - // The local theme should be committed to the server. - const syncer::SyncChangeList& changes = fake_change_processor()->changes(); - ASSERT_EQ(changes.size(), 1u); - const sync_pb::ThemeSpecifics& change_specifics = - changes.back().sync_data().GetSpecifics().theme(); - ASSERT_TRUE(change_specifics.has_browser_color_scheme()); - ASSERT_TRUE(change_specifics.has_user_color_theme()); - EXPECT_EQ(change_specifics.user_color_theme().color(), SK_ColorBLUE); - EXPECT_EQ(change_specifics.user_color_theme().browser_color_variant(), + sync_pb::ThemeSpecifics current_specifics = + theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting(); + ASSERT_TRUE(current_specifics.has_browser_color_scheme()); + ASSERT_TRUE(current_specifics.has_user_color_theme()); + EXPECT_EQ(current_specifics.user_color_theme().color(), SK_ColorBLUE); + EXPECT_EQ(current_specifics.user_color_theme().browser_color_variant(), sync_pb::ThemeSpecifics_UserColorTheme_BrowserColorVariant_NEUTRAL); } @@ -2481,6 +2480,12 @@ } ASSERT_TRUE(theme_service()->UsingExtensionTheme()); + theme_sync_service()->MergeDataAndStartSyncing( + syncer::THEMES, MakeThemeDataList(sync_pb::ThemeSpecifics()), + std::unique_ptr<syncer::SyncChangeProcessor>( + new syncer::SyncChangeProcessorWrapperForTest( + fake_change_processor()))); + sync_pb::ThemeSpecifics expected_theme_specifics; expected_theme_specifics.set_use_custom_theme(true); expected_theme_specifics.set_browser_color_scheme( @@ -2504,22 +2509,20 @@ // Local extension theme is still there. ASSERT_TRUE(theme_service()->UsingExtensionTheme()); - theme_sync_service()->MergeDataAndStartSyncing( - syncer::THEMES, MakeThemeDataList(sync_pb::ThemeSpecifics()), - std::unique_ptr<syncer::SyncChangeProcessor>( - new syncer::SyncChangeProcessorWrapperForTest( - fake_change_processor()))); - // ThemeSpecifics should be valid, i.e. should not contain ntp background when // there is an extension theme. EXPECT_THAT( theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting(), base::test::EqualsProto(expected_theme_specifics)); - // Nothing committed to the server. - ASSERT_EQ(fake_change_processor()->changes().size(), 1u); - EXPECT_THAT( - fake_change_processor()->changes()[0].sync_data().GetSpecifics().theme(), - base::test::EqualsProto(expected_theme_specifics)); + // Only the extension theme is committed. + ASSERT_GE(fake_change_processor()->changes().size(), 1u); + EXPECT_THAT(fake_change_processor() + ->changes() + .back() + .sync_data() + .GetSpecifics() + .theme(), + base::test::EqualsProto(expected_theme_specifics)); } TEST_F(RealThemeSyncableServiceTest, @@ -2550,41 +2553,6 @@ } TEST_F(RealThemeSyncableServiceTest, - ShouldCommitExtensionThemeAndBrowserColorSchemeOnInitialSync) { - // Local extension theme with browser color scheme. - theme_service()->SetTheme(theme_extension()); - EXPECT_TRUE(base::test::RunUntil( - [&]() { return theme_service()->UsingExtensionTheme(); })); - theme_service()->SetBrowserColorScheme( - ThemeService::BrowserColorScheme::kLight); - - // Start syncing. - ASSERT_FALSE(theme_sync_service() - ->MergeDataAndStartSyncing( - syncer::THEMES, syncer::SyncDataList(), - std::unique_ptr<syncer::SyncChangeProcessor>( - new syncer::SyncChangeProcessorWrapperForTest( - fake_change_processor()))) - .has_value()); - - EXPECT_TRUE(theme_service()->UsingExtensionTheme()); - EXPECT_EQ(theme_service()->GetBrowserColorScheme(), - ThemeService::BrowserColorScheme::kLight); - EXPECT_THAT( - theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting(), - testing::AllOf( - testing::Property(&sync_pb::ThemeSpecifics::use_custom_theme, true), - testing::Property(&sync_pb::ThemeSpecifics::browser_color_scheme, - sync_pb::ThemeSpecifics::LIGHT))); - // Local extension theme is committed along with the browser color scheme. - ASSERT_EQ(fake_change_processor()->changes().size(), 1u); - EXPECT_THAT( - fake_change_processor()->changes()[0].sync_data().GetSpecifics().theme(), - base::test::EqualsProto( - theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting())); -} - -TEST_F(RealThemeSyncableServiceTest, ShouldCommitBrowserColorSchemeAlongsideNewExtensionTheme) { // Local browser color scheme. theme_service()->SetBrowserColorScheme( @@ -2792,6 +2760,41 @@ EXPECT_EQ(fake_change_processor()->changes().size(), 1u); } +TEST_F(ThemeSyncableServiceTestWithoutAccountThemesSeparation, + ShouldCommitExtensionThemeAndBrowserColorSchemeOnInitialSync) { + // Local extension theme with browser color scheme. + theme_service()->SetTheme(theme_extension()); + EXPECT_TRUE(base::test::RunUntil( + [&]() { return theme_service()->UsingExtensionTheme(); })); + theme_service()->SetBrowserColorScheme( + ThemeService::BrowserColorScheme::kLight); + + // Start syncing. + ASSERT_FALSE(theme_sync_service() + ->MergeDataAndStartSyncing( + syncer::THEMES, syncer::SyncDataList(), + std::unique_ptr<syncer::SyncChangeProcessor>( + new syncer::SyncChangeProcessorWrapperForTest( + fake_change_processor()))) + .has_value()); + + EXPECT_TRUE(theme_service()->UsingExtensionTheme()); + EXPECT_EQ(theme_service()->GetBrowserColorScheme(), + ThemeService::BrowserColorScheme::kLight); + EXPECT_THAT( + theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting(), + testing::AllOf( + testing::Property(&sync_pb::ThemeSpecifics::use_custom_theme, true), + testing::Property(&sync_pb::ThemeSpecifics::browser_color_scheme, + sync_pb::ThemeSpecifics::LIGHT))); + // Local extension theme is committed along with the browser color scheme. + ASSERT_EQ(fake_change_processor()->changes().size(), 1u); + EXPECT_THAT( + fake_change_processor()->changes()[0].sync_data().GetSpecifics().theme(), + base::test::EqualsProto( + theme_sync_service()->GetThemeSpecificsFromCurrentThemeForTesting())); +} + class ThemeSyncableServiceTestWithAccountThemesSeparation : public RealThemeSyncableServiceTest { public:
diff --git a/chrome/browser/touch_to_fill/autofill/android/BUILD.gn b/chrome/browser/touch_to_fill/autofill/android/BUILD.gn index 664a6961b..d49376ce 100644 --- a/chrome/browser/touch_to_fill/autofill/android/BUILD.gn +++ b/chrome/browser/touch_to_fill/autofill/android/BUILD.gn
@@ -26,6 +26,7 @@ ":public", "//chrome/browser/autofill", "//chrome/browser/profiles", + "//components/autofill/android:main_autofill_jni_headers", "//components/autofill/core/common:features", "//content/public/browser:browser", "//third_party/libaddressinput:util",
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/BUILD.gn b/chrome/browser/touch_to_fill/autofill/android/internal/BUILD.gn index 072e3b6..764dd1b 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/BUILD.gn +++ b/chrome/browser/touch_to_fill/autofill/android/internal/BUILD.gn
@@ -58,6 +58,7 @@ sources = [ "java/res/layout/touch_to_fill_credit_card_sheet_item.xml", "java/res/layout/touch_to_fill_iban_sheet_item.xml", + "java/res/layout/touch_to_fill_loyalty_card_sheet_item.xml", "java/res/layout/touch_to_fill_payment_method_footer_item.xml", "java/res/layout/touch_to_fill_payment_method_header_item.xml", "java/res/layout/touch_to_fill_terms_label_sheet_item.xml",
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/res/layout/touch_to_fill_loyalty_card_sheet_item.xml b/chrome/browser/touch_to_fill/autofill/android/internal/java/res/layout/touch_to_fill_loyalty_card_sheet_item.xml new file mode 100644 index 0000000..cfa601e1 --- /dev/null +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/res/layout/touch_to_fill_loyalty_card_sheet_item.xml
@@ -0,0 +1,49 @@ +<?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. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:descendantFocusability="blocksDescendants" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="2dp" + android:layout_marginHorizontal="8dp" + android:background="@color/baseline_neutral_90" + android:gravity="center_vertical" + android:orientation="horizontal" + android:padding="16dp"> + + <ImageView + android:id="@+id/loyalty_card_icon" + android:src="@drawable/ic_globe_24dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="16dp" + android:layout_gravity="center" + android:contentDescription="@string/autofill_loyalty_card_generic"/> + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:orientation="vertical"> + <TextView + android:id="@+id/loyalty_card_number" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="1" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" + android:ellipsize="middle"/> + <TextView + android:id="@+id/merchant_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:maxLines="1" + android:visibility="gone" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" + android:ellipsize="end"/> + </LinearLayout> +</LinearLayout>
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodControllerRobolectricTest.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodControllerRobolectricTest.java index d5780e83..019895b7 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodControllerRobolectricTest.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodControllerRobolectricTest.java
@@ -44,7 +44,10 @@ import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.FOOTER; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.HEADER; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.IBAN; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.LOYALTY_CARD; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.TERMS_LABEL; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.LOYALTY_CARD_NUMBER; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.MERCHANT_NAME; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.SHEET_ITEMS; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.TermsLabelProperties.CARD_BENEFITS_TERMS_AVAILABLE; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.VISIBLE; @@ -79,6 +82,7 @@ import org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodMediator.TouchToFillIbanOutcome; import org.chromium.components.autofill.AutofillFeatures; import org.chromium.components.autofill.AutofillSuggestion; +import org.chromium.components.autofill.LoyaltyCard; import org.chromium.components.autofill.SuggestionType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -89,6 +93,7 @@ import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeoutException; @@ -160,6 +165,25 @@ /* label= */ "FR76 **** **** **** **** ***0 189", /* nickname= */ "", /* value= */ "FR7630006000011234567890189"); + + private static final LoyaltyCard LOYALTY_CARD_1 = + new LoyaltyCard( + /* loyaltyCardId= */ "cvs", + /* merchantName= */ "CVS Pharmacy", + /* programName= */ "Loyalty program", + /* programLogo= */ new GURL("https://site.com/icon.png"), + /* loyaltyCardNumber= */ "1234", + /* merchantDomains= */ Collections.emptyList()); + + private static final LoyaltyCard LOYALTY_CARD_2 = + new LoyaltyCard( + /* loyaltyCardId= */ "stb", + /* merchantName= */ "Starbucks", + /* programName= */ "Coffee pro", + /* programLogo= */ new GURL("https://coffee.com/logo.png"), + /* loyaltyCardNumber= */ "4321", + /* merchantDomains= */ Collections.emptyList()); + private static final AutofillSuggestion VISA_SUGGESTION = createCreditCardSuggestion( VISA.getCardNameForAutofillDisplay(), @@ -811,6 +835,40 @@ assertEquals(0, getModelsOfType(itemList, FILL_BUTTON).size()); } + @Test + public void testShowOneLoyaltyCard() throws TimeoutException { + mCoordinator.showLoyaltyCards(List.of(LOYALTY_CARD_1)); + + ModelList itemList = mTouchToFillPaymentMethodModel.get(SHEET_ITEMS); + assertThat(getModelsOfType(itemList, LOYALTY_CARD).size(), is(1)); + + PropertyModel loyaltyCardModel = itemList.get(0).model; + assertThat( + loyaltyCardModel.get(LOYALTY_CARD_NUMBER), + is(LOYALTY_CARD_1.getLoyaltyCardNumber())); + assertThat(loyaltyCardModel.get(MERCHANT_NAME), is(LOYALTY_CARD_1.getMerchantName())); + } + + @Test + public void testShowTwoLoyaltyCards() throws TimeoutException { + mCoordinator.showLoyaltyCards(List.of(LOYALTY_CARD_1, LOYALTY_CARD_2)); + + ModelList itemList = mTouchToFillPaymentMethodModel.get(SHEET_ITEMS); + assertThat(getModelsOfType(itemList, LOYALTY_CARD).size(), is(2)); + + PropertyModel loyaltyCardModel1 = itemList.get(0).model; + assertThat( + loyaltyCardModel1.get(LOYALTY_CARD_NUMBER), + is(LOYALTY_CARD_1.getLoyaltyCardNumber())); + assertThat(loyaltyCardModel1.get(MERCHANT_NAME), is(LOYALTY_CARD_1.getMerchantName())); + + PropertyModel loyaltyCardModel2 = itemList.get(1).model; + assertThat( + loyaltyCardModel2.get(LOYALTY_CARD_NUMBER), + is(LOYALTY_CARD_2.getLoyaltyCardNumber())); + assertThat(loyaltyCardModel2.get(MERCHANT_NAME), is(LOYALTY_CARD_2.getMerchantName())); + } + private static List<PropertyModel> getModelsOfType(ModelList items, int type) { return StreamSupport.stream(items.spliterator(), false) .filter(item -> item.type == type)
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodCoordinator.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodCoordinator.java index 8a9ad36..85dc649 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodCoordinator.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodCoordinator.java
@@ -11,6 +11,7 @@ import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.FOOTER; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.HEADER; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.IBAN; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.LOYALTY_CARD; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.TERMS_LABEL; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.SHEET_ITEMS; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.VISIBLE; @@ -26,6 +27,7 @@ import org.chromium.chrome.browser.touch_to_fill.common.BottomSheetFocusHelper; import org.chromium.components.autofill.AutofillSuggestion; import org.chromium.components.autofill.ImageSize; +import org.chromium.components.autofill.LoyaltyCard; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.PropertyModel; @@ -83,6 +85,11 @@ } @Override + public void showLoyaltyCards(List<LoyaltyCard> loyaltyCards) { + mMediator.showLoyaltyCards(loyaltyCards); + } + + @Override public void hideSheet() { mMediator.hideSheet(); } @@ -109,6 +116,10 @@ TouchToFillPaymentMethodViewBinder::createIbanItemView, TouchToFillPaymentMethodViewBinder::bindIbanItemView); adapter.registerType( + LOYALTY_CARD, + TouchToFillPaymentMethodViewBinder::createLoyaltyCardItemView, + TouchToFillPaymentMethodViewBinder::bindLoyaltyCardItemView); + adapter.registerType( HEADER, TouchToFillPaymentMethodViewBinder::createHeaderItemView, TouchToFillPaymentMethodViewBinder::bindHeaderView);
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodMediator.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodMediator.java index 7b9c8da..44cbb46 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodMediator.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodMediator.java
@@ -27,7 +27,11 @@ import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.FOOTER; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.HEADER; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.IBAN; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.LOYALTY_CARD; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.TERMS_LABEL; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.LOYALTY_CARD_NUMBER; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.MERCHANT_NAME; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.NON_TRANSFORMING_LOYALTY_CARD_KEYS; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.SHEET_ITEMS; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.TermsLabelProperties.CARD_BENEFITS_TERMS_AVAILABLE; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.VISIBLE; @@ -49,6 +53,7 @@ import org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.TermsLabelProperties; import org.chromium.components.autofill.AutofillSuggestion; import org.chromium.components.autofill.IbanRecordType; +import org.chromium.components.autofill.LoyaltyCard; import org.chromium.components.autofill.SuggestionType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; @@ -137,6 +142,7 @@ private PropertyModel mModel; private List<CreditCard> mCards; private List<Iban> mIbans; + private List<LoyaltyCard> mLoyaltyCards; private BottomSheetFocusHelper mBottomSheetFocusHelper; private InputProtector mInputProtector = new InputProtector(); @@ -160,6 +166,7 @@ assert cards != null; mCards = cards; mIbans = null; + mLoyaltyCards = null; assert mCards.size() == suggestions.size() : "The number of cards and suggestions should be same."; @@ -204,6 +211,7 @@ assert ibans != null; mIbans = ibans; mCards = null; + mLoyaltyCards = null; ModelList sheetItems = mModel.get(SHEET_ITEMS); sheetItems.clear(); @@ -229,6 +237,28 @@ RecordHistogram.recordCount100Histogram(TOUCH_TO_FILL_NUMBER_OF_IBANS_SHOWN, mIbans.size()); } + public void showLoyaltyCards(List<LoyaltyCard> loyaltyCards) { + mInputProtector.markShowTime(); + + assert loyaltyCards != null; + mLoyaltyCards = loyaltyCards; + mCards = null; + mIbans = null; + + ModelList sheetItems = mModel.get(SHEET_ITEMS); + sheetItems.clear(); + + for (LoyaltyCard loyaltyCard : mLoyaltyCards) { + final PropertyModel model = createLoyaltyCardModel(loyaltyCard); + sheetItems.add(new ListItem(LOYALTY_CARD, model)); + } + + mBottomSheetFocusHelper.registerForOneTimeUse(); + mModel.set(VISIBLE, true); + + // TODO: crbug.com/404437211 - Log the number of loyalty cards shown. + } + void hideSheet() { onDismissed(BottomSheetController.StateChangeReason.NONE); } @@ -248,12 +278,14 @@ TOUCH_TO_FILL_CREDIT_CARD_OUTCOME_HISTOGRAM, TouchToFillCreditCardOutcome.DISMISS, TouchToFillCreditCardOutcome.MAX_VALUE); - } else { - assert mIbans != null; + } else if (mIbans != null) { RecordHistogram.recordEnumeratedHistogram( TOUCH_TO_FILL_IBAN_OUTCOME_HISTOGRAM, TouchToFillIbanOutcome.DISMISS, TouchToFillIbanOutcome.MAX_VALUE); + } else { + assert mLoyaltyCards != null; + // TODO: crbug.com/404437211 - Log loyalty card metrics. } } } @@ -344,6 +376,15 @@ return ibanModelBuilder.build(); } + private PropertyModel createLoyaltyCardModel(LoyaltyCard loyaltyCard) { + PropertyModel.Builder loyaltyCardModelBuilder = + new PropertyModel.Builder(NON_TRANSFORMING_LOYALTY_CARD_KEYS) + .with(LOYALTY_CARD_NUMBER, loyaltyCard.getLoyaltyCardNumber()) + .with(MERCHANT_NAME, loyaltyCard.getMerchantName()); + + return loyaltyCardModelBuilder.build(); + } + private ListItem buildTermsLabel(boolean cardBenefitsTermsAvailable) { return new ListItem( TERMS_LABEL,
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodProperties.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodProperties.java index 82a71f9..cdc330c4 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodProperties.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodProperties.java
@@ -39,15 +39,18 @@ // A section containing the IBAN data. int IBAN = 2; + // A section containing the loyalty card data. + int LOYALTY_CARD = 3; + // A "Continue" button, which is shown when there is only one payment // method available. - int FILL_BUTTON = 3; + int FILL_BUTTON = 4; // A footer section containing additional actions. - int FOOTER = 4; + int FOOTER = 5; // A section with a terms label is present when card benefits are available. - int TERMS_LABEL = 5; + int TERMS_LABEL = 6; } /** Metadata associated with a card's image. */ @@ -122,6 +125,20 @@ private IbanProperties() {} } + /** Properties for a loyalty card entry in the TouchToFill sheet for payments. */ + static class LoyaltyCardProperties { + static final PropertyModel.ReadableObjectPropertyKey<String> LOYALTY_CARD_NUMBER = + new PropertyModel.ReadableObjectPropertyKey<>("loyalty_card_number"); + static final PropertyModel.ReadableObjectPropertyKey<String> MERCHANT_NAME = + new PropertyModel.ReadableObjectPropertyKey<>("merchant_name"); + + static final PropertyKey[] NON_TRANSFORMING_LOYALTY_CARD_KEYS = { + LOYALTY_CARD_NUMBER, MERCHANT_NAME + }; + + private LoyaltyCardProperties() {} + } + /** * Properties defined here reflect the visible state of the terms message in the TouchToFill * sheet for payments.
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodView.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodView.java index 86d5261..db49eb1 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodView.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodView.java
@@ -48,6 +48,7 @@ return true; case ItemType.CREDIT_CARD: case ItemType.IBAN: + case ItemType.LOYALTY_CARD: return false; } assert false : "Undefined whether to skip setting background for item of type: " + type; @@ -86,21 +87,25 @@ @Override public @NonNull String getSheetContentDescription(Context context) { + // TODO - crbug.com/: Update for loyalty cards. return context.getString(R.string.autofill_payment_method_bottom_sheet_content_description); } @Override public @StringRes int getSheetHalfHeightAccessibilityStringId() { + // TODO - crbug.com/: Update for loyalty cards. return R.string.autofill_payment_method_bottom_sheet_half_height; } @Override public @StringRes int getSheetFullHeightAccessibilityStringId() { + // TODO - crbug.com/: Update for loyalty cards. return R.string.autofill_payment_method_bottom_sheet_full_height; } @Override public @StringRes int getSheetClosedAccessibilityStringId() { + // TODO - crbug.com/: Update for loyalty cards. return R.string.autofill_payment_method_bottom_sheet_closed; } @@ -121,7 +126,10 @@ @Override protected Set<Integer> listedItemTypes() { - return Set.of(TouchToFillPaymentMethodProperties.ItemType.CREDIT_CARD, TouchToFillPaymentMethodProperties.ItemType.IBAN); + return Set.of( + TouchToFillPaymentMethodProperties.ItemType.CREDIT_CARD, + TouchToFillPaymentMethodProperties.ItemType.IBAN, + TouchToFillPaymentMethodProperties.ItemType.LOYALTY_CARD); } @Override
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewBinder.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewBinder.java index f98c680b..4d20ae0 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewBinder.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewBinder.java
@@ -21,6 +21,8 @@ import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.IbanProperties.IBAN_NICKNAME; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.IbanProperties.IBAN_VALUE; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.IbanProperties.ON_IBAN_CLICK_ACTION; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.LOYALTY_CARD_NUMBER; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.MERCHANT_NAME; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.SHEET_ITEMS; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.TermsLabelProperties.CARD_BENEFITS_TERMS_AVAILABLE; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.VISIBLE; @@ -136,6 +138,14 @@ return ibanItem; } + static View createLoyaltyCardItemView(ViewGroup parent) { + View loyaltyCardItem = + LayoutInflater.from(parent.getContext()) + .inflate(R.layout.touch_to_fill_loyalty_card_sheet_item, parent, false); + AutofillUiUtils.setFilterTouchForSecurity(loyaltyCardItem); + return loyaltyCardItem; + } + /** Binds the item view to the model properties. */ static void bindCardItemView(PropertyModel model, View view, PropertyKey propertyKey) { TextView mainText = view.findViewById(R.id.main_text); @@ -219,8 +229,24 @@ } } + static void bindLoyaltyCardItemView(PropertyModel model, View view, PropertyKey propertyKey) { + if (propertyKey == LOYALTY_CARD_NUMBER) { + TextView loyaltyCardNumber = view.findViewById(R.id.loyalty_card_number); + loyaltyCardNumber.setText(model.get(LOYALTY_CARD_NUMBER)); + loyaltyCardNumber.setTextAppearance(R.style.TextAppearance_TextLarge_Primary); + } else if (propertyKey == MERCHANT_NAME) { + TextView merchantName = view.findViewById(R.id.merchant_name); + merchantName.setText(model.get(MERCHANT_NAME)); + merchantName.setVisibility(View.VISIBLE); + } else { + assert false : "Unhandled update to property:" + propertyKey; + } + } + /** - * Factory used to create a new header inside the ListView inside the TouchToFillPaymentMethodView. + * Factory used to create a new header inside the ListView inside the {@link + * TouchToFillPaymentMethodView}. + * * @param parent The parent {@link ViewGroup} of the new item. */ static View createHeaderItemView(ViewGroup parent) { @@ -271,7 +297,9 @@ || propertyKey == IBAN_VALUE || propertyKey == IBAN_NICKNAME || propertyKey == ITEM_COLLECTION_INFO - || propertyKey == APPLY_DEACTIVATED_STYLE) { + || propertyKey == APPLY_DEACTIVATED_STYLE + || propertyKey == LOYALTY_CARD_NUMBER + || propertyKey == MERCHANT_NAME) { // Skip, because none of these changes affect the button } else { assert false : "Unhandled update to property:" + propertyKey;
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewBridge.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewBridge.java index 2badd93..e308b54 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewBridge.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewBridge.java
@@ -18,6 +18,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.touch_to_fill.common.BottomSheetFocusHelper; import org.chromium.components.autofill.AutofillSuggestion; +import org.chromium.components.autofill.LoyaltyCard; import org.chromium.components.autofill.SuggestionType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider; @@ -83,6 +84,11 @@ } @CalledByNative + private void showLoyaltyCards(@JniType("std::vector") List<LoyaltyCard> loyaltyCards) { + mComponent.showLoyaltyCards(loyaltyCards); + } + + @CalledByNative private void hideSheet() { mComponent.hideSheet(); }
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewTest.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewTest.java index ead3bce2..37c95df 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewTest.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewTest.java
@@ -42,7 +42,11 @@ import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.CREDIT_CARD; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.FILL_BUTTON; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.IBAN; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.LOYALTY_CARD; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.ItemType.TERMS_LABEL; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.LOYALTY_CARD_NUMBER; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.MERCHANT_NAME; +import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.LoyaltyCardProperties.NON_TRANSFORMING_LOYALTY_CARD_KEYS; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.SHEET_ITEMS; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.TermsLabelProperties.ALL_TERMS_LABEL_KEYS; import static org.chromium.chrome.browser.touch_to_fill.payments.TouchToFillPaymentMethodProperties.TermsLabelProperties.CARD_BENEFITS_TERMS_AVAILABLE; @@ -85,6 +89,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.components.autofill.AutofillSuggestion; +import org.chromium.components.autofill.LoyaltyCard; import org.chromium.components.autofill.SuggestionType; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState; @@ -96,6 +101,8 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.url.GURL; +import java.util.Collections; + /** Tests for {@link TouchToFillPaymentMethodView} */ @RunWith(ChromeJUnit4ClassRunner.class) @DoNotBatch(reason = "The methods of ChromeAccessibilityUtil don't seem to work with batching.") @@ -258,6 +265,14 @@ /* label= */ "CH56 **** **** **** *800 9", /* nickname= */ "", /* value= */ "CH5604835012345678009"); + private static final LoyaltyCard CVS_LOYALTY_CARD = + new LoyaltyCard( + /* loyaltyCardId= */ "cvs", + /* merchantName= */ "CVS Pharmacy", + /* programName= */ "Loyalty program", + /* programLogo= */ new GURL("https://site.com/icon.png"), + /* loyaltyCardNumber= */ "1234", + /* merchantDomains= */ Collections.emptyList()); @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); @@ -952,6 +967,33 @@ assertThat(ibanSecondaryText.getVisibility(), is(View.GONE)); } + @Test + @MediumTest + public void testLoyaltyCardTouchToFillItem() { + runOnUiThreadBlocking( + () -> { + mTouchToFillPaymentMethodModel + .get(SHEET_ITEMS) + .add( + new ListItem( + LOYALTY_CARD, + createLoyaltyCardModel(CVS_LOYALTY_CARD))); + mTouchToFillPaymentMethodModel.set(VISIBLE, true); + }); + BottomSheetTestSupport.waitForOpen(mBottomSheetController); + + TextView loyaltyCardNumber = + mTouchToFillPaymentMethodView + .getContentView() + .findViewById(R.id.loyalty_card_number); + assertThat( + loyaltyCardNumber.getText().toString(), + is(CVS_LOYALTY_CARD.getLoyaltyCardNumber())); + TextView merchantName = + mTouchToFillPaymentMethodView.getContentView().findViewById(R.id.merchant_name); + assertThat(merchantName.getText().toString(), is(CVS_LOYALTY_CARD.getMerchantName())); + } + private RecyclerView getCreditCardSuggestions() { return mTouchToFillPaymentMethodView.getContentView().findViewById(R.id.sheet_item_list); } @@ -1023,6 +1065,14 @@ return ibanModelBuilder.build(); } + private static PropertyModel createLoyaltyCardModel(LoyaltyCard loyaltyCard) { + PropertyModel.Builder loyaltyCardModelBuilder = + new PropertyModel.Builder(NON_TRANSFORMING_LOYALTY_CARD_KEYS) + .with(LOYALTY_CARD_NUMBER, loyaltyCard.getLoyaltyCardNumber()) + .with(MERCHANT_NAME, loyaltyCard.getMerchantName()); + return loyaltyCardModelBuilder.build(); + } + private static PropertyModel createTermsLabelModel(boolean cardBenefitsTermsAvailable) { return new PropertyModel.Builder(ALL_TERMS_LABEL_KEYS) .with(CARD_BENEFITS_TERMS_AVAILABLE, cardBenefitsTermsAvailable)
diff --git a/chrome/browser/touch_to_fill/autofill/android/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodComponent.java b/chrome/browser/touch_to_fill/autofill/android/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodComponent.java index 1daf8222..ff52fcc 100644 --- a/chrome/browser/touch_to_fill/autofill/android/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodComponent.java +++ b/chrome/browser/touch_to_fill/autofill/android/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodComponent.java
@@ -11,6 +11,7 @@ import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.touch_to_fill.common.BottomSheetFocusHelper; import org.chromium.components.autofill.AutofillSuggestion; +import org.chromium.components.autofill.LoyaltyCard; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import java.util.List; @@ -91,6 +92,9 @@ /** Displays a new IBAN bottom sheet. */ void showIbans(List<PersonalDataManager.Iban> ibans); + /** Displays a new loyalty card bottom sheet. */ + void showLoyaltyCards(List<LoyaltyCard> loyaltyCards); + /** Hides the bottom sheet if shown. */ void hideSheet(); }
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc index eaaa6c5..1c316ad 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.cc
@@ -6,11 +6,14 @@ #include <variant> +#include "base/containers/to_vector.h" #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "components/autofill/core/browser/autofill_browser_util.h" #include "components/autofill/core/browser/data_manager/payments/payments_data_manager.h" +#include "components/autofill/core/browser/data_manager/valuables/valuables_data_manager.h" #include "components/autofill/core/browser/data_model/payments/credit_card.h" +#include "components/autofill/core/browser/data_model/valuables/loyalty_card.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/form_types.h" @@ -46,23 +49,25 @@ SanitizedFieldIsEmpty(form_field->value()); } -bool IsTriggeredOnIbanField(const FormStructure* form_field, - const FormFieldData& field) { +bool IsTriggeredOnFieldWithGroup(const FormStructure* form_field, + const FormFieldData& field, + FieldTypeGroup field_type_group) { if (!form_field) { return false; } const autofill::AutofillField* autofill_field = form_field->GetFieldById(field.global_id()); - return autofill_field && - autofill_field->Type().group() == FieldTypeGroup::kIban; + return autofill_field && autofill_field->Type().group() == field_type_group; } } // namespace TouchToFillDelegateAndroidImpl::DryRunResult::DryRunResult( TriggerOutcome outcome, - std::variant<std::vector<CreditCard>, std::vector<Iban>> items_to_suggest) + std::variant<std::vector<CreditCard>, + std::vector<Iban>, + std::vector<LoyaltyCard>> items_to_suggest) : outcome(outcome), items_to_suggest(std::move(items_to_suggest)) {} TouchToFillDelegateAndroidImpl::DryRunResult::DryRunResult(DryRunResult&&) = @@ -124,6 +129,8 @@ return DryRunForIban(); } else if (field->Type().group() == FieldTypeGroup::kCreditCard) { return DryRunForCreditCard(*field, *form, received_form); + } else if (field->Type().group() == FieldTypeGroup::kLoyaltyCard) { + return DryRunForLoyaltyCard(); } return {TriggerOutcome::kUnsupportedFieldType, {}}; @@ -171,6 +178,19 @@ std::move(cards_to_suggest)); } +TouchToFillDelegateAndroidImpl::DryRunResult +TouchToFillDelegateAndroidImpl::DryRunForLoyaltyCard() { + ValuablesDataManager* vdm = manager_->client().GetValuablesDataManager(); + if (!vdm) { + return DryRunResult(TriggerOutcome::kNoValidPaymentMethods, {}); + } + base::span<const LoyaltyCard> loyalty_cards = vdm->GetLoyaltyCards(); + return loyalty_cards.empty() + ? DryRunResult(TriggerOutcome::kNoValidPaymentMethods, {}) + : DryRunResult(TriggerOutcome::kShown, + base::ToVector(loyalty_cards)); +} + // TODO(crbug.com/40282650): Remove received FormData bool TouchToFillDelegateAndroidImpl::IntendsToShowTouchToFill( FormGlobalId form_id, @@ -214,14 +234,29 @@ ->ShowTouchToFillIban(GetWeakPtr(), std::move(*ibans_to_suggest))) { dry_run.outcome = TriggerOutcome::kFailedToDisplayBottomSheet; + } else if (std::vector<LoyaltyCard>* loyalty_cards_to_suggest = + std::get_if<std::vector<LoyaltyCard>>( + &dry_run.items_to_suggest); + loyalty_cards_to_suggest && + !manager_->client() + .GetPaymentsAutofillClient() + ->ShowTouchToFillLoyaltyCard( + GetWeakPtr(), std::move(*loyalty_cards_to_suggest))) { + dry_run.outcome = TriggerOutcome::kFailedToDisplayBottomSheet; } } if (dry_run.outcome != TriggerOutcome::kUnsupportedFieldType) { - if (IsTriggeredOnIbanField(manager_->FindCachedFormById(form.global_id()), - field)) { + if (IsTriggeredOnFieldWithGroup( + manager_->FindCachedFormById(form.global_id()), field, + FieldTypeGroup::kIban)) { base::UmaHistogramEnumeration(kUmaTouchToFillIbanTriggerOutcome, dry_run.outcome); + } else if (IsTriggeredOnFieldWithGroup( + manager_->FindCachedFormById(form.global_id()), field, + FieldTypeGroup::kLoyaltyCard)) { + base::UmaHistogramEnumeration(kUmaTouchToFillLoyaltyCardTriggerOutcome, + dry_run.outcome); } else { base::UmaHistogramEnumeration(kUmaTouchToFillCreditCardTriggerOutcome, dry_run.outcome); @@ -244,6 +279,11 @@ manager_->DidShowSuggestions({Suggestion(SuggestionType::kCreditCardEntry)}, form, field.global_id(), /*update_suggestions_callback=*/{}); + } else if (std::get_if<std::vector<LoyaltyCard>>(&dry_run.items_to_suggest)) { + manager_->DidShowSuggestions( + {Suggestion(SuggestionType::kLoyaltyCardEntry)}, form, + field.global_id(), + /*update_suggestions_callback=*/{}); } else { manager_->DidShowSuggestions({Suggestion(SuggestionType::kIbanEntry)}, form, field.global_id(),
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h index 14218e25..a0a363d5 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h
@@ -11,6 +11,7 @@ #include "base/memory/weak_ptr.h" #include "components/autofill/core/browser/data_model/payments/credit_card.h" #include "components/autofill/core/browser/data_model/payments/iban.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/foundations/autofill_manager.h" #include "components/autofill/core/browser/integrators/fast_checkout/fast_checkout_client.h" @@ -73,13 +74,13 @@ "Autofill.TouchToFill.CreditCard.TriggerOutcome"; inline constexpr const char kUmaTouchToFillIbanTriggerOutcome[] = "Autofill.TouchToFill.Iban.TriggerOutcome"; +inline constexpr const char kUmaTouchToFillLoyaltyCardTriggerOutcome[] = + "Autofill.TouchToFill.LoyaltyCard.TriggerOutcome"; class BrowserAutofillManager; class FormStructure; // Delegate for in-browser Touch To Fill (TTF) surface display and selection. -// Currently TTF surface is eligible for credit card and IBAN forms on click -// on an empty focusable field. // // If the surface was shown once, it won't be triggered again on the same page. // But calling |Reset()| on navigation restores such showing eligibility. @@ -150,14 +151,18 @@ struct DryRunResult { DryRunResult(TriggerOutcome outcome, - std::variant<std::vector<CreditCard>, std::vector<Iban>> - items_to_suggest); + std::variant<std::vector<CreditCard>, + std::vector<Iban>, + std::vector<LoyaltyCard>> items_to_suggest); DryRunResult(DryRunResult&&); DryRunResult& operator=(DryRunResult&&); ~DryRunResult(); TriggerOutcome outcome; - std::variant<std::vector<CreditCard>, std::vector<Iban>> items_to_suggest; + std::variant<std::vector<CreditCard>, + std::vector<Iban>, + std::vector<LoyaltyCard>> + items_to_suggest; }; // Checks all preconditions for showing the TTF, that is, for calling @@ -182,6 +187,10 @@ const FormStructure& form, const FormData& received_form); + // Returns a DryRunResult with the user's fillable loyalty cards, or + // an error reason if TTF should not be triggered. + DryRunResult DryRunForLoyaltyCard(); + bool HasAnyAutofilledFields(const FormStructure& submitted_form) const; // The form is considered perfectly filled if all non-empty fields are
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl_unittest.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl_unittest.cc index e1fab5cb..73b3b31 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl_unittest.cc +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl_unittest.cc
@@ -4,12 +4,17 @@ #include "chrome/browser/touch_to_fill/autofill/android/touch_to_fill_delegate_android_impl.h" +#include "base/notreached.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "components/autofill/core/browser/data_manager/payments/payments_data_manager.h" +#include "components/autofill/core/browser/data_manager/valuables/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/payments/credit_card.h" +#include "components/autofill/core/browser/data_model/valuables/loyalty_card.h" +#include "components/autofill/core/browser/filling/filling_product.h" #include "components/autofill/core/browser/form_structure.h" #include "components/autofill/core/browser/foundations/test_autofill_client.h" #include "components/autofill/core/browser/foundations/test_autofill_driver.h" @@ -19,9 +24,11 @@ #include "components/autofill/core/browser/suggestions/suggestion.h" #include "components/autofill/core/browser/suggestions/suggestion_type.h" #include "components/autofill/core/browser/test_utils/autofill_test_utils.h" +#include "components/autofill/core/browser/test_utils/valuables_data_test_utils.h" #include "components/autofill/core/browser/ui/autofill_external_delegate.h" #include "components/autofill/core/common/autofill_clock.h" #include "components/autofill/core/common/autofill_constants.h" +#include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/autofill_test_utils.h" #include "components/autofill/core/common/form_data_test_api.h" #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" @@ -81,6 +88,11 @@ (base::WeakPtr<autofill::TouchToFillDelegate> delegate, base::span<const Iban> ibans_to_suggest), (override)); + MOCK_METHOD(bool, + ShowTouchToFillLoyaltyCard, + (base::WeakPtr<autofill::TouchToFillDelegate> delegate, + base::span<const LoyaltyCard> loyalty_cards_to_suggest), + (override)); MOCK_METHOD(void, HideTouchToFillPaymentMethod, (), (override)); void ExpectDelegateWeakPtrFromShowInvalidatedOnHideForCards() { @@ -108,6 +120,19 @@ }); } + void ExpectDelegateWeakPtrFromShowInvalidatedOnHideForLoyaltyCards() { + EXPECT_CALL(*this, ShowTouchToFillLoyaltyCard) + .WillOnce( + [this](base::WeakPtr<autofill::TouchToFillDelegate> delegate, + base::span<const LoyaltyCard> loyalty_cards_to_suggest) { + captured_delegate_ = delegate; + return true; + }); + EXPECT_CALL(*this, HideTouchToFillPaymentMethod).WillOnce([this] { + EXPECT_FALSE(captured_delegate_); + }); + } + private: base::WeakPtr<autofill::TouchToFillDelegate> captured_delegate_; }; @@ -194,6 +219,8 @@ .WillByDefault(Return(true)); ON_CALL(payments_autofill_client(), ShowTouchToFillIban) .WillByDefault(Return(true)); + ON_CALL(payments_autofill_client(), ShowTouchToFillLoyaltyCard) + .WillByDefault(Return(true)); // Calling HideTouchToFillPaymentMethod in production code leads to that // OnDismissed gets triggered (HideTouchToFillPaymentMethod calls // view->Hide() on java side, which in its turn triggers onDismissed). Here @@ -233,6 +260,16 @@ return guid; } + void ConfigureForLoyaltyCards() { + LoyaltyCard loyalty_card = test::CreateLoyaltyCard(); + // The touch-to-fill bottom sheet is shown only if the user has at least + // 1 saved loyalty card. + test_api(*autofill_client_.GetValuablesDataManager()) + .AddLoyaltyCard(loyalty_card); + form_ = test::CreateTestLoyaltyCardFormData(); + test_api(form_).field(0).set_is_focusable(true); + } + void OnFormsSeen() { if (!browser_autofill_manager_->FindCachedFormById(form_.global_id())) { browser_autofill_manager_->OnFormsSeen({form_}, {}); @@ -269,6 +306,8 @@ base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; test::AutofillUnitTestEnvironment autofill_test_environment_; + base::test::ScopedFeatureList features_{ + features::kAutofillEnableLoyaltyCardsFilling}; NiceMock<MockAutofillClient> autofill_client_; std::unique_ptr<TestAutofillDriver> autofill_driver_; std::unique_ptr<MockBrowserAutofillManager> browser_autofill_manager_; @@ -277,32 +316,55 @@ }; // Params of TouchToFillDelegateAndroidImplPaymentMethodUnitTest: -// -- bool IsCreditCard: Indicates whether the payment method is a credit card -// or an IBAN. +// -- FillingProduct: Indicates the Autofill data type to test. Supported data +// types are: +// * Credit card +// * IBAN +// * Loyalty card class TouchToFillDelegateAndroidImplPaymentMethodUnitTest : public TouchToFillDelegateAndroidImplUnitTest, - public testing::WithParamInterface<bool> { + public testing::WithParamInterface<FillingProduct> { protected: void SetUp() override { TouchToFillDelegateAndroidImplUnitTest::SetUp(); - if (IsCreditCard()) { - ConfigureForCreditCards(test::GetCreditCard()); - } else { - ConfigureForIbans(); + switch (GetFillingProduct()) { + case FillingProduct::kCreditCard: + ConfigureForCreditCards(test::GetCreditCard()); + break; + case FillingProduct::kIban: + ConfigureForIbans(); + break; + case FillingProduct::kLoyaltyCard: + ConfigureForLoyaltyCards(); + break; + default: + NOTREACHED() << "Unsupported filling product: " + << FillingProductToString(GetFillingProduct()); } } - bool IsCreditCard() const { return GetParam(); } + FillingProduct GetFillingProduct() const { return GetParam(); } std::string GetTriggerOutcomeHistogramName() { - return IsCreditCard() ? kUmaTouchToFillCreditCardTriggerOutcome - : kUmaTouchToFillIbanTriggerOutcome; + switch (GetFillingProduct()) { + case FillingProduct::kCreditCard: + return kUmaTouchToFillCreditCardTriggerOutcome; + case FillingProduct::kIban: + return kUmaTouchToFillIbanTriggerOutcome; + case FillingProduct::kLoyaltyCard: + return kUmaTouchToFillLoyaltyCardTriggerOutcome; + default: + NOTREACHED() << "Unsupported filling product: " + << FillingProductToString(GetFillingProduct()); + } } }; INSTANTIATE_TEST_SUITE_P(All, TouchToFillDelegateAndroidImplPaymentMethodUnitTest, - testing::Bool()); + testing::ValuesIn({FillingProduct::kCreditCard, + FillingProduct::kIban, + FillingProduct::kLoyaltyCard})); TEST_P(TouchToFillDelegateAndroidImplPaymentMethodUnitTest, TryToShowTouchToFillFailsForInvalidForm) { @@ -396,7 +458,7 @@ } TEST_P(TouchToFillDelegateAndroidImplPaymentMethodUnitTest, - TryToShowTouchToFillPaymentMethodSucceeds) { + TryToShowTouchToFillSucceeds) { ASSERT_FALSE(touch_to_fill_delegate_->IsShowingTouchToFill()); EXPECT_CALL(*browser_autofill_manager_, DidShowSuggestions); @@ -407,7 +469,7 @@ } TEST_P(TouchToFillDelegateAndroidImplPaymentMethodUnitTest, - TryToShowTouchToFillFailsForPaymentMethodIfWasShown) { + TryToShowTouchToFillFailsIfWasShown) { TryToShowTouchToFill(/*expected_success=*/true); touch_to_fill_delegate_->HideTouchToFill(); @@ -418,7 +480,7 @@ } TEST_P(TouchToFillDelegateAndroidImplPaymentMethodUnitTest, - TryToShowTouchToFillFailsForPaymentMethodIfFieldIsNotFocusable) { + TryToShowTouchToFillFailsIfFieldIsNotFocusable) { test_api(form_).field(0).set_is_focusable(false); ASSERT_FALSE(touch_to_fill_delegate_->IsShowingTouchToFill()); @@ -429,7 +491,7 @@ } TEST_P(TouchToFillDelegateAndroidImplPaymentMethodUnitTest, - TryToShowTouchToFillFailsForPaymentMethodIfFieldHasValue) { + TryToShowTouchToFillFailsIfFieldHasValue) { ASSERT_FALSE(touch_to_fill_delegate_->IsShowingTouchToFill()); test_api(form_).field(0).set_value(u"Initial value"); @@ -440,11 +502,12 @@ } TEST_P(TouchToFillDelegateAndroidImplPaymentMethodUnitTest, - TryToShowTouchToFillFailsForPaymentMethodIfNoPaymentMethodsOnFile) { + TryToShowTouchToFillFailsIfNoDataOnFile) { ASSERT_FALSE(touch_to_fill_delegate_->IsShowingTouchToFill()); autofill_client_.GetPersonalDataManager() .test_payments_data_manager() .ClearAllLocalData(); + test_api(*autofill_client_.GetValuablesDataManager()).ClearLoyaltyCards(); TryToShowTouchToFill(/*expected_success=*/false); histogram_tester_.ExpectUniqueSample( @@ -1058,6 +1121,46 @@ Iban::InstrumentId(instrument_id)); } +class TouchToFillDelegateAndroidImplLoyaltyCardUnitTest + : public TouchToFillDelegateAndroidImplUnitTest { + protected: + void SetUp() override { + TouchToFillDelegateAndroidImplUnitTest::SetUp(); + ConfigureForLoyaltyCards(); + } +}; + +TEST_F(TouchToFillDelegateAndroidImplLoyaltyCardUnitTest, + TryToShowTouchToFillFailsIfShowLoyaltyCardsFails) { + ASSERT_FALSE(touch_to_fill_delegate_->IsShowingTouchToFill()); + EXPECT_CALL(payments_autofill_client(), ShowTouchToFillLoyaltyCard) + .WillOnce(Return(false)); + + TryToShowTouchToFill(/*expected_success=*/false); +} + +TEST_F(TouchToFillDelegateAndroidImplLoyaltyCardUnitTest, + PassTheLoyaltyCardsToTheClient) { + // TODO: crbug.com/404437211 - Test that the loyalty cards are sorted. + std::vector<LoyaltyCard> loyalty_cards{test::CreateLoyaltyCard()}; + test_api(*autofill_client_.GetValuablesDataManager()) + .SetLoyaltyCards(loyalty_cards); + + EXPECT_CALL(payments_autofill_client(), + ShowTouchToFillLoyaltyCard(_, ElementsAreArray(loyalty_cards))); + + TryToShowTouchToFill(/*expected_success=*/true); +} + +TEST_F(TouchToFillDelegateAndroidImplLoyaltyCardUnitTest, + SafelyHideTouchToFillInDtor) { + payments_autofill_client() + .ExpectDelegateWeakPtrFromShowInvalidatedOnHideForLoyaltyCards(); + TryToShowTouchToFill(/*expected_success=*/true); + + browser_autofill_manager_.reset(); +} + class TouchToFillDelegateAndroidImplVcnGrayOutForMerchantOptOutUnitTest : public TouchToFillDelegateAndroidImplCreditCardUnitTest { public:
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller.cc index 71c04cc..666c695 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller.cc +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view.h" #include "components/autofill/content/browser/content_autofill_client.h" #include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/core/browser/data_model/valuables/loyalty_card.h" #include "components/autofill/core/browser/foundations/autofill_manager.h" #include "components/autofill/core/browser/foundations/browser_autofill_manager.h" #include "components/autofill/core/browser/integrators/touch_to_fill/touch_to_fill_delegate.h" @@ -134,6 +135,31 @@ return true; } +bool TouchToFillPaymentMethodController::ShowLoyaltyCards( + std::unique_ptr<TouchToFillPaymentMethodView> view, + base::WeakPtr<TouchToFillDelegate> delegate, + base::span<const LoyaltyCard> loyalty_cards_to_suggest) { + // TODO(crbug.com/404437211): Unify `ShowX()` methods to avoid code + // duplication. + if (!keyboard_suppressor_.is_suppressing()) { + return false; + } + + // Abort if TTF surface is already shown. + if (view_) { + return false; + } + + if (!view->ShowLoyaltyCards(this, loyalty_cards_to_suggest)) { + ResetJavaObject(); + return false; + } + + view_ = std::move(view); + delegate_ = std::move(delegate); + return true; +} + void TouchToFillPaymentMethodController::Hide() { if (view_) view_->Hide();
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller.h b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller.h index cf6e5ea..a827094 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller.h +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller.h
@@ -20,6 +20,7 @@ class ContentAutofillClient; class CreditCard; class Iban; +class LoyaltyCard; class TouchToFillDelegate; class TouchToFillPaymentMethodView; @@ -70,6 +71,13 @@ base::WeakPtr<TouchToFillDelegate> delegate, base::span<const Iban> ibans_to_suggest); + // Shows the Touch To Fill `view`. `delegate` will provide the fillable + // loyalty cards and be notified of the user's decision. Returns whether the + // surface was successfully shown. + bool ShowLoyaltyCards(std::unique_ptr<TouchToFillPaymentMethodView> view, + base::WeakPtr<TouchToFillDelegate> delegate, + base::span<const LoyaltyCard> loyalty_cards_to_suggest); + // Hides the surface if it is currently shown. void Hide();
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_unittest.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_unittest.cc index 3cf28235..46574e3 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_unittest.cc +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_controller_unittest.cc
@@ -15,11 +15,14 @@ #include "components/autofill/content/browser/test_autofill_client_injector.h" #include "components/autofill/content/browser/test_autofill_manager_injector.h" #include "components/autofill/content/browser/test_content_autofill_client.h" +#include "components/autofill/core/browser/data_model/valuables/loyalty_card.h" #include "components/autofill/core/browser/foundations/test_autofill_client.h" #include "components/autofill/core/browser/foundations/test_browser_autofill_manager.h" #include "components/autofill/core/browser/integrators/touch_to_fill/touch_to_fill_delegate.h" #include "components/autofill/core/browser/suggestions/suggestion.h" #include "components/autofill/core/browser/test_utils/autofill_test_utils.h" +#include "components/autofill/core/browser/test_utils/valuables_data_test_utils.h" +#include "components/autofill/core/common/autofill_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -48,6 +51,10 @@ ShowIbans, (TouchToFillPaymentMethodViewController * controller, base::span<const Iban> ibans_to_suggest)); + MOCK_METHOD(bool, + ShowLoyaltyCards, + (TouchToFillPaymentMethodViewController * controller, + base::span<const LoyaltyCard> loyalty_cards_to_suggest)); MOCK_METHOD(void, Hide, ()); }; @@ -121,6 +128,12 @@ some_field_ = test::MakeFieldGlobalId(); } + void SetUpLoyaltyCardFormField() { + some_form_data_ = test::CreateTestLoyaltyCardFormData(); + some_form_ = some_form_data_.global_id(); + some_field_ = test::MakeFieldGlobalId(); + } + void TearDown() override { mock_view_.reset(); ChromeRenderViewHostTestHarness::TearDown(); @@ -148,6 +161,8 @@ test::GetCreditCard2()}; const std::vector<Iban> ibans_ = {test::GetLocalIban(), test::GetServerIban()}; + const std::vector<LoyaltyCard> loyalty_cards_ = {test::CreateLoyaltyCard(), + test::CreateLoyaltyCard2()}; const std::vector<Suggestion> suggestions_{ test::CreateAutofillSuggestion( credit_cards_[0].CardNameForAutofillDisplay(), @@ -225,6 +240,18 @@ OnAfterAskForValuesToFill(); } +TEST_F(TouchToFillPaymentMethodControllerTest, + ShowLoyaltyCardsPassesLoyaltyCardsToTheView) { + SetUpLoyaltyCardFormField(); + // Test that the loyalty cards have propagated to the view. + EXPECT_CALL(*mock_view_, ShowLoyaltyCards(&payment_method_controller(), + ElementsAreArray(loyalty_cards_))); + OnBeforeAskForValuesToFill(); + payment_method_controller().ShowLoyaltyCards( + std::move(mock_view_), ttf_delegate().GetWeakPointer(), loyalty_cards_); + OnAfterAskForValuesToFill(); +} + TEST_F(TouchToFillPaymentMethodControllerTest, ScanCreditCardIsCalled) { OnBeforeAskForValuesToFill(); payment_method_controller().ShowCreditCards(std::move(mock_view_),
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view.h b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view.h index 47f21c6..2c22edc 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view.h +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view.h
@@ -11,6 +11,7 @@ class CreditCard; class Iban; +class LoyaltyCard; struct Suggestion; class TouchToFillPaymentMethodViewController; @@ -27,6 +28,9 @@ bool should_show_scan_credit_card) = 0; virtual bool ShowIbans(TouchToFillPaymentMethodViewController* controller, base::span<const Iban> ibans_to_suggest) = 0; + virtual bool ShowLoyaltyCards( + TouchToFillPaymentMethodViewController* controller, + base::span<const LoyaltyCard> loyalty_cards_to_suggest) = 0; virtual void Hide() = 0; };
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_impl.cc b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_impl.cc index 2f92fd6..85eefbe 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_impl.cc +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_impl.cc
@@ -10,10 +10,12 @@ #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/containers/to_vector.h" +#include "base/notimplemented.h" #include "base/strings/string_util.h" #include "chrome/browser/autofill/android/personal_data_manager_android.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_controller.h" +#include "components/autofill/core/browser/data_model/valuables/loyalty_card.h" #include "components/autofill/core/browser/suggestions/suggestion.h" #include "components/autofill/core/browser/ui/autofill_resource_utils.h" #include "components/autofill/core/common/autofill_features.h" @@ -24,6 +26,7 @@ // Must come after all headers that specialize FromJniType() / ToJniType(). #include "chrome/browser/touch_to_fill/autofill/android/internal/jni/TouchToFillPaymentMethodViewBridge_jni.h" +#include "components/autofill/android/main_autofill_jni_headers/LoyaltyCard_jni.h" namespace autofill { @@ -142,6 +145,28 @@ return true; } +bool TouchToFillPaymentMethodViewImpl::ShowLoyaltyCards( + TouchToFillPaymentMethodViewController* controller, + base::span<const LoyaltyCard> loyalty_cards_to_suggest) { + JNIEnv* env = base::android::AttachCurrentThread(); + if (!IsReadyToShow(controller, env)) { + return false; + } + + std::vector<base::android::ScopedJavaLocalRef<jobject>> loyalty_cards_array; + loyalty_cards_array.reserve(loyalty_cards_to_suggest.size()); + for (const LoyaltyCard& loyalty_card : loyalty_cards_to_suggest) { + loyalty_cards_array.push_back(Java_LoyaltyCard_Constructor( + env, *loyalty_card.id(), loyalty_card.merchant_name(), + loyalty_card.program_name(), loyalty_card.program_logo(), + loyalty_card.loyalty_card_number(), loyalty_card.merchant_domains())); + } + Java_TouchToFillPaymentMethodViewBridge_showLoyaltyCards( + env, java_object_, std::move(loyalty_cards_array)); + + return true; +} + void TouchToFillPaymentMethodViewImpl::Hide() { if (java_object_) { Java_TouchToFillPaymentMethodViewBridge_hideSheet(
diff --git a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_impl.h b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_impl.h index 03a4c10..9cca41ed 100644 --- a/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_impl.h +++ b/chrome/browser/touch_to_fill/autofill/android/touch_to_fill_payment_method_view_impl.h
@@ -17,6 +17,7 @@ class CreditCard; class Iban; +class LoyaltyCard; struct Suggestion; class TouchToFillPaymentMethodViewController; @@ -42,6 +43,9 @@ bool should_show_scan_credit_card) override; bool ShowIbans(TouchToFillPaymentMethodViewController* controller, base::span<const autofill::Iban> ibans_to_suggest) override; + bool ShowLoyaltyCards( + TouchToFillPaymentMethodViewController* controller, + base::span<const LoyaltyCard> loyalty_cards_to_suggest) override; void Hide() override; // The corresponding Java TouchToFillPaymentMethodViewBridge.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 475f6c9..1c0780e 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2599,7 +2599,6 @@ "//chromeos/ash/experiences/arc/video_accelerator:protected_native_pixmap_query_client", "//chromeos/ash/experiences/system_web_apps/types", "//chromeos/ash/resources", - "//chromeos/ash/services/assistant:lib", "//chromeos/ash/services/assistant/public/cpp", "//chromeos/ash/services/assistant/public/mojom", "//chromeos/ash/services/assistant/public/proto", @@ -3959,8 +3958,6 @@ "views/data_sharing/collaboration_controller_delegate_desktop.h", "views/data_sharing/data_sharing_bubble_controller.cc", "views/data_sharing/data_sharing_bubble_controller.h", - "views/data_sharing/data_sharing_open_group_helper.cc", - "views/data_sharing/data_sharing_open_group_helper.h", "views/data_sharing/data_sharing_utils.cc", "views/data_sharing/data_sharing_utils.h", "views/desktop_capture/desktop_media_content_pane_view.cc", @@ -5734,6 +5731,7 @@ ] deps += [ "//chrome/browser/actor", + "//chrome/browser/ai:ai", "//chrome/browser/background/glic", "//chrome/browser/glic", "//chrome/browser/glic:impl",
diff --git a/chrome/browser/ui/android/omnibox/BUILD.gn b/chrome/browser/ui/android/omnibox/BUILD.gn index 4eae539..8b8171d 100644 --- a/chrome/browser/ui/android/omnibox/BUILD.gn +++ b/chrome/browser/ui/android/omnibox/BUILD.gn
@@ -213,6 +213,7 @@ "//components/page_info/android:java", "//components/permissions/android:java", "//components/prefs/android:java", + "//components/saved_tab_groups/public:java", "//components/search_engines/android:java", "//components/security_state/core:security_state_enums_java", "//components/signin/public/android:java",
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/FullscreenSigninAndHistorySyncCoordinator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/FullscreenSigninAndHistorySyncCoordinator.java index 1c08379e..c2c6568 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/FullscreenSigninAndHistorySyncCoordinator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/FullscreenSigninAndHistorySyncCoordinator.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.ui.signin; +import static org.chromium.build.NullUtil.assertNonNull; import static org.chromium.build.NullUtil.assumeNonNull; import android.accounts.Account; @@ -15,6 +16,7 @@ import android.widget.FrameLayout; import androidx.annotation.IntDef; +import androidx.annotation.NonNull; import org.chromium.base.Promise; import org.chromium.base.metrics.RecordHistogram; @@ -182,8 +184,8 @@ /** Implements {@link SigninAndHistorySyncCoordinator}. */ @Override - public void onAccountAdded(String accountName) { - assumeNonNull(mSigninCoordinator); + public void onAccountAdded(@NonNull String accountName) { + assertNonNull(mSigninCoordinator); mSigninCoordinator.onAccountAdded(accountName); }
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fullscreen_signin/FullscreenSigninCoordinator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fullscreen_signin/FullscreenSigninCoordinator.java index af00273..fdb5645 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fullscreen_signin/FullscreenSigninCoordinator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fullscreen_signin/FullscreenSigninCoordinator.java
@@ -8,6 +8,7 @@ import android.content.Context; import androidx.annotation.MainThread; +import androidx.annotation.NonNull; import androidx.annotation.StringRes; import org.chromium.base.Promise; @@ -168,7 +169,7 @@ } } - public void onAccountAdded(String accountName) { + public void onAccountAdded(@NonNull String accountName) { mMediator.onAccountAdded(accountName); }
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fullscreen_signin/FullscreenSigninMediator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fullscreen_signin/FullscreenSigninMediator.java index e6a1ce5..695de7d 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fullscreen_signin/FullscreenSigninMediator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fullscreen_signin/FullscreenSigninMediator.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.ui.signin.fullscreen_signin; +import static org.chromium.build.NullUtil.assertNonNull; import static org.chromium.build.NullUtil.assumeNonNull; import android.accounts.Account; @@ -12,6 +13,7 @@ import android.text.TextUtils; import androidx.annotation.IntDef; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import org.chromium.base.BuildInfo; @@ -57,6 +59,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; +import java.util.Objects; @NullMarked @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) @@ -103,12 +106,12 @@ private boolean mInitialLoadCompleted; private @Nullable AccountPickerDialogCoordinator mDialogCoordinator; - // TODO(crbug.com/40921927): Replace with CoreAccountInfo. - private @Nullable String mAddedAccountEmail; - // TODO(crbug.com/40921927): Replace with CoreAccountInfo. - private @Nullable String mSelectedAccountEmail; - // TODO(crbug.com/40921927): Replace with CoreAccountInfo. - private @Nullable String mDefaultAccountEmail; + private @Nullable CoreAccountInfo mSelectedAccount; + private @Nullable CoreAccountInfo mDefaultAccount; + private @Nullable CoreAccountInfo mAddedAccount; + // This field is used to save the added account email while the account info becomes available + // in AccountManagerFacade for sign-in. + private @Nullable String mPendingAddedAccountEmail; private boolean mAllowMetricsAndCrashUploading; FullscreenSigninMediator( @@ -174,7 +177,7 @@ } private Account getSelectedAccount() { - return AccountUtils.createAccountFromName(assumeNonNull(mSelectedAccountEmail)); + return AccountUtils.createAccountFromName(assertNonNull(mSelectedAccount).getEmail()); } private void onNativeLoaded() { @@ -278,9 +281,16 @@ getFooterString(isMetricsReportingDisabledByPolicy)); } - void onAccountAdded(String accountEmail) { - mAddedAccountEmail = accountEmail; - setSelectedAccountEmail(accountEmail); + void onAccountAdded(@NonNull String accountEmail) { + var accounts = + AccountUtils.getAccountsIfFulfilledOrEmpty(mAccountManagerFacade.getAccounts()); + mAddedAccount = AccountUtils.findAccountByEmail(accounts, accountEmail); + if (mAddedAccount == null) { + mPendingAddedAccountEmail = accountEmail; + return; + } + + setSelectedAccount(mAddedAccount); if (mDialogCoordinator != null) mDialogCoordinator.dismissDialog(); } @@ -298,8 +308,14 @@ } @Override - public void onAccountSelected(CoreAccountInfo coreAccountInfo) { - setSelectedAccountEmail(coreAccountInfo.getEmail()); + public void onAccountSelected(CoreAccountInfo account) { + if (mPendingAddedAccountEmail != null) { + // If another account is selected before the added account is available in account + // manager facade then clear the pending added account email so that it doesn't get + // selected automatically in #updateAccounts(). + mPendingAddedAccountEmail = null; + } + setSelectedAccount(account); if (mDialogCoordinator != null) mDialogCoordinator.dismissDialog(); } @@ -340,7 +356,7 @@ mDelegate.advanceToNextPage(); return; } - if (mSelectedAccountEmail == null) { + if (mSelectedAccount == null) { mDelegate.addAccount(); return; } @@ -368,7 +384,7 @@ .get() .getOriginalProfile())) .getPrimaryAccountInfo(ConsentLevel.SIGNIN); - if (signedInAccount != null && signedInAccount.getEmail().equals(mSelectedAccountEmail)) { + if (signedInAccount != null && Objects.equals(signedInAccount, mSelectedAccount)) { mDelegate.advanceToNextPage(); return; } @@ -400,11 +416,8 @@ mModel.set(FullscreenSigninProperties.SHOW_SIGNIN_PROGRESS_SPINNER, false); } }; - CoreAccountInfo selectedAccount = - AccountUtils.findCoreAccountInfoByEmail( - mAccountManagerFacade.getCoreAccountInfos().getResult(), - assumeNonNull(mSelectedAccountEmail)); - if (selectedAccount != null) { + + if (mSelectedAccount != null) { mModel.set(FullscreenSigninProperties.SHOW_SIGNIN_PROGRESS_SPINNER_WITH_TEXT, true); final @SigninAccessPoint int accessPoint = mModel.get(FullscreenSigninProperties.IS_SELECTED_ACCOUNT_SUPERVISED) @@ -414,10 +427,10 @@ // If there already exists another signed-in account, first sign-out and then // sign-in with the selected account. signOutThenSignInWithSelectedAccount( - selectedAccount, signinManager, accessPoint, signInCallback); + mSelectedAccount, signinManager, accessPoint, signInCallback); } else { FreManagementNoticeDialogHelper.checkAccountManagementAndSignIn( - selectedAccount, + mSelectedAccount, signinManager, accessPoint, signInCallback, @@ -446,11 +459,10 @@ } private @AccountConsistencyPromoAction int getSigninPromoAction() { - assert mSelectedAccountEmail != null; - if (TextUtils.equals(mSelectedAccountEmail, mDefaultAccountEmail)) { + assert mSelectedAccount != null; + if (Objects.equals(mSelectedAccount, mDefaultAccount)) { return AccountConsistencyPromoAction.SIGNED_IN_WITH_DEFAULT_ACCOUNT; - } else if (mAddedAccountEmail != null - && TextUtils.equals(mSelectedAccountEmail, mAddedAccountEmail)) { + } else if (Objects.equals(mSelectedAccount, mAddedAccount)) { return AccountConsistencyPromoAction.SIGNED_IN_WITH_ADDED_ACCOUNT; } return AccountConsistencyPromoAction.SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT; @@ -507,13 +519,14 @@ || mModel.get(FullscreenSigninProperties.SHOW_SIGNIN_PROGRESS_SPINNER); } - private void setSelectedAccountEmail(String accountEmail) { - mSelectedAccountEmail = accountEmail; - updateSelectedAccountData(mSelectedAccountEmail); + private void setSelectedAccount(CoreAccountInfo account) { + mSelectedAccount = account; + updateSelectedAccountData(account.getEmail()); } private void updateSelectedAccountData(String accountEmail) { - if (TextUtils.equals(mSelectedAccountEmail, accountEmail)) { + if (mSelectedAccount != null + && TextUtils.equals(mSelectedAccount.getEmail(), accountEmail)) { mModel.set( FullscreenSigninProperties.SELECTED_ACCOUNT_DATA, mProfileDataCache.getProfileDataOrDefault(accountEmail)); @@ -521,18 +534,33 @@ } private void updateAccounts(List<AccountInfo> accounts) { + @Nullable AccountInfo pendingAddedAccount = + mPendingAddedAccountEmail == null + ? null + : AccountUtils.findAccountByEmail(accounts, mPendingAddedAccountEmail); + if (pendingAddedAccount != null) { + mPendingAddedAccountEmail = null; + mAddedAccount = pendingAddedAccount; + onAccountSelected(mAddedAccount); + return; + } + if (accounts.isEmpty()) { - mDefaultAccountEmail = null; - mSelectedAccountEmail = null; + mDefaultAccount = null; + mSelectedAccount = null; mModel.set(FullscreenSigninProperties.SELECTED_ACCOUNT_DATA, null); if (mDialogCoordinator != null) { mDialogCoordinator.dismissDialog(); } } else { - mDefaultAccountEmail = accounts.get(0).getEmail(); - if (mSelectedAccountEmail == null - || AccountUtils.findAccountByEmail(accounts, mSelectedAccountEmail) == null) { - setSelectedAccountEmail(mDefaultAccountEmail); + mDefaultAccount = accounts.get(0); + mSelectedAccount = + mSelectedAccount == null + ? null + : AccountUtils.findAccountByEmail( + accounts, mSelectedAccount.getEmail()); + if (mSelectedAccount == null) { + setSelectedAccount(mDefaultAccount); } }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index b7a3d73d..619df4ef 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1909,6 +1909,9 @@ <message name="IDS_SAFETY_HUB_LOCAL_PASSWORD_CHECK_UNAVAILABLE_TITLE" desc="Title for the local password check row in the Safety Check page indicating that the local password checkup could not be completed."> Can’t check passwords on this device </message> + <message name="IDS_SAFETY_HUB_PASSWORD_CHECK_UNAVAILABLE_TITLE" desc="Title for the password check row in the Safety Check page indicating that the local and/or account password checkup could not be completed."> + Can’t check passwords + </message> <message name="IDS_SAFETY_HUB_UNAVAILABLE_SUMMARY" desc="Summary for the rows in the Safety Check page indicating that the checkup for the specific module could not be run at this time and to check again later."> Try again later </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFETY_HUB_PASSWORD_CHECK_UNAVAILABLE_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFETY_HUB_PASSWORD_CHECK_UNAVAILABLE_TITLE.png.sha1 new file mode 100644 index 0000000..08b27a8 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFETY_HUB_PASSWORD_CHECK_UNAVAILABLE_TITLE.png.sha1
@@ -0,0 +1 @@ +47a77890973c8e8523d8b4866f61b75a13983463 \ No newline at end of file
diff --git a/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc b/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc index a73adde..52672230 100644 --- a/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc +++ b/chrome/browser/ui/android/tab_model/tab_model_jni_bridge.cc
@@ -127,7 +127,7 @@ WebContents* TabModelJniBridge::GetWebContentsAt(int index) const { TabAndroid* tab = GetTabAt(index); - return tab == NULL ? NULL : tab->web_contents(); + return tab == nullptr ? nullptr : tab->web_contents(); } TabAndroid* TabModelJniBridge::GetTabAt(int index) const { @@ -135,7 +135,7 @@ ScopedJavaLocalRef<jobject> jtab = Java_TabModelJniBridge_getTabAt(env, java_object_.get(env), index); - return jtab.is_null() ? NULL : TabAndroid::GetNativeTab(env, jtab); + return jtab.is_null() ? nullptr : TabAndroid::GetNativeTab(env, jtab); } ScopedJavaLocalRef<jobject> TabModelJniBridge::GetJavaObject() const { @@ -169,12 +169,12 @@ url::GURLAndroid::FromNativeGURL(env, url), new_window); if (obj.is_null()) { VLOG(0) << "Failed to create java tab"; - return NULL; + return nullptr; } TabAndroid* tab = TabAndroid::GetNativeTab(env, obj); if (!tab) { VLOG(0) << "Failed to create java tab"; - return NULL; + return nullptr; } return tab->web_contents(); } @@ -253,9 +253,7 @@ } tabs::TabInterface* TabModelJniBridge::GetTab(int index) { - // TODO(crbug.com/415351293): Implement. - NOTIMPLEMENTED(); - return nullptr; + return GetTabAt(index); } void TabModelJniBridge::HighlightTabs(std::set<int> indicies) { @@ -269,8 +267,7 @@ } void TabModelJniBridge::CloseTab(int index) { - // TODO(crbug.com/415351293): Implement. - NOTIMPLEMENTED(); + CloseTabAt(index); } std::vector<tabs::TabInterface*> TabModelJniBridge::GetAllTabs() {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonCoordinator.java index 2a03ab2..5dee070 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonCoordinator.java
@@ -9,7 +9,6 @@ import android.graphics.Rect; import android.view.View; -import org.chromium.base.Callback; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.Supplier; import org.chromium.build.annotations.NullMarked; @@ -19,6 +18,7 @@ import org.chromium.chrome.browser.toolbar.top.NavigationPopup; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; +import org.chromium.ui.util.ClickWithMetaStateCallback; import org.chromium.ui.widget.ChromeImageButton; /** @@ -36,9 +36,9 @@ * Creates an instance of {@link BackButtonCoordinator}. * * @param view an Android {@link ChromeImageButton}. - * @param onBackPressed a {@link Callback<Integer>} (taking a parameter of meta key state) that - * is invoked on back button click event. Allows parent components to intercept click and - * navigate back in the history or hide custom UI components. + * @param onBackPressed a {@link ClickWithMetaStateCallback} (taking a parameter of meta key + * state) that is invoked on back button click event. Allows parent components to intercept + * click and navigate back in the history or hide custom UI components. * @param themeColorProvider a provider that notifies about theme changes. * @param tabSupplier a supplier that provides current active tab. * @param historyDelegate a delegate that allows parent components to decide how to display @@ -46,7 +46,7 @@ */ public BackButtonCoordinator( ChromeImageButton view, - Callback<Integer> onBackPressed, + ClickWithMetaStateCallback onBackPressed, ThemeColorProvider themeColorProvider, ObservableSupplier<@Nullable Tab> tabSupplier, ObservableSupplier<Boolean> enabledSupplier,
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonMediator.java index 8e96ca2..95f0340 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonMediator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonMediator.java
@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelAnimatorFactory; +import org.chromium.ui.util.ClickWithMetaStateCallback; /** * A class responsible for mediating external events like theme changes or visibility changes from @@ -51,7 +52,7 @@ */ public BackButtonMediator( PropertyModel model, - Callback<Integer> onBackPressed, + ClickWithMetaStateCallback onBackPressed, ThemeColorProvider themeColorProvider, ObservableSupplier<@Nullable Tab> tabSupplier, ObservableSupplier<Boolean> enabledSupplier, @@ -62,7 +63,7 @@ mModel.set( BackButtonProperties.CLICK_LISTENER, (metaState) -> { - onBackPressed.onResult(metaState); + onBackPressed.onClickWithMeta(metaState); updateButtonEnabledState(); }); mModel.set(
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonMediatorTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonMediatorTest.java index 5caf3c4..641cf78 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonMediatorTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonMediatorTest.java
@@ -33,6 +33,7 @@ import org.chromium.chrome.browser.theme.ThemeColorProvider; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.util.ClickWithMetaStateCallback; @RunWith(BaseRobolectricTestRunner.class) @LooperMode(LooperMode.Mode.PAUSED) @@ -40,7 +41,7 @@ private static final int TAB_ID = 0; @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); - @Mock public Callback<Integer> mOnBackPressed; + @Mock public ClickWithMetaStateCallback mOnBackPressed; @Mock public ThemeColorProvider mThemeColorProvider; @Mock public Callback<Tab> mShowNavigationPopup; @Mock public Profile mProfile; @@ -149,8 +150,8 @@ @Test public void testClick_shouldForwardCallToParent() { - mModel.get(BackButtonProperties.CLICK_LISTENER).onResult(0); - verify(mOnBackPressed).onResult(0); + mModel.get(BackButtonProperties.CLICK_LISTENER).onClickWithMeta(0); + verify(mOnBackPressed).onClickWithMeta(0); } @Test
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonProperties.java index 7985818..6b4dee6 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonProperties.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/back_button/BackButtonProperties.java
@@ -7,13 +7,13 @@ import android.content.res.ColorStateList; import android.view.View; -import org.chromium.base.Callback; import org.chromium.build.annotations.NullMarked; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableFloatPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; +import org.chromium.ui.util.ClickWithMetaStateCallback; /** * A set of back button properties to reflect its state. @@ -22,7 +22,7 @@ */ @NullMarked class BackButtonProperties { - public static final WritableObjectPropertyKey<Callback<Integer>> CLICK_LISTENER = + public static final WritableObjectPropertyKey<ClickWithMetaStateCallback> CLICK_LISTENER = new WritableObjectPropertyKey<>(); public static final WritableObjectPropertyKey<ColorStateList> TINT_COLOR_LIST = new WritableObjectPropertyKey<>();
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 fdc51d3..2afbf1be 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
@@ -324,7 +324,6 @@ } private void maybeShowDeclutterIph(int tabCount) { - if (!ChromeFeatureList.sAndroidTabDeclutter.isEnabled()) return; if (mIsIncognitoSupplier.get()) return; if (mAlreadyRequestedDeclutterIph) return; if (tabCount == 0) return;
diff --git a/chrome/browser/ui/ash/assistant/BUILD.gn b/chrome/browser/ui/ash/assistant/BUILD.gn index 0fbdeae..8830ee0 100644 --- a/chrome/browser/ui/ash/assistant/BUILD.gn +++ b/chrome/browser/ui/ash/assistant/BUILD.gn
@@ -48,7 +48,6 @@ "//chromeos/ash/experiences/arc:arc_base_utils", "//chromeos/ash/experiences/arc/mojom", "//chromeos/ash/experiences/arc/session", - "//chromeos/ash/services/assistant:lib", "//chromeos/ash/services/assistant/public/cpp", "//chromeos/ash/services/assistant/public/proto", "//chromeos/ash/services/bluetooth_config/public/mojom", @@ -88,7 +87,6 @@ "//chromeos/ash/components/dbus/concierge", "//chromeos/ash/experiences/arc:arc_base_utils", "//chromeos/ash/experiences/arc:arc_test_support", - "//chromeos/ash/services/assistant:lib", "//chromeos/ash/services/assistant/public/cpp", "//chromeos/services/assistant/public/shared", "//components/language/core/browser",
diff --git a/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.cc b/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.cc index 304d483..0a2d633 100644 --- a/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.cc +++ b/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.cc
@@ -190,11 +190,6 @@ device_actions_ = std::make_unique<DeviceActions>( std::make_unique<DeviceActionsDelegateImpl>()); - service_ = std::make_unique<ash::assistant::Service>( - profile->GetURLLoaderFactory()->Clone(), - IdentityManagerFactory::GetForProfile(profile), profile->GetPrefs()); - service_->Init(); - assistant_setup_ = std::make_unique<AssistantSetup>(); } @@ -210,8 +205,6 @@ if (!initialized_) { return; } - - ash::assistant::AssistantService::Get()->Shutdown(); } void AssistantBrowserDelegateImpl::InitializeNewEntryPointFor(
diff --git a/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.h b/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.h index 7c99e959..cffcc92 100644 --- a/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.h +++ b/chrome/browser/ui/ash/assistant/assistant_browser_delegate_impl.h
@@ -18,7 +18,6 @@ #include "chrome/browser/web_applications/web_app_registrar.h" #include "chromeos/ash/components/assistant/buildflags.h" #include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/service.h" #include "components/session_manager/core/session_manager_observer.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -124,7 +123,6 @@ void InitializeNewEntryPointFor(Profile* primary_profile); std::unique_ptr<DeviceActions> device_actions_; - std::unique_ptr<ash::assistant::Service> service_; std::unique_ptr<AssistantSetup> assistant_setup_; bool initialized_ = false;
diff --git a/chrome/browser/ui/ash/assistant/test_support/BUILD.gn b/chrome/browser/ui/ash/assistant/test_support/BUILD.gn deleted file mode 100644 index 50772e3..0000000 --- a/chrome/browser/ui/ash/assistant/test_support/BUILD.gn +++ /dev/null
@@ -1,23 +0,0 @@ -# Copyright 2021 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -assert(is_chromeos) - -static_library("test_support") { - testonly = true - - sources = [ - "fake_s3_server.cc", - "fake_s3_server.h", - "test_util.h", - ] - - deps = [ - "//chromeos/ash/services/assistant:lib", - "//chromeos/assistant/internal:internal", - "//testing/gmock", - "//testing/gtest", - "//ui/views:views", - ] -}
diff --git a/chrome/browser/ui/ash/assistant/test_support/DEPS b/chrome/browser/ui/ash/assistant/test_support/DEPS deleted file mode 100644 index 0e2a56a..0000000 --- a/chrome/browser/ui/ash/assistant/test_support/DEPS +++ /dev/null
@@ -1,13 +0,0 @@ -include_rules = [ - # ChromeOS should not depend on //chrome. See //docs/chromeos/code.md for - # details. - "-chrome", - - # This directory is in //chrome, which violates the rule above. Allow this - # directory to #include its own files. - "+chrome/browser/ui/ash/assistant/test_support", - - # Existing dependencies within //chrome. There is an active effort to - # refactor ash codes in //chrome to break these dependencies; see b/332804822. - # Whenever possible, avoid adding new //chrome dependencies to this list. -]
diff --git a/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.cc b/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.cc deleted file mode 100644 index 9dda67d5..0000000 --- a/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.cc +++ /dev/null
@@ -1,263 +0,0 @@ -// Copyright 2019 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/ash/assistant/test_support/fake_s3_server.h" - -#include <memory> - -#include "base/check.h" -#include "base/check_op.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/notreached.h" -#include "base/path_service.h" -#include "base/process/launch.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "chromeos/ash/services/assistant/service.h" -#include "chromeos/assistant/internal/internal_constants.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash::assistant { - -namespace { - -// TODO(b/258750971): remove when internal assistant codes are migrated to -// namespace ash. -using ::chromeos::assistant::kFakeS3ServerBinary; -using ::chromeos::assistant::kFakeS3ServerBinaryV2; -using ::chromeos::assistant::kGenerateTokenInstructions; - -// Folder where the S3 communications are stored when running in replay mode. -constexpr char kTestDataFolder[] = "chromeos/assistant/internal/test_data/"; - -// Fake device id passed to Libassistant. By fixing this we ensure it remains -// consistent between the current session and the value stored in the stored -// test data. -// This must be a 16 characters hex string or it will be rejected. -constexpr char kDeviceId[] = "11112222333344445555666677778888"; - -base::FilePath GetExecutableDir() { - base::FilePath result; - base::PathService::Get(base::DIR_EXE, &result); - return result; -} - -base::FilePath GetSourceDir() { - base::FilePath result; - base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &result); - return result; -} - -std::string GetSanitizedTestName() { - std::string test_name = base::ToLowerASCII(base::StringPrintf( - "%s_%s", - testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(), - testing::UnitTest::GetInstance()->current_test_info()->name())); - // The test name may has `disabled_`. Remove it to match the data_file - // name. - base::ReplaceSubstringsAfterOffset(&test_name, 0, "disabled_", ""); - return test_name; -} - -const std::string GetAccessTokenFromEnvironmentOrDie() { - const char* token = std::getenv("TOKEN"); - CHECK(token && strlen(token)) - << "No token found in the environmental variable $TOKEN.\n" - << kGenerateTokenInstructions; - return token; -} - -std::string FakeS3ModeToString(FakeS3Mode mode) { - switch (mode) { - case FakeS3Mode::kProxy: - return "PROXY"; - case FakeS3Mode::kRecord: - return "RECORD"; - case FakeS3Mode::kReplay: - return "REPLAY"; - } - NOTREACHED(); -} - -void AppendArgument(base::CommandLine* command_line, - const std::string& name, - const std::string& value) { - // Note we can't use |AppendSwitchASCII| as that will add "<name>=<value>", - // and the fake s3 server binary does not support '='. - command_line->AppendArg(name); - command_line->AppendArg(value); -} - -} // namespace - -// Selects a port for the fake S3 server to use. -// This will use a file-based lock because different test shards might be trying -// to run fake S3 servers at the same time, and we need to ensure they use -// different ports. -class PortSelector { - public: - PortSelector() { SelectPort(); } - PortSelector(PortSelector&) = delete; - PortSelector& operator=(PortSelector&) = delete; - ~PortSelector() { - lock_file_.Close(); - base::DeletePathRecursively(GetLockFilePath()); - } - - int port() const { return port_; } - - private: - // The first port we'll try to use. Randomly chosen to be outside of the range - // of known ports. - constexpr static int kStartPort = 23600; - // Maximum number of ports we'll try before we give up and conclude no ports - // are available (which really should not happen). - constexpr static int kMaxAttempts = 20000; - - void SelectPort() { - for (int offset = 0; offset + 1 < kMaxAttempts; offset += 2) { - port_ = kStartPort + offset; - lock_file_ = base::File(GetLockFilePath(), GetFileFlags()); - if (lock_file_.IsValid()) { - return; - } - } - NOTREACHED() << "Failed to find an available port."; - } - - base::FilePath GetLockFilePath() const { - std::string file_name = "port_" + base::NumberToString(port_) + "_lock"; - return GetLockFileDirectory().Append(file_name); - } - static base::FilePath GetLockFileDirectory() { - base::FilePath result; - bool success = base::GetTempDir(&result); - EXPECT_TRUE(success); - return result; - } - - static int GetFileFlags() { - return base::File::FLAG_CREATE | base::File::FLAG_WRITE; - } - - // File exclusively opened on the file-system, to ensure no other fake S3 - // server uses the same port. - base::File lock_file_; - int port_; -}; - -FakeS3Server::FakeS3Server(int data_file_version) - : data_file_version_(data_file_version), - port_selector_(std::make_unique<PortSelector>()) { - DCHECK_GT(data_file_version, 0); -} - -FakeS3Server::~FakeS3Server() { - Teardown(); -} - -void FakeS3Server::Setup(FakeS3Mode mode) { - SetAccessTokenForMode(mode); - StartS3ServerProcess(mode); - SetFakeS3ServerURI(); - SetDeviceId(); -} - -void FakeS3Server::Teardown() { - StopS3ServerProcess(); - UnsetDeviceId(); - UnsetFakeS3ServerURI(); -} - -std::string FakeS3Server::GetAccessToken() const { - return access_token_; -} - -void FakeS3Server::SetAccessTokenForMode(FakeS3Mode mode) { - if (mode == FakeS3Mode::kProxy || mode == FakeS3Mode::kRecord) { - access_token_ = GetAccessTokenFromEnvironmentOrDie(); - } -} - -void FakeS3Server::SetFakeS3ServerURI() { - // Note this must be stored in a local variable, as - // `Service::OverrideS3ServerUriForTesting` does not take ownership of the - // `const char *`. - fake_s3_server_uri_ = "localhost:" + base::NumberToString(port()); - Service::OverrideS3ServerUriForTesting(fake_s3_server_uri_.c_str()); -} - -void FakeS3Server::SetDeviceId() { - Service::OverrideDeviceIdForTesting(kDeviceId); -} - -void FakeS3Server::UnsetDeviceId() { - Service::OverrideDeviceIdForTesting(nullptr); -} - -void FakeS3Server::UnsetFakeS3ServerURI() { - Service::OverrideS3ServerUriForTesting(nullptr); - fake_s3_server_uri_ = ""; -} - -void FakeS3Server::StartS3ServerProcess(FakeS3Mode mode) { - if (process_running_) { - LOG(WARNING) - << "Called FakeS3Server::StartS3ServerProcess when already running."; - return; - } - - base::FilePath fake_s3_server_main; - fake_s3_server_main = - GetExecutableDir().Append(FILE_PATH_LITERAL(kFakeS3ServerBinaryV2)); - - base::CommandLine command_line(fake_s3_server_main); - AppendArgument(&command_line, "--port", base::NumberToString(port())); - AppendArgument(&command_line, "--http_port", - base::NumberToString(port() + 1)); - AppendArgument(&command_line, "--mode", FakeS3ModeToString(mode)); - AppendArgument(&command_line, "--auth_token", GetAccessToken()); - AppendArgument(&command_line, "--test_data_file", GetTestDataFileName()); - - fake_s3_server_ = base::LaunchProcess(command_line, base::LaunchOptions{}); - process_running_ = true; -} - -void FakeS3Server::StopS3ServerProcess() { - if (!process_running_) { - LOG(WARNING) - << "Called FakeS3Server::StopS3ServerProcess when already stopped."; - return; - } - fake_s3_server_.Terminate(/*exit_code=*/0, /*wait=*/true); - process_running_ = false; -} - -std::string FakeS3Server::GetTestDataFileName() { - auto create_file_path = [](const std::string& test_name, int version) { - return GetSourceDir() - .Append(FILE_PATH_LITERAL(kTestDataFolder)) - .Append(FILE_PATH_LITERAL(test_name + ".v" + - base::NumberToString(version) + - ".fake_s3.proto")); - }; - // Look for the latest version of the data file, if not found, look for older - // ones. - auto data_file = create_file_path(GetSanitizedTestName(), data_file_version_); - for (int version = data_file_version_ - 1; - !base::PathExists(data_file) && version > 0; --version) { - data_file = create_file_path(GetSanitizedTestName(), version); - } - - return data_file.MaybeAsASCII(); -} - -int FakeS3Server::port() const { - return port_selector_->port(); -} - -} // namespace ash::assistant
diff --git a/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h b/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h deleted file mode 100644 index 186a1bf5..0000000 --- a/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h +++ /dev/null
@@ -1,81 +0,0 @@ -// Copyright 2019 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_ASH_ASSISTANT_TEST_SUPPORT_FAKE_S3_SERVER_H_ -#define CHROME_BROWSER_UI_ASH_ASSISTANT_TEST_SUPPORT_FAKE_S3_SERVER_H_ - -#include <memory> -#include <string> - -#include "base/process/process.h" - -namespace ash::assistant { - -class PortSelector; - -enum class FakeS3Mode { - // In this mode all S3 requests are forwarded to the S3 server. - kProxy, - // In this mode all S3 requests are forwarded to the S3 server, and the - // responses are recorded. - kRecord, - // In this mode all S3 requests are handled by replaying the responses stored - // while running in |kRecord| mode. - kReplay, -}; - -// Class that starts/stops a fake S3 server. -// Note that this will also ensure the Assistant service knows to use the fake -// s3 server. -// -// A valid access token is required if mode is |kProxy| or |kReplay|. See -// |kGenerateTokenInstructions| for information on how to get one. -class FakeS3Server { - public: - // |data_file_version| is used to look for a particular set of test data - // files to use. This enables updating tests and checking in test data and - // test themselves separately. If the latest version of the test data file - // does not exist, it will automatically looker for an older version of the - // file. - explicit FakeS3Server(int data_file_version); - - FakeS3Server(const FakeS3Server&) = delete; - FakeS3Server& operator=(const FakeS3Server&) = delete; - - ~FakeS3Server(); - - // Starts the fake S3 server, and tells the Assistant service to use its URI - // for all S3 requests. - void Setup(FakeS3Mode mode); - void Teardown(); - - // Returns the access token used by the S3 Server. This is only populated - // after |Setup| is called. - std::string GetAccessToken() const; - - private: - void SetAccessTokenForMode(FakeS3Mode mode); - void SetFakeS3ServerURI(); - void UnsetFakeS3ServerURI(); - void SetDeviceId(); - void UnsetDeviceId(); - void StartS3ServerProcess(FakeS3Mode mode); - void StopS3ServerProcess(); - std::string GetTestDataFileName(); - - int port() const; - - std::string access_token_{"FAKE_ACCESS_TOKEN"}; - std::string fake_s3_server_uri_; - int data_file_version_; - bool process_running_ = false; - - std::unique_ptr<PortSelector> port_selector_; - - base::Process fake_s3_server_; -}; - -} // namespace ash::assistant - -#endif // CHROME_BROWSER_UI_ASH_ASSISTANT_TEST_SUPPORT_FAKE_S3_SERVER_H_
diff --git a/chrome/browser/ui/ash/assistant/test_support/test_util.h b/chrome/browser/ui/ash/assistant/test_support/test_util.h deleted file mode 100644 index 711721c6..0000000 --- a/chrome/browser/ui/ash/assistant/test_support/test_util.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_ASH_ASSISTANT_TEST_SUPPORT_TEST_UTIL_H_ -#define CHROME_BROWSER_UI_ASH_ASSISTANT_TEST_SUPPORT_TEST_UTIL_H_ - -#include <string> -#include <vector> - -#include "ui/views/view.h" - -namespace ash::assistant { - -// Finds any descendents of |parent| with the desired |class_name| and pushes -// them onto the strongly typed |result| vector. -// NOTE: Callers are expected to ensure that casting to <T> makes sense. It is -// preferred to use the two argument variant of FindDescendentsOfClass() when -// possible for stronger type safety. -template <typename T> -void FindDescendentsOfClass(views::View* parent, - const std::string& class_name, - std::vector<T*>* result) { - for (views::View* child : parent->children()) { - if (child->GetClassName() == class_name) { - result->push_back(static_cast<T*>(child)); - } - FindDescendentsOfClass(child, class_name, result); - } -} - -// Finds any descendents of |parent| with class name equal to the static class -// variable |kViewClassName| and pushes them onto the strongly typed |result| -// vector. -// NOTE: This variant of FindDescendentsOfClass() is safer than the three -// argument variant and its usage should be preferred where possible. -template <typename T> -void FindDescendentsOfClass(views::View* parent, std::vector<T*>* result) { - FindDescendentsOfClass(parent, T::kViewClassName, result); -} - -} // namespace ash::assistant - -#endif // CHROME_BROWSER_UI_ASH_ASSISTANT_TEST_SUPPORT_TEST_UTIL_H_
diff --git a/chrome/browser/ui/ash/desks/chrome_desks_util.h b/chrome/browser/ui/ash/desks/chrome_desks_util.h index 4f583d59..c9b66f2 100644 --- a/chrome/browser/ui/ash/desks/chrome_desks_util.h +++ b/chrome/browser/ui/ash/desks/chrome_desks_util.h
@@ -16,7 +16,7 @@ namespace chrome_desks_util { // Name for app not available toast. -constexpr char kAppNotAvailableTemplateToastName[] = +inline constexpr char kAppNotAvailableTemplateToastName[] = "AppNotAvailableTemplateToast"; // Given a TabGroupModel that contains at least a single TabGroup this method
diff --git a/chrome/browser/ui/ash/editor_menu/BUILD.gn b/chrome/browser/ui/ash/editor_menu/BUILD.gn index a4ab61d..3ec42db27 100644 --- a/chrome/browser/ui/ash/editor_menu/BUILD.gn +++ b/chrome/browser/ui/ash/editor_menu/BUILD.gn
@@ -21,7 +21,6 @@ deps = [ "//base", - "//chrome/browser:browser_process", "//chromeos/ash/components/editor_menu/public/cpp", "//chromeos/crosapi/mojom", "//ui/aura", @@ -98,6 +97,7 @@ "//chromeos/constants:constants", "//chromeos/strings:strings_grit", "//chromeos/ui/vector_icons", + "//components/application_locale_storage", "//components/vector_icons", "//ui/aura", "//ui/base",
diff --git a/chrome/browser/ui/ash/editor_menu/DEPS b/chrome/browser/ui/ash/editor_menu/DEPS index c43c417..6d35abdd 100644 --- a/chrome/browser/ui/ash/editor_menu/DEPS +++ b/chrome/browser/ui/ash/editor_menu/DEPS
@@ -4,9 +4,14 @@ "+chrome/browser/ash/input_method", "+chrome/browser/ash/lobster", - "+chrome/browser/browser_process.h", "+chrome/browser/profiles/profile.h", "+chrome/browser/ui/ash/read_write_cards", "+chrome/browser/ui/browser.h", "+chrome/test/views/chrome_views_test_base.h", ] + +specific_include_rules = { + ".*unittest\\.cc": [ + "+chrome/browser/global_features.h", + ], +}
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.cc index fa22ef2..4933bbf9 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.cc
@@ -14,7 +14,9 @@ #include "ash/shell.h" #include "ash/webui/settings/public/constants/routes.mojom.h" #include "ash/webui/settings/public/constants/setting.mojom.h" +#include "base/check_deref.h" #include "base/feature_list.h" +#include "base/memory/raw_ref.h" #include "base/notreached.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" @@ -79,7 +81,9 @@ } // namespace -EditorMenuControllerImpl::EditorMenuControllerImpl() = default; +EditorMenuControllerImpl::EditorMenuControllerImpl( + const ApplicationLocaleStorage* application_locale_storage) + : application_locale_storage_(CHECK_DEREF(application_locale_storage)) {} EditorMenuControllerImpl::~EditorMenuControllerImpl() = default; @@ -328,8 +332,8 @@ if (chromeos::features::IsMagicBoostRevampEnabled()) { NOTREACHED(); } - editor_menu_widget_ = - EditorMenuPromoCardView::CreateWidget(anchor_bounds, this); + editor_menu_widget_ = EditorMenuPromoCardView::CreateWidget( + &application_locale_storage_.get(), anchor_bounds, this); editor_menu_widget_->ShowInactive(); break; case TextAndImageMode::kEditorWriteOnly: @@ -339,8 +343,8 @@ case TextAndImageMode::kEditorWriteAndLobster: case TextAndImageMode::kEditorRewriteAndLobster: editor_menu_widget_ = EditorMenuView::CreateWidget( - text_and_image_mode, editor_menu_card_context.preset_queries(), - anchor_bounds, this); + &application_locale_storage_.get(), text_and_image_mode, + editor_menu_card_context.preset_queries(), anchor_bounds, this); editor_menu_widget_->ShowInactive(); break; }
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.h b/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.h index 899d542..12989f3 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.h +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.h
@@ -9,6 +9,7 @@ #include <string_view> #include "ash/lobster/lobster_controller.h" +#include "base/memory/raw_ref.h" #include "base/memory/weak_ptr.h" #include "build/build_config.h" #include "chrome/browser/ui/ash/editor_menu/editor_manager.h" @@ -21,12 +22,13 @@ #include "chromeos/ash/components/editor_menu/public/cpp/editor_mode.h" #include "content/public/browser/browser_context.h" +class ApplicationLocaleStorage; +class Profile; + namespace views { class Widget; } -class Profile; - namespace chromeos::editor_menu { // Implementation of ReadWriteCardController. It manages the editor menu related @@ -34,7 +36,8 @@ class EditorMenuControllerImpl : public chromeos::ReadWriteCardController, public EditorMenuViewDelegate { public: - EditorMenuControllerImpl(); + explicit EditorMenuControllerImpl( + const ApplicationLocaleStorage* application_locale_storage); EditorMenuControllerImpl(const EditorMenuControllerImpl&) = delete; EditorMenuControllerImpl& operator=(const EditorMenuControllerImpl&) = delete; ~EditorMenuControllerImpl() override; @@ -138,6 +141,8 @@ // buttons or textfield to receive keyboard or mouse input. void DisableEditorMenu(); + const raw_ref<const ApplicationLocaleStorage> application_locale_storage_; + std::unique_ptr<views::Widget> editor_menu_widget_; // May hold the currently active editor card session. If this is nullptr then
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.cc index 1f5abd96..16a23cd9 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.cc
@@ -4,8 +4,10 @@ #include "chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.h" +#include "base/check_deref.h" #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_ref.h" #include "base/task/sequenced_task_runner.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_strings.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_view_delegate.h" @@ -13,6 +15,7 @@ #include "chrome/browser/ui/ash/editor_menu/utils/utils.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "chromeos/ui/vector_icons/vector_icons.h" +#include "components/application_locale_storage/application_locale_storage.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/models/image_model.h" @@ -63,9 +66,11 @@ } // namespace EditorMenuPromoCardView::EditorMenuPromoCardView( + const ApplicationLocaleStorage* application_locale_storage, const gfx::Rect& anchor_view_bounds, EditorMenuViewDelegate* delegate) - : pre_target_handler_( + : application_locale_storage_(CHECK_DEREF(application_locale_storage)), + pre_target_handler_( std::make_unique<PreTargetHandler>(/*delegate=*/*this, CardType::kEditorMenu)), delegate_(delegate) { @@ -80,6 +85,7 @@ // static std::unique_ptr<views::Widget> EditorMenuPromoCardView::CreateWidget( + const ApplicationLocaleStorage* application_locale_storage, const gfx::Rect& anchor_view_bounds, EditorMenuViewDelegate* delegate) { views::Widget::InitParams params( @@ -95,7 +101,7 @@ auto widget = std::make_unique<views::Widget>(std::move(params)); EditorMenuPromoCardView* editor_menu_promo_card_view = widget->SetContentsView(std::make_unique<EditorMenuPromoCardView>( - anchor_view_bounds, delegate)); + application_locale_storage, anchor_view_bounds, delegate)); editor_menu_promo_card_view->UpdateBounds(anchor_view_bounds); return widget; @@ -177,7 +183,8 @@ void EditorMenuPromoCardView::UpdateBounds( const gfx::Rect& anchor_view_bounds) { - GetWidget()->SetBounds(GetEditorMenuBounds(anchor_view_bounds, this)); + GetWidget()->SetBounds(GetEditorMenuBounds( + anchor_view_bounds, this, application_locale_storage_->Get())); } views::View* EditorMenuPromoCardView::GetRootView() {
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.h b/chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.h index 60c1ba3..87b048c 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.h +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_promo_card_view.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/memory/raw_ptr.h" +#include "base/memory/raw_ref.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "chrome/browser/ui/ash/editor_menu/utils/pre_target_handler.h" @@ -15,6 +16,8 @@ #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" +class ApplicationLocaleStorage; + namespace views { class Label; class MdTextButton; @@ -31,15 +34,20 @@ METADATA_HEADER(EditorMenuPromoCardView, views::View) public: - EditorMenuPromoCardView(const gfx::Rect& anchor_view_bounds, - EditorMenuViewDelegate* delegate); + // `application_locale_storage` must be non-null and must outlive `this`. + EditorMenuPromoCardView( + const ApplicationLocaleStorage* application_locale_storage, + const gfx::Rect& anchor_view_bounds, + EditorMenuViewDelegate* delegate); EditorMenuPromoCardView(const EditorMenuPromoCardView&) = delete; EditorMenuPromoCardView& operator=(const EditorMenuPromoCardView&) = delete; ~EditorMenuPromoCardView() override; + // `application_locale_storage` must be non-null and must outlive the widget. static std::unique_ptr<views::Widget> CreateWidget( + const ApplicationLocaleStorage* application_locale_storage, const gfx::Rect& anchor_view_bounds, EditorMenuViewDelegate* delegate); @@ -76,6 +84,8 @@ void ResetPreTargetHandler(); + const raw_ref<const ApplicationLocaleStorage> application_locale_storage_; + std::unique_ptr<PreTargetHandler> pre_target_handler_; // `delegate_` outlives `this`.
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_view.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_view.cc index 973a27a..866d29d 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_view.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_view.cc
@@ -10,9 +10,11 @@ #include <utility> #include <vector> +#include "base/check_deref.h" #include "base/functional/bind.h" #include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" +#include "base/memory/raw_ref.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_badge_view.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_chip_view.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_strings.h" @@ -24,6 +26,7 @@ #include "chromeos/ash/components/editor_menu/public/cpp/icon.h" #include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/strings/grit/chromeos_strings.h" +#include "components/application_locale_storage/application_locale_storage.h" #include "components/vector_icons/vector_icons.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/metadata/metadata_impl_macros.h" @@ -108,11 +111,14 @@ return total_chips_height + total_chips_paddings; } -EditorMenuView::EditorMenuView(TextAndImageMode text_and_image_mode, - const PresetTextQueries& preset_text_queries, - const gfx::Rect& anchor_view_bounds, - EditorMenuViewDelegate* delegate) +EditorMenuView::EditorMenuView( + const ApplicationLocaleStorage* application_locale_storage, + TextAndImageMode text_and_image_mode, + const PresetTextQueries& preset_text_queries, + const gfx::Rect& anchor_view_bounds, + EditorMenuViewDelegate* delegate) : PreTargetHandlerView(CardType::kEditorMenu), + application_locale_storage_(CHECK_DEREF(application_locale_storage)), text_and_image_mode_(text_and_image_mode), delegate_(delegate) { CHECK(delegate_); @@ -127,6 +133,7 @@ // static std::unique_ptr<views::Widget> EditorMenuView::CreateWidget( + const ApplicationLocaleStorage* application_locale_storage, TextAndImageMode text_and_image_mode, const PresetTextQueries& preset_text_queries, const gfx::Rect& anchor_view_bounds, @@ -144,9 +151,10 @@ params.name = kWidgetName; auto widget = std::make_unique<views::Widget>(std::move(params)); - EditorMenuView* editor_menu_view = widget->SetContentsView( - std::make_unique<EditorMenuView>(text_and_image_mode, preset_text_queries, - anchor_view_bounds, delegate)); + EditorMenuView* editor_menu_view = + widget->SetContentsView(std::make_unique<EditorMenuView>( + application_locale_storage, text_and_image_mode, preset_text_queries, + anchor_view_bounds, delegate)); editor_menu_view->UpdateBounds(anchor_view_bounds); return widget; @@ -244,7 +252,8 @@ } void EditorMenuView::UpdateBounds(const gfx::Rect& anchor_view_bounds) { - gfx::Rect editor_menu_bounds = GetEditorMenuBounds(anchor_view_bounds, this); + gfx::Rect editor_menu_bounds = GetEditorMenuBounds( + anchor_view_bounds, this, application_locale_storage_->Get()); GetWidget()->SetBounds(editor_menu_bounds); UpdateChipsContainer(/*editor_menu_width=*/editor_menu_bounds.width()); }
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_view.h b/chrome/browser/ui/ash/editor_menu/editor_menu_view.h index 2e51b5c..bc6a3c18 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_view.h +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_view.h
@@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/memory/raw_ref.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/ash/editor_menu/utils/pre_target_handler_view.h" #include "chrome/browser/ui/ash/editor_menu/utils/text_and_image_mode.h" @@ -17,6 +18,8 @@ #include "ui/views/controls/tabbed_pane/tabbed_pane_listener.h" #include "ui/views/layout/flex_layout_view.h" +class ApplicationLocaleStorage; + namespace views { class ImageButton; class FlexLayoutView; @@ -35,7 +38,9 @@ METADATA_HEADER(EditorMenuView, views::View) public: - EditorMenuView(TextAndImageMode text_and_image_mode, + // `application_locale_storage` must be non-null and must outlive `this`. + EditorMenuView(const ApplicationLocaleStorage* application_locale_storage, + TextAndImageMode text_and_image_mode, const PresetTextQueries& preset_text_queries, const gfx::Rect& anchor_view_bounds, EditorMenuViewDelegate* delegate); @@ -45,7 +50,9 @@ ~EditorMenuView() override; + // `application_locale_storage` must be non-null and must outlive the widget. static std::unique_ptr<views::Widget> CreateWidget( + const ApplicationLocaleStorage* application_locale_storage, TextAndImageMode text_and_image_mode, const PresetTextQueries& preset_text_queries, const gfx::Rect& anchor_view_bounds, @@ -73,8 +80,6 @@ static const char* GetWidgetNameForTest(); private: - const TextAndImageMode text_and_image_mode_; - void InitLayout(const PresetTextQueries& preset_text_queries); gfx::Insets GetTitleContainerInsets() const; void AddTitleContainer(); @@ -88,6 +93,10 @@ void OnSettingsButtonPressed(); void OnChipButtonPressed(const std::string& text_query_id); + const raw_ref<const ApplicationLocaleStorage> application_locale_storage_; + + const TextAndImageMode text_and_image_mode_; + // `delegate_` outlives `this`. raw_ptr<EditorMenuViewDelegate> delegate_ = nullptr;
diff --git a/chrome/browser/ui/ash/editor_menu/editor_menu_view_unittest.cc b/chrome/browser/ui/ash/editor_menu/editor_menu_view_unittest.cc index dbc1774..61cd8947 100644 --- a/chrome/browser/ui/ash/editor_menu/editor_menu_view_unittest.cc +++ b/chrome/browser/ui/ash/editor_menu/editor_menu_view_unittest.cc
@@ -7,11 +7,13 @@ #include <string_view> #include "base/test/scoped_feature_list.h" +#include "chrome/browser/global_features.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_chip_view.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_strings.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_textfield_view.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_view.h" #include "chrome/browser/ui/ash/editor_menu/editor_menu_view_delegate.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/views/chrome_views_test_base.h" #include "chromeos/ash/components/editor_menu/public/cpp/preset_text_query.h" #include "chromeos/constants/chromeos_features.h" @@ -81,7 +83,10 @@ PresetTextQuery("ID2", u"Elaborate", PresetQueryCategory::kElaborate)}; std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorRewriteOnly, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorRewriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); auto* editor_menu_view = @@ -107,7 +112,10 @@ PresetTextQuery("ID5", u"Formalize", PresetQueryCategory::kFormalize)}; std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorRewriteOnly, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorRewriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); auto* editor_menu_view = @@ -131,7 +139,10 @@ // Create and focus the editor menu. std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorRewriteOnly, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorRewriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); @@ -173,7 +184,10 @@ // Create and show the editor menu. std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorRewriteOnly, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorRewriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); @@ -200,7 +214,10 @@ // Create and show the editor menu. std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorRewriteOnly, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorRewriteOnly, PresetTextQueries(), gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); @@ -230,7 +247,10 @@ PresetTextQuery("ID2", u"Emojify", PresetQueryCategory::kEmojify)}; std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorRewriteOnly, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorRewriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); @@ -257,7 +277,10 @@ PresetTextQuery("ID2", u"Emojify", PresetQueryCategory::kEmojify)}; std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorWriteAndLobster, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorWriteAndLobster, queries, gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); @@ -285,7 +308,10 @@ // Rewrite Editor Mode std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorRewriteOnly, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorRewriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); @@ -300,7 +326,10 @@ // Write Editor Mode editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorWriteOnly, queries, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorWriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); editor_menu_view = @@ -321,7 +350,10 @@ // Rewrite Editor Mode std::unique_ptr<views::Widget> editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorRewriteOnly, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorRewriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); @@ -336,7 +368,10 @@ // Write Editor Mode editor_menu_widget = - EditorMenuView::CreateWidget(TextAndImageMode::kEditorWriteOnly, queries, + EditorMenuView::CreateWidget(TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage(), + TextAndImageMode::kEditorWriteOnly, queries, gfx::Rect(200, 300, 400, 200), &delegate); editor_menu_widget->Show(); editor_menu_view =
diff --git a/chrome/browser/ui/ash/editor_menu/utils/utils.cc b/chrome/browser/ui/ash/editor_menu/utils/utils.cc index e3ff5a2..d9469e5b 100644 --- a/chrome/browser/ui/ash/editor_menu/utils/utils.cc +++ b/chrome/browser/ui/ash/editor_menu/utils/utils.cc
@@ -4,7 +4,8 @@ #include "chrome/browser/ui/ash/editor_menu/utils/utils.h" -#include "chrome/browser/browser_process.h" +#include <string> + #include "ui/display/screen.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" @@ -13,14 +14,8 @@ namespace { -std::string GetSystemLocale() { - return g_browser_process != nullptr - ? g_browser_process->GetApplicationLocale() - : ""; -} - -int ComputeWidthOnSide() { - if (GetSystemLocale() == "ta") { +int ComputeWidthOnSide(const std::string& app_locale) { + if (app_locale == "ta") { return kBigEditorMenuMinWidthDip; } return kEditorMenuMinWidthDip; @@ -31,7 +26,8 @@ const views::View* target, const gfx::Rect screen_work_area, const gfx::Point cursor_point, - const CardType& card_type) { + const CardType& card_type, + const std::string& application_locale) { const int width_on_top_or_bottom = std::max( card_type == CardType::kMahiDefaultMenu ? kMahiMenuTopBottomMinWidthDip : kEditorMenuMinWidthDip, @@ -39,7 +35,7 @@ const int height_on_top_or_bottom = target->GetHeightForWidth(width_on_top_or_bottom); - const int width_on_side = ComputeWidthOnSide(); + const int width_on_side = ComputeWidthOnSide(application_locale); const int height_on_side = target->GetHeightForWidth(width_on_side); // The vertical starting position of top side candidates which makes them be @@ -212,6 +208,7 @@ gfx::Rect GetEditorMenuBounds(const gfx::Rect& anchor_view_bounds, const views::View* target, + const std::string& application_locale, const CardType card_type) { display::Screen* screen = display::Screen::GetScreen(); const gfx::Rect screen_work_area = @@ -219,7 +216,8 @@ const gfx::Point cursor_point = screen->GetCursorScreenPoint(); std::vector<gfx::Rect> candidates = GetEditorMenuBoundsCandidates( - anchor_view_bounds, target, screen_work_area, cursor_point, card_type); + anchor_view_bounds, target, screen_work_area, cursor_point, card_type, + application_locale); return PickBestEditorMenuBounds(candidates, screen_work_area, cursor_point); }
diff --git a/chrome/browser/ui/ash/editor_menu/utils/utils.h b/chrome/browser/ui/ash/editor_menu/utils/utils.h index d9fe0b0..18a6f45d 100644 --- a/chrome/browser/ui/ash/editor_menu/utils/utils.h +++ b/chrome/browser/ui/ash/editor_menu/utils/utils.h
@@ -83,6 +83,7 @@ // gfx::Rect GetEditorMenuBounds(const gfx::Rect& anchor_view_bounds, const views::View* target, + const std::string& application_locale, const CardType card_type = CardType::kDefault); } // namespace chromeos::editor_menu
diff --git a/chrome/browser/ui/ash/editor_menu/utils/utils_unittest.cc b/chrome/browser/ui/ash/editor_menu/utils/utils_unittest.cc index 755ad4d7..6b4b381 100644 --- a/chrome/browser/ui/ash/editor_menu/utils/utils_unittest.cc +++ b/chrome/browser/ui/ash/editor_menu/utils/utils_unittest.cc
@@ -4,6 +4,11 @@ #include "utils.h" +#include <string> + +#include "chrome/browser/global_features.h" +#include "chrome/test/base/testing_browser_process.h" +#include "components/application_locale_storage/application_locale_storage.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/display/test/test_screen.h" @@ -287,9 +292,13 @@ TEST_P(GetEditorMenuBoundsTest, Verify) { test_screen_.set_cursor_screen_point(GetParam().cursor_point); + const std::string& locale = TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage() + ->Get(); const gfx::Rect editor_menu_bounds = chromeos::editor_menu::GetEditorMenuBounds(GetParam().anchor_view_bounds, - target_.get()); + target_.get(), locale); EXPECT_EQ(editor_menu_bounds.x(), GetParam().editor_menu_bounds.x()); EXPECT_EQ(editor_menu_bounds.y(), GetParam().editor_menu_bounds.y());
diff --git a/chrome/browser/ui/ash/google_one/google_one_offer_iph_tab_helper_constants.h b/chrome/browser/ui/ash/google_one/google_one_offer_iph_tab_helper_constants.h index 7608a9a2..119b20172 100644 --- a/chrome/browser/ui/ash/google_one/google_one_offer_iph_tab_helper_constants.h +++ b/chrome/browser/ui/ash/google_one/google_one_offer_iph_tab_helper_constants.h
@@ -7,12 +7,13 @@ // Fallback texts are used if params are not provided, e.g. IPH demo mode. We // won't expect that those fallback texts are used in prod. -constexpr char kFallbackNotificationDisplaySource[] = "ChromeOS Perks"; -constexpr char kFallbackNotificationTitle[] = "Get 100 GB of cloud storage"; -constexpr char kFallbackNotificationMessage[] = +inline constexpr char kFallbackNotificationDisplaySource[] = "ChromeOS Perks"; +inline constexpr char kFallbackNotificationTitle[] = + "Get 100 GB of cloud storage"; +inline constexpr char kFallbackNotificationMessage[] = "Keep your files & photos backed up with 12 months of Google One at no " "charge"; -constexpr char kFallbackGetPerkButtonTitle[] = "Claim now"; +inline constexpr char kFallbackGetPerkButtonTitle[] = "Claim now"; inline constexpr char kIPHGoogleOneOfferNotificationId[] = "iph-google-one-offer-notification-id"; @@ -31,13 +32,13 @@ "google_one_offer_iph_notification_get_perk"; // IPH Feature Param names -constexpr char kNotificationDisplaySourceParamName[] = +inline constexpr char kNotificationDisplaySourceParamName[] = "x_google-one-offer-notification-display-source"; -constexpr char kNotificationTitleParamName[] = +inline constexpr char kNotificationTitleParamName[] = "x_google-one-offer-notification-title"; -constexpr char kNotificationMessageParamName[] = +inline constexpr char kNotificationMessageParamName[] = "x_google-one-offer-notification-message"; -constexpr char kGetPerkButtonTitleParamName[] = +inline constexpr char kGetPerkButtonTitleParamName[] = "x_google-one-offer-get-perk-title"; #endif // CHROME_BROWSER_UI_ASH_GOOGLE_ONE_GOOGLE_ONE_OFFER_IPH_TAB_HELPER_CONSTANTS_H_
diff --git a/chrome/browser/ui/ash/input_method/candidate_window_constants.h b/chrome/browser/ui/ash/input_method/candidate_window_constants.h index 689b7cf..1675759 100644 --- a/chrome/browser/ui/ash/input_method/candidate_window_constants.h +++ b/chrome/browser/ui/ash/input_method/candidate_window_constants.h
@@ -13,7 +13,7 @@ const int kFontSizeDelta = 2; // Currently the infolist window only supports Japanese font. -const char kJapaneseFontName[] = "Noto Sans CJK JP"; +inline constexpr char kJapaneseFontName[] = "Noto Sans CJK JP"; // The minimum width of candidate labels in the vertical candidate // window. We use this value to prevent the candidate window from being
diff --git a/chrome/browser/ui/ash/input_method/completion_suggestion_view.h b/chrome/browser/ui/ash/input_method/completion_suggestion_view.h index 5979527..f73d56aa 100644 --- a/chrome/browser/ui/ash/input_method/completion_suggestion_view.h +++ b/chrome/browser/ui/ash/input_method/completion_suggestion_view.h
@@ -27,7 +27,7 @@ class CompletionSuggestionLabelView; // Font-related constants -constexpr char kFontStyle[] = "Roboto"; +inline constexpr char kFontStyle[] = "Roboto"; constexpr int kAnnotationFontSize = 10; constexpr int kIndexFontSize = 10; @@ -38,7 +38,7 @@ constexpr int kAnnotationPaddingLeft = 12; constexpr int kAnnotationPaddingBottom = 16; constexpr int kAnnotationPaddingTop = 6; -constexpr char kTabKey[] = "tab"; +inline constexpr char kTabKey[] = "tab"; constexpr cros_styles::ColorName kButtonHighlightColor = cros_styles::ColorName::kRippleColor;
diff --git a/chrome/browser/ui/ash/magic_boost/BUILD.gn b/chrome/browser/ui/ash/magic_boost/BUILD.gn index a151970..9310fb9 100644 --- a/chrome/browser/ui/ash/magic_boost/BUILD.gn +++ b/chrome/browser/ui/ash/magic_boost/BUILD.gn
@@ -19,6 +19,8 @@ deps = [ ":magic_boost_constants", "//base", + "//chrome/browser:browser_process", + "//chrome/browser:global_features", "//chrome/browser/ash/magic_boost", "//chrome/browser/resources:component_extension_resources", "//chrome/browser/ui/ash/editor_menu:utils", @@ -28,6 +30,7 @@ "//chromeos/crosapi/mojom", "//chromeos/strings:strings_grit", "//chromeos/ui/vector_icons", + "//components/application_locale_storage", "//ui/color", "//ui/display", "//ui/gfx",
diff --git a/chrome/browser/ui/ash/magic_boost/DEPS b/chrome/browser/ui/ash/magic_boost/DEPS index 651e79c..a0d9abb1 100644 --- a/chrome/browser/ui/ash/magic_boost/DEPS +++ b/chrome/browser/ui/ash/magic_boost/DEPS
@@ -6,7 +6,16 @@ ] specific_include_rules = { + # TODO(crbug.com/416170323): Remove browser_process dependency. + "magic_boost_opt_in_card\\.cc": [ + "+chrome/browser/browser_process.h", + "+chrome/browser/global_features.h", + ], + "magic_boost_card_controller_unittest.cc": [ "+ash/system/mahi", ], + ".*unittest\\.cc": [ + "+chrome/browser/global_features.h", + ], }
diff --git a/chrome/browser/ui/ash/magic_boost/magic_boost_card_controller_unittest.cc b/chrome/browser/ui/ash/magic_boost/magic_boost_card_controller_unittest.cc index 500313e8..ed7c6772 100644 --- a/chrome/browser/ui/ash/magic_boost/magic_boost_card_controller_unittest.cc +++ b/chrome/browser/ui/ash/magic_boost/magic_boost_card_controller_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/ash/magic_boost/magic_boost_card_controller.h" #include <memory> +#include <string> #include "ash/system/mahi/test/mock_mahi_media_app_events_proxy.h" #include "base/test/metrics/histogram_tester.h" @@ -12,13 +13,16 @@ #include "chrome/browser/ash/magic_boost/magic_boost_state_ash.h" #include "chrome/browser/ash/magic_boost/mock_editor_panel_manager.h" #include "chrome/browser/ash/magic_boost/mock_magic_boost_state.h" +#include "chrome/browser/global_features.h" #include "chrome/browser/ui/ash/magic_boost/magic_boost_metrics.h" #include "chrome/browser/ui/ash/magic_boost/magic_boost_opt_in_card.h" #include "chrome/browser/ui/ash/magic_boost/test/mock_magic_boost_controller_crosapi.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/views/chrome_views_test_base.h" #include "chromeos/components/magic_boost/public/cpp/magic_boost_state.h" #include "chromeos/components/mahi/public/cpp/mahi_media_app_events_proxy.h" #include "chromeos/constants/chromeos_features.h" +#include "components/application_locale_storage/application_locale_storage.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "testing/gmock/include/gmock/gmock.h" @@ -27,6 +31,15 @@ namespace chromeos { +namespace { +const std::string& GetApplicationLocale() { + return TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage() + ->Get(); +} +} // namespace + using OptInFeatures = crosapi::mojom::MagicBoostController::OptInFeatures; class MagicBoostCardControllerTest : public ChromeViewsTestBase { @@ -117,17 +130,19 @@ EXPECT_TRUE(widget); // Correct bounds should be set. - EXPECT_EQ(editor_menu::GetEditorMenuBounds(anchor_bounds, - widget->GetContentsView()), - widget->GetRestoredBounds()); + EXPECT_EQ( + editor_menu::GetEditorMenuBounds(anchor_bounds, widget->GetContentsView(), + GetApplicationLocale()), + widget->GetRestoredBounds()); anchor_bounds = gfx::Rect(0, 50, 55, 80); // Widget should change bounds accordingly. card_controller_.OnAnchorBoundsChanged(anchor_bounds); - EXPECT_EQ(editor_menu::GetEditorMenuBounds(anchor_bounds, - widget->GetContentsView()), - widget->GetRestoredBounds()); + EXPECT_EQ( + editor_menu::GetEditorMenuBounds(anchor_bounds, widget->GetContentsView(), + GetApplicationLocale()), + widget->GetRestoredBounds()); } TEST_F(MagicBoostCardControllerTest, DisclaimerUi) {
diff --git a/chrome/browser/ui/ash/magic_boost/magic_boost_opt_in_card.cc b/chrome/browser/ui/ash/magic_boost/magic_boost_opt_in_card.cc index 46d9385..b7173ed4 100644 --- a/chrome/browser/ui/ash/magic_boost/magic_boost_opt_in_card.cc +++ b/chrome/browser/ui/ash/magic_boost/magic_boost_opt_in_card.cc
@@ -6,6 +6,8 @@ #include <string> +#include "chrome/browser/browser_process.h" +#include "chrome/browser/global_features.h" #include "chrome/browser/ui/ash/editor_menu/utils/utils.h" #include "chrome/browser/ui/ash/magic_boost/magic_boost_card_controller.h" #include "chrome/browser/ui/ash/magic_boost/magic_boost_constants.h" @@ -14,6 +16,7 @@ #include "chromeos/crosapi/mojom/magic_boost.mojom.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "chromeos/ui/vector_icons/vector_icons.h" +#include "components/application_locale_storage/application_locale_storage.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/compositor/layer.h" @@ -251,9 +254,13 @@ void MagicBoostOptInCard::UpdateWidgetBounds( const gfx::Rect& anchor_view_bounds) { + // TODO(crbug.com/416170323): Remove g_browser_process usage. + const std::string& app_locale = + g_browser_process->GetFeatures()->application_locale_storage()->Get(); + // TODO(b/318733414): Move `GetEditorMenuBounds` to a common place to use. GetWidget()->SetBounds( - editor_menu::GetEditorMenuBounds(anchor_view_bounds, this)); + editor_menu::GetEditorMenuBounds(anchor_view_bounds, this, app_locale)); } void MagicBoostOptInCard::RequestFocus() {
diff --git a/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.cc b/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.cc index 1db02085..5a9d1d7 100644 --- a/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.cc +++ b/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.cc
@@ -49,7 +49,8 @@ if (chromeos::features::IsOrcaEnabled() || ash::features::IsLobsterEnabled()) { editor_menu_controller_ = - std::make_unique<editor_menu::EditorMenuControllerImpl>(); + std::make_unique<editor_menu::EditorMenuControllerImpl>( + application_locale_storage); } if (chromeos::features::IsMahiEnabled()) {
diff --git a/chrome/browser/ui/ash/wallpaper/wallpaper_controller_client_impl.cc b/chrome/browser/ui/ash/wallpaper/wallpaper_controller_client_impl.cc index bf8ac9e2..06b8841 100644 --- a/chrome/browser/ui/ash/wallpaper/wallpaper_controller_client_impl.cc +++ b/chrome/browser/ui/ash/wallpaper/wallpaper_controller_client_impl.cc
@@ -53,10 +53,10 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chromeos/ash/components/cryptohome/system_salt_getter.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ui/base/window_properties.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/pref_service.h" #include "components/services/app_service/public/cpp/app_launch_util.h" #include "components/session_manager/core/session_manager.h"
diff --git a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc index c828360..941ff22 100644 --- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc +++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
@@ -31,6 +31,7 @@ #include "components/autofill/core/browser/data_model/payments/autofill_offer_data.h" #include "components/autofill/core/browser/data_model/payments/bnpl_issuer.h" #include "components/autofill/core/browser/data_model/payments/credit_card.h" +#include "components/autofill/core/browser/data_model/valuables/loyalty_card.h" #include "components/autofill/core/browser/integrators/touch_to_fill/touch_to_fill_delegate.h" #include "components/autofill/core/browser/metrics/payments/risk_data_metrics.h" #include "components/autofill/core/browser/payments/autofill_error_dialog_context.h" @@ -901,6 +902,19 @@ #endif } +bool ChromePaymentsAutofillClient::ShowTouchToFillLoyaltyCard( + base::WeakPtr<TouchToFillDelegate> delegate, + base::span<const autofill::LoyaltyCard> loyalty_cards_to_suggest) { +#if BUILDFLAG(IS_ANDROID) + return touch_to_fill_payment_method_controller_.ShowLoyaltyCards( + std::make_unique<TouchToFillPaymentMethodViewImpl>(web_contents()), + delegate, std::move(loyalty_cards_to_suggest)); +#else + // Touch To Fill is not supported on Desktop. + NOTREACHED(); +#endif +} + void ChromePaymentsAutofillClient::HideTouchToFillPaymentMethod() { #if BUILDFLAG(IS_ANDROID) touch_to_fill_payment_method_controller_.Hide();
diff --git a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h index a0fb40f..fcc7ec3 100644 --- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h +++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.h
@@ -199,6 +199,9 @@ bool ShowTouchToFillIban( base::WeakPtr<TouchToFillDelegate> delegate, base::span<const autofill::Iban> ibans_to_suggest) override; + bool ShowTouchToFillLoyaltyCard(base::WeakPtr<TouchToFillDelegate> delegate, + base::span<const autofill::LoyaltyCard> + loyalty_cards_to_suggest) override; void HideTouchToFillPaymentMethod() override; std::unique_ptr<webauthn::InternalAuthenticator> CreateCreditCardInternalAuthenticator(AutofillDriver* driver) override;
diff --git a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h index 2c02b7e..c35c5387 100644 --- a/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h +++ b/chrome/browser/ui/blocked_content/tab_under_navigation_throttle.h
@@ -14,7 +14,7 @@ class NavigationHandle; } -constexpr char kBlockTabUnderFormatMessage[] = +inline constexpr char kBlockTabUnderFormatMessage[] = "Chrome stopped this site from navigating to %s, see " "https://www.chromestatus.com/feature/5675755719622656 for more details.";
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 1dbef7a2..25216a4 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -299,6 +299,13 @@ #include "ui/ozone/public/platform_session_manager.h" #endif +#if BUILDFLAG(ENABLE_GLIC) +#include "chrome/browser/ai/ai_data_keyed_service.h" // nogncheck +#include "chrome/browser/ai/ai_data_keyed_service_factory.h" // nogncheck +#include "chrome/browser/glic/glic_enabling.h" +#include "chrome/browser/glic/glic_keyed_service.h" +#endif + using base::UserMetricsAction; using content::NavigationController; using content::NavigationEntry; @@ -451,6 +458,26 @@ : &AlwaysReturnFalse; } +bool IsActorCoordinatorActingOnTab(Profile* profile, + const content::WebContents* tab) { +#if BUILDFLAG(ENABLE_GLIC) + if (glic::GlicEnabling::IsEnabledByFlags()) { + if (const auto* glic_service = glic::GlicKeyedService::Get(profile); + glic_service && glic_service->IsActorCoordinatorActingOnTab(tab)) { + return true; + } + } + // TODO(https://crbug.com/411462297): Deduplicate ownership of + // ActorCoordinators. + if (const auto* ai_data_service = + AiDataKeyedServiceFactory::GetAiDataKeyedService(profile); + ai_data_service && ai_data_service->IsActorCoordinatorActingOnTab(tab)) { + return true; + } +#endif + return false; +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -2330,10 +2357,18 @@ const GURL& opener_url, const std::string& frame_name, const GURL& target_url) { - return window_container_type == - content::mojom::WindowContainerType::BACKGROUND && - ShouldCreateBackgroundContents(source_site_instance, opener_url, - frame_name); + if (IsActorCoordinatorActingOnTab( + profile(), content::WebContents::FromRenderFrameHost(opener))) { + // If an ActorCoordinator is acting on the opener, prevent it from creating + // a new WebContents. We'll instead force the navigation to happen in the + // same tab. + return true; + } + + return (window_container_type == + content::mojom::WindowContainerType::BACKGROUND && + ShouldCreateBackgroundContents(source_site_instance, opener_url, + frame_name)); } WebContents* Browser::CreateCustomWebContents( @@ -2345,6 +2380,23 @@ const GURL& target_url, const content::StoragePartitionConfig& partition_config, content::SessionStorageNamespace* session_storage_namespace) { + if (auto* opener_contents = content::WebContents::FromRenderFrameHost(opener); + IsActorCoordinatorActingOnTab(profile(), opener_contents)) { + // If an ActorCoordinator is acting on the opener, we force the navigation + // to happen in the same tab. + content::NavigationController::LoadURLParams params(target_url); + params.initiator_frame_token = opener->GetFrameToken(); + params.initiator_process_id = opener->GetProcess()->GetDeprecatedID(); + params.initiator_origin = opener->GetLastCommittedOrigin(); + params.source_site_instance = source_site_instance; + params.transition_type = ui::PAGE_TRANSITION_LINK; + params.is_renderer_initiated = true; + opener_contents->GetController().LoadURLWithParams(params); + VLOG(1) << "Actor treated window open as same tab navigation. " + << target_url; + return nullptr; + } + BackgroundContents* background_contents = CreateBackgroundContents( source_site_instance, opener, opener_url, is_new_browsing_instance, frame_name, target_url, partition_config, session_storage_namespace);
diff --git a/chrome/browser/ui/browser_window/browser_window_features.cc b/chrome/browser/ui/browser_window/browser_window_features.cc index 2d59c0c..587bdd0 100644 --- a/chrome/browser/ui/browser_window/browser_window_features.cc +++ b/chrome/browser/ui/browser_window/browser_window_features.cc
@@ -40,7 +40,6 @@ #include "chrome/browser/ui/toolbar/chrome_labs/chrome_labs_utils.h" #include "chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.h" #include "chrome/browser/ui/ui_features.h" -#include "chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h" #include "chrome/browser/ui/views/download/bubble/download_toolbar_ui_controller.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/tab_strip_region_view.h" @@ -239,15 +238,6 @@ base::FeatureList::IsEnabled(toast_features::kToastFramework)) { toast_service_ = std::make_unique<ToastService>(browser); } - - collaboration::CollaborationService* service = - collaboration::CollaborationServiceFactory::GetForProfile( - browser->profile()); - if (service && service->GetServiceStatus().IsAllowedToJoin() && - tab_groups::IsTabGroupSyncServiceDesktopMigrationEnabled()) { - data_sharing_open_group_helper_ = - std::make_unique<DataSharingOpenGroupHelper>(browser); - } } void BrowserWindowFeatures::InitPostBrowserViewConstruction(
diff --git a/chrome/browser/ui/browser_window/public/browser_window_features.h b/chrome/browser/ui/browser_window/public/browser_window_features.h index ad185c6..6fa6100 100644 --- a/chrome/browser/ui/browser_window/public/browser_window_features.h +++ b/chrome/browser/ui/browser_window/public/browser_window_features.h
@@ -32,7 +32,6 @@ class TranslateBubbleController; class ToastController; class ToastService; -class DataSharingOpenGroupHelper; class DownloadToolbarUIController; #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) @@ -197,10 +196,6 @@ return extension_side_panel_manager_.get(); } - DataSharingOpenGroupHelper* data_sharing_open_group_helper() { - return data_sharing_open_group_helper_.get(); - } - DownloadToolbarUIController* download_toolbar_ui_controller() { return download_toolbar_ui_controller_.get(); } @@ -286,8 +281,6 @@ std::unique_ptr<extensions::ExtensionSidePanelManager> extension_side_panel_manager_; - std::unique_ptr<DataSharingOpenGroupHelper> data_sharing_open_group_helper_; - std::unique_ptr<media_router::CastBrowserController> cast_browser_controller_; std::unique_ptr<DownloadToolbarUIController> download_toolbar_ui_controller_;
diff --git a/chrome/browser/ui/color/BUILD.gn b/chrome/browser/ui/color/BUILD.gn index 77c7485..29c3daf 100644 --- a/chrome/browser/ui/color/BUILD.gn +++ b/chrome/browser/ui/color/BUILD.gn
@@ -125,7 +125,6 @@ if (is_chromeos) { deps += [ "//chrome/services/sharing/nearby", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", ] }
diff --git a/chrome/browser/ui/global_media_controls/media_item_ui_metrics.h b/chrome/browser/ui/global_media_controls/media_item_ui_metrics.h index d0fa3da..76bafc3 100644 --- a/chrome/browser/ui/global_media_controls/media_item_ui_metrics.h +++ b/chrome/browser/ui/global_media_controls/media_item_ui_metrics.h
@@ -10,11 +10,12 @@ namespace { -const char kStartCastingModeHistogramName[] = +inline constexpr char kStartCastingModeHistogramName[] = "Media.GlobalMediaControls.MediaCastMode.Start"; -const char kStopCastingModeHistogramName[] = +inline constexpr char kStopCastingModeHistogramName[] = "Media.GlobalMediaControls.MediaCastMode.Stop"; -const char kCastStartStopHistogramName[] = "Media.Notification.Cast.StartStop"; +inline constexpr char kCastStartStopHistogramName[] = + "Media.Notification.Cast.StartStop"; // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused.
diff --git a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc b/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc index 6c10e622..3885564 100644 --- a/chrome/browser/ui/lens/lens_overlay_controller_browsertest.cc +++ b/chrome/browser/ui/lens/lens_overlay_controller_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 "base/test/bind.h" -#include "components/optimization_guide/content/browser/page_context_eligibility.h" -#include "components/optimization_guide/content/browser/page_context_eligibility_api.h" #ifdef UNSAFE_BUFFERS_BUILD // TODO(crbug.com/390223051): Remove C-library calls to fix the errors. #pragma allow_unsafe_libc_calls @@ -14,6 +11,8 @@ // web browser, but allow for inspection and modification of internal state of // LensOverlayController and other business-logic classes. +#include "chrome/browser/ui/lens/lens_overlay_controller.h" + #include <memory> #include "base/base64url.h" @@ -22,6 +21,7 @@ #include "base/memory/raw_ptr_exclusion.h" #include "base/path_service.h" #include "base/strings/string_util.h" +#include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/protobuf_matchers.h" @@ -61,7 +61,6 @@ #include "chrome/browser/ui/hats/hats_service_factory.h" #include "chrome/browser/ui/hats/mock_hats_service.h" #include "chrome/browser/ui/lens/lens_overlay_colors.h" -#include "chrome/browser/ui/lens/lens_overlay_controller.h" #include "chrome/browser/ui/lens/lens_overlay_entry_point_controller.h" #include "chrome/browser/ui/lens/lens_overlay_gen204_controller.h" #include "chrome/browser/ui/lens/lens_overlay_query_controller.h" @@ -86,6 +85,7 @@ #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h" #include "chrome/browser/ui/views/side_panel/side_panel_entry_id.h" #include "chrome/browser/ui/views/side_panel/side_panel_util.h" +#include "chrome/browser/ui/webui/feedback/feedback_dialog.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/api/pdf_viewer_private.h" #include "chrome/test/base/in_process_browser_test.h" @@ -101,6 +101,8 @@ #include "components/lens/lens_overlay_side_panel_menu_option.h" #include "components/lens/lens_overlay_side_panel_result.h" #include "components/lens/proto/server/lens_overlay_response.pb.h" +#include "components/optimization_guide/content/browser/page_context_eligibility.h" +#include "components/optimization_guide/content/browser/page_context_eligibility_api.h" #include "components/permissions/test/permission_request_observer.h" #include "components/prefs/pref_service.h" #include "components/sessions/content/session_tab_helper.h" @@ -5171,6 +5173,45 @@ EXPECT_EQ(0u, observer.dispatched_events().size()); } +IN_PROC_BROWSER_TEST_F(LensOverlayControllerBrowserTest, + FeedbackRequestedOpensFeedbackUI) { + WaitForPaint(); + + // State should start in off. + auto* controller = GetLensOverlayController(); + ASSERT_EQ(controller->state(), State::kOff); + + // Showing UI should change the state to screenshot and eventually to overlay. + OpenLensOverlay(LensOverlayInvocationSource::kAppMenu); + ASSERT_EQ(controller->state(), State::kScreenshot); + ASSERT_TRUE(base::test::RunUntil( + [&]() { return controller->state() == State::kOverlay; })); + ASSERT_TRUE(content::WaitForLoadStop(GetOverlayWebContents())); + + // Open the side panel. + controller->OpenSidePanelForTesting(); + ASSERT_TRUE(content::WaitForLoadStop( + controller->GetSidePanelWebContentsForTesting())); + + // Get the coordinator. + auto* coordinator = controller->results_side_panel_coordinator(); + ASSERT_TRUE(coordinator); + + base::HistogramTester histogram_tester; + + ASSERT_FALSE(FeedbackDialog::GetInstanceForTest()); + coordinator->RequestSendFeedback(); + +// ChromeOS opens its own feedback dialog. +#if !BUILDFLAG(IS_CHROMEOS) + // Wait for the feedback dialog to appear instead of a new tab. + ASSERT_TRUE(base::test::RunUntil( + []() { return FeedbackDialog::GetInstanceForTest() != nullptr; })); +#endif // !BUILDFLAG(IS_CHROMEOS) + + histogram_tester.ExpectTotalCount("Feedback.RequestSource", 1); +} + class LensOverlayControllerBrowserStartQueryFlowOptimization : public LensOverlayControllerBrowserTest { protected:
diff --git a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc index ae6cc5b..e8827807 100644 --- a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc +++ b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.cc
@@ -409,6 +409,10 @@ GetLensOverlayController()->GetIsContextualSearchbox(std::move(callback)); } +void LensOverlaySidePanelCoordinator::RequestSendFeedback() { + GetLensOverlayController()->FeedbackRequestedByEvent(ui::EF_NONE); +} + void LensOverlaySidePanelCoordinator::OnScrollToMessage( const std::vector<std::string>& text_fragments, uint32_t pdf_page_number) {
diff --git a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h index 4bb495c5..6dcb705f 100644 --- a/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h +++ b/chrome/browser/ui/lens/lens_overlay_side_panel_coordinator.h
@@ -152,7 +152,8 @@ void GetIsContextualSearchbox( GetIsContextualSearchboxCallback callback) override; void OnScrollToMessage(const std::vector<std::string>& text_fragments, - uint32_t pdf_page_number) override; + uint32_t pdf_page_number) override; + void RequestSendFeedback() override; // This method is used to set up communication between this instance and the // side panel WebUI. This is called by the WebUIController when the WebUI is
diff --git a/chrome/browser/ui/safety_hub/notification_permission_review_service.h b/chrome/browser/ui/safety_hub/notification_permission_review_service.h index fb07a027..a027ee2 100644 --- a/chrome/browser/ui/safety_hub/notification_permission_review_service.h +++ b/chrome/browser/ui/safety_hub/notification_permission_review_service.h
@@ -18,8 +18,9 @@ #include "components/keyed_service/core/keyed_service.h" #include "components/site_engagement/content/site_engagement_service.h" -constexpr char kSafetyHubNotificationInfoString[] = "notificationInfoString"; -constexpr char kSafetyHubNotificationPermissionsResultKey[] = +inline constexpr char kSafetyHubNotificationInfoString[] = + "notificationInfoString"; +inline constexpr char kSafetyHubNotificationPermissionsResultKey[] = "notificationPermissions"; struct NotificationPermissions {
diff --git a/chrome/browser/ui/safety_hub/revoked_permissions_service.h b/chrome/browser/ui/safety_hub/revoked_permissions_service.h index 63eba06..f563a05 100644 --- a/chrome/browser/ui/safety_hub/revoked_permissions_service.h +++ b/chrome/browser/ui/safety_hub/revoked_permissions_service.h
@@ -36,7 +36,7 @@ class PrefChangeRegistrar; class PrefService; -constexpr char kRevokedPermissionsResultKey[] = "permissions"; +inline constexpr char kRevokedPermissionsResultKey[] = "permissions"; namespace url { class Origin;
diff --git a/chrome/browser/ui/safety_hub/safety_hub_service.h b/chrome/browser/ui/safety_hub/safety_hub_service.h index 64dd43a..caf19912 100644 --- a/chrome/browser/ui/safety_hub/safety_hub_service.h +++ b/chrome/browser/ui/safety_hub/safety_hub_service.h
@@ -19,8 +19,8 @@ #include "base/values.h" #include "components/keyed_service/core/keyed_service.h" -constexpr char kSafetyHubTimestampResultKey[] = "timestamp"; -constexpr char kSafetyHubOriginKey[] = "origin"; +inline constexpr char kSafetyHubTimestampResultKey[] = "timestamp"; +inline constexpr char kSafetyHubOriginKey[] = "origin"; // Base class for Safety Hub services. The background and UI tasks of the // derived classes will be executed periodically, according to the time delta
diff --git a/chrome/browser/ui/tabs/tab_strip_api/BUILD.gn b/chrome/browser/ui/tabs/tab_strip_api/BUILD.gn index 6fcd7bd1..b346f7d 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/BUILD.gn +++ b/chrome/browser/ui/tabs/tab_strip_api/BUILD.gn
@@ -91,3 +91,22 @@ "//testing/gtest", ] } + +source_set("browser_tests") { + testonly = true + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + sources = [ "tab_strip_service_impl_browsertest.cc" ] + + deps = [ + ":impl", + ":tab_strip_api", + "//base", + "//base/test:test_support", + "//chrome/browser/ui:ui_features", + "//chrome/browser/ui/browser_window:browser_window", + "//chrome/browser/ui/tabs:tab_strip", + "//chrome/test:test_support", + "//content/test:test_support", + "//testing/gtest", + ] +}
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 646370d..d83db22 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
@@ -86,14 +86,13 @@ return; } - std::vector<tabs_api::mojom::PositionPtr> positions; - for (const auto& content : insert_change.contents) { - auto pos = tabs_api::mojom::Position::New(); - pos->index = content.index; - positions.emplace_back(std::move(pos)); - } - for (auto& observer : observers_) { + std::vector<tabs_api::mojom::PositionPtr> positions; + for (const auto& content : insert_change.contents) { + auto pos = tabs_api::mojom::Position::New(); + pos->index = content.index; + positions.emplace_back(std::move(pos)); + } observer.OnTabsCreated(std::move(positions)); } }
diff --git a/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl_browsertest.cc b/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl_browsertest.cc new file mode 100644 index 0000000..d3c34e3 --- /dev/null +++ b/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl_browsertest.cc
@@ -0,0 +1,138 @@ +// 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/tab_strip_service_impl.h" + +#include "base/logging.h" +#include "base/run_loop.h" +#include "base/test/bind.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/browser_window/public/browser_window_interface.h" +#include "chrome/browser/ui/tabs/tab_strip_api/tab_strip_api.mojom.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/ui_features.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "mojo/public/mojom/base/error.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +using testing::_; + +class MockTabsObserver : public tabs_api::mojom::TabsObserver { + public: + MockTabsObserver() = default; + ~MockTabsObserver() override = default; + + MOCK_METHOD(void, + OnTabsCreated, + (std::vector<tabs_api::mojom::PositionPtr> positions), + (override)); +}; + +class TabStripServiceImplBrowserTest : public InProcessBrowserTest { + public: + TabStripServiceImplBrowserTest() { + feature_list_.InitAndEnableFeature(features::kTabStripBrowserApi); + } + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + tab_strip_service_impl_ = std::make_unique<TabStripServiceImpl>( + browser(), browser()->tab_strip_model()); + } + + void TearDownOnMainThread() override { + tab_strip_service_impl_.reset(); + InProcessBrowserTest::TearDownOnMainThread(); + } + + void CreateTabAtApiCallback( + base::RunLoop* run_loop, + base::expected<bool, mojo_base::mojom::ErrorPtr>* out_result, + base::expected<bool, mojo_base::mojom::ErrorPtr> result) { + *out_result = std::move(result); + if (run_loop) { + run_loop->Quit(); + } + } + + protected: + TabStripModel* GetTabStripModel() { return browser()->tab_strip_model(); } + + tabs_api::mojom::PositionPtr CreatePosition(int index) { + auto position = tabs_api::mojom::Position::New(); + position->index = index; + return position; + } + + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<TabStripServiceImpl> tab_strip_service_impl_; +}; + +IN_PROC_BROWSER_TEST_F(TabStripServiceImplBrowserTest, CreateTabAt) { + TabStripModel* model = GetTabStripModel(); + const int expected_tab_count = model->count() + 1; + const GURL url("http://example.com/"); + + base::expected<bool, mojo_base::mojom::ErrorPtr> result; + base::RunLoop run_loop; + tabs_api::mojom::PositionPtr position = CreatePosition(0); + + tab_strip_service_impl_->CreateTabAt( + std::move(position), std::make_optional(url), + base::BindOnce(&TabStripServiceImplBrowserTest::CreateTabAtApiCallback, + base::Unretained(this), &run_loop, &result)); + run_loop.Run(); + + ASSERT_TRUE(result.has_value()) + << "CreateTabAt failed: " << (result.error()->message); + EXPECT_TRUE(result.value()); + EXPECT_EQ(model->count(), expected_tab_count); +} + +IN_PROC_BROWSER_TEST_F(TabStripServiceImplBrowserTest, ObserverOnTabsCreated) { + MockTabsObserver mock_observer; + tab_strip_service_impl_->AddObserver(&mock_observer); + const GURL url("http://example.com/"); + uint32_t target_index = 0; + + EXPECT_CALL( + mock_observer, + OnTabsCreated(testing::Truly( + [&target_index]( + const std::vector<tabs_api::mojom::PositionPtr>& positions) { + if (positions.size() != 1) { + return false; + } + if (!positions[0]) { + return false; + } + return positions[0]->index == target_index; + }))) + .Times(1); + + base::expected<bool, mojo_base::mojom::ErrorPtr> result; + base::RunLoop run_loop; + tabs_api::mojom::PositionPtr position = CreatePosition(target_index); + + tab_strip_service_impl_->CreateTabAt( + std::move(position), std::make_optional(url), + base::BindOnce(&TabStripServiceImplBrowserTest::CreateTabAtApiCallback, + base::Unretained(this), &run_loop, &result)); + run_loop.Run(); + + ASSERT_TRUE(result.has_value()) + << "CreateTabAt failed: " << (result.error()->message); + EXPECT_TRUE(result.value()); + + tab_strip_service_impl_->RemoveObserver(&mock_observer); +}
diff --git a/chrome/browser/ui/toasts/toast_view.cc b/chrome/browser/ui/toasts/toast_view.cc index e94aadd..4c559e3 100644 --- a/chrome/browser/ui/toasts/toast_view.cc +++ b/chrome/browser/ui/toasts/toast_view.cc
@@ -210,6 +210,7 @@ action_button_->GetViewAccessibility().SetRole(ax::mojom::Role::kAlert); action_button_->SetProperty(views::kElementIdentifierKey, kToastActionButton); + action_button_->SetAppearDisabledInInactiveWidget(false); action_button_->SetProperty( views::kMarginsKey, GetLeftMargin(lp->GetDistanceMetric(
diff --git a/chrome/browser/ui/translate/partial_translate_bubble_ui_action_logger.h b/chrome/browser/ui/translate/partial_translate_bubble_ui_action_logger.h index a41f262..d6828fc 100644 --- a/chrome/browser/ui/translate/partial_translate_bubble_ui_action_logger.h +++ b/chrome/browser/ui/translate/partial_translate_bubble_ui_action_logger.h
@@ -9,7 +9,7 @@ // Histogram for recording the UI events related to the Partial Translate // bubble. -constexpr char kPartialTranslateBubbleUiEventHistogramName[] = +inline constexpr char kPartialTranslateBubbleUiEventHistogramName[] = "Translate.PartialTranslateBubbleUiEvent"; enum class PartialTranslateBubbleUiEvent {
diff --git a/chrome/browser/ui/views/chrome_views_export.h b/chrome/browser/ui/views/chrome_views_export.h index c6b92e8f8..e5bd1c1 100644 --- a/chrome/browser/ui/views/chrome_views_export.h +++ b/chrome/browser/ui/views/chrome_views_export.h
@@ -19,11 +19,7 @@ #else // !defined(WIN32) -#if defined(CHROME_VIEWS_IMPLEMENTATION) #define CHROME_VIEWS_EXPORT __attribute__((visibility("default"))) -#else -#define CHROME_VIEWS_EXPORT -#endif #endif // defined(WIN32)
diff --git a/chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.cc b/chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.cc index 2d99db4..2c037d4 100644 --- a/chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.cc +++ b/chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.cc
@@ -321,9 +321,14 @@ std::optional<data_sharing::mojom::GroupActionProgress> progress) { // Joins flow should end when the shared tab group is open after join // or cancel without joining. - // TODO(crbug.org/380287432): Only cancel the flow if user doesn't join the - // group. - std::move(result).Run(CollaborationControllerDelegate::Outcome::kCancel); + CollaborationControllerDelegate::Outcome outcome = + CollaborationControllerDelegate::Outcome::kCancel; + if (action == data_sharing::mojom::GroupAction::kJoinGroup && + progress == data_sharing::mojom::GroupActionProgress::kSuccess) { + outcome = CollaborationControllerDelegate::Outcome::kSuccess; + } + + std::move(result).Run(outcome); } void CollaborationControllerDelegateDesktop::OnManageDialogClosing(
diff --git a/chrome/browser/ui/views/data_sharing/data_sharing_chrome_native_interactive_uitest.cc b/chrome/browser/ui/views/data_sharing/data_sharing_chrome_native_interactive_uitest.cc index 3722601f..f0049b0 100644 --- a/chrome/browser/ui/views/data_sharing/data_sharing_chrome_native_interactive_uitest.cc +++ b/chrome/browser/ui/views/data_sharing/data_sharing_chrome_native_interactive_uitest.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h" #include "chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.h" -#include "chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h" #include "chrome/browser/ui/views/data_sharing/data_sharing_utils.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/tabs/tab_group_header.h" @@ -300,41 +299,4 @@ EXPECT_EQ(url.value().spec(), expected_close_flow_url_with_token); } -IN_PROC_BROWSER_TEST_F(DataSharingChromeNativeUiTest, OpenGroupHelper) { - std::string fake_collab_id = "fake_collab_id"; - tab_groups::LocalTabGroupID local_group_id = InstrumentATabGroup(); - auto* tab_group_service = - tab_groups::SavedTabGroupUtils::GetServiceForProfile( - browser()->profile()); - std::optional<tab_groups::SavedTabGroup> group_copy = - tab_group_service->GetGroup(local_group_id); - - // Mock up a shared group. - group_copy->SetCollaborationId(tab_groups::CollaborationId(fake_collab_id)); - - RunTestSequence( - SaveGroupLeaveEditorBubbleOpen(local_group_id), - WaitForShow(kTabGroupHeaderElementId), - EnsurePresent(kTabGroupEditorBubbleId), - PressButton(kTabGroupEditorBubbleCloseGroupButtonId), - FinishTabstripAnimations(), WaitForHide(kTabGroupHeaderElementId), - Do([=, this]() { - DataSharingOpenGroupHelper* open_group_helper = - browser() - ->browser_window_features() - ->data_sharing_open_group_helper(); - open_group_helper->OpenTabGroupWhenAvailable(fake_collab_id); - EXPECT_TRUE(open_group_helper->group_ids_for_testing().contains( - fake_collab_id)); - - // Mock group sync from remote. - open_group_helper->OnTabGroupAdded(group_copy.value(), - tab_groups::TriggerSource::REMOTE); - EXPECT_FALSE(open_group_helper->group_ids_for_testing().contains( - fake_collab_id)); - }), - // The group is opened into the tab strip. - WaitForShow(kTabGroupHeaderElementId)); -} - } // namespace tab_groups
diff --git a/chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.cc b/chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.cc deleted file mode 100644 index 137b4b22..0000000 --- a/chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.cc +++ /dev/null
@@ -1,66 +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. - -#include "chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h" - -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h" -#include "chrome/browser/ui/tabs/saved_tab_groups/tab_group_action_context_desktop.h" - -DataSharingOpenGroupHelper::DataSharingOpenGroupHelper(Browser* browser) - : browser_(browser) { - tab_group_service_ = - tab_groups::SavedTabGroupUtils::GetServiceForProfile(browser_->profile()); - tab_group_sync_service_observation_.Observe(tab_group_service_); -} - -DataSharingOpenGroupHelper::~DataSharingOpenGroupHelper() = default; - -void DataSharingOpenGroupHelper::OpenTabGroupWhenAvailable( - std::string group_id) { - if (!OpenTabGroupIfSynced(group_id)) { - group_ids_.insert(group_id); - } -} - -void DataSharingOpenGroupHelper::OnTabGroupAdded( - const tab_groups::SavedTabGroup& group, - tab_groups::TriggerSource source) { - if (!group.collaboration_id().has_value()) { - return; - } - - tab_groups::CollaborationId collab_id = group.collaboration_id().value(); - if (source == tab_groups::TriggerSource::REMOTE && - std::find(group_ids_.begin(), group_ids_.end(), collab_id.value()) != - group_ids_.end()) { - group_ids_.erase(collab_id.value()); - tab_group_service_->OpenTabGroup( - group.saved_guid(), - std::make_unique<tab_groups::TabGroupActionContextDesktop>( - browser_, tab_groups::OpeningSource::kAutoOpenedFromSync)); - } -} - -bool DataSharingOpenGroupHelper::OpenTabGroupIfSynced(std::string group_id) { - std::vector<tab_groups::SavedTabGroup> all = - tab_group_service_->GetAllGroups(); - - auto exist = [=](tab_groups::SavedTabGroup group) { - std::optional<tab_groups::CollaborationId> collab_id = - group.collaboration_id(); - return collab_id && collab_id->value() == group_id; - }; - - if (auto it = std::find_if(begin(all), end(all), exist); - it != std::end(all)) { - tab_group_service_->OpenTabGroup( - it->saved_guid(), - std::make_unique<tab_groups::TabGroupActionContextDesktop>( - browser_, tab_groups::OpeningSource::kAutoOpenedFromSync)); - return true; - } else { - return false; - } -}
diff --git a/chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h b/chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h deleted file mode 100644 index 9ec0ce00..0000000 --- a/chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h +++ /dev/null
@@ -1,61 +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. - -#ifndef CHROME_BROWSER_UI_VIEWS_DATA_SHARING_DATA_SHARING_OPEN_GROUP_HELPER_H_ -#define CHROME_BROWSER_UI_VIEWS_DATA_SHARING_DATA_SHARING_OPEN_GROUP_HELPER_H_ - -#include <set> - -#include "base/scoped_observation.h" -#include "components/saved_tab_groups/public/tab_group_sync_service.h" -#include "components/saved_tab_groups/public/types.h" - -class Browser; - -// A helper that opens the shared tab group into browser tab strip. When a user -// tried to join a shared tab group via the share link, opens the group into -// browser direcetly if they are already in the group or wait for the group to -// be synced from remote after they press "Open and Join" on the Join dialog. -class DataSharingOpenGroupHelper - : public tab_groups::TabGroupSyncService::Observer { - public: - explicit DataSharingOpenGroupHelper(Browser* browser); - DataSharingOpenGroupHelper(const DataSharingOpenGroupHelper&) = delete; - DataSharingOpenGroupHelper& operator=(const DataSharingOpenGroupHelper&) = - delete; - ~DataSharingOpenGroupHelper() override; - - // TabGroupSyncService::Observer override. - // Compare `group_ids` against the collaboration_ids synced from remote. If - // they match (meaning the syncs are triggered by the user pressing "Join and - // Open" on the Join dialog) open the tab groups into current window. - void OnTabGroupAdded(const tab_groups::SavedTabGroup& group, - tab_groups::TriggerSource source) override; - - // If group is synced open it otherwise store `group_id` and wait to be synced - // from remote. Called after users press "Open and Join" from the Join dialog. - void OpenTabGroupWhenAvailable(std::string group_id); - - // Open the shared tab group in current window (focus if open) if the group - // the user tries to join from share link is already synced to the local - // client (namely the user is already in the group). Return true if it is the - // case. - bool OpenTabGroupIfSynced(std::string group_id); - - std::set<std::string> group_ids_for_testing() const { return group_ids_; } - - private: - raw_ptr<Browser> browser_; - raw_ptr<tab_groups::TabGroupSyncService> tab_group_service_ = nullptr; - - base::ScopedObservation<tab_groups::TabGroupSyncService, - tab_groups::TabGroupSyncService::Observer> - tab_group_sync_service_observation_{this}; - - // The group_ids passed from the Join webui. They're the same as - // SavedTabGroup::collaboration_id for shared tab groups. - std::set<std::string> group_ids_; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_DATA_SHARING_DATA_SHARING_OPEN_GROUP_HELPER_H_
diff --git a/chrome/browser/ui/views/device_signals_consent/consent_dialog_browsertest.cc b/chrome/browser/ui/views/device_signals_consent/consent_dialog_browsertest.cc index 8ad5cc5..3251fb75 100644 --- a/chrome/browser/ui/views/device_signals_consent/consent_dialog_browsertest.cc +++ b/chrome/browser/ui/views/device_signals_consent/consent_dialog_browsertest.cc
@@ -68,7 +68,13 @@ testing::NiceMock<policy::MockConfigurationPolicyProvider> provider_; }; -IN_PROC_BROWSER_TEST_F(ConsentDialogUiTest, GetConsentDialogBodyTest) { +// TODO(crbug.com/416157468): Enable the test. +#if BUILDFLAG(IS_WIN) +#define MAYBE_GetConsentDialogBodyTest DISABLED_GetConsentDialogBodyTest +#else +#define MAYBE_GetConsentDialogBodyTest GetConsentDialogBodyTest +#endif +IN_PROC_BROWSER_TEST_F(ConsentDialogUiTest, MAYBE_GetConsentDialogBodyTest) { // Simulate a managed profile. AddEnterpriseManagedPolicies(); policy::ScopedManagementServiceOverrideForTesting browser_management(
diff --git a/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h index fb3f826..b6862ad9 100644 --- a/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h
@@ -26,13 +26,13 @@ class ExpandDeviceSelectorLabel; class ExpandDeviceSelectorButton; -const char kAudioDevicesCountHistogramName[] = +inline constexpr char kAudioDevicesCountHistogramName[] = "Media.GlobalMediaControls.NumberOfAvailableAudioDevices"; -const char kCastDeviceCountHistogramName[] = +inline constexpr char kCastDeviceCountHistogramName[] = "Media.GlobalMediaControls.CastDeviceCount"; -const char kDeviceSelectorAvailableHistogramName[] = +inline constexpr char kDeviceSelectorAvailableHistogramName[] = "Media.GlobalMediaControls.DeviceSelectorAvailable"; -const char kDeviceSelectorOpenedHistogramName[] = +inline constexpr char kDeviceSelectorOpenedHistogramName[] = "Media.GlobalMediaControls.DeviceSelectorOpened"; } // anonymous namespace
diff --git a/chrome/browser/ui/views/mahi/BUILD.gn b/chrome/browser/ui/views/mahi/BUILD.gn index a739b338..642f472c 100644 --- a/chrome/browser/ui/views/mahi/BUILD.gn +++ b/chrome/browser/ui/views/mahi/BUILD.gn
@@ -19,6 +19,8 @@ deps = [ "//base", + "//chrome/browser:browser_process", + "//chrome/browser:global_features", "//chrome/browser/ui/ash/editor_menu:utils", "//chrome/browser/ui/ash/magic_boost", "//chrome/browser/ui/ash/magic_boost:magic_boost_constants", @@ -29,6 +31,7 @@ "//chromeos/constants:constants", "//chromeos/strings:strings_grit", "//chromeos/ui/vector_icons", + "//components/application_locale_storage", "//ui/accessibility:ax_base", "//ui/color", "//ui/display",
diff --git a/chrome/browser/ui/views/mahi/DEPS b/chrome/browser/ui/views/mahi/DEPS index 8e2c4cf..27eaf3c2 100644 --- a/chrome/browser/ui/views/mahi/DEPS +++ b/chrome/browser/ui/views/mahi/DEPS
@@ -18,3 +18,15 @@ "+chrome/test", ] + +specific_include_rules = { + # TODO(crbug.com/416170122): Remove browser_process dependency. + "mahi_menu_view\\.cc": [ + "+chrome/browser/browser_process.h", + "+chrome/browser/global_features.h", + ], + + ".*unittest\\.cc": [ + "+chrome/browser/global_features.h", + ], +}
diff --git a/chrome/browser/ui/views/mahi/mahi_menu_controller_unittest.cc b/chrome/browser/ui/views/mahi/mahi_menu_controller_unittest.cc index 03eddfe..3ea6abb 100644 --- a/chrome/browser/ui/views/mahi/mahi_menu_controller_unittest.cc +++ b/chrome/browser/ui/views/mahi/mahi_menu_controller_unittest.cc
@@ -16,15 +16,18 @@ #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/ash/mahi/web_contents/test_support/fake_mahi_web_contents_manager.h" +#include "chrome/browser/global_features.h" #include "chrome/browser/ui/ash/editor_menu/utils/utils.h" #include "chrome/browser/ui/ash/read_write_cards/read_write_cards_ui_controller.h" #include "chrome/browser/ui/views/mahi/mahi_condensed_menu_view.h" #include "chrome/browser/ui/views/mahi/mahi_menu_constants.h" #include "chrome/browser/ui/views/mahi/mahi_menu_view.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/views/chrome_views_test_base.h" #include "chromeos/components/mahi/public/cpp/mahi_media_app_events_proxy.h" #include "chromeos/components/mahi/public/cpp/mahi_web_contents_manager.h" #include "chromeos/constants/chromeos_features.h" +#include "components/application_locale_storage/application_locale_storage.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,6 +36,15 @@ namespace chromeos::mahi { +namespace { +const std::string& GetApplicationLocale() { + return TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage() + ->Get(); +} +} // namespace + using ::testing::IsNull; using ::testing::Mock; using ::testing::NiceMock; @@ -146,6 +158,7 @@ EXPECT_EQ( editor_menu::GetEditorMenuBounds(anchor_bounds, widget->GetContentsView(), + GetApplicationLocale(), editor_menu::CardType::kMahiDefaultMenu), widget->GetRestoredBounds()); @@ -155,6 +168,7 @@ menu_controller()->OnAnchorBoundsChanged(anchor_bounds); EXPECT_EQ( editor_menu::GetEditorMenuBounds(anchor_bounds, widget->GetContentsView(), + GetApplicationLocale(), editor_menu::CardType::kMahiDefaultMenu), widget->GetRestoredBounds()); }
diff --git a/chrome/browser/ui/views/mahi/mahi_menu_view.cc b/chrome/browser/ui/views/mahi/mahi_menu_view.cc index be38770..0beb5f8 100644 --- a/chrome/browser/ui/views/mahi/mahi_menu_view.cc +++ b/chrome/browser/ui/views/mahi/mahi_menu_view.cc
@@ -13,6 +13,8 @@ #include "base/functional/callback_helpers.h" #include "base/metrics/histogram_functions.h" #include "base/notreached.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/global_features.h" #include "chrome/browser/ui/ash/editor_menu/utils/pre_target_handler.h" #include "chrome/browser/ui/ash/editor_menu/utils/pre_target_handler_view.h" #include "chrome/browser/ui/ash/editor_menu/utils/utils.h" @@ -26,6 +28,7 @@ #include "chromeos/components/mahi/public/cpp/mahi_web_contents_manager.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "chromeos/ui/vector_icons/vector_icons.h" +#include "components/application_locale_storage/application_locale_storage.h" #include "components/vector_icons/vector_icons.h" #include "ui/accessibility/ax_enums.mojom-shared.h" #include "ui/accessibility/ax_node_data.h" @@ -375,10 +378,15 @@ } void MahiMenuView::UpdateBounds(const gfx::Rect& anchor_view_bounds) { + // TODO(crbug.com/416170122): Remove g_browser_process usage. + const std::string& app_locale = + g_browser_process->GetFeatures()->application_locale_storage()->Get(); + // TODO(b/318733414): Move `editor_menu::GetEditorMenuBounds` to a common // place for use GetWidget()->SetBounds(editor_menu::GetEditorMenuBounds( - anchor_view_bounds, this, editor_menu::CardType::kMahiDefaultMenu)); + anchor_view_bounds, this, app_locale, + editor_menu::CardType::kMahiDefaultMenu)); } void MahiMenuView::OnWidgetVisibilityChanged(views::Widget* widget,
diff --git a/chrome/browser/ui/views/mahi/mahi_menu_view_unittest.cc b/chrome/browser/ui/views/mahi/mahi_menu_view_unittest.cc index 976d7c6..5a428ba 100644 --- a/chrome/browser/ui/views/mahi/mahi_menu_view_unittest.cc +++ b/chrome/browser/ui/views/mahi/mahi_menu_view_unittest.cc
@@ -11,13 +11,16 @@ #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" #include "chrome/browser/ash/mahi/web_contents/test_support/fake_mahi_web_contents_manager.h" +#include "chrome/browser/global_features.h" #include "chrome/browser/ui/ash/editor_menu/utils/utils.h" #include "chrome/browser/ui/views/mahi/mahi_menu_constants.h" +#include "chrome/test/base/testing_browser_process.h" #include "chrome/test/views/chrome_views_test_base.h" #include "chromeos/components/mahi/public/cpp/mahi_browser_util.h" #include "chromeos/components/mahi/public/cpp/mahi_util.h" #include "chromeos/components/mahi/public/cpp/mahi_web_contents_manager.h" #include "chromeos/strings/grit/chromeos_strings.h" +#include "components/application_locale_storage/application_locale_storage.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" @@ -84,6 +87,13 @@ } } +const std::string& GetApplicationLocale() { + return TestingBrowserProcess::GetGlobal() + ->GetFeatures() + ->application_locale_storage() + ->Get(); +} + } // namespace TEST_F(MahiMenuViewTest, Bounds) { @@ -94,7 +104,8 @@ // The bounds of the created widget should be similar to the value from the // utils function. EXPECT_EQ(editor_menu::GetEditorMenuBounds( - anchor_view_bounds, menu_widget.get()->GetContentsView()), + anchor_view_bounds, menu_widget.get()->GetContentsView(), + GetApplicationLocale()), menu_widget->GetRestoredBounds()); }
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc index 02e209c..fab42a3 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -146,6 +146,58 @@ } } +std::u16string GetSyncPromoDescription(signin_metrics::AccessPoint access_point, + std::string_view email) { + switch (access_point) { + case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPillOnStartup: + case signin_metrics::AccessPoint:: + kHistorySyncOptinExpansionPillOnInactivity: +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + if (base::FeatureList::IsEnabled( + switches::kEnableHistorySyncOptinExpansionPill)) { + switch (switches::kHistorySyncOptinExpansionPillOption.Get()) { + case switches::HistorySyncOptinExpansionPillOption:: + kBrowseAcrossDevices: + return l10n_util::GetStringFUTF16( + IDS_PROFILE_MENU_SYNC_PROMO_BROWSE_ACROSS_DEVICES_DESCRIPTION, + base::UTF8ToUTF16(email)); + case switches::HistorySyncOptinExpansionPillOption::kSyncHistory: + return l10n_util::GetStringFUTF16( + IDS_PROFILE_MENU_SYNC_PROMO_SYNC_HISTORY_DESCRIPTION, + base::UTF8ToUTF16(email)); + case switches::HistorySyncOptinExpansionPillOption:: + kSeeTabsFromOtherDevices: + return l10n_util::GetStringFUTF16( + IDS_PROFILE_MENU_SYNC_PROMO_SEE_TABS_FROM_OTHER_DEVICES_DESCRIPTION, + base::UTF8ToUTF16(email)); + } + } +#endif + [[fallthrough]]; + default: + return l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SYNC_PROMO); + } +} + +std::u16string GetSyncPromoButtonLabel( + signin_metrics::AccessPoint access_point) { + switch (access_point) { + case signin_metrics::AccessPoint::kHistorySyncOptinExpansionPillOnStartup: + case signin_metrics::AccessPoint:: + kHistorySyncOptinExpansionPillOnInactivity: +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + if (base::FeatureList::IsEnabled( + switches::kEnableHistorySyncOptinExpansionPill)) { + return l10n_util::GetStringUTF16( + IDS_PROFILE_MENU_SYNC_PROMO_BUTTON_LABEL); + } +#endif + [[fallthrough]]; + default: + return l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON); + } +} + } // namespace // static @@ -688,9 +740,11 @@ break; } case signin_util::SignedInState::kSignedIn: - params.subtitle = l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SYNC_PROMO); - params.button_text = - l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON); + params.subtitle = GetSyncPromoDescription( + explicit_signin_access_point_.value_or(access_point), + primary_account_info.email); + params.button_text = GetSyncPromoButtonLabel( + explicit_signin_access_point_.value_or(access_point)); signin_metrics::LogSyncOptInOffered( explicit_signin_access_point_.value_or(access_point)); break;
diff --git a/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog_manager.h b/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog_manager.h index 202ec7a..46dbdce 100644 --- a/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog_manager.h +++ b/chrome/browser/ui/views/safe_browsing/tailored_security_desktop_dialog_manager.h
@@ -12,9 +12,9 @@ namespace safe_browsing { // UMA histogram names for the dialogs. -const char kDisabledDialogOutcome[] = +inline constexpr char kDisabledDialogOutcome[] = "SafeBrowsing.TailoredSecurity.ConsentedDesktopDialogDisabledOutcome"; -const char kEnabledDialogOutcome[] = +inline constexpr char kEnabledDialogOutcome[] = "SafeBrowsing.TailoredSecurity.ConsentedDesktopDialogEnabledOutcome"; inline constexpr char kTailoredSecurityNoticeDialog[] =
diff --git a/chrome/browser/ui/views/tabs/groups/avatar_container_view.cc b/chrome/browser/ui/views/tabs/groups/avatar_container_view.cc index ff157d09..be77ce9 100644 --- a/chrome/browser/ui/views/tabs/groups/avatar_container_view.cc +++ b/chrome/browser/ui/views/tabs/groups/avatar_container_view.cc
@@ -207,6 +207,15 @@ ManageSharingAvatarContainer::~ManageSharingAvatarContainer() = default; +void ManageSharingAvatarContainer::OnDeviceScaleFactorChanged( + float old_device_scale_factor, + float new_device_scale_factor) { + views::View::OnDeviceScaleFactorChanged(old_device_scale_factor, + new_device_scale_factor); + RequeryMemberInfo(); + RebuildChildren(); +} + void ManageSharingAvatarContainer::RequeryMemberInfo() { // This action cant be performed if there is no DataSharingService. if (!data_sharing_service_) { @@ -223,17 +232,25 @@ image_fetcher_service->GetImageFetcher( image_fetcher::ImageFetcherConfig::kDiskCacheOnly); + // Attempt to get the exact scaled avatar image, default to a overscaled by 2 + // to support HiDPI displays. + auto image_size = kCircleSize * 2; + if (GetWidget() && GetWidget()->GetCompositor()) { + image_size = + GetWidget()->GetCompositor()->device_scale_factor() * kCircleSize; + } + // If we have up to three members, initiate fetch for each. if (members_for_display_.size() > 0) { data_sharing_service_->GetAvatarImageForURL( - members_for_display_[0].avatar_url, signin::kAccountInfoImageSize, + members_for_display_[0].avatar_url, image_size, base::BindOnce(&ManageSharingAvatarContainer::UpdateMemberGfxImage, weak_ptr_factory_.GetWeakPtr(), 0), image_fetcher); } if (members_for_display_.size() > 1) { data_sharing_service_->GetAvatarImageForURL( - members_for_display_[1].avatar_url, signin::kAccountInfoImageSize, + members_for_display_[1].avatar_url, image_size, base::BindOnce(&ManageSharingAvatarContainer::UpdateMemberGfxImage, weak_ptr_factory_.GetWeakPtr(), 1), image_fetcher); @@ -242,7 +259,7 @@ // we show the overflow. if (members_for_display_.size() == 3) { data_sharing_service_->GetAvatarImageForURL( - members_for_display_[2].avatar_url, signin::kAccountInfoImageSize, + members_for_display_[2].avatar_url, image_size, base::BindOnce(&ManageSharingAvatarContainer::UpdateMemberGfxImage, weak_ptr_factory_.GetWeakPtr(), 2), image_fetcher);
diff --git a/chrome/browser/ui/views/tabs/groups/avatar_container_view.h b/chrome/browser/ui/views/tabs/groups/avatar_container_view.h index 603c671..3ebb667 100644 --- a/chrome/browser/ui/views/tabs/groups/avatar_container_view.h +++ b/chrome/browser/ui/views/tabs/groups/avatar_container_view.h
@@ -35,6 +35,10 @@ void AddedToWidget() override; void OnThemeChanged() override; + protected: + void OnDeviceScaleFactorChanged(float old_device_scale_factor, + float new_device_scale_factor) override; + private: // Callback when data sharing service fetches the avatar. void UpdateMemberGfxImage(size_t index, const gfx::Image&);
diff --git a/chrome/browser/ui/views/tabs/tab_style_views.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc index b7dbd8b..61171ed 100644 --- a/chrome/browser/ui/views/tabs/tab_style_views.cc +++ b/chrome/browser/ui/views/tabs/tab_style_views.cc
@@ -492,7 +492,6 @@ } gfx::Insets TabStyleViewsImpl::GetContentsInsets() const { - const int stroke_thickness = GetStrokeThickness(false); gfx::Insets base_style_insets = tab_style()->GetContentsInsets(); gfx::Insets split_insets = gfx::Insets(0); @@ -509,10 +508,8 @@ split_insets.set_right(total_separator_width / -2); } - return gfx::Insets::TLBR( - stroke_thickness, 0, - stroke_thickness + GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP), - 0) + + return gfx::Insets::TLBR(0, 0, GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP), + 0) + base_style_insets + split_insets; }
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc index c2785d7..44e20b2 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view_unittest.cc
@@ -135,7 +135,8 @@ gfx::Image::CreateFrom1xBitmap(gfx::test::CreateBitmap(1)); idp_data_ = base::MakeRefCounted<content::IdentityProviderData>( kIdpForDisplay, idp_metadata, CreateTestClientMetadata(), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false); accounts_ = {CreateAccount(idp_data_)}; } @@ -850,12 +851,14 @@ base::MakeRefCounted<content::IdentityProviderData>( kIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata(kTermsOfServiceUrl), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false), base::MakeRefCounted<content::IdentityProviderData>( kSecondIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata("https://tos-2.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false)}; std::vector<IdentityRequestAccountPtr> account_list = { CreateTestIdentityRequestAccount(kAccountSuffixes1[0], idp_list[0]), @@ -893,12 +896,14 @@ base::MakeRefCounted<content::IdentityProviderData>( kIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata(kTermsOfServiceUrl), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false), base::MakeRefCounted<content::IdentityProviderData>( kSecondIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata("https://tos-2.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/true)}; std::vector<IdentityRequestAccountPtr> accounts_list = CreateTestIdentityRequestAccounts(kAccountSuffixes1, idp_list[0]); @@ -937,12 +942,14 @@ base::MakeRefCounted<content::IdentityProviderData>( kIdpForDisplay, idp_with_supports_add, CreateTestClientMetadata(kTermsOfServiceUrl), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false), base::MakeRefCounted<content::IdentityProviderData>( kSecondIdpForDisplay, idp_with_supports_add, CreateTestClientMetadata("https://tos-2.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false)}; std::vector<IdentityRequestAccountPtr> accounts_list = { CreateTestIdentityRequestAccount(kAccountSuffixes1[0], idp_list[0]), @@ -978,22 +985,26 @@ idp_list_ = {base::MakeRefCounted<content::IdentityProviderData>( kIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata(kTermsOfServiceUrl), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false), base::MakeRefCounted<content::IdentityProviderData>( kSecondIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata("https://tos-2.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false), base::MakeRefCounted<content::IdentityProviderData>( "idp3.com", content::IdentityProviderMetadata(), CreateTestClientMetadata("https://tos-3.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/true), base::MakeRefCounted<content::IdentityProviderData>( "idp4.com", content::IdentityProviderMetadata(), CreateTestClientMetadata("https://tos-4.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/true)}; accounts_ = { CreateTestIdentityRequestAccount(kAccountSuffixes2[0], idp_list_[1], @@ -1036,12 +1047,14 @@ base::MakeRefCounted<content::IdentityProviderData>( kIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata(kTermsOfServiceUrl), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/true), base::MakeRefCounted<content::IdentityProviderData>( kSecondIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata("https://tos-2.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/true)}; CreateAndShowMultiIdpAccountPicker(std::vector<IdentityRequestAccountPtr>(), idp_list); @@ -1068,12 +1081,14 @@ base::MakeRefCounted<content::IdentityProviderData>( kIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata(kTermsOfServiceUrl), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false), base::MakeRefCounted<content::IdentityProviderData>( kSecondIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata("https://tos-2.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false)}; // The UI code receives the accounts sorted in the order in which they should // be displayed. @@ -1117,12 +1132,14 @@ base::MakeRefCounted<content::IdentityProviderData>( kIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata(kTermsOfServiceUrl), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false), base::MakeRefCounted<content::IdentityProviderData>( kSecondIdpForDisplay, content::IdentityProviderMetadata(), CreateTestClientMetadata("https://tos-2.com"), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false)}; // Note that `new2` is last despite having last_used_timestamp because it is // not considered a returning account.
diff --git a/chrome/browser/ui/views/webid/account_selection_modal_view_browsertest.cc b/chrome/browser/ui/views/webid/account_selection_modal_view_browsertest.cc index fbdb00c..c313f5f 100644 --- a/chrome/browser/ui/views/webid/account_selection_modal_view_browsertest.cc +++ b/chrome/browser/ui/views/webid/account_selection_modal_view_browsertest.cc
@@ -62,6 +62,7 @@ content::IdentityProviderMetadata(), CreateTestClientMetadata(), blink::mojom::RpContext::kSignIn, + /*format=*/std::nullopt, kDefaultDisclosureFields, /*has_login_status_mismatch=*/false)) { test_shared_url_loader_factory_ =
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_browsertest.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_browsertest.cc index de529a5..cb4d7d9 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_browsertest.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_browsertest.cc
@@ -45,7 +45,8 @@ idps_ = {base::MakeRefCounted<content::IdentityProviderData>( "idp-example.com", content::IdentityProviderMetadata(), content::ClientMetadata(GURL(), GURL(), GURL(), gfx::Image()), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false)}; accounts_ = {base::MakeRefCounted<Account>( "id", "display_identifier", "display_name", "email", "name", @@ -316,7 +317,8 @@ idps_ = {base::MakeRefCounted<content::IdentityProviderData>( "idp-example.com", content::IdentityProviderMetadata(), content::ClientMetadata(GURL(), GURL(), GURL(), gfx::Image()), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false)}; accounts_ = {base::MakeRefCounted<Account>( "id", "display_identifier", "display_name", "email", "name",
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc index d57dfde7..5c95ced 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc
@@ -303,8 +303,8 @@ return base::MakeRefCounted<content::IdentityProviderData>( /*idp_for_display=*/"", content::IdentityProviderMetadata(), content::ClientMetadata(GURL(), GURL(), GURL(), gfx::Image()), - blink::mojom::RpContext::kSignIn, disclosure_fields, - has_login_status_mismatch); + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + disclosure_fields, has_login_status_mismatch); } IdentityRequestAccountPtr CreateAccount(
diff --git a/chrome/browser/ui/views/webid/fedcm_interactive_uitest.cc b/chrome/browser/ui/views/webid/fedcm_interactive_uitest.cc index fef1f27..fd2151f 100644 --- a/chrome/browser/ui/views/webid/fedcm_interactive_uitest.cc +++ b/chrome/browser/ui/views/webid/fedcm_interactive_uitest.cc
@@ -41,7 +41,8 @@ idps_ = {base::MakeRefCounted<content::IdentityProviderData>( "idp-example.com", content::IdentityProviderMetadata(), content::ClientMetadata(GURL(), GURL(), GURL(), gfx::Image()), - blink::mojom::RpContext::kSignIn, kDefaultDisclosureFields, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultDisclosureFields, /*has_login_status_mismatch=*/false)}; accounts_ = {base::MakeRefCounted<Account>( "id", "display_identifier", "display_name", "email", "name",
diff --git a/chrome/browser/ui/webid/identity_dialog_controller_unittest.cc b/chrome/browser/ui/webid/identity_dialog_controller_unittest.cc index 13494efb..c713954 100644 --- a/chrome/browser/ui/webid/identity_dialog_controller_unittest.cc +++ b/chrome/browser/ui/webid/identity_dialog_controller_unittest.cc
@@ -169,7 +169,8 @@ base::MakeRefCounted<content::IdentityProviderData>( kIdpEtldPlusOne, content::IdentityProviderMetadata(), content::ClientMetadata(GURL(), GURL(), GURL(), gfx::Image()), - blink::mojom::RpContext::kSignIn, kDefaultPermissions, + blink::mojom::RpContext::kSignIn, /*format=*/std::nullopt, + kDefaultPermissions, /*has_login_status_mismatch=*/false); for (auto& account : accounts) { account->identity_provider = idp_data;
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h index 0091639..f7efda0 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_dialog.h
@@ -67,15 +67,15 @@ }; // The string conversions of ash::cloud_upload::mojom::UserAction. -constexpr char kUserActionCancel[] = "cancel"; -constexpr char kUserActionCancelGoogleDrive[] = "cancel-drive"; -constexpr char kUserActionCancelOneDrive[] = "cancel-onedrive"; -constexpr char kUserActionSetUpOneDrive[] = "setup-onedrive"; -constexpr char kUserActionUploadToGoogleDrive[] = "upload-drive"; -constexpr char kUserActionUploadToOneDrive[] = "upload-onedrive"; -constexpr char kUserActionConfirmOrUploadToGoogleDrive[] = +inline constexpr char kUserActionCancel[] = "cancel"; +inline constexpr char kUserActionCancelGoogleDrive[] = "cancel-drive"; +inline constexpr char kUserActionCancelOneDrive[] = "cancel-onedrive"; +inline constexpr char kUserActionSetUpOneDrive[] = "setup-onedrive"; +inline constexpr char kUserActionUploadToGoogleDrive[] = "upload-drive"; +inline constexpr char kUserActionUploadToOneDrive[] = "upload-onedrive"; +inline constexpr char kUserActionConfirmOrUploadToGoogleDrive[] = "confirm-or-upload-google-drive"; -constexpr char kUserActionConfirmOrUploadToOneDrive[] = +inline constexpr char kUserActionConfirmOrUploadToOneDrive[] = "confirm-or-upload-onedrive"; // Options for which setup or move confirmation sub-page/flow we want to show.
diff --git a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h index 5c17c7a6..202e1ea 100644 --- a/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h +++ b/chrome/browser/ui/webui/ash/cloud_upload/cloud_upload_util.h
@@ -229,95 +229,96 @@ kMaxValue = kFileNotAnOfficeFile, }; -constexpr char kGoogleDriveTaskResultMetricName[] = +inline constexpr char kGoogleDriveTaskResultMetricName[] = "FileBrowser.OfficeFiles.TaskResult.Drive"; -constexpr char kGoogleDriveTaskResultMetricStateMetricName[] = +inline constexpr char kGoogleDriveTaskResultMetricStateMetricName[] = "FileBrowser.OfficeFiles.TaskResult.GoogleDrive.MetricState"; -constexpr char kOneDriveTaskResultMetricName[] = +inline constexpr char kOneDriveTaskResultMetricName[] = "FileBrowser.OfficeFiles.TaskResult.OneDrive"; -constexpr char kOneDriveTaskResultMetricStateMetricName[] = +inline constexpr char kOneDriveTaskResultMetricStateMetricName[] = "FileBrowser.OfficeFiles.TaskResult.OneDrive.MetricState"; -constexpr char kGoogleDriveUploadResultMetricName[] = +inline constexpr char kGoogleDriveUploadResultMetricName[] = "FileBrowser.OfficeFiles.Open.UploadResult.GoogleDrive"; -constexpr char kGoogleDriveUploadResultMetricStateMetricName[] = +inline constexpr char kGoogleDriveUploadResultMetricStateMetricName[] = "FileBrowser.OfficeFiles.Open.UploadResult.GoogleDrive.MetricState"; -constexpr char kOneDriveUploadResultMetricName[] = +inline constexpr char kOneDriveUploadResultMetricName[] = "FileBrowser.OfficeFiles.Open.UploadResult.OneDrive"; -constexpr char kOneDriveUploadResultMetricStateMetricName[] = +inline constexpr char kOneDriveUploadResultMetricStateMetricName[] = "FileBrowser.OfficeFiles.Open.UploadResult.OneDrive.MetricState"; -constexpr char kGoogleDriveMoveErrorMetricName[] = +inline constexpr char kGoogleDriveMoveErrorMetricName[] = "FileBrowser.OfficeFiles.Open.IOTaskError.GoogleDrive.Move"; -constexpr char kGoogleDriveMoveErrorMetricStateMetricName[] = +inline constexpr char kGoogleDriveMoveErrorMetricStateMetricName[] = "FileBrowser.OfficeFiles.Open.IOTaskError.GoogleDrive.Move.MetricState"; -constexpr char kGoogleDriveCopyErrorMetricName[] = +inline constexpr char kGoogleDriveCopyErrorMetricName[] = "FileBrowser.OfficeFiles.Open.IOTaskError.GoogleDrive.Copy"; -constexpr char kGoogleDriveCopyErrorMetricStateMetricName[] = +inline constexpr char kGoogleDriveCopyErrorMetricStateMetricName[] = "FileBrowser.OfficeFiles.Open.IOTaskError.GoogleDrive.Copy.MetricState"; -constexpr char kOneDriveMoveErrorMetricName[] = +inline constexpr char kOneDriveMoveErrorMetricName[] = "FileBrowser.OfficeFiles.Open.IOTaskError.OneDrive.Move"; -constexpr char kOneDriveMoveErrorMetricStateMetricName[] = +inline constexpr char kOneDriveMoveErrorMetricStateMetricName[] = "FileBrowser.OfficeFiles.Open.IOTaskError.OneDrive.Move.MetricState"; -constexpr char kOneDriveCopyErrorMetricName[] = +inline constexpr char kOneDriveCopyErrorMetricName[] = "FileBrowser.OfficeFiles.Open.IOTaskError.OneDrive.Copy"; -constexpr char kOneDriveCopyErrorMetricStateMetricName[] = +inline constexpr char kOneDriveCopyErrorMetricStateMetricName[] = "FileBrowser.OfficeFiles.Open.IOTaskError.OneDrive.Copy.MetricState"; -constexpr char kDriveOpenSourceVolumeMetric[] = +inline constexpr char kDriveOpenSourceVolumeMetric[] = "FileBrowser.OfficeFiles.Open.SourceVolume.GoogleDrive"; -constexpr char kDriveOpenSourceVolumeMetricStateMetric[] = +inline constexpr char kDriveOpenSourceVolumeMetricStateMetric[] = "FileBrowser.OfficeFiles.Open.SourceVolume.GoogleDrive.MetricState"; -constexpr char kOneDriveOpenSourceVolumeMetric[] = +inline constexpr char kOneDriveOpenSourceVolumeMetric[] = "FileBrowser.OfficeFiles.Open.SourceVolume.MicrosoftOneDrive"; -constexpr char kOneDriveOpenSourceVolumeMetricStateMetric[] = +inline constexpr char kOneDriveOpenSourceVolumeMetricStateMetric[] = "FileBrowser.OfficeFiles.Open.SourceVolume.OneDrive.MetricState"; -constexpr char kNumberOfFilesToOpenWithGoogleDriveMetric[] = +inline constexpr char kNumberOfFilesToOpenWithGoogleDriveMetric[] = "FileBrowser.OfficeFiles.Open.NumberOfFiles.GoogleDrive"; -constexpr char kNumberOfFilesToOpenWithOneDriveMetric[] = +inline constexpr char kNumberOfFilesToOpenWithOneDriveMetric[] = "FileBrowser.OfficeFiles.Open.NumberOfFiles.OneDrive"; -constexpr char kOpenInitialCloudProviderMetric[] = +inline constexpr char kOpenInitialCloudProviderMetric[] = "FileBrowser.OfficeFiles.Open.CloudProvider"; -constexpr char kDriveTransferRequiredMetric[] = +inline constexpr char kDriveTransferRequiredMetric[] = "FileBrowser.OfficeFiles.Open.TransferRequired.GoogleDrive"; -constexpr char kDriveTransferRequiredMetricStateMetric[] = +inline constexpr char kDriveTransferRequiredMetricStateMetric[] = "FileBrowser.OfficeFiles.Open.TransferRequired.GoogleDrive.MetricState"; -constexpr char kOneDriveTransferRequiredMetric[] = +inline constexpr char kOneDriveTransferRequiredMetric[] = "FileBrowser.OfficeFiles.Open.TransferRequired.OneDrive"; -constexpr char kOneDriveTransferRequiredMetricStateMetric[] = +inline constexpr char kOneDriveTransferRequiredMetricStateMetric[] = "FileBrowser.OfficeFiles.Open.TransferRequired.OneDrive.MetricState"; -constexpr char kDriveErrorMetricName[] = "FileBrowser.OfficeFiles.Errors.Drive"; -constexpr char kDriveErrorMetricStateMetricName[] = +inline constexpr char kDriveErrorMetricName[] = + "FileBrowser.OfficeFiles.Errors.Drive"; +inline constexpr char kDriveErrorMetricStateMetricName[] = "FileBrowser.OfficeFiles.Errors.GoogleDrive.MetricState"; -constexpr char kOneDriveErrorMetricName[] = +inline constexpr char kOneDriveErrorMetricName[] = "FileBrowser.OfficeFiles.Errors.OneDrive"; -constexpr char kOneDriveErrorMetricStateMetricName[] = +inline constexpr char kOneDriveErrorMetricStateMetricName[] = "FileBrowser.OfficeFiles.Errors.OneDrive.MetricState"; // Query actions for this path to get ODFS Metadata. -const char kODFSMetadataQueryPath[] = "/"; +inline constexpr char kODFSMetadataQueryPath[] = "/"; // Custom action ids passed from ODFS. -const char kOneDriveUrlActionId[] = "HIDDEN_ONEDRIVE_URL"; -const char kUserEmailActionId[] = "HIDDEN_ONEDRIVE_USER_EMAIL"; +inline constexpr char kOneDriveUrlActionId[] = "HIDDEN_ONEDRIVE_URL"; +inline constexpr char kUserEmailActionId[] = "HIDDEN_ONEDRIVE_USER_EMAIL"; // TODO(b/330786891): Remove this once it's no longer needed for backwards // compatibility with ODFS. -const char kReauthenticationRequiredId[] = +inline constexpr char kReauthenticationRequiredId[] = "HIDDEN_ONEDRIVE_REAUTHENTICATION_REQUIRED"; -const char kAccountStateId[] = "HIDDEN_ONEDRIVE_ACCOUNT_STATE"; +inline constexpr char kAccountStateId[] = "HIDDEN_ONEDRIVE_ACCOUNT_STATE"; // Get generic error message for uploading office files. std::string GetGenericErrorMessage();
diff --git a/chrome/browser/ui/webui/ash/diagnostics_dialog/diagnostics_dialog.h b/chrome/browser/ui/webui/ash/diagnostics_dialog/diagnostics_dialog.h index c23d7be..0a0bc2c 100644 --- a/chrome/browser/ui/webui/ash/diagnostics_dialog/diagnostics_dialog.h +++ b/chrome/browser/ui/webui/ash/diagnostics_dialog/diagnostics_dialog.h
@@ -15,7 +15,7 @@ // ID used to lookup existing DiagnosticsDialog instance from // SystemWebDialogDelegate list and ensure only one instance of // DiagnosticsDialog exists at a time. -constexpr char kDiagnosticsDialogId[] = "diagnostics-dialog"; +inline constexpr char kDiagnosticsDialogId[] = "diagnostics-dialog"; } // namespace
diff --git a/chrome/browser/ui/webui/ash/login/consolidated_consent_screen_handler.h b/chrome/browser/ui/webui/ash/login/consolidated_consent_screen_handler.h index 59e867a..52e1459 100644 --- a/chrome/browser/ui/webui/ash/login/consolidated_consent_screen_handler.h +++ b/chrome/browser/ui/webui/ash/login/consolidated_consent_screen_handler.h
@@ -16,9 +16,9 @@ class ConsolidatedConsentScreen; namespace { -const char kGoogleEulaDefaultUrl[] = +inline constexpr char kGoogleEulaDefaultUrl[] = "https://policies.google.com/terms/embedded?hl=en"; -const char kCrosEulaDefaultUrl[] = +inline constexpr char kCrosEulaDefaultUrl[] = "https://www.google.com/intl/en/chrome/terms/"; } // namespace
diff --git a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_ui.h b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_ui.h index 3184b57..1416c7d0 100644 --- a/chrome/browser/ui/webui/ash/office_fallback/office_fallback_ui.h +++ b/chrome/browser/ui/webui/ash/office_fallback/office_fallback_ui.h
@@ -23,10 +23,10 @@ namespace ash::office_fallback { // The string conversions of ash::office_fallback::mojom::DialogChoice. -const char kDialogChoiceCancel[] = "cancel"; -const char kDialogChoiceOk[] = "ok"; -const char kDialogChoiceQuickOffice[] = "quick-office"; -const char kDialogChoiceTryAgain[] = "try-again"; +inline constexpr char kDialogChoiceCancel[] = "cancel"; +inline constexpr char kDialogChoiceOk[] = "ok"; +inline constexpr char kDialogChoiceQuickOffice[] = "quick-office"; +inline constexpr char kDialogChoiceTryAgain[] = "try-again"; class OfficeFallbackUI;
diff --git a/chrome/browser/ui/webui/ash/parent_access/parent_access_metrics_utils.h b/chrome/browser/ui/webui/ash/parent_access/parent_access_metrics_utils.h index 4402383..a7e03ca 100644 --- a/chrome/browser/ui/webui/ash/parent_access/parent_access_metrics_utils.h +++ b/chrome/browser/ui/webui/ash/parent_access/parent_access_metrics_utils.h
@@ -14,11 +14,11 @@ namespace parent_access { // Title bases used in histogram title generation. -constexpr char kParentAccessWidgetShowDialogErrorHistogramBase[] = +inline constexpr char kParentAccessWidgetShowDialogErrorHistogramBase[] = "ChromeOS.FamilyLinkUser.ParentAccessWidgetShowDialogError"; -constexpr char kParentAccessFlowResultHistogramBase[] = +inline constexpr char kParentAccessFlowResultHistogramBase[] = "ChromeOS.FamilyLinkUser.ParentAccess.FlowResult"; -constexpr char kParentAccessWidgetErrorHistogramBase[] = +inline constexpr char kParentAccessWidgetErrorHistogramBase[] = "ChromeOS.FamilyLinkUser.ParentAccessWidgetError"; // Returns the title string for a histogram given a title base and flow
diff --git a/chrome/browser/ui/webui/ash/sanitize_dialog/sanitize_dialog.h b/chrome/browser/ui/webui/ash/sanitize_dialog/sanitize_dialog.h index 7d8e9f1..8f25a331 100644 --- a/chrome/browser/ui/webui/ash/sanitize_dialog/sanitize_dialog.h +++ b/chrome/browser/ui/webui/ash/sanitize_dialog/sanitize_dialog.h
@@ -13,7 +13,7 @@ namespace { // ID used to check if there are any other instances of the dialog open. -constexpr char kSanitizeDialogId[] = "sanitize-dialog"; +inline constexpr char kSanitizeDialogId[] = "sanitize-dialog"; } // namespace
diff --git a/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.h b/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.h index 762ab8d..1f1abeb9 100644 --- a/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.h +++ b/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.h
@@ -27,10 +27,11 @@ namespace autofill { -constexpr char kCacheResetDone[] = +inline constexpr char kCacheResetDone[] = "Done. Please close and reopen all tabs that should be affected by the " "cache reset."; -constexpr char kCacheResetAlreadyInProgress[] = "Reset already in progress"; +inline constexpr char kCacheResetAlreadyInProgress[] = + "Reset already in progress"; void CreateAndAddInternalsHTMLSource(Profile* profile, const std::string& source_name);
diff --git a/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.h b/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.h index 18354cd..70ce5ec2 100644 --- a/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.h +++ b/chrome/browser/ui/webui/cr_components/history_clusters/history_clusters_util.h
@@ -5,10 +5,11 @@ #ifndef CHROME_BROWSER_UI_WEBUI_CR_COMPONENTS_HISTORY_CLUSTERS_HISTORY_CLUSTERS_UTIL_H_ #define CHROME_BROWSER_UI_WEBUI_CR_COMPONENTS_HISTORY_CLUSTERS_HISTORY_CLUSTERS_UTIL_H_ -constexpr char kIsHistoryClustersVisibleKey[] = "isHistoryClustersVisible"; -constexpr char kIsHistoryClustersVisibleManagedByPolicyKey[] = +inline constexpr char kIsHistoryClustersVisibleKey[] = + "isHistoryClustersVisible"; +inline constexpr char kIsHistoryClustersVisibleManagedByPolicyKey[] = "isHistoryClustersVisibleManagedByPolicy"; -constexpr char kRenameJourneysKey[] = "renameJourneys"; +inline constexpr char kRenameJourneysKey[] = "renameJourneys"; class Profile;
diff --git a/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.cc b/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.cc index c432ccd8..d0fbec8 100644 --- a/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.cc +++ b/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.cc
@@ -12,9 +12,9 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window/public/browser_window_features.h" -#include "chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h" #include "chrome/browser/ui/views/data_sharing/data_sharing_utils.h" #include "chrome/browser/ui/webui/data_sharing/data_sharing_ui.h" +#include "components/saved_tab_groups/public/tab_group_sync_service.h" #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "google_apis/gaia/gaia_constants.h" @@ -101,11 +101,6 @@ } void DataSharingPageHandler::OpenTabGroup(const std::string& group_id) { - Browser* const browser = chrome::FindLastActiveWithProfile(GetProfile()); - CHECK(browser); - browser->browser_window_features() - ->data_sharing_open_group_helper() - ->OpenTabGroupWhenAvailable(group_id); } void DataSharingPageHandler::AboutToUnShareTabGroup(
diff --git a/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler_unittest.cc b/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler_unittest.cc index 2b63e8a2..b5da366 100644 --- a/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler_unittest.cc
@@ -8,7 +8,6 @@ #include "base/test/scoped_feature_list.h" #include "build/branding_buildflags.h" #include "chrome/browser/ui/browser_window/public/browser_window_features.h" -#include "chrome/browser/ui/views/data_sharing/data_sharing_open_group_helper.h" #include "chrome/browser/ui/webui/data_sharing/data_sharing_ui.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "components/data_sharing/public/features.h" @@ -118,15 +117,6 @@ std::move(callback)); } -// TODO(crbug.com/381173816): This test should not run without setting sync -// service. -TEST_F(DataSharingPageHandlerUnitTest, DISABLED_OpenTabGroup) { - handler()->OpenTabGroup("FAKE_GROUP_ID"); - DataSharingOpenGroupHelper* helper = - browser()->browser_window_features()->data_sharing_open_group_helper(); - EXPECT_TRUE(helper->group_ids_for_testing().contains("FAKE_GROUP_ID")); -} - TEST_F(DataSharingPageHandlerUnitTest, OnAccessTokenFetched) { #if BUILDFLAG(GOOGLE_CHROME_BRANDING) GTEST_SKIP() << "N/A for Google Chrome Branding Build";
diff --git a/chrome/browser/ui/webui/settings/glic_handler_browsertest.cc b/chrome/browser/ui/webui/settings/glic_handler_browsertest.cc index d890fb2..ea64e670 100644 --- a/chrome/browser/ui/webui/settings/glic_handler_browsertest.cc +++ b/chrome/browser/ui/webui/settings/glic_handler_browsertest.cc
@@ -75,7 +75,13 @@ } #endif // !BUILDFLAG(IS_OZONE_WAYLAND) -IN_PROC_BROWSER_TEST_F(GlicHandlerBrowserTest, UpdateGlicShortcut) { +// TODO(crbug.com/416160303): Enable the test. +#if BUILDFLAG(IS_WIN) +#define MAYBE_UpdateGlicShortcut DISABLED_UpdateGlicShortcut +#else +#define MAYBE_UpdateGlicShortcut UpdateGlicShortcut +#endif +IN_PROC_BROWSER_TEST_F(GlicHandlerBrowserTest, MAYBE_UpdateGlicShortcut) { const ui::Accelerator invalid_shortcut(ui::VKEY_A, ui::EF_NONE); glic_handler()->HandleSetGlicShortcut( base::Value::List()
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 978ceaeb..e3a1e00 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -755,6 +755,9 @@ {"glicNavigationShortcut", IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT}, {"glicNavigationShortcutSublabel", IDS_SETTINGS_GLIC_NAVIGATION_SHORTCUT_SUBLABEL}, + {"glicClosedCaptionsToggle", IDS_SETTINGS_GLIC_CLOSED_CAPTIONING}, + {"glicClosedCaptionsToggleSublabel", + IDS_SETTINGS_GLIC_CLOSED_CAPTIONING_SUBLABEL}, {"glicLocationToggle", IDS_SETTINGS_GLIC_PERMISSIONS_LOCATION_TOGGLE}, {"glicLocationToggleSublabel", IDS_SETTINGS_GLIC_PERMISSIONS_LOCATION_TOGGLE_SUBLABEL},
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper.h b/chrome/browser/ui/webui/settings/site_settings_helper.h index 5052df1ec..69e81f25 100644 --- a/chrome/browser/ui/webui/settings/site_settings_helper.h +++ b/chrome/browser/ui/webui/settings/site_settings_helper.h
@@ -92,35 +92,35 @@ using ChooserExceptionDetails = std::set<std::tuple<GURL, SiteSettingSource, bool>>; -constexpr char kChooserType[] = "chooserType"; -constexpr char kCloseDescription[] = "closeDescription"; -constexpr char kDisabled[] = "disabled"; -constexpr char kDisplayName[] = "displayName"; -constexpr char kDescription[] = "description"; -constexpr char kEmbeddingOrigin[] = "embeddingOrigin"; -constexpr char kEmbeddingDisplayName[] = "embeddingDisplayName"; -constexpr char kExceptions[] = "exceptions"; -constexpr char kFileSystemFilePath[] = "filePath"; -constexpr char kFileSystemIsDirectory[] = "isDirectory"; -constexpr char kFileSystemEditGrants[] = "editGrants"; -constexpr char kFileSystemViewGrants[] = "viewGrants"; -constexpr char kHostOrSpec[] = "hostOrSpec"; -constexpr char kIncognito[] = "incognito"; -constexpr char kIsEmbargoed[] = "isEmbargoed"; -constexpr char kObject[] = "object"; -constexpr char kOpenDescription[] = "openDescription"; -constexpr char kOrigin[] = "origin"; -constexpr char kOrigins[] = "origins"; -constexpr char kOriginForFavicon[] = "originForFavicon"; -constexpr char kPermissions[] = "permissions"; -constexpr char kPolicyIndicator[] = "indicator"; -constexpr char kReaderName[] = "readerName"; -constexpr char kRecentPermissions[] = "recentPermissions"; -constexpr char kSetting[] = "setting"; -constexpr char kSites[] = "sites"; -constexpr char kSource[] = "source"; -constexpr char kType[] = "type"; -constexpr char kNotificationPermissionsReviewListMaybeChangedEvent[] = +inline constexpr char kChooserType[] = "chooserType"; +inline constexpr char kCloseDescription[] = "closeDescription"; +inline constexpr char kDisabled[] = "disabled"; +inline constexpr char kDisplayName[] = "displayName"; +inline constexpr char kDescription[] = "description"; +inline constexpr char kEmbeddingOrigin[] = "embeddingOrigin"; +inline constexpr char kEmbeddingDisplayName[] = "embeddingDisplayName"; +inline constexpr char kExceptions[] = "exceptions"; +inline constexpr char kFileSystemFilePath[] = "filePath"; +inline constexpr char kFileSystemIsDirectory[] = "isDirectory"; +inline constexpr char kFileSystemEditGrants[] = "editGrants"; +inline constexpr char kFileSystemViewGrants[] = "viewGrants"; +inline constexpr char kHostOrSpec[] = "hostOrSpec"; +inline constexpr char kIncognito[] = "incognito"; +inline constexpr char kIsEmbargoed[] = "isEmbargoed"; +inline constexpr char kObject[] = "object"; +inline constexpr char kOpenDescription[] = "openDescription"; +inline constexpr char kOrigin[] = "origin"; +inline constexpr char kOrigins[] = "origins"; +inline constexpr char kOriginForFavicon[] = "originForFavicon"; +inline constexpr char kPermissions[] = "permissions"; +inline constexpr char kPolicyIndicator[] = "indicator"; +inline constexpr char kReaderName[] = "readerName"; +inline constexpr char kRecentPermissions[] = "recentPermissions"; +inline constexpr char kSetting[] = "setting"; +inline constexpr char kSites[] = "sites"; +inline constexpr char kSource[] = "source"; +inline constexpr char kType[] = "type"; +inline constexpr char kNotificationPermissionsReviewListMaybeChangedEvent[] = "notification-permission-review-list-maybe-changed"; // Returns whether a group name has been registered for the given type.
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h index 726be896..69046ce 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h
@@ -28,8 +28,9 @@ class TabStripUIEmbedder; // These data types must be in all lowercase. -constexpr char16_t kWebUITabIdDataType[] = u"application/vnd.chromium.tab"; -constexpr char16_t kWebUITabGroupIdDataType[] = +inline constexpr char16_t kWebUITabIdDataType[] = + u"application/vnd.chromium.tab"; +inline constexpr char16_t kWebUITabGroupIdDataType[] = u"application/vnd.chromium.tabgroup"; class TabStripUI;
diff --git a/chrome/browser/vr/vr_base_export.h b/chrome/browser/vr/vr_base_export.h index cf5ae11..ed5a94b2 100644 --- a/chrome/browser/vr/vr_base_export.h +++ b/chrome/browser/vr/vr_base_export.h
@@ -15,11 +15,7 @@ #endif // defined(VR_BASE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VR_BASE_IMPLEMENTATION) #define VR_BASE_EXPORT __attribute__((visibility("default"))) -#else -#define VR_BASE_EXPORT -#endif // defined(VR_BASE_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/chrome/browser/vr/vr_export.h b/chrome/browser/vr/vr_export.h index 32cb17b6..1f046359 100644 --- a/chrome/browser/vr/vr_export.h +++ b/chrome/browser/vr/vr_export.h
@@ -15,11 +15,7 @@ #endif // defined(VR_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VR_IMPLEMENTATION) #define VR_EXPORT __attribute__((visibility("default"))) -#else -#define VR_EXPORT -#endif // defined(VR_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/chrome/browser/vr/vr_ui_export.h b/chrome/browser/vr/vr_ui_export.h index 23e591a9..9a35ec6 100644 --- a/chrome/browser/vr/vr_ui_export.h +++ b/chrome/browser/vr/vr_ui_export.h
@@ -15,11 +15,7 @@ #endif // defined(VR_UI_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VR_UI_IMPLEMENTATION) #define VR_UI_EXPORT __attribute__((visibility("default"))) -#else -#define VR_UI_EXPORT -#endif // defined(VR_UI_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index f2cc5ec..aff5551 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -394,6 +394,8 @@ "commands/install_app_from_verified_manifest_command.h", "isolated_web_apps/commands/cleanup_bundle_cache_command.cc", "isolated_web_apps/commands/cleanup_bundle_cache_command.h", + "isolated_web_apps/commands/copy_bundle_to_cache_command.cc", + "isolated_web_apps/commands/copy_bundle_to_cache_command.h", "isolated_web_apps/policy/isolated_web_app_cache_client.cc", "isolated_web_apps/policy/isolated_web_app_cache_client.h", "isolated_web_apps/policy/isolated_web_app_cache_manager.cc", @@ -982,6 +984,7 @@ sources += [ "chromeos_web_app_experiments_unittest.cc", "isolated_web_apps/commands/cleanup_bundle_cache_command_unittest.cc", + "isolated_web_apps/commands/copy_bundle_to_cache_command_unittest.cc", "isolated_web_apps/policy/isolated_web_app_cache_client_unittest.cc", "os_integration/web_app_run_on_os_login_chromeos_unittest.cc", "web_app_run_on_os_login_manager_unittest.cc",
diff --git a/chrome/browser/web_applications/isolated_web_apps/commands/cleanup_bundle_cache_command_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/commands/cleanup_bundle_cache_command_unittest.cc index 81c80c21..0ecd64c 100644 --- a/chrome/browser/web_applications/isolated_web_apps/commands/cleanup_bundle_cache_command_unittest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/commands/cleanup_bundle_cache_command_unittest.cc
@@ -17,7 +17,6 @@ #include "chrome/browser/web_applications/test/web_app_test.h" #include "chrome/browser/web_applications/web_app_command_scheduler.h" #include "chrome/common/chrome_features.h" -#include "components/user_manager/fake_user_manager.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" #include "testing/gtest/include/gtest/gtest.h" @@ -72,7 +71,7 @@ EXPECT_TRUE(base::CreateTemporaryFileInDir(CacheRootPath(), &temp_file)); base::FilePath bundle_path = - bundle_directory_path.AppendASCII(kMainSwbnFileName); + IwaCacheClient::GetBundleFullName(bundle_directory_path); EXPECT_TRUE(base::CopyFile(temp_file, bundle_path)); return bundle_path; } @@ -92,8 +91,11 @@ base::FilePath GetBundleDirWithVersion(const SignedWebBundleId& bundle_id, const base::Version& version, SessionType session_type) { - return GetBundleDirForSession(bundle_id, session_type) - .AppendASCII(version.GetString()); + auto session_cache_dir = + IwaCacheClient::GetCacheBaseDirectoryForSessionType(session_type, + CacheRootPath()); + return IwaCacheClient::GetCacheDirectoryForBundleWithVersion( + session_cache_dir, bundle_id, version); } void ScheduleCommand( @@ -114,7 +116,6 @@ private: base::test::ScopedFeatureList scoped_feature_list_{ features::kIsolatedWebAppBundleCache}; - user_manager::ScopedUserManager user_manager_; base::ScopedTempDir cache_root_dir_; std::unique_ptr<base::ScopedPathOverride> cache_root_dir_override_; };
diff --git a/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.cc b/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.cc new file mode 100644 index 0000000..d7d60bd --- /dev/null +++ b/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.cc
@@ -0,0 +1,152 @@ +// 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/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h" + +#include "base/files/file.h" +#include "base/files/file_util.h" +#include "base/task/thread_pool.h" +#include "base/types/expected.h" +#include "base/version.h" +#include "chrome/browser/web_applications/commands/web_app_command.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h" +#include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h" +#include "chrome/browser/web_applications/locks/app_lock.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/browser/web_applications/web_app_registrar.h" + +namespace web_app { +namespace { + +using SessionType = IwaCacheClient::SessionType; + +// This function is blocking. It should be called by +// `CopyBundleToCacheCommand::StartWithLock`. +CopyBundleToCacheResult CopyBundleToCacheCommandImpl( + const base::FilePath& copy_from_bundle_path, + const web_package::SignedWebBundleId& web_bundle_id, + base::Version version, + SessionType session_type) { + const base::FilePath cache_dir = + IwaCacheClient::GetCacheBaseDirectoryForSessionType(session_type); + base::FilePath bundle_dir_with_version = + IwaCacheClient::GetCacheDirectoryForBundleWithVersion( + cache_dir, web_bundle_id, version); + if (base::File::Error error; + !base::CreateDirectoryAndGetError(bundle_dir_with_version, &error)) { + LOG(ERROR) << "Failed to create IWA cache directory with path: " + << bundle_dir_with_version << ", error: " << error; + return base::unexpected(CopyBundleToCacheError::kFailedToCreateDir); + } + + const base::FilePath destination_bundle_path = + IwaCacheClient::GetBundleFullName(bundle_dir_with_version); + if (!base::CopyFile(copy_from_bundle_path, destination_bundle_path)) { + base::DeleteFile(destination_bundle_path); + LOG(ERROR) << "Failed to copy IWA bundle to cache, destination path: " + << destination_bundle_path; + return base::unexpected(CopyBundleToCacheError::kFailedToCopyFile); + } + + return CopyBundleToCacheSuccess(destination_bundle_path); +} + +// Returns bundle path for owned bundle, otherwise returns std::nullopt. +std::optional<base::FilePath> GetOwnedBundlePath( + const IsolatedWebAppStorageLocation& location, + Profile& profile) { + const auto* owned_bundle = + std::get_if<IsolatedWebAppStorageLocation::OwnedBundle>( + &location.variant()); + if (!owned_bundle) { + return std::nullopt; + } + return owned_bundle->GetPath(profile.GetPath()); +} + +} // namespace + +std::string CopyBundleToCacheErrorToString(CopyBundleToCacheError error) { + switch (error) { + case CopyBundleToCacheError::kSystemShutdown: + return "System shutdown"; + case CopyBundleToCacheError::kAppNotInstalled: + return "IWA is not installed"; + case CopyBundleToCacheError::kNotIwa: + return "App is not IWA"; + case CopyBundleToCacheError::kCannotExtractOwnedBundlePath: + return "Cannot extract owned bundle path"; + case CopyBundleToCacheError::kFailedToCreateDir: + return "Failed to create directory"; + case CopyBundleToCacheError::kFailedToCopyFile: + return "Failed to copy file"; + } +} + +CopyBundleToCacheCommand::CopyBundleToCacheCommand( + const IsolatedWebAppUrlInfo& url_info, + SessionType session_type, + Profile& profile, + Callback callback) + : WebAppCommand<AppLock, CopyBundleToCacheResult>( + "CopyBundleToCacheCommand", + AppLockDescription(url_info.app_id()), + std::move(callback), + /*args_for_shutdown=*/ + base::unexpected( + CopyBundleToCacheError{CopyBundleToCacheError::kSystemShutdown})), + url_info_(url_info), + session_type_(session_type), + profile_(profile) {} + +CopyBundleToCacheCommand::~CopyBundleToCacheCommand() = default; + +void CopyBundleToCacheCommand::StartWithLock(std::unique_ptr<AppLock> lock) { + CHECK(lock); + lock_ = std::move(lock); + + const WebApp* app = lock_->registrar().GetAppById(url_info_.app_id()); + if (!app) { + CommandComplete(base::unexpected( + CopyBundleToCacheError{CopyBundleToCacheError::kAppNotInstalled})); + return; + } + if (!app->isolation_data()) { + CommandComplete(base::unexpected( + CopyBundleToCacheError{CopyBundleToCacheError::kNotIwa})); + return; + } + + // Only copies owned bundles, since all policy-installed IWAs have owned + // bundles. + std::optional<base::FilePath> bundle_path = + GetOwnedBundlePath(app->isolation_data()->location(), *profile_); + if (bundle_path->empty()) { + CommandComplete(base::unexpected(CopyBundleToCacheError{ + CopyBundleToCacheError::kCannotExtractOwnedBundlePath})); + return; + } + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, + {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, + base::BindOnce(&CopyBundleToCacheCommandImpl, bundle_path.value(), + url_info_.web_bundle_id(), + app->isolation_data()->version(), session_type_), + base::BindOnce(&CopyBundleToCacheCommand::CommandComplete, + weak_ptr_factory_.GetWeakPtr())); +} + +void CopyBundleToCacheCommand::CommandComplete( + const CopyBundleToCacheResult& result) { + if (!result.has_value()) { + LOG(ERROR) << "Copy IWA bundle to cache failed: " + << CopyBundleToCacheErrorToString(result.error()); + } + CompleteAndSelfDestruct( + result.has_value() ? CommandResult::kSuccess : CommandResult::kFailure, + result); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h b/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h new file mode 100644 index 0000000..b9f3a2d --- /dev/null +++ b/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h
@@ -0,0 +1,84 @@ +// 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_WEB_APPLICATIONS_ISOLATED_WEB_APPS_COMMANDS_COPY_BUNDLE_TO_CACHE_COMMAND_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_COMMANDS_COPY_BUNDLE_TO_CACHE_COMMAND_H_ + +#include "base/types/expected.h" +#include "base/version.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/commands/web_app_command.h" +#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h" +#include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h" +#include "chrome/browser/web_applications/locks/app_lock.h" +#include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" + +namespace web_app { + +class CopyBundleToCacheSuccess { + public: + explicit CopyBundleToCacheSuccess(const base::FilePath& cached_bundle_path) + : cached_bundle_path_(cached_bundle_path) {} + + CopyBundleToCacheSuccess(const CopyBundleToCacheSuccess& other) = default; + ~CopyBundleToCacheSuccess() = default; + + bool operator==(const CopyBundleToCacheSuccess& other) const = default; + + const base::FilePath& cached_bundle_path() const { + return cached_bundle_path_; + } + + private: + base::FilePath cached_bundle_path_; +}; + +enum class CopyBundleToCacheError { + kSystemShutdown, + kAppNotInstalled, + kNotIwa, + kCannotExtractOwnedBundlePath, + kFailedToCreateDir, + kFailedToCopyFile, +}; + +std::string CopyBundleToCacheErrorToString(CopyBundleToCacheError error); + +using CopyBundleToCacheResult = + base::expected<CopyBundleToCacheSuccess, CopyBundleToCacheError>; + +// Copies IWA bundle file to the cache. To prevent race conditions with other +// cache operations, this class takes `AppLock` for the bundle. +class CopyBundleToCacheCommand + : public WebAppCommand<AppLock, CopyBundleToCacheResult> { + public: + using Callback = base::OnceCallback<void(CopyBundleToCacheResult)>; + + CopyBundleToCacheCommand(const IsolatedWebAppUrlInfo& url_info, + IwaCacheClient::SessionType session_type, + Profile& profile, + Callback callback); + CopyBundleToCacheCommand(const CopyBundleToCacheCommand&) = delete; + CopyBundleToCacheCommand& operator=(const CopyBundleToCacheCommand&) = delete; + + ~CopyBundleToCacheCommand() override; + + protected: + // WebAppCommand: + void StartWithLock(std::unique_ptr<AppLock> lock) override; + + private: + void CommandComplete(const CopyBundleToCacheResult& result); + + std::unique_ptr<AppLock> lock_; + const IsolatedWebAppUrlInfo url_info_; + const IwaCacheClient::SessionType session_type_; + const raw_ref<Profile> profile_; + + base::WeakPtrFactory<CopyBundleToCacheCommand> weak_ptr_factory_{this}; +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_ISOLATED_WEB_APPS_COMMANDS_COPY_BUNDLE_TO_CACHE_COMMAND_H_
diff --git a/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command_unittest.cc new file mode 100644 index 0000000..68dc415 --- /dev/null +++ b/chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command_unittest.cc
@@ -0,0 +1,224 @@ +// 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/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h" + +#include "ash/constants/ash_paths.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/test/gmock_expected_support.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/scoped_path_override.h" +#include "base/test/test_future.h" +#include "base/version.h" +#include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h" +#include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_builder.h" +#include "chrome/browser/web_applications/isolated_web_apps/test/test_signed_web_bundle_builder.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/browser/web_applications/test/web_app_test.h" +#include "chrome/browser/web_applications/web_app_command_scheduler.h" +#include "chrome/common/chrome_features.h" +#include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" +#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_app { + +namespace { + +using base::test::ErrorIs; +using base::test::HasValue; +using base::test::TestFuture; +using base::test::ValueIs; +using web_package::SignedWebBundleId; +using SessionType = IwaCacheClient::SessionType; + +const SignedWebBundleId kBundleId = test::GetDefaultEd25519WebBundleId(); +const web_package::test::Ed25519KeyPair kPublicKeyPair = + test::GetDefaultEd25519KeyPair(); +const base::Version kVersion1 = base::Version("0.0.1"); +const base::Version kVersion2 = base::Version("2.0.0"); + +} // namespace + +// TODO(crbug.com/414793394): Reduce code duplications for cache command unit +// tests. +class CopyBundleToCacheCommandTest + : public WebAppTest, + public testing::WithParamInterface<SessionType> { + public: + void SetUp() override { + WebAppTest::SetUp(); + test::AwaitStartWebAppProviderAndSubsystems(profile()); + + ASSERT_TRUE(cache_root_dir_.CreateUniqueTempDir()); + cache_root_dir_override_ = std::make_unique<base::ScopedPathOverride>( + ash::DIR_DEVICE_LOCAL_ACCOUNT_IWA_CACHE, cache_root_dir_.GetPath()); + } + + base::FilePath CreateBundleInCacheDir(const SignedWebBundleId& bundle_id, + const base::Version& version) { + base::FilePath bundle_directory_path = + GetBundleDirWithVersion(bundle_id, version); + EXPECT_TRUE(base::CreateDirectory(bundle_directory_path)); + + base::FilePath temp_file; + EXPECT_TRUE(base::CreateTemporaryFileInDir(CacheRootPath(), &temp_file)); + base::FilePath bundle_path = + IwaCacheClient::GetBundleFullName(bundle_directory_path); + EXPECT_TRUE(base::CopyFile(temp_file, bundle_path)); + return bundle_path; + } + + base::FilePath GetBundleDirWithVersion(const SignedWebBundleId& bundle_id, + const base::Version& version) { + auto session_cache_dir = + IwaCacheClient::GetCacheBaseDirectoryForSessionType(GetSessionType(), + CacheRootPath()); + return IwaCacheClient::GetCacheDirectoryForBundleWithVersion( + session_cache_dir, bundle_id, version); + } + + base::FilePath GetBundleFullPath(const SignedWebBundleId& bundle_id, + const base::Version& version) { + return IwaCacheClient::GetBundleFullName( + GetBundleDirWithVersion(bundle_id, version)); + } + + const base::FilePath& CacheRootPath() { return cache_root_dir_.GetPath(); } + + void ScheduleCommand( + const web_package::SignedWebBundleId& web_bundle_id, + base::OnceCallback<void(CopyBundleToCacheResult)> callback) { + auto url_info = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(web_bundle_id); + fake_provider().scheduler().CopyIsolatedWebAppBundleToCache( + url_info, GetSessionType(), std::move(callback)); + } + + void RestrictDirectoryPermission(const base::FilePath& dir) { + // Allows to check that file exists, but disallows to change it. + EXPECT_TRUE( + SetPosixFilePermissions(dir, base::FILE_PERMISSION_EXECUTE_BY_USER)); + } + + std::unique_ptr<BundledIsolatedWebApp> CreateApp(const std::string& version) { + base::FilePath bundle_path = + IwaStorageOwnedBundle{"bundle-" + version, /*dev_mode=*/false}.GetPath( + profile()->GetPath()); + EXPECT_TRUE(base::CreateDirectory(bundle_path.DirName())); + + std::unique_ptr<BundledIsolatedWebApp> app = + IsolatedWebAppBuilder(ManifestBuilder().SetVersion(version)) + .BuildBundle(bundle_path, kPublicKeyPair); + app->TrustSigningKey(); + app->FakeInstallPageState(profile()); + return app; + } + + SessionType GetSessionType() { return GetParam(); } + + private: + base::test::ScopedFeatureList scoped_feature_list_{ + features::kIsolatedWebAppBundleCache}; + base::ScopedTempDir cache_root_dir_; + std::unique_ptr<base::ScopedPathOverride> cache_root_dir_override_; + data_decoder::test::InProcessDataDecoder in_process_data_decoder_; +}; + +TEST_P(CopyBundleToCacheCommandTest, CopyBundleToCache) { + std::unique_ptr<BundledIsolatedWebApp> app = CreateApp(kVersion1.GetString()); + ASSERT_THAT(app->Install(profile()), HasValue()); + + TestFuture<CopyBundleToCacheResult> copy_future; + ScheduleCommand(kBundleId, copy_future.GetCallback()); + + base::FilePath bundle_path = GetBundleFullPath(kBundleId, kVersion1); + EXPECT_THAT(copy_future.Get(), + ValueIs(CopyBundleToCacheSuccess{bundle_path})); + EXPECT_TRUE(base::PathExists(bundle_path)); +} + +TEST_P(CopyBundleToCacheCommandTest, AppNotInstalled) { + TestFuture<CopyBundleToCacheResult> copy_future; + ScheduleCommand(kBundleId, copy_future.GetCallback()); + + EXPECT_THAT(copy_future.Get(), + ErrorIs(CopyBundleToCacheError::kAppNotInstalled)); +} + +TEST_P(CopyBundleToCacheCommandTest, FailedToCreateDir) { + std::unique_ptr<BundledIsolatedWebApp> app = CreateApp(kVersion1.GetString()); + ASSERT_THAT(app->Install(profile()), HasValue()); + + // Restricts cache root directory permissions, so copy to that directory will + // fail. + RestrictDirectoryPermission(CacheRootPath()); + + TestFuture<CopyBundleToCacheResult> copy_future; + ScheduleCommand(kBundleId, copy_future.GetCallback()); + + EXPECT_THAT(copy_future.Get(), + ErrorIs(CopyBundleToCacheError::kFailedToCreateDir)); +} + +TEST_P(CopyBundleToCacheCommandTest, FailedToCopyFile) { + std::unique_ptr<BundledIsolatedWebApp> app = CreateApp(kVersion1.GetString()); + ASSERT_THAT(app->Install(profile()), HasValue()); + + // Bundle directory is already created, but restricted, so copy to that + // directory will fail. + base::FilePath bundle_directory_path = + GetBundleDirWithVersion(kBundleId, kVersion1); + EXPECT_TRUE(base::CreateDirectory(bundle_directory_path)); + RestrictDirectoryPermission(bundle_directory_path); + + TestFuture<CopyBundleToCacheResult> copy_future; + ScheduleCommand(kBundleId, copy_future.GetCallback()); + + EXPECT_THAT(copy_future.Get(), + ErrorIs(CopyBundleToCacheError::kFailedToCopyFile)); +} + +TEST_P(CopyBundleToCacheCommandTest, CopyBundleToCacheReplacesExistingFile) { + base::FilePath existing_bundle = CreateBundleInCacheDir(kBundleId, kVersion1); + std::unique_ptr<BundledIsolatedWebApp> app = CreateApp(kVersion1.GetString()); + ASSERT_THAT(app->Install(profile()), HasValue()); + + TestFuture<CopyBundleToCacheResult> copy_future; + ScheduleCommand(kBundleId, copy_future.GetCallback()); + + base::FilePath bundle_path = GetBundleFullPath(kBundleId, kVersion1); + EXPECT_THAT(copy_future.Get(), + ValueIs(CopyBundleToCacheSuccess{bundle_path})); + EXPECT_TRUE(base::PathExists(bundle_path)); +} + +TEST_P(CopyBundleToCacheCommandTest, CopyAnotherBundleVersion) { + base::FilePath existing_bundle_path = + CreateBundleInCacheDir(kBundleId, kVersion1); + std::unique_ptr<BundledIsolatedWebApp> app = CreateApp(kVersion2.GetString()); + ASSERT_THAT(app->Install(profile()), HasValue()); + + TestFuture<CopyBundleToCacheResult> copy_future; + ScheduleCommand(kBundleId, copy_future.GetCallback()); + + base::FilePath updated_bundle_path = GetBundleFullPath(kBundleId, kVersion2); + EXPECT_THAT(copy_future.Get(), + ValueIs(CopyBundleToCacheSuccess{updated_bundle_path})); + // Check that both versions are cached. + EXPECT_TRUE(base::PathExists(existing_bundle_path)); + EXPECT_TRUE(base::PathExists(updated_bundle_path)); +} + +INSTANTIATE_TEST_SUITE_P( + /* no prefix */, + CopyBundleToCacheCommandTest, + testing::Values(IwaCacheClient::SessionType::kManagedGuestSession, + IwaCacheClient::SessionType::kKiosk)); + +} // namespace web_app
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_task.cc b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_task.cc index d8bb9ed..832af36 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_task.cc +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_task.cc
@@ -29,6 +29,7 @@ #include "components/keep_alive_registry/scoped_keep_alive.h" #if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h" #include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -38,21 +39,6 @@ #if BUILDFLAG(IS_CHROMEOS) constexpr char kCopyToCacheResult[] = "copy_to_cache_result"; -constexpr char kCannotExtractBundlePath[] = "Cannot extract bundle path"; - -// Returns bundle path for owned bundle, otherwise returns std::nullopt. -std::optional<base::FilePath> GetOwnedBundlePath( - const IsolatedWebAppStorageLocation& location, - Profile& profile) { - const auto* owned_bundle = - std::get_if<IsolatedWebAppStorageLocation::OwnedBundle>( - &location.variant()); - if (!owned_bundle) { - return std::nullopt; - } - return owned_bundle->GetPath(profile.GetPath()); -} - #endif // BUILDFLAG(IS_CHROMEOS) } // namespace @@ -120,37 +106,24 @@ #if BUILDFLAG(IS_CHROMEOS) void IsolatedWebAppUpdateApplyTask::CopyUpdatedBundleToCache( const IsolatedWebAppApplyUpdateCommandSuccess& apply_success_result) { - const auto bundle_path = - GetOwnedBundlePath(apply_success_result.updated_location(), *profile_); - if (!bundle_path) { - debug_log_.Set(kCopyToCacheResult, kCannotExtractBundlePath); - std::move(callback_).Run( - base::unexpected<IsolatedWebAppApplyUpdateCommandError>( - IsolatedWebAppApplyUpdateCommandError{ - .message = kCannotExtractBundlePath})); - return; - } - - cache_client_->CopyBundleToCache( - bundle_path.value(), url_info_.web_bundle_id(), - apply_success_result.updated_version(), + command_scheduler_->CopyIsolatedWebAppBundleToCache( + url_info_, IwaCacheClient::GetCurrentSessionType(), base::BindOnce(&IsolatedWebAppUpdateApplyTask::OnBundleCopiedToCache, weak_factory_.GetWeakPtr(), apply_success_result)); } void IsolatedWebAppUpdateApplyTask::OnBundleCopiedToCache( const IsolatedWebAppApplyUpdateCommandSuccess& apply_success_result, - base::expected<IwaCacheClient::CopyBundleToCacheSuccess, - IwaCacheClient::CopyBundleToCacheError> result) { + CopyBundleToCacheResult result) { if (result.has_value()) { debug_log_.Set(kCopyToCacheResult, "Successfully copied bundle to: " + - result->cached_bundle_path.MaybeAsASCII()); + result->cached_bundle_path().MaybeAsASCII()); std::move(callback_).Run(apply_success_result); return; } debug_log_.Set(kCopyToCacheResult, - IwaCacheClient::CopyErrorToString(result.error())); + CopyBundleToCacheErrorToString(result.error())); std::move(callback_).Run( base::unexpected<IsolatedWebAppApplyUpdateCommandError>( IsolatedWebAppApplyUpdateCommandError{
diff --git a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_task.h b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_task.h index 4e1ef94..80e2809 100644 --- a/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_task.h +++ b/chrome/browser/web_applications/isolated_web_apps/isolated_web_app_update_apply_task.h
@@ -16,6 +16,7 @@ #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h" #if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h" #include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -71,8 +72,7 @@ void OnBundleCopiedToCache( const IsolatedWebAppApplyUpdateCommandSuccess& apply_success_result, - base::expected<IwaCacheClient::CopyBundleToCacheSuccess, - IwaCacheClient::CopyBundleToCacheError> result); + CopyBundleToCacheResult result); #endif // BUILDFLAG(IS_CHROMEOS) IsolatedWebAppUrlInfo url_info_;
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_browsertest.cc index f96a27c..85060e1 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_browsertest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_browsertest.cc
@@ -45,7 +45,7 @@ #include "chrome/common/chrome_features.h" #include "chrome/test/base/ui_test_utils.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" -#include "components/policy/core/common/device_local_account_type.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h" #include "components/web_package/test_support/signed_web_bundles/ed25519_key_pair.h"
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.cc index f27c27d5..73b4d88b 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.cc
@@ -32,25 +32,13 @@ using SessionType = IwaCacheClient::SessionType; -base::FilePath GetCacheBundleDirectoryWithVersion( - const base::FilePath& cache_dir, - const web_package::SignedWebBundleId& web_bundle_id, - const base::Version& version) { - return IwaCacheClient::GetCacheDirectoryForBundle(cache_dir, web_bundle_id) - .AppendASCII(version.GetString()); -} - -base::FilePath GetBundleFullName( - const base::FilePath& bundle_dir_with_version) { - return bundle_dir_with_version.AppendASCII(kMainSwbnFileName); -} - base::FilePath GetBundleFullName( const base::FilePath& cache_dir, const web_package::SignedWebBundleId& web_bundle_id, const base::Version& version) { - return GetBundleFullName( - GetCacheBundleDirectoryWithVersion(cache_dir, web_bundle_id, version)); + return IwaCacheClient::GetBundleFullName( + IwaCacheClient::GetCacheDirectoryForBundleWithVersion( + cache_dir, web_bundle_id, version)); } // Expects the following bundle path: @@ -117,36 +105,6 @@ std::move(newest_version.value())); } -// This function is blocking. It should be called by `CopyBundleToCache`. -base::expected<IwaCacheClient::CopyBundleToCacheSuccess, - IwaCacheClient::CopyBundleToCacheError> -CopyBundleToCacheImpl(const base::FilePath& copy_from_bundle_path, - const web_package::SignedWebBundleId& web_bundle_id, - base::Version version, - const base::FilePath& cache_dir) { - base::FilePath bundle_dir_with_version = - GetCacheBundleDirectoryWithVersion(cache_dir, web_bundle_id, version); - if (base::File::Error error; - !base::CreateDirectoryAndGetError(bundle_dir_with_version, &error)) { - LOG(ERROR) << "Failed to create IWA cache directory with path: " - << bundle_dir_with_version << ", error: " << error; - return base::unexpected( - IwaCacheClient::CopyBundleToCacheError::kFailedToCreateDir); - } - - const base::FilePath destination_bundle_path = - GetBundleFullName(bundle_dir_with_version); - if (!base::CopyFile(copy_from_bundle_path, destination_bundle_path)) { - base::DeleteFile(destination_bundle_path); - LOG(ERROR) << "Failed to copy IWA bundle to cache, destination path: " - << destination_bundle_path; - return base::unexpected( - IwaCacheClient::CopyBundleToCacheError::kFailedToCopyFile); - } - - return IwaCacheClient::CopyBundleToCacheSuccess(destination_bundle_path); -} - base::FilePath GetIwaCacheDirectoryForCurrentSession( const base::FilePath& base = base::PathService::CheckedGet( ash::DIR_DEVICE_LOCAL_ACCOUNT_IWA_CACHE)) { @@ -167,21 +125,16 @@ (chromeos::IsManagedGuestSession() || chromeos::IsKioskSession()); } -base::FilePath GetCacheBundleDirectory( - const base::FilePath& main_cache_dir, - const web_package::SignedWebBundleId& web_bundle_id) { - return main_cache_dir.AppendASCII(web_bundle_id.id()); -} - // static -std::string IwaCacheClient::CopyErrorToString( - IwaCacheClient::CopyBundleToCacheError error) { - switch (error) { - case IwaCacheClient::CopyBundleToCacheError::kFailedToCreateDir: - return "FailedToCreateDir"; - case IwaCacheClient::CopyBundleToCacheError::kFailedToCopyFile: - return "FailedToCopyFile"; +SessionType IwaCacheClient::GetCurrentSessionType() { + if (chromeos::IsKioskSession()) { + return SessionType::kKiosk; } + if (chromeos::IsManagedGuestSession()) { + return SessionType::kManagedGuestSession; + } + NOTREACHED() + << "IwaCacheClient supports only kiosk and Managed Guest Session."; } IwaCacheClient::IwaCacheClient() @@ -201,19 +154,6 @@ std::move(callback)); } -void IwaCacheClient::CopyBundleToCache( - const base::FilePath& copy_from_bundle_path, - const web_package::SignedWebBundleId& web_bundle_id, - const base::Version& version, - base::OnceCallback<void(base::expected<CopyBundleToCacheSuccess, - CopyBundleToCacheError>)> callback) { - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::MayBlock()}, - base::BindOnce(&CopyBundleToCacheImpl, copy_from_bundle_path, - web_bundle_id, version, cache_dir_), - std::move(callback)); -} - void IwaCacheClient::SetCacheDirForTesting(const base::FilePath& cache_dir) { cache_dir_ = GetIwaCacheDirectoryForCurrentSession(cache_dir); } @@ -242,6 +182,22 @@ } // static +base::FilePath IwaCacheClient::GetCacheDirectoryForBundleWithVersion( + const base::FilePath& cache_base_dir, + const web_package::SignedWebBundleId& web_bundle_id, + const base::Version& version) { + return IwaCacheClient::GetCacheDirectoryForBundle(cache_base_dir, + web_bundle_id) + .AppendASCII(version.GetString()); +} + +// static +base::FilePath IwaCacheClient::GetBundleFullName( + const base::FilePath& bundle_dir_with_version) { + return bundle_dir_with_version.AppendASCII(kMainSwbnFileName); +} + +// static std::string IwaCacheClient::SessionTypeToString(SessionType session_type) { switch (session_type) { case SessionType::kKiosk:
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h index a5139c1..e4b705a 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h
@@ -32,17 +32,7 @@ kManagedGuestSession, }; - enum class CopyBundleToCacheError { - kFailedToCreateDir = 0, - kFailedToCopyFile = 1, - }; - - static std::string CopyErrorToString( - IwaCacheClient::CopyBundleToCacheError error); - - struct CopyBundleToCacheSuccess { - base::FilePath cached_bundle_path; - }; + static SessionType GetCurrentSessionType(); struct CachedBundleData { base::FilePath path; @@ -65,17 +55,6 @@ const std::optional<base::Version>& version, base::OnceCallback<void(std::optional<CachedBundleData>)> callback); - // Copies bundle file to the cache, so next time the installation can be done - // from the cache. - // TODO(crbug.com/411116232): use AppLock to prevent race conditions. - void CopyBundleToCache( - const base::FilePath& copy_from_bundle_path, - const web_package::SignedWebBundleId& web_bundle_id, - const base::Version& version, - base::OnceCallback<void( - base::expected<CopyBundleToCacheSuccess, CopyBundleToCacheError>)> - callback); - // TODO(crbug.com/392069400): clean cache for old IWA versions. void SetCacheDirForTesting(const base::FilePath& cache_dir); @@ -89,6 +68,14 @@ const base::FilePath& cache_base_dir, const web_package::SignedWebBundleId& web_bundle_id); + static base::FilePath GetCacheDirectoryForBundleWithVersion( + const base::FilePath& cache_dir, + const web_package::SignedWebBundleId& web_bundle_id, + const base::Version& version); + + static base::FilePath GetBundleFullName( + const base::FilePath& bundle_dir_with_version); + static std::string SessionTypeToString(SessionType session_type); static constexpr base::FilePath::CharType kMgsDirName[] = "mgs";
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client_unittest.cc index 1b52047..215cc72fc 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client_unittest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client_unittest.cc
@@ -36,8 +36,6 @@ using base::test::TestFuture; using Bundle = IwaCacheClient::CachedBundleData; -using CopyBundleToCacheSuccess = IwaCacheClient::CopyBundleToCacheSuccess; -using CopyBundleToCacheError = IwaCacheClient::CopyBundleToCacheError; using base::test::ErrorIs; using base::test::ValueIs; using testing::Field; @@ -90,8 +88,6 @@ IwaCacheClient* cache_client() { return cache_client_.get(); } - const base::FilePath& CacheDirPath() { return cache_root_dir_.GetPath(); } - base::FilePath CreateBundleInCacheDir(const SignedWebBundleId& bundle_id, const base::Version& version) { base::FilePath bundle_directory_path = @@ -99,7 +95,7 @@ EXPECT_TRUE(base::CreateDirectory(bundle_directory_path)); base::FilePath temp_file; - EXPECT_TRUE(base::CreateTemporaryFileInDir(CacheDirPath(), &temp_file)); + EXPECT_TRUE(base::CreateTemporaryFileInDir(CacheRootPath(), &temp_file)); base::FilePath bundle_path = bundle_directory_path.AppendASCII(kMainSwbnFileName); @@ -107,9 +103,10 @@ return bundle_path; } + private: base::FilePath GetBundleDirWithVersion(const SignedWebBundleId& bundle_id, const base::Version& version) { - base::FilePath bundle_directory_path = CacheDirPath(); + base::FilePath bundle_directory_path = CacheRootPath(); switch (GetSessionType()) { case SessionType::kMgs: bundle_directory_path = @@ -126,26 +123,8 @@ .AppendASCII(version.GetString()); } - base::FilePath GetFullBundlePath(const SignedWebBundleId& bundle_id, - const base::Version& version) { - return GetBundleDirWithVersion(bundle_id, version) - .AppendASCII(kMainSwbnFileName); - } + const base::FilePath& CacheRootPath() { return cache_root_dir_.GetPath(); } - base::FilePath CreateFileInDir(base::ScopedTempDir& dir) { - EXPECT_TRUE(dir.CreateUniqueTempDir()); - base::FilePath temp_file; - EXPECT_TRUE(base::CreateTemporaryFileInDir(dir.GetPath(), &temp_file)); - return temp_file; - } - - void ResetCacheDir() { - cache_root_dir_override_.reset(); - cache_client()->SetCacheDirForTesting( - base::PathService::CheckedGet(ash::DIR_DEVICE_LOCAL_ACCOUNT_IWA_CACHE)); - } - - private: SessionType GetSessionType() { return GetParam(); } base::test::ScopedFeatureList scoped_feature_list_{ @@ -257,106 +236,6 @@ EXPECT_FALSE(bundle_future.Get()); } -TEST_P(IwaCacheClientTest, CopyBundleToCache) { - base::ScopedTempDir original_file_dir; - base::FilePath original_file = CreateFileInDir(original_file_dir); - - TestFuture<base::expected<CopyBundleToCacheSuccess, CopyBundleToCacheError>> - copy_future; - cache_client()->CopyBundleToCache(original_file, kBundleId, kVersion1, - copy_future.GetCallback()); - - base::FilePath bundle_path = GetFullBundlePath(kBundleId, kVersion1); - EXPECT_THAT(copy_future.Get(), - ValueIs(Field(&CopyBundleToCacheSuccess::cached_bundle_path, - bundle_path))); - EXPECT_TRUE(base::PathExists(bundle_path)); -} - -TEST_P(IwaCacheClientTest, FailedToCreateDirForFileCopying) { - // Reset the cache directory back to the production value, since tests cannot - // create subdirectories there. - ResetCacheDir(); - - base::ScopedTempDir original_file_dir; - base::FilePath original_file = CreateFileInDir(original_file_dir); - - TestFuture<base::expected<CopyBundleToCacheSuccess, CopyBundleToCacheError>> - copy_future; - cache_client()->CopyBundleToCache(original_file, kBundleId, kVersion1, - copy_future.GetCallback()); - - EXPECT_THAT(copy_future.Get(), - ErrorIs(CopyBundleToCacheError::kFailedToCreateDir)); -} - -TEST_P(IwaCacheClientTest, FailedToCopyFile) { - TestFuture<base::expected<CopyBundleToCacheSuccess, CopyBundleToCacheError>> - copy_future; - cache_client()->CopyBundleToCache(base::FilePath("/do/not/exist/file"), - kBundleId, kVersion1, - copy_future.GetCallback()); - - EXPECT_THAT(copy_future.Get(), - ErrorIs(CopyBundleToCacheError::kFailedToCopyFile)); -} - -TEST_P(IwaCacheClientTest, CopyAndGet) { - base::ScopedTempDir original_file_dir; - base::FilePath original_file = CreateFileInDir(original_file_dir); - TestFuture<base::expected<CopyBundleToCacheSuccess, CopyBundleToCacheError>> - copy_future; - - cache_client()->CopyBundleToCache(original_file, kBundleId, kVersion1, - copy_future.GetCallback()); - EXPECT_TRUE(copy_future.Get().has_value()); - - TestFuture<std::optional<Bundle>> get_future; - cache_client()->GetCacheFilePath(kBundleId, kVersion1, - get_future.GetCallback()); - - EXPECT_EQ(get_future.Get()->path, GetFullBundlePath(kBundleId, kVersion1)); - EXPECT_EQ(get_future.Get()->version, kVersion1); -} - -TEST_P(IwaCacheClientTest, CopyBundleToCacheReplacesExistingFile) { - base::ScopedTempDir original_file_dir; - base::FilePath original_file = CreateFileInDir(original_file_dir); - - base::FilePath existing_bundle = CreateBundleInCacheDir(kBundleId, kVersion1); - - TestFuture<base::expected<CopyBundleToCacheSuccess, CopyBundleToCacheError>> - copy_future; - cache_client()->CopyBundleToCache(original_file, kBundleId, kVersion1, - copy_future.GetCallback()); - - EXPECT_THAT(copy_future.Get(), - ValueIs(Field(&CopyBundleToCacheSuccess::cached_bundle_path, - GetFullBundlePath(kBundleId, kVersion1)))); -} - -TEST_P(IwaCacheClientTest, CopyAnotherBundleVersion) { - base::ScopedTempDir original_file_dir; - base::FilePath original_file = CreateFileInDir(original_file_dir); - - base::FilePath existing_bundle_path = - CreateBundleInCacheDir(kBundleId, kVersion1); - - TestFuture<base::expected<CopyBundleToCacheSuccess, CopyBundleToCacheError>> - copy_future; - cache_client()->CopyBundleToCache(original_file, kBundleId, kVersion2, - copy_future.GetCallback()); - - base::FilePath updated_bundle_path = GetFullBundlePath(kBundleId, kVersion2); - EXPECT_THAT(copy_future.Get(), - ValueIs(Field(&CopyBundleToCacheSuccess::cached_bundle_path, - updated_bundle_path))); - - // Check that both versions are cached. - EXPECT_TRUE(base::PathExists(existing_bundle_path)); - EXPECT_TRUE(base::PathExists(updated_bundle_path)); -} - INSTANTIATE_TEST_SUITE_P( /* no prefix */, IwaCacheClientTest,
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_manager.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_manager.cc index a5056f5..8405a28 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_manager.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_manager.cc
@@ -30,17 +30,6 @@ using SessionType = IwaCacheClient::SessionType; -SessionType GetCurrentSessionType() { - if (chromeos::IsKioskSession()) { - return SessionType::kKiosk; - } - if (chromeos::IsManagedGuestSession()) { - return SessionType::kManagedGuestSession; - } - NOTREACHED() << "IwaCacheManager::Starts already checked the current session " - << "is kiosk or Managed Guest Session."; -} - std::vector<web_package::SignedWebBundleId> GetPolicyInstalledIwasForKiosk() { const std::vector<policy::DeviceLocalAccount> device_local_accounts = policy::GetDeviceLocalAccounts(ash::CrosSettings::Get()); @@ -104,7 +93,7 @@ } void IwaBundleCacheManager::CleanCacheForIwasDeletedFromPolicy() { - SessionType session_type = GetCurrentSessionType(); + SessionType session_type = IwaCacheClient::GetCurrentSessionType(); std::vector<web_package::SignedWebBundleId> iwas_in_policy = GetIwasInPolicy(session_type, *profile_);
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.cc index f5595739..e142792 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.cc
@@ -25,6 +25,7 @@ #include "services/network/public/cpp/shared_url_loader_factory.h" #if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h" #include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h" #include "chromeos/components/mgs/managed_guest_session_utils.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -141,12 +142,14 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::unique_ptr<IwaInstallCommandWrapper> install_command_wrapper, base::Value::List& log, + WebAppProvider* provider, ResultCallback callback) : install_options_(std::move(install_options)), install_source_type_(install_source_type), url_loader_factory_(std::move(url_loader_factory)), install_command_wrapper_(std::move(install_command_wrapper)), log_(log), + provider_(provider), callback_(std::move(callback)) { #if BUILDFLAG(IS_CHROMEOS) if (IsIwaBundleCacheEnabled()) { @@ -235,16 +238,13 @@ // installation. } -void IwaInstaller::OnBundleCopiedToCache( - base::expected<IwaCacheClient::CopyBundleToCacheSuccess, - IwaCacheClient::CopyBundleToCacheError> result) { +void IwaInstaller::OnBundleCopiedToCache(CopyBundleToCacheResult result) { if (result.has_value()) { log_->Append(base::Value(u"successfully copied bundle to the cache: " + - result->cached_bundle_path.LossyDisplayName())); + result->cached_bundle_path().LossyDisplayName())); } else { - log_->Append( - base::Value("failed to copy bundle to cache: " + - IwaCacheClient::CopyErrorToString(result.error()))); + log_->Append(base::Value("failed to copy bundle to cache: " + + CopyBundleToCacheErrorToString(result.error()))); } // TODO(crbug.com/388727600): add UMA metrics for failed and successful copy @@ -376,23 +376,9 @@ // TODO: crbug.com/306638108 - In the time it took to download everything, the // app might have already been installed by other means. - IwaSourceBundleProdFileOp bundle_source_operation = - IwaSourceBundleProdFileOp::kMove; - -#if BUILDFLAG(IS_CHROMEOS) - if (IsIwaBundleCacheEnabled()) { - // Bundle should be copied to the cache later, so we should not move it - // during the installation. - // Note: `bundle_` will be deleted later when this class is destroyed, since - // it is `ScopedTempWebBundleFile`, no need to delete it manually after the - // copying. - bundle_source_operation = IwaSourceBundleProdFileOp::kCopy; - } -#endif // BUILDFLAG(IS_CHROMEOS) - install_command_wrapper_->Install( GetIsolatedWebAppInstallSource(install_source_type_, bundle_.path(), - bundle_source_operation), + IwaSourceBundleProdFileOp::kMove), url_info, expected_version, base::BindOnce(&IwaInstaller::OnIwaInstalledFromInternet, weak_factory_.GetWeakPtr(), expected_version)); @@ -413,13 +399,19 @@ if (IsIwaBundleCacheEnabled()) { // Successfully installed bundles should be copied to cache, so next time // the installation will happen from the cache. - log_->Append( - base::Value("start copying bundle to cache after successful " - "installation from the Internet")); - cache_client_->CopyBundleToCache( - bundle_.path(), install_options_.web_bundle_id(), installed_version, - base::BindOnce(&IwaInstaller::OnBundleCopiedToCache, - weak_factory_.GetWeakPtr())); + log_->Append(base::Value( + "start copying bundle: " + install_options_.web_bundle_id().id() + + " to cache after successful installation from the Internet")); + + IsolatedWebAppUrlInfo url_info = + IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId( + install_options_.web_bundle_id()); + CHECK_DEREF(provider_.get()) + .scheduler() + .CopyIsolatedWebAppBundleToCache( + url_info, IwaCacheClient::GetCurrentSessionType(), + base::BindOnce(&IwaInstaller::OnBundleCopiedToCache, + weak_factory_.GetWeakPtr())); return; } #endif // BUILDFLAG(IS_CHROMEOS) @@ -466,7 +458,7 @@ std::move(url_loader_factory), std::make_unique<IwaInstaller::IwaInstallCommandWrapperImpl>( provider), - log, std::move(callback)); + log, provider, std::move(callback)); }); }
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.h b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.h index 1f66fdba..3f3cecf 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.h +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.h
@@ -20,6 +20,7 @@ #include "chrome/browser/web_applications/web_app_command_scheduler.h" #if BUILDFLAG(IS_CHROMEOS) +#include "chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h" #include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h" #endif // BUILDFLAG(IS_CHROMEOS) @@ -111,6 +112,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, std::unique_ptr<IwaInstallCommandWrapper> install_command_wrapper, base::Value::List& log, + WebAppProvider* provider, ResultCallback callback); ~IwaInstaller(); @@ -134,9 +136,7 @@ // Bundle should be copied to cache after the successful installation from the // Internet. - void OnBundleCopiedToCache( - base::expected<IwaCacheClient::CopyBundleToCacheSuccess, - IwaCacheClient::CopyBundleToCacheError> result); + void OnBundleCopiedToCache(CopyBundleToCacheResult result); #endif // BUILDFLAG(IS_CHROMEOS) void CreateTempFile(base::OnceClosure next_step_callback); @@ -177,6 +177,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; std::unique_ptr<IwaInstallCommandWrapper> install_command_wrapper_; raw_ref<base::Value::List> log_; + const raw_ptr<web_app::WebAppProvider> provider_; ResultCallback callback_; ScopedTempWebBundleFile bundle_;
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc index eb8bbb18..a0b8b756 100644 --- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc +++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_ash_browsertest.cc
@@ -59,8 +59,8 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/policy/core/common/cloud/test/policy_builder.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_namespace.h" #include "components/policy/policy_constants.h"
diff --git a/chrome/browser/web_applications/isolated_web_apps/test/test_iwa_installer_factory.cc b/chrome/browser/web_applications/isolated_web_apps/test/test_iwa_installer_factory.cc index 7fdb5b7..d5507f4 100644 --- a/chrome/browser/web_applications/isolated_web_apps/test/test_iwa_installer_factory.cc +++ b/chrome/browser/web_applications/isolated_web_apps/test/test_iwa_installer_factory.cc
@@ -70,6 +70,7 @@ return std::make_unique<IwaInstaller>( std::move(install_options), install_source_type, std::move(url_loader_factory), std::move(install_command_wrapper), log, + provider, base::BindOnce( [](TestIwaInstallerFactory* installer_instance, IwaInstaller::ResultCallback callback, webapps::AppId app_id,
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.cc b/chrome/browser/web_applications/web_app_command_scheduler.cc index b50a575..4a3cc14 100644 --- a/chrome/browser/web_applications/web_app_command_scheduler.cc +++ b/chrome/browser/web_applications/web_app_command_scheduler.cc
@@ -89,6 +89,7 @@ #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/web_applications/isolated_web_apps/commands/cleanup_bundle_cache_command.h" +#include "chrome/browser/web_applications/isolated_web_apps/commands/copy_bundle_to_cache_command.h" #include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_client.h" #else // !BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/web_applications/jobs/link_capturing.h" @@ -374,6 +375,17 @@ } #if BUILDFLAG(IS_CHROMEOS) +void WebAppCommandScheduler::CopyIsolatedWebAppBundleToCache( + const IsolatedWebAppUrlInfo& url_info, + IwaCacheClient::SessionType session_type, + base::OnceCallback<void(CopyBundleToCacheResult)> callback, + const base::Location& call_location) { + provider_->command_manager().ScheduleCommand( + std::make_unique<CopyBundleToCacheCommand>( + url_info, session_type, *profile_, std::move(callback)), + call_location); +} + void WebAppCommandScheduler::CleanupIsolatedWebAppBundleCache( const std::vector<web_package::SignedWebBundleId>& iwas_to_keep_in_cache, IwaCacheClient::SessionType session_type,
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.h b/chrome/browser/web_applications/web_app_command_scheduler.h index 2affcee..0be38c4 100644 --- a/chrome/browser/web_applications/web_app_command_scheduler.h +++ b/chrome/browser/web_applications/web_app_command_scheduler.h
@@ -80,6 +80,8 @@ #if BUILDFLAG(IS_CHROMEOS) class CleanupBundleCacheSuccess; class CleanupBundleCacheError; +class CopyBundleToCacheSuccess; +enum class CopyBundleToCacheError; #endif // BUILDFLAG(IS_CHROMEOS) // The command scheduler is the main API to access the web app system. The @@ -298,6 +300,14 @@ const base::Location& call_location = FROM_HERE); #if BUILDFLAG(IS_CHROMEOS) + // Copies IWA bundle file to the cache for `session_type`. + void CopyIsolatedWebAppBundleToCache( + const IsolatedWebAppUrlInfo& url_info, + IwaCacheClient::SessionType session_type, + base::OnceCallback<void(base::expected<CopyBundleToCacheSuccess, + CopyBundleToCacheError>)> callback, + const base::Location& call_location = FROM_HERE); + // Cleans all IWA cached bundles for `session_type` which are not in the // `iwas_to_keep_in_cache`. void CleanupIsolatedWebAppBundleCache(
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc index 24ef987..d64a8613 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -49,6 +49,7 @@ #include "chrome/browser/webauthn/cablev2_devices.h" #include "chrome/browser/webauthn/enclave_manager.h" #include "chrome/browser/webauthn/gpm_enclave_controller.h" +#include "chrome/browser/webauthn/immediate_request_rate_limiter_factory.h" #include "chrome/browser/webauthn/passkey_model_factory.h" #include "chrome/browser/webauthn/webauthn_metrics_util.h" #include "chrome/browser/webauthn/webauthn_pref_names.h" @@ -64,6 +65,7 @@ #include "components/sync/service/sync_service.h" #include "components/trusted_vault/frontend_trusted_vault_connection.h" #include "components/user_prefs/user_prefs.h" +#include "components/webauthn/core/browser/immediate_request_rate_limiter.h" #include "components/webauthn/core/browser/passkey_model.h" #include "content/public/browser/authenticator_request_client_delegate.h" #include "content/public/browser/browser_context.h" @@ -945,11 +947,21 @@ return false; } - // Always return not found immediate in incognito. + // Always return not allowed immediate in incognito. if (profile()->IsOffTheRecord()) { return true; } + if (auto* rate_limiter = + ImmediateRequestRateLimiterFactory::GetForProfile(profile())) { + const url::Origin origin = GetRenderFrameHost()->GetLastCommittedOrigin(); + if (!rate_limiter->IsRequestAllowed(origin)) { + FIDO_LOG(ERROR) + << "Immediate request rate limit exceeded for the origin."; + return true; + } + } + if (data.recognized_credentials.size() + passwords.size() == 0) { return true; }
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc index 5790af8..7672d48 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate_unittest.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/webauthn/authenticator_request_dialog_model.h" #include "chrome/browser/webauthn/chrome_web_authentication_delegate.h" +#include "chrome/browser/webauthn/immediate_request_rate_limiter_factory.h" #include "chrome/browser/webauthn/passkey_model_factory.h" #include "chrome/browser/webauthn/password_credential_controller.h" #include "chrome/browser/webauthn/webauthn_pref_names.h" @@ -40,6 +41,7 @@ #include "components/sync/base/user_selectable_type.h" #include "components/sync/protocol/webauthn_credential_specifics.pb.h" #include "components/sync/test/test_sync_service.h" +#include "components/webauthn/core/browser/immediate_request_rate_limiter.h" #include "components/webauthn/core/browser/passkey_model.h" #include "components/webauthn/core/browser/test_passkey_model.h" #include "content/public/browser/authenticator_request_client_delegate.h" @@ -148,6 +150,10 @@ class ChromeAuthenticatorRequestDelegateTest : public ChromeRenderViewHostTestHarness { public: + ChromeAuthenticatorRequestDelegateTest() + : ChromeRenderViewHostTestHarness( + base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); PasskeyModelFactory::GetInstance()->SetTestingFactoryAndUse( @@ -157,6 +163,12 @@ return std::make_unique<webauthn::TestPasskeyModel>(); })); ChromeAuthenticatorRequestDelegate::SetGlobalObserverForTesting(&observer_); + + ImmediateRequestRateLimiterFactory::GetInstance()->SetTestingFactoryAndUse( + profile(), base::BindRepeating([](content::BrowserContext* context) + -> std::unique_ptr<KeyedService> { + return std::make_unique<webauthn::ImmediateRequestRateLimiter>(); + })); } void TearDown() override { @@ -1019,6 +1031,78 @@ std::move(callback).Run({}); } +TEST_F(ChromeAuthenticatorRequestDelegateTest, ImmediateMediationRateLimit) { + constexpr base::TimeDelta kWindowSize = base::Minutes(1); + constexpr int kMaxRequestsPerWindow = 2; + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeatureWithParameters( + device::kWebAuthnImmediateRequestRateLimit, + {{"max_requests", base::NumberToString(kMaxRequestsPerWindow)}, + {"window_seconds", "60"}}); + // Navigate to commit the origin. + content::WebContentsTester::For(web_contents()) + ->NavigateAndCommit(GURL(kOrigin)); + ChromeAuthenticatorRequestDelegate delegate(main_rfh()); + delegate.SetRelyingPartyId(kRpId); + delegate.SetUIPresentation(UIPresentation::kModalImmediate); + + // Register a mock callback for the immediate_not_found case. + // This is called when MaybeHandleImmediateMediation returns true (e.g., rate + // limited). + base::MockCallback<base::OnceClosure> mock_immediate_not_found_callback; + delegate.RegisterActionCallbacks( + /*cancel_callback=*/base::DoNothing(), + mock_immediate_not_found_callback.Get(), + /*start_over_callback=*/base::DoNothing(), + /*account_preselected_callback=*/base::DoNothing(), + /*password_selected_callback=*/base::DoNothing(), + /*request_callback=*/base::DoNothing(), + /*bluetooth_adapter_power_on_callback=*/base::DoNothing(), + /*bluetooth_query_status_callback=*/base::DoNothing()); + + TransportAvailabilityInfo transports_info; + transports_info.request_type = device::FidoRequestType::kGetAssertion; + transports_info.recognized_credentials = { + device::DiscoverableCredentialMetadata( + device::AuthenticatorType::kEnclave, kRpId, {}, + device::PublicKeyCredentialUserEntity(), + /*provider_name=*/std::nullopt)}; + + for (int i = 0; i < kMaxRequestsPerWindow; ++i) { + SCOPED_TRACE(testing::Message() << "Request " << i + 1); + EXPECT_CALL(mock_immediate_not_found_callback, Run).Times(0); + // Need to pass a copy as OnTransportAvailabilityEnumerated takes by value. + TransportAvailabilityInfo info_copy = transports_info; + delegate.OnTransportAvailabilityEnumerated(std::move(info_copy)); + testing::Mock::VerifyAndClearExpectations( + &mock_immediate_not_found_callback); + } + + // The next request should be rate-limited (callback is called). + { + SCOPED_TRACE(testing::Message() << "Request " << kMaxRequestsPerWindow + 1); + EXPECT_CALL(mock_immediate_not_found_callback, Run).Times(1); + TransportAvailabilityInfo info_copy = transports_info; + delegate.OnTransportAvailabilityEnumerated(std::move(info_copy)); + testing::Mock::VerifyAndClearExpectations( + &mock_immediate_not_found_callback); + } + + // Advance time beyond the window. + task_environment()->FastForwardBy(kWindowSize + base::Seconds(1)); + + // The next request should be allowed again (callback not called). + { + SCOPED_TRACE(testing::Message() << "Request after time window"); + EXPECT_CALL(mock_immediate_not_found_callback, Run).Times(0); + TransportAvailabilityInfo info_copy = transports_info; + delegate.OnTransportAvailabilityEnumerated(std::move(info_copy)); + testing::Mock::VerifyAndClearExpectations( + &mock_immediate_not_found_callback); + } +} + } // namespace #if BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/webauthn/immediate_request_rate_limiter_factory.cc b/chrome/browser/webauthn/immediate_request_rate_limiter_factory.cc new file mode 100644 index 0000000..2b7f16c --- /dev/null +++ b/chrome/browser/webauthn/immediate_request_rate_limiter_factory.cc
@@ -0,0 +1,37 @@ +// 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/webauthn/immediate_request_rate_limiter_factory.h" + +#include "chrome/browser/profiles/profile.h" +#include "components/webauthn/core/browser/immediate_request_rate_limiter.h" + +// static +webauthn::ImmediateRequestRateLimiter* +ImmediateRequestRateLimiterFactory::GetForProfile( + content::BrowserContext* context) { + return static_cast<webauthn::ImmediateRequestRateLimiter*>( + GetInstance()->GetServiceForBrowserContext(context, /*create=*/true)); +} + +// static +ImmediateRequestRateLimiterFactory* +ImmediateRequestRateLimiterFactory::GetInstance() { + static base::NoDestructor<ImmediateRequestRateLimiterFactory> instance; + return instance.get(); +} + +ImmediateRequestRateLimiterFactory::ImmediateRequestRateLimiterFactory() + : ProfileKeyedServiceFactory( + "ImmediateRequestRateLimiter", + ProfileSelections::BuildForRegularProfile()) {} + +ImmediateRequestRateLimiterFactory::~ImmediateRequestRateLimiterFactory() = + default; + +std::unique_ptr<KeyedService> +ImmediateRequestRateLimiterFactory::BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const { + return std::make_unique<webauthn::ImmediateRequestRateLimiter>(); +}
diff --git a/chrome/browser/webauthn/immediate_request_rate_limiter_factory.h b/chrome/browser/webauthn/immediate_request_rate_limiter_factory.h new file mode 100644 index 0000000..2ddc44c --- /dev/null +++ b/chrome/browser/webauthn/immediate_request_rate_limiter_factory.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 CHROME_BROWSER_WEBAUTHN_IMMEDIATE_REQUEST_RATE_LIMITER_FACTORY_H_ +#define CHROME_BROWSER_WEBAUTHN_IMMEDIATE_REQUEST_RATE_LIMITER_FACTORY_H_ + +#include "base/no_destructor.h" +#include "chrome/browser/profiles/profile_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} + +namespace webauthn { +class ImmediateRequestRateLimiter; +} + +class ImmediateRequestRateLimiterFactory : public ProfileKeyedServiceFactory { + public: + static webauthn::ImmediateRequestRateLimiter* GetForProfile( + content::BrowserContext* context); + static ImmediateRequestRateLimiterFactory* GetInstance(); + + ImmediateRequestRateLimiterFactory( + const ImmediateRequestRateLimiterFactory&) = delete; + ImmediateRequestRateLimiterFactory& operator=( + const ImmediateRequestRateLimiterFactory&) = delete; + + private: + friend class base::NoDestructor<ImmediateRequestRateLimiterFactory>; + + ImmediateRequestRateLimiterFactory(); + ~ImmediateRequestRateLimiterFactory() override; + + // BrowserContextKeyedServiceFactory: + std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext( + content::BrowserContext* context) const override; +}; + +#endif // CHROME_BROWSER_WEBAUTHN_IMMEDIATE_REQUEST_RATE_LIMITER_FACTORY_H_
diff --git a/chrome/browser/win/BUILD.gn b/chrome/browser/win/BUILD.gn index 3663e50..94ff012 100644 --- a/chrome/browser/win/BUILD.gn +++ b/chrome/browser/win/BUILD.gn
@@ -13,3 +13,14 @@ "//ui/native_theme", ] } + +source_set("cloud_synced_folder_checker") { + sources = [ + "cloud_synced_folder_checker.cc", + "cloud_synced_folder_checker.h", + ] + deps = [ + "//base", + "//chrome/common:constants", + ] +}
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index bf98545..26cc3c53 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1746552233-58978cccbebf037a10c3dd2b5fd4cbc833b76c25-30165321783ced200f97bf7d0630e468c6dfecd0.profdata +chrome-android32-main-1746596669-ef8f8aa2940bd8e3489db976acee09a6c6c0bd5c-f962687515b7bc001bf4380904b6da50ba8bce93.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 2163d93..b15487c 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1746551424-0a92db44a4b5d6fb6dab47c5b2b8e6f331774811-0e99b96cdd6f28cdae67586273c5116547bc7c08.profdata +chrome-android64-main-1746610755-301f078e07fffda94a9613609e7b8e51d71e59e8-cd85033399f79ffaf7515e015ebc8e4efd6e7946.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 80e163e..b155f474 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1746532755-db4a6f3a971a04bbb04b92f04f08c9f1f214bfcb-494b8e90e23862cde023bbf172195f22d227a0f6.profdata +chrome-linux-main-1746596669-47b28193f25eb9fc6cde369697a0eead37c766dc-f962687515b7bc001bf4380904b6da50ba8bce93.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index b97b8a32..f8e42e4 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1746552233-e3b77a96e6271f28332dc33ccb437ecc4584dda8-30165321783ced200f97bf7d0630e468c6dfecd0.profdata +chrome-mac-arm-main-1746611847-a37b7979e47bc6116f862351c4c6942108e07406-796016156828373f03c583de4d0cea2e8338a96e.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index f24f15e..945449c 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1746532755-7c187b0b569358e12914392f48696317e7b01a9a-494b8e90e23862cde023bbf172195f22d227a0f6.profdata +chrome-mac-main-1746596669-a41951026aaaa090d4e91390aba9925bceb0d77b-f962687515b7bc001bf4380904b6da50ba8bce93.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index 35d19c78f..ccc92e09 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1746532755-6cdd90db30eeca99b8a7ee87af7d271881097780-494b8e90e23862cde023bbf172195f22d227a0f6.profdata +chrome-win-arm64-main-1746596669-f63224fa8420683ad9dbd4186e6b4f4157627982-f962687515b7bc001bf4380904b6da50ba8bce93.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 1b9e1c1..42c5814 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1746532755-5ffa733f407730a139990d436115757e25f2f1ef-494b8e90e23862cde023bbf172195f22d227a0f6.profdata +chrome-win32-main-1746596669-5d433969caa89462c395d3b15c51a26d637b1aff-f962687515b7bc001bf4380904b6da50ba8bce93.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index f29635e..6942990 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1746510390-3d3d31f355983ee63806e7b06169f5f00494da46-d34d80d0e5df7e43587a2fb485d60228efe44aec.profdata +chrome-win64-main-1746575735-abdf678ab1bebcfdc0d37b724b37f63e82d7e6c1-3e7a899eb30f7f372790ede75edc6f47fbedf024.profdata
diff --git a/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc b/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc index ff74e7e5..ec44b8c 100644 --- a/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc +++ b/chrome/common/extensions/api/storage/storage_schema_manifest_handler_unittest.cc
@@ -12,12 +12,15 @@ #include "base/files/scoped_temp_dir.h" #include "base/values.h" #include "components/version_info/version_info.h" +#include "extensions/buildflags/buildflags.h" #include "extensions/common/extension.h" #include "extensions/common/features/feature_channel.h" #include "extensions/common/file_util.h" #include "extensions/common/manifest.h" #include "testing/gtest/include/gtest/gtest.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + namespace extensions { class StorageSchemaManifestHandlerTest : public testing::Test {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 1764e0d2..b897c99f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1505,6 +1505,7 @@ "../browser/extensions/api/runtime/runtime_apitest.cc", "../browser/extensions/api/scripting/scripting_apitest.cc", "../browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc", + "../browser/extensions/api/storage/settings_apitest.cc", "../browser/extensions/api/system_network/system_network_apitest.cc", "../browser/extensions/api/test/apitest_apitest.cc", "../browser/extensions/api/web_accessible_resources_apitest.cc", @@ -2245,10 +2246,6 @@ "//chrome/browser/preloading/search_preload:browser_tests", "//chrome/browser/privacy_budget:browser_tests", "//chrome/browser/privacy_sandbox:browser_tests", - - # TODO(413315837): Remove this dep when privacy_sandbox_countries_browsertest.cc - # gets build off of c/b/privacy_sandbox/BUILD.gn. - "//chrome/browser/privacy_sandbox:headers", "//chrome/browser/profiles:profile_util", "//chrome/browser/profiling_host:profiling_browsertests", "//chrome/browser/promos:utils", @@ -2323,6 +2320,7 @@ "//chrome/browser/ui/tabs:tab_menu", "//chrome/browser/ui/tabs:tab_model", "//chrome/browser/ui/tabs:tabs_public", + "//chrome/browser/ui/tabs/tab_strip_api:browser_tests", "//chrome/browser/ui/toasts", "//chrome/browser/ui/toolbar/cast", "//chrome/browser/ui/user_education", @@ -4336,7 +4334,6 @@ "../browser/extensions/api/settings_private/settings_private_apitest.cc", "../browser/extensions/api/side_panel/side_panel_apitest.cc", "../browser/extensions/api/socket/socket_apitest.cc", - "../browser/extensions/api/storage/settings_apitest.cc", "../browser/extensions/api/system_display/system_display_extension_apitest.cc", "../browser/extensions/api/system_private/system_private_apitest.cc", "../browser/extensions/api/tab_capture/tab_capture_apitest.cc", @@ -5317,7 +5314,6 @@ "//chromeos/ash/experiences/arc:prefs", "//chromeos/ash/experiences/arc/session:arc_base_enums", "//chromeos/ash/experiences/system_web_apps/types", - "//chromeos/ash/services/assistant:lib", "//chromeos/ash/services/assistant/public/cpp", "//chromeos/ash/services/assistant/public/proto", "//chromeos/ash/services/auth_factor_config", @@ -6386,7 +6382,6 @@ "../browser/page_load_metrics/observers/non_tab_webui_page_load_metrics_observer_unittest.cc", "../browser/performance_manager/metrics/metrics_provider_desktop_unittest.cc", "../browser/policy/messaging_layer/util/reporting_server_connector_unittest.cc", - "../browser/privacy_sandbox/privacy_sandbox_survey_desktop_controller_unittest.cc", "../browser/screen_ai/screen_ai_install_state_unittest.cc", "../browser/segmentation_platform/client_util/local_tab_handler_unittest.cc", "../browser/site_protection/site_protection_metrics_observer_unittest.cc", @@ -6404,10 +6399,6 @@ ] } - if (is_android) { - sources += [ "../browser/privacy_sandbox/privacy_sandbox_activity_types_service_unittest.cc" ] - } - if (is_mac) { sources += [ "../browser/metrics/google_update_metrics_provider_mac_unittest.cc" ] @@ -7468,7 +7459,7 @@ "../browser/autofill/android/save_update_address_profile_message_controller_unittest.cc", "../browser/autofill/android/save_update_address_profile_prompt_controller_unittest.cc", "../browser/autofill/autofill_save_card_infobar_delegate_mobile_unittest.cc", - "../browser/auxiliary_search/auxiliary_search_provider_unittest.cc", + "../browser/auxiliary_search/auxiliary_search_top_site_provider_bridge_unittest.cc", "../browser/bookmarks//android/bookmark_bridge_unittest.cc", "../browser/commerce/merchant_viewer/merchant_viewer_data_manager_unittest.cc", "../browser/device_reauth/android/device_authenticator_android_unittest.cc", @@ -8579,6 +8570,7 @@ "//ash/webui/recorder_app_ui", "//ash/webui/scanning", "//ash/webui/settings/public/constants:mojom", + "//chrome/browser:global_features", "//chrome/browser/accessibility:test_support", "//chrome/browser/accessibility/media_app/test:test_support", "//chrome/browser/apps/app_service/promise_apps/proto", @@ -8706,6 +8698,7 @@ "//chrome/services/sharing/nearby/decoder", "//chrome/services/sharing/public/cpp", "//chrome/services/speech:lib", + "//chrome/test:test_support", "//chromeos/ash/components/assistant:buildflags", "//chromeos/ash/components/audio", "//chromeos/ash/components/browser_context_helper", @@ -8785,6 +8778,7 @@ "//chromeos/ui/frame:test_support", "//chromeos/ui/wm", "//components/app_constants", + "//components/application_locale_storage", "//components/cross_device/nearby:nearby", "//components/metrics/structured:structured_events", "//components/metrics/structured:structured_metrics_features", @@ -8927,6 +8921,7 @@ "../browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc", "../browser/extensions/api/storage/managed_value_store_cache_unittest.cc", "../browser/extensions/api/storage/policy_value_store_unittest.cc", + "../browser/extensions/api/storage/settings_sync_unittest.cc", "../browser/extensions/api/storage/storage_session_unittest.cc", "../browser/extensions/api/webstore_private/extension_install_status_unittest.cc", "../browser/extensions/api/webstore_private/webstore_private_unittest.cc", @@ -9091,7 +9086,6 @@ "../browser/extensions/api/socket/tls_socket_unittest.cc", "../browser/extensions/api/socket/udp_socket_unittest.cc", "../browser/extensions/api/sockets_tcp_server/sockets_tcp_server_api_unittest.cc", - "../browser/extensions/api/storage/settings_sync_unittest.cc", "../browser/extensions/api/streams_private/streams_private_manifest_unittest.cc", "../browser/extensions/api/tab_groups/tab_groups_api_unittest.cc", "../browser/extensions/api/tabs/tabs_api_unittest.cc", @@ -11608,7 +11602,6 @@ "//chromeos/ui/frame", "//chromeos/ui/frame:test_support", "//chromeos/ui/frame:test_support", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", "//components/file_access:test_support", "//components/reporting/client:report_queue",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 8775212..8bb3cc986 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -243,6 +243,7 @@ "javatests/src/org/chromium/chrome/test/transit/omnibox/FakeOmniboxSuggestions.java", "javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxEnteredTextFacility.java", "javatests/src/org/chromium/chrome/test/transit/omnibox/OmniboxFacility.java", + "javatests/src/org/chromium/chrome/test/transit/page/BasePageStation.java", "javatests/src/org/chromium/chrome/test/transit/page/IncognitoWebPageAppMenuFacility.java", "javatests/src/org/chromium/chrome/test/transit/page/NativePageCondition.java", "javatests/src/org/chromium/chrome/test/transit/page/PageAppMenuFacility.java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AppMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AppMenuFacility.java index 1a2ce95..39c611b 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AppMenuFacility.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AppMenuFacility.java
@@ -127,6 +127,7 @@ public static final @IdRes int NEW_TAB_ID = R.id.new_tab_menu_id; public static final @IdRes int NEW_INCOGNITO_TAB_ID = R.id.new_incognito_tab_menu_id; + public static final @IdRes int NEW_WINDOW_ID = R.id.new_window_menu_id; public static final @IdRes int HISTORY_ID = R.id.open_history_menu_id; public static final @IdRes int DELETE_BROWSING_DATA_ID = R.id.quick_delete_menu_id; public static final @IdRes int DOWNLOADS_ID = R.id.downloads_menu_id; @@ -172,6 +173,11 @@ .build(); } + /** Default behavior for "Open new window". */ + protected RegularNewTabPageStation createNewWindowStation() { + return RegularNewTabPageStation.newBuilder().withEntryPoint().build(); + } + /** Default behavior for "Delete browsing data". */ protected QuickDeleteDialogFacility createQuickDeleteDialogFacility() { return new QuickDeleteDialogFacility();
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AutoResetCtaTransitTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AutoResetCtaTransitTestRule.java index bdf462e..4fbba9a8 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AutoResetCtaTransitTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/AutoResetCtaTransitTestRule.java
@@ -10,7 +10,6 @@ import org.junit.runners.model.Statement; import org.chromium.base.test.transit.BatchedPublicTransitRule; -import org.chromium.base.test.transit.EntryPointSentinelStation; import org.chromium.base.test.transit.Station; import org.chromium.base.test.transit.TrafficControl; import org.chromium.build.annotations.NullMarked; @@ -20,6 +19,8 @@ import org.chromium.chrome.test.transit.page.WebPageStation; import org.chromium.components.embedder_support.util.UrlConstants; +import java.util.List; + /** * Rule for integration tests that reuse a ChromeTabbedActivity but reset tab state between cases. * @@ -54,18 +55,23 @@ * <p>From the second test onwards, state was reset by {@link BlankCTATabInitialStateRule}. */ public WebPageStation startOnBlankPage() { - // Null in the first test, non-null from the second test onwards. - Station<?> homeStation = TrafficControl.getActiveStation(); - if (homeStation == null) { - EntryPointSentinelStation entryPoint = new EntryPointSentinelStation(); - entryPoint.setAsEntryPoint(); - homeStation = entryPoint; + // Empty in the first test, should be size 1 from the second test onwards. + List<Station<?>> activeStations = TrafficControl.getActiveStations(); + if (activeStations.size() > 1) { + throw new IllegalStateException( + String.format( + "Expected at most one active station, found %d", + activeStations.size())); } + // Remove the last station of the previous test from |activeStations| to go to an entry + // point again. + TrafficControl.hopOffPublicTransit(); + WebPageStation entryPageStation = WebPageStation.newBuilder().withEntryPoint().build(); // Wait for the Conditions to be met to return an active PageStation. - return homeStation.travelToSync(entryPageStation, /* trigger= */ null); + return Station.spawnSync(entryPageStation, /* trigger= */ null); } /**
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/IncognitoNewTabPageAppMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/IncognitoNewTabPageAppMenuFacility.java index 961ebdfa..8425d5ce 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/IncognitoNewTabPageAppMenuFacility.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/IncognitoNewTabPageAppMenuFacility.java
@@ -15,6 +15,7 @@ mNewIncognitoTab = declareMenuItemToStation( items, NEW_INCOGNITO_TAB_ID, this::createIncognitoNewTabPageStation); + mNewWindow = declarePossibleMenuItem(items, NEW_WINDOW_ID, this::handleOpenNewWindow); declareStubMenuItem(items, HISTORY_ID); declareAbsentMenuItem(items, DELETE_BROWSING_DATA_ID);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageAppMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageAppMenuFacility.java index 4c5fa54..a384686 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageAppMenuFacility.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageAppMenuFacility.java
@@ -18,6 +18,7 @@ mNewIncognitoTab = declareMenuItemToStation( items, NEW_INCOGNITO_TAB_ID, this::createIncognitoNewTabPageStation); + mNewWindow = declarePossibleMenuItem(items, NEW_WINDOW_ID, this::handleOpenNewWindow); declareStubMenuItem(items, HISTORY_ID); mQuickDelete =
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java index caae0ace..7dc84bb 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/ntp/RegularNewTabPageStation.java
@@ -37,7 +37,6 @@ public ViewElement<View> searchBoxElement; public ViewElement<UrlBar> urlBarElement; public ViewElement<View> logoElement; - public ViewElement<View> mvtsContainerElement; public Element<NewTabPage> nativePageElement; protected <T extends RegularNewTabPageStation> RegularNewTabPageStation(Builder<T> builder) { @@ -64,7 +63,6 @@ logoElement = elements.declareView(viewSpec(withId(R.id.search_provider_logo))); searchBoxElement = elements.declareView(viewSpec(withId(R.id.search_box))); - mvtsContainerElement = elements.declareView(viewSpec(withId(R.id.mv_tiles_container))); nativePageElement = elements.declareEnterConditionAsElement(
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/BasePageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/BasePageStation.java new file mode 100644 index 0000000..1835437 --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/BasePageStation.java
@@ -0,0 +1,491 @@ +// 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.test.transit.page; + +import static org.chromium.base.test.transit.Condition.whether; + +import org.chromium.base.ThreadUtils; +import org.chromium.base.supplier.Supplier; +import org.chromium.base.test.transit.CallbackCondition; +import org.chromium.base.test.transit.Condition; +import org.chromium.base.test.transit.ConditionStatus; +import org.chromium.base.test.transit.ConditionStatusWithResult; +import org.chromium.base.test.transit.ConditionWithResult; +import org.chromium.base.test.transit.Element; +import org.chromium.base.test.transit.Elements; +import org.chromium.base.test.transit.Facility; +import org.chromium.base.test.transit.Station; +import org.chromium.base.test.transit.Transition; +import org.chromium.base.test.transit.Transition.Trigger; +import org.chromium.chrome.browser.app.ChromeActivity; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.TabModel; +import org.chromium.chrome.browser.tabmodel.TabModelObserver; +import org.chromium.content_public.browser.LoadUrlParams; +import org.chromium.ui.base.PageTransition; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; + +/** + * Base class for the screen that shows a web or native page in ChromeActivity. {@link PageStation} + * subclasses this for ChromeTabbedActivity and {@link CctPageStation} for CustomTabActivity. + * + * <p>Contains extra configurable Conditions such as waiting for a tab to be created, selected, have + * the expected title, etc. + * + * @param <HostActivity> The type of activity this station is associate to. + */ +public class BasePageStation<HostActivity extends ChromeActivity> extends Station<HostActivity> { + + /** + * Basic builder for all BasePageStation subclasses. + * + * @param <ActivityT> the subclass of ChromeActivity on which the BasePageStation being built is + * based upon. + * @param <PageT> the subclass of BasePageStation to build. + * @param <BuilderT> the subclass of this Builder. + */ + public static class Builder< + ActivityT extends ChromeActivity, + PageT extends BasePageStation<ActivityT>, + BuilderT extends Builder<ActivityT, PageT, BuilderT>> { + protected final Function<BuilderT, PageT> mFactoryMethod; + protected boolean mIsEntryPoint; + protected Boolean mIncognito; + protected Integer mNumTabsBeingOpened; + protected Integer mNumTabsBeingSelected; + protected Tab mTabAlreadySelected; + protected String mExpectedUrlSubstring; + protected String mExpectedTitle; + protected List<Facility<PageT>> mFacilities; + + public Builder(Function<BuilderT, PageT> factoryMethod) { + mFactoryMethod = factoryMethod; + } + + public BuilderT self() { + return (BuilderT) this; + } + + public BuilderT withIncognito(boolean incognito) { + mIncognito = incognito; + return self(); + } + + public BuilderT withIsOpeningTabs(int numTabsBeingOpened) { + assert numTabsBeingOpened >= 0; + mNumTabsBeingOpened = numTabsBeingOpened; + return self(); + } + + public BuilderT withTabAlreadySelected(Tab currentTab) { + mTabAlreadySelected = currentTab; + mNumTabsBeingSelected = 0; + return self(); + } + + public BuilderT withIsSelectingTabs(int numTabsBeingSelected) { + assert numTabsBeingSelected > 0 + : "Use withIsSelectingTab() if the PageStation is still in the current tab"; + mNumTabsBeingSelected = numTabsBeingSelected; + // Commonly already set via initFrom(). + mTabAlreadySelected = null; + return self(); + } + + public BuilderT withEntryPoint() { + mNumTabsBeingOpened = 0; + mNumTabsBeingSelected = 0; + mIsEntryPoint = true; + return self(); + } + + public BuilderT withExpectedUrlSubstring(String value) { + mExpectedUrlSubstring = value; + return self(); + } + + public BuilderT withExpectedTitle(String title) { + mExpectedTitle = title; + return self(); + } + + public BuilderT withFacility(Facility<PageT> facility) { + if (mFacilities == null) { + mFacilities = new ArrayList<>(); + } + mFacilities.add(facility); + return self(); + } + + public BuilderT initFrom(BasePageStation<ActivityT> previousStation) { + if (mIncognito == null) { + mIncognito = previousStation.mIncognito; + } + if (mNumTabsBeingOpened == null) { + mNumTabsBeingOpened = 0; + } + if (mNumTabsBeingSelected == null) { + mNumTabsBeingSelected = 0; + } + if (mTabAlreadySelected == null && mNumTabsBeingSelected == 0) { + mTabAlreadySelected = previousStation.loadedTabElement.getFromPast(); + } + // Cannot copy over facilities because we have no way to clone them. It's also not + // obvious that we should... + return self(); + } + + public PageT build() { + return mFactoryMethod.apply(self()); + } + } + + protected final boolean mIncognito; + protected final boolean mIsEntryPoint; + protected final int mNumTabsBeingOpened; + protected final int mNumTabsBeingSelected; + protected final Tab mTabAlreadySelected; + protected final String mExpectedUrlSubstring; + protected final String mExpectedTitle; + public Element<Tab> activityTabElement; + protected Supplier<Tab> mSelectedTabSupplier; + public Element<Tab> loadedTabElement; + + protected <T extends BasePageStation<HostActivity>> BasePageStation( + Class<HostActivity> activityClass, Builder<HostActivity, T, ?> builder) { + super(activityClass); + + // incognito is optional and defaults to false + mIncognito = builder.mIncognito == null ? false : builder.mIncognito; + + // isEntryPoint is optional and defaults to false + mIsEntryPoint = builder.mIsEntryPoint; + + // mNumTabsBeingOpened is required + assert builder.mNumTabsBeingOpened != null + : "PageStation.Builder needs withIsOpeningTabs() or initFrom()"; + mNumTabsBeingOpened = builder.mNumTabsBeingOpened; + + // mNumTabsBeingSelected is required + assert builder.mNumTabsBeingSelected != null + : "PageStation.Builder needs withIsSelectingTabs(), withTabAlreadySelected() or" + + " initFrom()"; + mNumTabsBeingSelected = builder.mNumTabsBeingSelected; + + // Pages must have an already selected tab, or be selecting a tab. + mTabAlreadySelected = builder.mTabAlreadySelected; + assert mIsEntryPoint || (mTabAlreadySelected != null) != (mNumTabsBeingSelected != 0) + : String.format( + "mTabAlreadySelected=%s mNumTabsBeingSelected=%s", + mTabAlreadySelected, mNumTabsBeingSelected); + + // URL substring is optional. + mExpectedUrlSubstring = builder.mExpectedUrlSubstring; + + // title is optional + mExpectedTitle = builder.mExpectedTitle; + + if (builder.mFacilities != null) { + for (Facility<T> facility : builder.mFacilities) { + addInitialFacility(facility); + } + } + } + + @Override + public void declareElements(Elements.Builder elements) { + super.declareElements(elements); + + if (mNumTabsBeingOpened > 0) { + elements.declareEnterCondition( + new TabAddedCondition(mNumTabsBeingOpened, mActivityElement)); + } + + if (mIsEntryPoint) { + // In entry points we just match the first ActivityTab we see, instead of waiting for + // callbacks. + activityTabElement = + elements.declareEnterConditionAsElement( + new AnyActivityTabCondition(mActivityElement)); + } else { + if (mNumTabsBeingSelected > 0) { + // The last tab of N opened is the Tab that mSelectedTabSupplier will supply. + TabSelectedCondition tabSelectedCondition = + new TabSelectedCondition(mNumTabsBeingSelected, mActivityElement); + elements.declareEnterCondition(tabSelectedCondition); + mSelectedTabSupplier = tabSelectedCondition; + } else { + // The Tab already created and provided to the constructor is the one that is + // expected to be the activityTab. + mSelectedTabSupplier = () -> mTabAlreadySelected; + } + // Only returns the tab when it is the activityTab. + activityTabElement = + elements.declareEnterConditionAsElement( + new CorrectActivityTabCondition( + mActivityElement, mSelectedTabSupplier)); + } + loadedTabElement = + elements.declareEnterConditionAsElement( + new PageLoadedCondition(activityTabElement, mIncognito)); + + elements.declareEnterCondition(new PageInteractableOrHiddenCondition(loadedTabElement)); + + if (mExpectedUrlSubstring != null) { + elements.declareEnterCondition( + new PageUrlContainsCondition(mExpectedUrlSubstring, loadedTabElement)); + } + + if (mExpectedTitle != null) { + elements.declareEnterCondition( + new PageTitleCondition(mExpectedTitle, loadedTabElement)); + } + } + + public boolean isIncognito() { + return mIncognito; + } + + /** Loads a |url| in the same tab and waits to transition. */ + public <DestinationT extends BasePageStation<HostActivity>> + DestinationT loadPageProgrammatically( + String url, Builder<HostActivity, DestinationT, ?> builder) { + builder.initFrom(this); + if (builder.mExpectedUrlSubstring == null) { + builder.mExpectedUrlSubstring = url; + } + + DestinationT destination = builder.build(); + Trigger trigger = + () -> { + @PageTransition + int transitionType = PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR; + loadedTabElement.get().loadUrl(new LoadUrlParams(url, transitionType)); + }; + Transition.TransitionOptions options = + Transition.newOptions() + .withCondition(new PageLoadCallbackCondition(loadedTabElement.get())) + .withTimeout(10000) + .withPossiblyAlreadyFulfilled() + .withRunTriggerOnUiThread() + .build(); + return travelToSync(destination, options, trigger); + } + + /** Condition to check the page url contains a certain substring. */ + public static class PageUrlContainsCondition extends Condition { + private final String mExpectedUrlPiece; + private final Supplier<Tab> mLoadedTabSupplier; + + public PageUrlContainsCondition(String expectedUrl, Supplier<Tab> loadedTabSupplier) { + super(/* isRunOnUiThread= */ true); + mExpectedUrlPiece = expectedUrl; + mLoadedTabSupplier = dependOnSupplier(loadedTabSupplier, "LoadedTab"); + } + + @Override + protected ConditionStatus checkWithSuppliers() throws Exception { + String url = mLoadedTabSupplier.get().getUrl().getSpec(); + return whether(url.contains(mExpectedUrlPiece), "ActivityTab url: \"%s\"", url); + } + + @Override + public String buildDescription() { + return String.format("URL of activity tab contains \"%s\"", mExpectedUrlPiece); + } + } + + /** Condition to check the page title. */ + public static class PageTitleCondition extends Condition { + private final String mExpectedTitle; + private final Supplier<Tab> mLoadedTabSupplier; + + public PageTitleCondition(String expectedTitle, Supplier<Tab> loadedTabSupplier) { + super(/* isRunOnUiThread= */ true); + mExpectedTitle = expectedTitle; + mLoadedTabSupplier = dependOnSupplier(loadedTabSupplier, "LoadedTab"); + } + + @Override + protected ConditionStatus checkWithSuppliers() throws Exception { + String title = mLoadedTabSupplier.get().getTitle(); + return whether(mExpectedTitle.equals(title), "ActivityTab title: \"%s\"", title); + } + + @Override + public String buildDescription() { + return String.format("Title of activity tab is \"%s\"", mExpectedTitle); + } + } + + private class TabAddedCondition<ActivityT extends ChromeActivity> extends CallbackCondition + implements TabModelObserver { + private TabModel mTabModel; + private Supplier<ActivityT> mActivitySupplier; + + protected TabAddedCondition(int numTabsBeingOpened, Supplier<ActivityT> activitySupplier) { + super("didAddTab", numTabsBeingOpened); + mActivitySupplier = dependOnSupplier(activitySupplier, "ChromeActivity"); + } + + @Override + public void didAddTab(Tab tab, int type, int creationState, boolean markedForSelection) { + notifyCalled(); + } + + @Override + public void onStartMonitoring() { + super.onStartMonitoring(); + ThreadUtils.runOnUiThreadBlocking( + () -> { + mTabModel = + mActivitySupplier + .get() + .getTabModelSelector() + .getModel(isIncognito()); + mTabModel.addObserver(this); + }); + } + + @Override + public void onStopMonitoring() { + super.onStopMonitoring(); + ThreadUtils.runOnUiThreadBlocking( + () -> { + mTabModel.removeObserver(this); + }); + } + } + + private class TabSelectedCondition<ActivityT extends ChromeActivity> extends CallbackCondition + implements TabModelObserver, Supplier<Tab> { + private final List<Tab> mTabsSelected = new ArrayList<>(); + private TabModel mTabModel; + private Supplier<ActivityT> mActivitySupplier; + + private TabSelectedCondition( + int numTabsBeingSelected, Supplier<ActivityT> activitySupplier) { + super("didSelectTab", numTabsBeingSelected); + mActivitySupplier = dependOnSupplier(activitySupplier, "ChromeActivity"); + } + + @Override + public void didSelectTab(Tab tab, int type, int lastId) { + if (mTabsSelected.contains(tab)) { + // We get multiple (2-3 depending on the case) didSelectTab when selecting a Tab, so + // filter out redundant callbacks to make sure we wait for different Tabs. + return; + } + mTabsSelected.add(tab); + notifyCalled(); + } + + @Override + public void onStartMonitoring() { + super.onStartMonitoring(); + ThreadUtils.runOnUiThreadBlocking( + () -> { + mTabModel = + mActivitySupplier + .get() + .getTabModelSelector() + .getModel(isIncognito()); + mTabModel.addObserver(this); + }); + } + + @Override + public void onStopMonitoring() { + super.onStopMonitoring(); + ThreadUtils.runOnUiThreadBlocking( + () -> { + mTabModel.removeObserver(this); + }); + } + + @Override + public Tab get() { + if (mTabsSelected.isEmpty()) { + return null; + } + return mTabsSelected.get(mTabsSelected.size() - 1); + } + + @Override + public boolean hasValue() { + return !mTabsSelected.isEmpty(); + } + } + + private static class CorrectActivityTabCondition<ActivityT extends ChromeActivity> + extends ConditionWithResult<Tab> { + + private final Supplier<ActivityT> mActivitySupplier; + private final Supplier<Tab> mExpectedTab; + + private CorrectActivityTabCondition( + Supplier<ActivityT> activitySupplier, Supplier<Tab> expectedTabSupplier) { + super(/* isRunOnUiThread= */ false); + mActivitySupplier = dependOnSupplier(activitySupplier, "ChromeActivity"); + mExpectedTab = dependOnSupplier(expectedTabSupplier, "ExpectedTab"); + } + + @Override + protected ConditionStatusWithResult<Tab> resolveWithSuppliers() { + Tab currentActivityTab = mActivitySupplier.get().getActivityTab(); + if (currentActivityTab == null) { + return notFulfilled("null activityTab").withoutResult(); + } + + Tab expectedTab = mExpectedTab.get(); + if (currentActivityTab == expectedTab) { + return fulfilled("matched expected activityTab: " + currentActivityTab) + .withResult(currentActivityTab); + } else { + return notFulfilled( + "activityTab is " + + currentActivityTab + + ", expected " + + expectedTab) + .withoutResult(); + } + } + + @Override + public String buildDescription() { + return "Activity tab is the expected one"; + } + } + + private static class AnyActivityTabCondition<ActivityT extends ChromeActivity> + extends ConditionWithResult<Tab> { + + private final Supplier<ActivityT> mActivitySupplier; + + private AnyActivityTabCondition(Supplier<ActivityT> activitySupplier) { + super(/* isRunOnUiThread= */ false); + mActivitySupplier = dependOnSupplier(activitySupplier, "ChromeActivity"); + } + + @Override + protected ConditionStatusWithResult<Tab> resolveWithSuppliers() { + Tab currentActivityTab = mActivitySupplier.get().getActivityTab(); + if (currentActivityTab == null) { + return notFulfilled("null activityTab").withoutResult(); + } else { + return fulfilled("found activityTab " + currentActivityTab) + .withResult(currentActivityTab); + } + } + + @Override + public String buildDescription() { + return "Activity has an activityTab"; + } + } +}
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/IncognitoWebPageAppMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/IncognitoWebPageAppMenuFacility.java index 4fbfc0d..9600e67 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/IncognitoWebPageAppMenuFacility.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/IncognitoWebPageAppMenuFacility.java
@@ -12,6 +12,7 @@ mNewIncognitoTab = declareMenuItemToStation( items, NEW_INCOGNITO_TAB_ID, this::createIncognitoNewTabPageStation); + mNewWindow = declarePossibleMenuItem(items, NEW_WINDOW_ID, this::handleOpenNewWindow); declareStubMenuItem(items, HISTORY_ID); declareAbsentMenuItem(items, DELETE_BROWSING_DATA_ID);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageAppMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageAppMenuFacility.java index 313dcc7..11a6bc51 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageAppMenuFacility.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageAppMenuFacility.java
@@ -7,6 +7,8 @@ import androidx.annotation.CallSuper; import org.chromium.base.test.transit.Elements; +import org.chromium.base.test.transit.Station; +import org.chromium.chrome.browser.tabbed_mode.TabbedAppMenuPropertiesDelegate; import org.chromium.chrome.test.transit.CtaAppMenuFacility; import org.chromium.chrome.test.transit.ntp.IncognitoNewTabPageAppMenuFacility; import org.chromium.chrome.test.transit.ntp.IncognitoNewTabPageStation; @@ -33,6 +35,7 @@ protected Item<RegularNewTabPageStation> mNewTab; protected Item<IncognitoNewTabPageStation> mNewIncognitoTab; + protected Item<RegularNewTabPageStation> mNewWindow; protected Item<SettingsStation> mSettings; @Override @@ -64,8 +67,35 @@ return mNewIncognitoTab.scrollToAndSelect(); } + /** Select "New window" from the app menu. */ + public RegularNewTabPageStation openNewWindow() { + TabbedAppMenuPropertiesDelegate delegate = getTabbedAppMenuPropertiesDelegate(); + assert delegate.shouldShowNewWindow() : "App menu is not expected to show 'New window'"; + return mNewWindow.scrollToAndSelect(); + } + + private TabbedAppMenuPropertiesDelegate getTabbedAppMenuPropertiesDelegate() { + return (TabbedAppMenuPropertiesDelegate) + mHostStation + .getActivity() + .getRootUiCoordinatorForTesting() + .getAppMenuCoordinatorForTesting() + .getAppMenuPropertiesDelegate(); + } + /** Select "Settings" from the app menu. */ public SettingsStation openSettings() { return mSettings.scrollToAndSelect(); } + + /** + * Use as lambda from subclasses to handle selecting |mNewWindow|. + * + * <p>Called from {@link #openNewWindow()} after scrolling to the item. + */ + protected RegularNewTabPageStation handleOpenNewWindow( + ItemOnScreenFacility<RegularNewTabPageStation> itemOnScreen) { + return Station.spawnSync( + createNewWindowStation(), itemOnScreen.viewElement.getClickTrigger()); + } }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageStation.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageStation.java index b7a70a9..51d8407 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageStation.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/PageStation.java
@@ -6,7 +6,6 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static org.chromium.base.test.transit.Condition.whether; import static org.chromium.base.test.transit.ViewSpec.viewSpec; import android.app.Activity; @@ -16,17 +15,8 @@ import androidx.test.platform.app.InstrumentationRegistry; -import org.chromium.base.ThreadUtils; import org.chromium.base.supplier.Supplier; -import org.chromium.base.test.transit.CallbackCondition; -import org.chromium.base.test.transit.Condition; -import org.chromium.base.test.transit.ConditionStatus; -import org.chromium.base.test.transit.ConditionStatusWithResult; -import org.chromium.base.test.transit.ConditionWithResult; -import org.chromium.base.test.transit.Element; import org.chromium.base.test.transit.Elements; -import org.chromium.base.test.transit.Facility; -import org.chromium.base.test.transit.Station; import org.chromium.base.test.transit.Transition; import org.chromium.base.test.transit.Transition.Trigger; import org.chromium.base.test.transit.ViewElement; @@ -38,8 +28,6 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tab.TabSelectionType; -import org.chromium.chrome.browser.tabmodel.TabModel; -import org.chromium.chrome.browser.tabmodel.TabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModelUtils; import org.chromium.chrome.browser.toolbar.home_button.HomeButton; import org.chromium.chrome.browser.toolbar.top.ToggleTabStackButton; @@ -50,12 +38,8 @@ import org.chromium.chrome.test.transit.ntp.IncognitoNewTabPageStation; import org.chromium.chrome.test.transit.ntp.RegularNewTabPageStation; import org.chromium.chrome.test.util.MenuUtils; -import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.test.util.TouchCommon; -import org.chromium.ui.base.PageTransition; -import java.util.ArrayList; -import java.util.List; import java.util.function.Function; /** @@ -64,113 +48,21 @@ * <p>Contains extra configurable Conditions such as waiting for a tab to be created, selected, have * the expected title, etc. */ -public class PageStation extends Station<ChromeTabbedActivity> { +public class PageStation extends BasePageStation<ChromeTabbedActivity> { /** * Builder for all PageStation subclasses. * * @param <T> the subclass of PageStation to build. */ - public static class Builder<T extends PageStation> { - private final Function<Builder<T>, T> mFactoryMethod; - private boolean mIsEntryPoint; - private Boolean mIncognito; - private Integer mNumTabsBeingOpened; - private Integer mNumTabsBeingSelected; - private Tab mTabAlreadySelected; - private String mExpectedUrlSubstring; - private String mExpectedTitle; - private List<Facility<T>> mFacilities; - + public static class Builder<T extends PageStation> + extends BasePageStation.Builder<ChromeTabbedActivity, T, Builder<T>> { public Builder(Function<Builder<T>, T> factoryMethod) { - mFactoryMethod = factoryMethod; - } - - public Builder<T> withIncognito(boolean incognito) { - mIncognito = incognito; - return this; - } - - public Builder<T> withIsOpeningTabs(int numTabsBeingOpened) { - assert numTabsBeingOpened >= 0; - mNumTabsBeingOpened = numTabsBeingOpened; - return this; - } - - public Builder<T> withTabAlreadySelected(Tab currentTab) { - mTabAlreadySelected = currentTab; - mNumTabsBeingSelected = 0; - return this; - } - - public Builder<T> withIsSelectingTabs(int numTabsBeingSelected) { - assert numTabsBeingSelected > 0 - : "Use withIsSelectingTab() if the PageStation is still in the current tab"; - mNumTabsBeingSelected = numTabsBeingSelected; - // Commonly already set via initFrom(). - mTabAlreadySelected = null; - return this; - } - - public Builder<T> withEntryPoint() { - mNumTabsBeingOpened = 0; - mNumTabsBeingSelected = 0; - mIsEntryPoint = true; - return this; - } - - public Builder<T> withExpectedUrlSubstring(String value) { - mExpectedUrlSubstring = value; - return this; - } - - public Builder<T> withExpectedTitle(String title) { - mExpectedTitle = title; - return this; - } - - public Builder<T> withFacility(Facility<T> facility) { - if (mFacilities == null) { - mFacilities = new ArrayList<>(); - } - mFacilities.add(facility); - return this; - } - - public Builder<T> initFrom(PageStation previousStation) { - if (mIncognito == null) { - mIncognito = previousStation.mIncognito; - } - if (mNumTabsBeingOpened == null) { - mNumTabsBeingOpened = 0; - } - if (mNumTabsBeingSelected == null) { - mNumTabsBeingSelected = 0; - } - if (mTabAlreadySelected == null && mNumTabsBeingSelected == 0) { - mTabAlreadySelected = previousStation.loadedTabElement.getFromPast(); - } - // Cannot copy over facilities because we have no way to clone them. It's also not - // obvious that we should... - return this; - } - - public T build() { - return mFactoryMethod.apply(this); + super(factoryMethod); } } - protected final boolean mIncognito; - protected final boolean mIsEntryPoint; - protected final int mNumTabsBeingOpened; - protected final int mNumTabsBeingSelected; - protected final Tab mTabAlreadySelected; - protected final String mExpectedUrlSubstring; - protected final String mExpectedTitle; public static final ViewSpec<UrlBar> URL_BAR = viewSpec(UrlBar.class, withId(R.id.url_bar)); - public Element<Tab> activityTabElement; - protected Supplier<Tab> mSelectedTabSupplier; - public Element<Tab> loadedTabElement; public ViewElement<ToolbarControlContainer> toolbarElement; public ViewElement<ToggleTabStackButton> tabSwitcherButtonElement; public ViewElement<ImageButton> menuButtonElement; @@ -182,42 +74,7 @@ /** Use the PageStation's subclass |newBuilder()|. */ protected <T extends PageStation> PageStation(Builder<T> builder) { - // incognito is optional and defaults to false - super(ChromeTabbedActivity.class); - mIncognito = builder.mIncognito == null ? false : builder.mIncognito; - - // isEntryPoint is optional and defaults to false - mIsEntryPoint = builder.mIsEntryPoint; - - // isOpeningTab is required - assert builder.mNumTabsBeingOpened != null - : "PageStation.Builder needs withIsOpeningTabs() or initFrom()"; - mNumTabsBeingOpened = builder.mNumTabsBeingOpened; - - // mNumTabsBeingSelected is required - assert builder.mNumTabsBeingSelected != null - : "PageStation.Builder needs withIsSelectingTabs(), withTabAlreadySelected() or" - + " initFrom()"; - mNumTabsBeingSelected = builder.mNumTabsBeingSelected; - - // Pages must have an already selected tab, or be selecting a tab. - mTabAlreadySelected = builder.mTabAlreadySelected; - assert mIsEntryPoint || (mTabAlreadySelected != null) != (mNumTabsBeingSelected != 0) - : String.format( - "mTabAlreadySelected=%s mNumTabsBeingSelected=%s", - mTabAlreadySelected, mNumTabsBeingSelected); - - // URL substring is optional. - mExpectedUrlSubstring = builder.mExpectedUrlSubstring; - - // title is optional - mExpectedTitle = builder.mExpectedTitle; - - if (builder.mFacilities != null) { - for (Facility<T> facility : builder.mFacilities) { - addInitialFacility(facility); - } - } + super(ChromeTabbedActivity.class, builder); } @Override @@ -245,100 +102,6 @@ elements.declareView( viewSpec(ImageButton.class, withId(R.id.menu_button)), ViewElement.unscopedOption()); - - if (mNumTabsBeingOpened > 0) { - elements.declareEnterCondition( - new TabAddedCondition(mNumTabsBeingOpened, mActivityElement)); - } - - if (mIsEntryPoint) { - // In entry points we just match the first ActivityTab we see, instead of waiting for - // callbacks. - activityTabElement = - elements.declareEnterConditionAsElement( - new AnyActivityTabCondition(mActivityElement)); - } else { - if (mNumTabsBeingSelected > 0) { - // The last tab of N opened is the Tab that mSelectedTabSupplier will supply. - TabSelectedCondition tabSelectedCondition = - new TabSelectedCondition(mNumTabsBeingSelected, mActivityElement); - elements.declareEnterCondition(tabSelectedCondition); - mSelectedTabSupplier = tabSelectedCondition; - } else { - // The Tab already created and provided to the constructor is the one that is - // expected to be the activityTab. - mSelectedTabSupplier = () -> mTabAlreadySelected; - } - // Only returns the tab when it is the activityTab. - activityTabElement = - elements.declareEnterConditionAsElement( - new CorrectActivityTabCondition( - mActivityElement, mSelectedTabSupplier)); - } - loadedTabElement = - elements.declareEnterConditionAsElement( - new PageLoadedCondition(activityTabElement, mIncognito)); - - elements.declareEnterCondition(new PageInteractableOrHiddenCondition(loadedTabElement)); - - if (mExpectedTitle != null) { - elements.declareEnterCondition( - new PageTitleCondition(mExpectedTitle, loadedTabElement)); - } - if (mExpectedUrlSubstring != null) { - elements.declareEnterCondition( - new PageUrlContainsCondition(mExpectedUrlSubstring, loadedTabElement)); - } - } - - public boolean isIncognito() { - return mIncognito; - } - - /** Condition to check the page title. */ - public static class PageTitleCondition extends Condition { - private final String mExpectedTitle; - private final Supplier<Tab> mLoadedTabSupplier; - - public PageTitleCondition(String expectedTitle, Supplier<Tab> loadedTabSupplier) { - super(/* isRunOnUiThread= */ true); - mExpectedTitle = expectedTitle; - mLoadedTabSupplier = dependOnSupplier(loadedTabSupplier, "LoadedTab"); - } - - @Override - protected ConditionStatus checkWithSuppliers() throws Exception { - String title = mLoadedTabSupplier.get().getTitle(); - return whether(mExpectedTitle.equals(title), "ActivityTab title: \"%s\"", title); - } - - @Override - public String buildDescription() { - return String.format("Title of activity tab is \"%s\"", mExpectedTitle); - } - } - - /** Condition to check the page url contains a certain substring. */ - public static class PageUrlContainsCondition extends Condition { - private final String mExpectedUrlPiece; - private final Supplier<Tab> mLoadedTabSupplier; - - public PageUrlContainsCondition(String expectedUrl, Supplier<Tab> loadedTabSupplier) { - super(/* isRunOnUiThread= */ true); - mExpectedUrlPiece = expectedUrl; - mLoadedTabSupplier = dependOnSupplier(loadedTabSupplier, "LoadedTab"); - } - - @Override - protected ConditionStatus checkWithSuppliers() throws Exception { - String url = mLoadedTabSupplier.get().getUrl().getSpec(); - return whether(url.contains(mExpectedUrlPiece), "ActivityTab url: \"%s\"", url); - } - - @Override - public String buildDescription() { - return String.format("URL of activity tab contains \"%s\"", mExpectedUrlPiece); - } } /** Long presses the tab switcher button to open the action menu. */ @@ -422,30 +185,6 @@ tabSwitcherButtonElement.getClickTrigger()); } - /** Loads a |url| in the same tab and waits to transition. */ - public <T extends PageStation> T loadPageProgrammatically(String url, Builder<T> builder) { - builder.initFrom(this); - if (builder.mExpectedUrlSubstring == null) { - builder.mExpectedUrlSubstring = url; - } - - T destination = builder.build(); - Trigger trigger = - () -> { - @PageTransition - int transitionType = PageTransition.TYPED | PageTransition.FROM_ADDRESS_BAR; - loadedTabElement.get().loadUrl(new LoadUrlParams(url, transitionType)); - }; - Transition.TransitionOptions options = - Transition.newOptions() - .withCondition(new PageLoadCallbackCondition(loadedTabElement.get())) - .withTimeout(10000) - .withPossiblyAlreadyFulfilled() - .withRunTriggerOnUiThread() - .build(); - return travelToSync(destination, options, trigger); - } - /** Loads a |url| leading to a web page in the same tab and waits to transition. */ public WebPageStation loadWebPageProgrammatically(String url) { return loadPageProgrammatically(url, WebPageStation.newBuilder()); @@ -561,169 +300,4 @@ this.mY = toolbarPos[1] + height / 2; } } - - private class TabAddedCondition extends CallbackCondition implements TabModelObserver { - private TabModel mTabModel; - private Supplier<ChromeTabbedActivity> mActivitySupplier; - - protected TabAddedCondition( - int numTabsBeingOpened, Supplier<ChromeTabbedActivity> activitySupplier) { - super("didAddTab", numTabsBeingOpened); - mActivitySupplier = dependOnSupplier(activitySupplier, "ChromeTabbedActivity"); - } - - @Override - public void didAddTab(Tab tab, int type, int creationState, boolean markedForSelection) { - notifyCalled(); - } - - @Override - public void onStartMonitoring() { - super.onStartMonitoring(); - ThreadUtils.runOnUiThreadBlocking( - () -> { - mTabModel = - mActivitySupplier - .get() - .getTabModelSelector() - .getModel(isIncognito()); - mTabModel.addObserver(this); - }); - } - - @Override - public void onStopMonitoring() { - super.onStopMonitoring(); - ThreadUtils.runOnUiThreadBlocking( - () -> { - mTabModel.removeObserver(this); - }); - } - } - - private class TabSelectedCondition extends CallbackCondition - implements TabModelObserver, Supplier<Tab> { - private final List<Tab> mTabsSelected = new ArrayList<>(); - private TabModel mTabModel; - private Supplier<ChromeTabbedActivity> mActivitySupplier; - - private TabSelectedCondition( - int numTabsBeingSelected, Supplier<ChromeTabbedActivity> activitySupplier) { - super("didSelectTab", numTabsBeingSelected); - mActivitySupplier = dependOnSupplier(activitySupplier, "ChromeTabbedActivity"); - } - - @Override - public void didSelectTab(Tab tab, int type, int lastId) { - if (mTabsSelected.contains(tab)) { - // We get multiple (2-3 depending on the case) didSelectTab when selecting a Tab, so - // filter out redundant callbacks to make sure we wait for different Tabs. - return; - } - mTabsSelected.add(tab); - notifyCalled(); - } - - @Override - public void onStartMonitoring() { - super.onStartMonitoring(); - ThreadUtils.runOnUiThreadBlocking( - () -> { - mTabModel = - mActivitySupplier - .get() - .getTabModelSelector() - .getModel(isIncognito()); - mTabModel.addObserver(this); - }); - } - - @Override - public void onStopMonitoring() { - super.onStopMonitoring(); - ThreadUtils.runOnUiThreadBlocking( - () -> { - mTabModel.removeObserver(this); - }); - } - - @Override - public Tab get() { - if (mTabsSelected.isEmpty()) { - return null; - } - return mTabsSelected.get(mTabsSelected.size() - 1); - } - - @Override - public boolean hasValue() { - return !mTabsSelected.isEmpty(); - } - } - - private static class CorrectActivityTabCondition extends ConditionWithResult<Tab> { - - private final Supplier<ChromeTabbedActivity> mActivitySupplier; - private final Supplier<Tab> mExpectedTab; - - private CorrectActivityTabCondition( - Supplier<ChromeTabbedActivity> activitySupplier, - Supplier<Tab> expectedTabSupplier) { - super(/* isRunOnUiThread= */ false); - mActivitySupplier = dependOnSupplier(activitySupplier, "ChromeTabbedActivity"); - mExpectedTab = dependOnSupplier(expectedTabSupplier, "ExpectedTab"); - } - - @Override - protected ConditionStatusWithResult<Tab> resolveWithSuppliers() { - Tab currentActivityTab = mActivitySupplier.get().getActivityTab(); - if (currentActivityTab == null) { - return notFulfilled("null activityTab").withoutResult(); - } - - Tab expectedTab = mExpectedTab.get(); - if (currentActivityTab == expectedTab) { - return fulfilled("matched expected activityTab: " + currentActivityTab) - .withResult(currentActivityTab); - } else { - return notFulfilled( - "activityTab is " - + currentActivityTab - + ", expected " - + expectedTab) - .withoutResult(); - } - } - - @Override - public String buildDescription() { - return "Activity tab is the expected one"; - } - } - - private static class AnyActivityTabCondition extends ConditionWithResult<Tab> { - - private final Supplier<ChromeTabbedActivity> mActivitySupplier; - - private AnyActivityTabCondition(Supplier<ChromeTabbedActivity> activitySupplier) { - super(/* isRunOnUiThread= */ false); - mActivitySupplier = dependOnSupplier(activitySupplier, "ChromeTabbedActivity"); - } - - @Override - protected ConditionStatusWithResult<Tab> resolveWithSuppliers() { - Tab currentActivityTab = mActivitySupplier.get().getActivityTab(); - if (currentActivityTab == null) { - return notFulfilled("null activityTab").withoutResult(); - } else { - return fulfilled("found activityTab " + currentActivityTab) - .withResult(currentActivityTab); - } - } - - @Override - public String buildDescription() { - return "Activity has an activityTab"; - } - } }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/RegularWebPageAppMenuFacility.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/RegularWebPageAppMenuFacility.java index 0aa4562..71cdf7b 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/RegularWebPageAppMenuFacility.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/page/RegularWebPageAppMenuFacility.java
@@ -16,6 +16,7 @@ mNewIncognitoTab = declareMenuItemToStation( items, NEW_INCOGNITO_TAB_ID, this::createIncognitoNewTabPageStation); + mNewWindow = declarePossibleMenuItem(items, NEW_WINDOW_ID, this::handleOpenNewWindow); declareStubMenuItem(items, HISTORY_ID); mQuickDelete =
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabThumbnailsCapturedCarryOn.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabThumbnailsCapturedCarryOn.java index c1ae7cc..d3c2674 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabThumbnailsCapturedCarryOn.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/transit/tabmodel/TabThumbnailsCapturedCarryOn.java
@@ -4,41 +4,20 @@ package org.chromium.chrome.test.transit.tabmodel; -import org.chromium.base.supplier.Supplier; import org.chromium.base.test.transit.CarryOn; -import org.chromium.base.test.transit.Element; -import org.chromium.base.test.transit.Elements; -import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelSelector; /** CarryOn to check for existence of all tab thumbnails on disk for a TabModel. */ public class TabThumbnailsCapturedCarryOn extends CarryOn { - private final boolean mIsIncognito; - - public TabThumbnailsCapturedCarryOn(boolean isIncognito) { - mIsIncognito = isIncognito; - } - - @Override - public void declareElements(Elements.Builder elements) { - Supplier<ChromeTabbedActivity> activitySupplier = - elements.declareActivity(ChromeTabbedActivity.class); - Element<TabModelSelector> tabModelSelectorElement = - elements.declareEnterConditionAsElement( - new TabModelSelectorCondition(activitySupplier)); - elements.declareElementFactory( - tabModelSelectorElement, - delayedElements -> { - TabModelSelector tabModelSelector = tabModelSelectorElement.get(); - TabModel tabModel = tabModelSelector.getModel(mIsIncognito); - int tabCount = tabModel.getCount(); - for (int i = 0; i < tabCount; i++) { - delayedElements.declareEnterCondition( - TabThumbnailCondition.etc1(tabModelSelector, tabModel.getTabAt(i))); - delayedElements.declareEnterCondition( - TabThumbnailCondition.jpeg(tabModelSelector, tabModel.getTabAt(i))); - } - }); + public TabThumbnailsCapturedCarryOn(TabModelSelector tabModelSelector, boolean isIncognito) { + TabModel tabModel = tabModelSelector.getModel(isIncognito); + int tabCount = tabModel.getCount(); + for (int i = 0; i < tabCount; i++) { + declareEnterCondition( + TabThumbnailCondition.etc1(tabModelSelector, tabModel.getTabAt(i))); + declareEnterCondition( + TabThumbnailCondition.jpeg(tabModelSelector, tabModel.getTabAt(i))); + } } }
diff --git a/chrome/test/chromedriver/test/run_py_tests.pydeps b/chrome/test/chromedriver/test/run_py_tests.pydeps index af399c7c..a3d6407b 100644 --- a/chrome/test/chromedriver/test/run_py_tests.pydeps +++ b/chrome/test/chromedriver/test/run_py_tests.pydeps
@@ -53,6 +53,7 @@ ../../../../third_party/catapult/devil/devil/devil_env.py ../../../../third_party/catapult/devil/devil/utils/__init__.py ../../../../third_party/catapult/devil/devil/utils/cmd_helper.py +../../../../third_party/catapult/devil/devil/utils/host_utils.py ../../../../third_party/catapult/devil/devil/utils/lazy/__init__.py ../../../../third_party/catapult/devil/devil/utils/lazy/weak_constant.py ../../../../third_party/catapult/devil/devil/utils/logging_common.py
diff --git a/chrome/test/data/actor/target_blank_links.html b/chrome/test/data/actor/target_blank_links.html new file mode 100644 index 0000000..933272b --- /dev/null +++ b/chrome/test/data/actor/target_blank_links.html
@@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> + <head> + <title>Links Opening in New Tab</title> + <meta name="viewport" content="width=device-width, minimum-scale=1.0"> + </head> + <body> + <h1>Links Opening in New Tab</h1> + <div><a id="anchorTarget" href="blank.html" target="_blank">Open link in new tab</a></div> + <div><a id="scriptOpen" href="#">Open link in new tab by script</a></div> + <script> + document.getElementById('scriptOpen').addEventListener('click', (e) => { + e.preventDefault(); + window.open('blank.html', '_blank'); + }); + </script> + </body> +</html>
diff --git a/chrome/test/data/webui/glic/api_test.ts b/chrome/test/data/webui/glic/api_test.ts index 4991dc17..1e0015e 100644 --- a/chrome/test/data/webui/glic/api_test.ts +++ b/chrome/test/data/webui/glic/api_test.ts
@@ -725,7 +725,7 @@ async testResizeWindowTooLarge() { assertTrue(!!this.host.resizeWindow); - await this.host.resizeWindow(2000, 2000); + await this.host.resizeWindow(20000, 20000); } async testResizeWindowWithinBounds() {
diff --git a/chrome/test/data/webui/glic/test_client/index.html b/chrome/test/data/webui/glic/test_client/index.html index c23e37f..4d7510f 100644 --- a/chrome/test/data/webui/glic/test_client/index.html +++ b/chrome/test/data/webui/glic/test_client/index.html
@@ -99,8 +99,24 @@ border-color: red; } + #screenWakeLockStatus::before { + content: "Can sleep normally."; + } + #screenWakeLockStatus[lockStatus*="acquired"]::before { + content: "Locked in awake state!"; + background-color: fuchsia; + } + #screenWakeLockStatus[lockStatus*="unexpectedRelease"]::before { + content: "Awake lock was released unexpectedly."; + background-color: yellow; + } + #screenWakeLockStatus[lockStatus*="error"]::before { + content: "Error acquiring awake lock! (can still sleep)"; + background-color: red; + } + #successUI { - border-color: green; + border-color: green; } .fitWindow html { @@ -410,6 +426,14 @@ <div id="audioStatus"></div> </div> <div class="section"> + <h1>Screen Wake Lock</h1> + <label for="screenWakeLockSwitch">Keep screen awake: + <input type="checkbox" id="screenWakeLockSwitch" /> + </label> + <br /> + <label id="screenWakeLockStatus" lockStatus="released"/> +</div> +<div class="section"> <h1>Desktop Screenshot</h1> <button id="desktopScreenshot">Capture</button> <button id="panelScreenshot">Capture Panel</button>
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 717adb4..6953c37 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
@@ -82,6 +82,8 @@ fileDropList: HTMLDivElement; showDirectoryPicker: HTMLButtonElement; failInitializationCheckbox: HTMLInputElement; + screenWakeLockSwitch: HTMLInputElement; + screenWakeLockStatus: HTMLLabelElement; setExperiment: HTMLButtonElement; trialName: HTMLInputElement; groupName: HTMLInputElement;
diff --git a/chrome/test/data/webui/glic/test_client/serve.py b/chrome/test/data/webui/glic/test_client/serve.py index 4ae0c3f..b497209d 100755 --- a/chrome/test/data/webui/glic/test_client/serve.py +++ b/chrome/test/data/webui/glic/test_client/serve.py
@@ -98,6 +98,10 @@ help="Alternates between 200 and" + " 404 responses, every minute", action="store_true") + parser.add_argument('--bind-all-interfaces', + help='Serves on all interfaces' + + ' (by default serves only localhost)', + action='store_true') args = parser.parse_args() RequestHandler.directory = f'{args.outdir}/gen/chrome/test/data/webui/glic' @@ -123,7 +127,9 @@ os.path.join(args.outdir, 'pyproto', 'components', 'optimization_guide', 'proto', 'features')) - with socketserver.ThreadingTCPServer(("", args.port), + server_addr = '' if args.bind_all_interfaces else '127.0.0.1' + + with socketserver.ThreadingTCPServer((server_addr, args.port), RequestHandler) as httpd: print("Server started at localhost:" + str(args.port)) httpd.serve_forever()
diff --git a/chrome/test/data/webui/glic/test_client/test_client.ts b/chrome/test/data/webui/glic/test_client/test_client.ts index 66726782..269fbd6 100644 --- a/chrome/test/data/webui/glic/test_client/test_client.ts +++ b/chrome/test/data/webui/glic/test_client/test_client.ts
@@ -246,3 +246,47 @@ localStorage.removeItem('test-init-failure'); } }); + +$.screenWakeLockSwitch.addEventListener('click', async () => { + if ($.screenWakeLockSwitch.checked) { + await acquireScreenWakeLock(); + } else { + await releaseScreenWakeLock(); + } +}); + +let screenWakeLock: WakeLockSentinel|null = null; +async function acquireScreenWakeLock(): Promise<void> { + if (screenWakeLock) { + console.warn('Screen wake lock was not released before! Releasing...'); + await screenWakeLock.release(); + } + try { + screenWakeLock = await navigator.wakeLock.request('screen'); + screenWakeLock.onrelease = () => { + if (screenWakeLock) { + $.screenWakeLockStatus.setAttribute('lockStatus', 'unexpectedRelease'); + $.screenWakeLockSwitch.checked = false; + screenWakeLock = null; + console.warn('Unexpected screen wake lock release.'); + } + }; + $.screenWakeLockStatus.setAttribute('lockStatus', 'acquired'); + } catch (err) { + $.screenWakeLockStatus.setAttribute('lockStatus', 'error'); + $.screenWakeLockSwitch.checked = false; + screenWakeLock = null; + console.error('Failed to acquire screen wake lock', err); + } +} +async function releaseScreenWakeLock(): Promise<void> { + const wakeLock = screenWakeLock; + if (!wakeLock) { + return; + } + screenWakeLock = null; + if (!wakeLock.released) { + await wakeLock.release(); + $.screenWakeLockStatus.setAttribute('lockStatus', 'released'); + } +}
diff --git a/chrome/test/data/webui/lens/side_panel/feedback_toast_test.ts b/chrome/test/data/webui/lens/side_panel/feedback_toast_test.ts index 68484d0..c0bbc1d 100644 --- a/chrome/test/data/webui/lens/side_panel/feedback_toast_test.ts +++ b/chrome/test/data/webui/lens/side_panel/feedback_toast_test.ts
@@ -7,6 +7,8 @@ import type {LensSidePanelPageRemote} from 'chrome-untrusted://lens-overlay/lens_side_panel.mojom-webui.js'; import type {LensSidePanelAppElement} from 'chrome-untrusted://lens/side_panel/side_panel_app.js'; import {SidePanelBrowserProxyImpl} from 'chrome-untrusted://lens/side_panel/side_panel_browser_proxy.js'; +import type {CrButtonElement} from 'chrome-untrusted://resources/cr_elements/cr_button/cr_button.js'; +import type {CrToastElement} from 'chrome-untrusted://resources/cr_elements/cr_toast/cr_toast.js'; import {loadTimeData} from 'chrome-untrusted://resources/js/load_time_data.js'; import {assertFalse, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; import {waitAfterNextRender} from 'chrome-untrusted://webui-test/polymer_test_util.js'; @@ -25,6 +27,11 @@ return isVisible(el) && getComputedStyle(el).visibility !== 'hidden'; } + function getFeedbackToast(): CrToastElement { + return lensSidePanelElement.$.feedbackToast.shadowRoot.querySelector( + 'cr-toast')!; + } + setup(() => { testBrowserProxy = new TestLensSidePanelBrowserProxy(); SidePanelBrowserProxyImpl.setInstance(testBrowserProxy); @@ -44,18 +51,18 @@ callbackRouterRemote.setIsLoadingResults(false); await waitAfterNextRender(lensSidePanelElement); - assertFalse(isRendered(lensSidePanelElement.$.feedbackToast)); + assertFalse(isRendered(getFeedbackToast())); }); test('FeedbackToastNotVisbleOnInitialization', () => { - assertFalse(isRendered(lensSidePanelElement.$.feedbackToast)); + assertFalse(isRendered(getFeedbackToast())); }); test('ShowFeedbackToastOnLoadFinished', async () => { callbackRouterRemote.setIsLoadingResults(false); await waitAfterNextRender(lensSidePanelElement); - assertTrue(isRendered(lensSidePanelElement.$.feedbackToast)); + assertTrue(isRendered(getFeedbackToast())); }); @@ -63,21 +70,44 @@ callbackRouterRemote.setIsLoadingResults(false); await waitAfterNextRender(lensSidePanelElement); - assertTrue(isRendered(lensSidePanelElement.$.feedbackToast)); + assertTrue(isRendered(getFeedbackToast())); callbackRouterRemote.setIsLoadingResults(true); await waitAfterNextRender(lensSidePanelElement); - assertFalse(isRendered(lensSidePanelElement.$.feedbackToast)); + assertFalse(isRendered(getFeedbackToast())); }); test('HideFeedbackToastOnCloseButtonClick', async () => { callbackRouterRemote.setIsLoadingResults(false); await waitAfterNextRender(lensSidePanelElement); - assertTrue(isRendered(lensSidePanelElement.$.feedbackToast)); + assertTrue(isRendered(getFeedbackToast())); - lensSidePanelElement.$.closeFeedbackToastButton.click(); + // Click the close button, which should hide the feedback toast. + const closeButton = + lensSidePanelElement.$.feedbackToast.shadowRoot.querySelector( + 'cr-icon-button'); + assertTrue(closeButton !== null); + closeButton.click(); await waitAfterNextRender(lensSidePanelElement); - assertFalse(isRendered(lensSidePanelElement.$.feedbackToast)); + assertFalse(isRendered(getFeedbackToast())); + }); + + test('SendFeedbackButtonClickCallsHandler', async () => { + // Show the toast first. + callbackRouterRemote.setIsLoadingResults(false); + await waitAfterNextRender(lensSidePanelElement); + assertTrue(isRendered(getFeedbackToast())); + + // Click the send feedback button. + const sendFeedbackButton = + lensSidePanelElement.$.feedbackToast.shadowRoot + .querySelector<CrButtonElement>('#sendFeedbackButton'); + assertTrue(sendFeedbackButton !== null); + sendFeedbackButton.click(); + + // Verify the handler method was called and toast was hidden. + await testBrowserProxy.handler.whenCalled('requestSendFeedback'); + assertFalse(isRendered(getFeedbackToast())); }); });
diff --git a/chrome/test/data/webui/lens/side_panel/test_side_panel_browser_proxy.ts b/chrome/test/data/webui/lens/side_panel/test_side_panel_browser_proxy.ts index 9446846..53fdeda 100644 --- a/chrome/test/data/webui/lens/side_panel/test_side_panel_browser_proxy.ts +++ b/chrome/test/data/webui/lens/side_panel/test_side_panel_browser_proxy.ts
@@ -17,6 +17,7 @@ 'popAndLoadQueryFromHistory', 'getIsContextualSearchbox', 'onScrollToMessage', + 'requestSendFeedback', ]); } @@ -36,6 +37,10 @@ pdfPageNumber, ); } + + requestSendFeedback() { + this.methodCalled('requestSendFeedback'); + } } /**
diff --git a/chrome/test/data/webui/settings/glic_page_test.ts b/chrome/test/data/webui/settings/glic_page_test.ts index 46bdcf4..0c322ed 100644 --- a/chrome/test/data/webui/settings/glic_page_test.ts +++ b/chrome/test/data/webui/settings/glic_page_test.ts
@@ -408,6 +408,36 @@ assertFalse(infoCard.opened); }); + test('ClosedCaptionsToggleEnabled', () => { + page.setPrefValue(PrefName.CLOSED_CAPTIONS_ENABLED, true); + + assertTrue( + $<SettingsToggleButtonElement>('closedCaptionsToggle')!.checked); + }); + + test('ClosedCaptionsToggleDisabled', () => { + page.setPrefValue(PrefName.CLOSED_CAPTIONS_ENABLED, false); + + assertFalse( + $<SettingsToggleButtonElement>('closedCaptionsToggle')!.checked); + }); + + test('ClosedCaptionsToggleChanged', () => { + page.setPrefValue(PrefName.CLOSED_CAPTIONS_ENABLED, false); + + const closedCaptionsToggle = + $<SettingsToggleButtonElement>('closedCaptionsToggle')!; + assertTrue(!!closedCaptionsToggle); + + closedCaptionsToggle.click(); + assertTrue(page.getPref(PrefName.CLOSED_CAPTIONS_ENABLED).value); + assertTrue(closedCaptionsToggle.checked); + + closedCaptionsToggle.click(); + assertFalse(page.getPref(PrefName.CLOSED_CAPTIONS_ENABLED).value); + assertFalse(closedCaptionsToggle.checked); + }); + suite('Metrics', () => { async function verifyUserAction(userAction: string) { const userActions = await metricsBrowserProxy.getArgs('recordAction'); @@ -457,6 +487,20 @@ tabAccessToggle.click(); await verifyUserAction('Glic.Settings.TabContext.Disabled'); }); + + test('ClosedCaptionsToggle', async () => { + page.setPrefValue(PrefName.CLOSED_CAPTIONS_ENABLED, false); + + const closedCaptionsToggle = + $<SettingsToggleButtonElement>('closedCaptionsToggle')!; + assertTrue(!!closedCaptionsToggle); + + closedCaptionsToggle.click(); + await verifyUserAction('Glic.Settings.ClosedCaptions.Enabled'); + + closedCaptionsToggle.click(); + await verifyUserAction('Glic.Settings.ClosedCaptions.Disabled'); + }); }); test('keyboardShortcutLearnMoreHidden', () => {
diff --git a/chrome/test/data/webui/side_panel/read_anything/voice_pack_controller_test.ts b/chrome/test/data/webui/side_panel/read_anything/voice_pack_controller_test.ts index cb05383..9a86d35 100644 --- a/chrome/test/data/webui/side_panel/read_anything/voice_pack_controller_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/voice_pack_controller_test.ts
@@ -5,7 +5,7 @@ import 'chrome-untrusted://read-anything-side-panel.top-chrome/read_anything.js'; import {BrowserProxy, EXTENSION_RESPONSE_TIMEOUT_MS, mojoVoicePackStatusToVoicePackStatusEnum, NotificationType, SpeechBrowserProxyImpl, VoiceClientSideStatusCode, VoiceNotificationManager, VoicePackController} from 'chrome-untrusted://read-anything-side-panel.top-chrome/read_anything.js'; -import type {VoiceNotificationListener} from 'chrome-untrusted://read-anything-side-panel.top-chrome/read_anything.js'; +import type {VoiceLanguageListener, VoiceNotificationListener} from 'chrome-untrusted://read-anything-side-panel.top-chrome/read_anything.js'; import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from 'chrome-untrusted://webui-test/chai_assert.js'; import {MockTimer} from 'chrome-untrusted://webui-test/mock_timer.js'; @@ -17,6 +17,9 @@ suite('VoicePackController', () => { let speech: TestSpeechBrowserProxy; let voicePackController: VoicePackController; + let listener: VoiceLanguageListener; + let onEnabledLangsChange: boolean; + let onAvailableVoicesChange: boolean; setup(() => { // Clearing the DOM should always be done first. @@ -27,6 +30,17 @@ speech = new TestSpeechBrowserProxy(); SpeechBrowserProxyImpl.setInstance(speech); voicePackController = new VoicePackController(); + onEnabledLangsChange = false; + onAvailableVoicesChange = false; + listener = { + onEnabledLangsChange() { + onEnabledLangsChange = true; + }, + onAvailableVoicesChange() { + onAvailableVoicesChange = true; + }, + }; + voicePackController.addListener(listener); }); suite('setLocalStatus', () => { @@ -99,24 +113,35 @@ }); test('disableLang', () => { - assertFalse(voicePackController.disableLang('no')); - assertFalse(voicePackController.disableLang('')); - voicePackController.enableLang('vi'); - assertTrue(voicePackController.disableLang('vi')); + onEnabledLangsChange = false; + + voicePackController.disableLang(''); + assertFalse(onEnabledLangsChange); + voicePackController.disableLang('no'); + assertFalse(onEnabledLangsChange); + + voicePackController.disableLang('vi'); + assertTrue(onEnabledLangsChange); assertFalse(voicePackController.isLangEnabled('vi')); assertFalse(voicePackController.isLangEnabled('VI')); }); test('enableLang', () => { - assertFalse(voicePackController.enableLang('')); - assertTrue(voicePackController.enableLang('no')); - assertFalse(voicePackController.enableLang('no')); + voicePackController.enableLang(''); + assertFalse(onEnabledLangsChange); + + voicePackController.enableLang('no'); + assertTrue(onEnabledLangsChange); + + onEnabledLangsChange = false; + voicePackController.enableLang('no'); + assertFalse(onEnabledLangsChange); assertTrue(voicePackController.isLangEnabled('no')); assertTrue(voicePackController.isLangEnabled('NO')); }); - test('getInitialListOfEnabledLanguages', () => { + test('restoreEnabledLanguagesFromPref', () => { const lang1 = 'en-gb'; const lang2 = 'fr'; const lang3 = 'bd'; @@ -129,15 +154,47 @@ createSpeechSynthesisVoice({lang: lang2, name: 'Google Thomas'}), createSpeechSynthesisVoice({lang: lang3, name: 'Google Matt'}), ]); - voicePackController.refreshAvailableVoices(); + + voicePackController.restoreEnabledLanguagesFromPref(); assertArrayEquals( - [lang1, lang2, lang3], - voicePackController.getInitialListOfEnabledLanguages()); - + [lang1, lang2, lang3], voicePackController.getEnabledLangs()); + assertEquals('en', voicePackController.getCurrentLanguage()); assertTrue(voicePackController.isLangEnabled(lang1)); assertTrue(voicePackController.isLangEnabled(lang2)); assertTrue(voicePackController.isLangEnabled(lang3)); + assertTrue(onEnabledLangsChange); + }); + + test('refreshAvailableVoices', () => { + const voices = [ + createSpeechSynthesisVoice({lang: 'en', name: 'Google Henry'}), + createSpeechSynthesisVoice({lang: 'en', name: 'Google Thomas'}), + createSpeechSynthesisVoice({lang: 'en', name: 'Google Matt'}), + ]; + speech.setVoices(voices); + + assertFalse(onAvailableVoicesChange); + assertArrayEquals([], voicePackController.getAvailableVoices()); + + voicePackController.refreshAvailableVoices(); + assertTrue(onAvailableVoicesChange); + assertArrayEquals(voices, voicePackController.getAvailableVoices()); + + // If we already have voices and new voices come in, we only get those + // voices when we force a refresh. + onAvailableVoicesChange = false; + const newVoices = voices.concat( + createSpeechSynthesisVoice({lang: 'it', name: 'Google Charles'})); + speech.setVoices(newVoices); + + voicePackController.refreshAvailableVoices(); + assertFalse(onAvailableVoicesChange); + assertArrayEquals(voices, voicePackController.getAvailableVoices()); + + voicePackController.refreshAvailableVoices(true); + assertTrue(onAvailableVoicesChange); + assertArrayEquals(newVoices, voicePackController.getAvailableVoices()); }); // <if expr="is_chromeos"> @@ -157,10 +214,17 @@ createSpeechSynthesisVoice({lang: lang1, name: 'Henry'}), createSpeechSynthesisVoice({lang: lang2, name: 'Google Thomas'}), ]); + onEnabledLangsChange = false; - assertTrue(voicePackController.disableLangIfNoVoices(lang1)); - assertFalse(voicePackController.disableLangIfNoVoices(lang2)); - assertTrue(voicePackController.disableLangIfNoVoices(lang3)); + voicePackController.disableLangIfNoVoices(lang1); + assertTrue(onEnabledLangsChange); + + onEnabledLangsChange = false; + voicePackController.disableLangIfNoVoices(lang2); + assertFalse(onEnabledLangsChange); + + voicePackController.disableLangIfNoVoices(lang3); + assertTrue(onEnabledLangsChange); const langsInPrefs = chrome.readingMode.getLanguagesEnabledInPref(); assertFalse(langsInPrefs.includes(lang1.toLowerCase())); @@ -189,10 +253,14 @@ createSpeechSynthesisVoice({lang: lang1, name: 'Henry'}), createSpeechSynthesisVoice({lang: lang2, name: 'Google Thomas'}), ]); + onEnabledLangsChange = false; - assertFalse(voicePackController.disableLangIfNoVoices(lang1)); - assertFalse(voicePackController.disableLangIfNoVoices(lang2)); - assertTrue(voicePackController.disableLangIfNoVoices(lang3)); + voicePackController.disableLangIfNoVoices(lang1); + assertFalse(onEnabledLangsChange); + voicePackController.disableLangIfNoVoices(lang2); + assertFalse(onEnabledLangsChange); + voicePackController.disableLangIfNoVoices(lang3); + assertTrue(onEnabledLangsChange); const langsInPrefs = chrome.readingMode.getLanguagesEnabledInPref(); assertTrue(langsInPrefs.includes(lang1.toLowerCase())); @@ -215,9 +283,10 @@ createSpeechSynthesisVoice({lang: lang1, name: 'Henry'}), ]); voicePackController.refreshAvailableVoices(); - assertArrayEquals( - [lang1], voicePackController.getInitialListOfEnabledLanguages()); + voicePackController.restoreEnabledLanguagesFromPref(); + assertArrayEquals([lang1], voicePackController.getEnabledLangs()); assertArrayEquals([], chrome.readingMode.getLanguagesEnabledInPref()); + onEnabledLangsChange = false; speech.setVoices([ createSpeechSynthesisVoice({lang: lang1, name: 'Henry'}), @@ -228,14 +297,15 @@ voicePackController.enableNowAvailableLangs(); // After voices come in, we should enable those langs. + voicePackController.restoreEnabledLanguagesFromPref(); assertArrayEquals( - [lang1, lang2, lang3], - voicePackController.getInitialListOfEnabledLanguages()); + [lang1, lang2, lang3], voicePackController.getEnabledLangs()); assertArrayEquals( [lang1, lang2, lang3], chrome.readingMode.getLanguagesEnabledInPref()); assertTrue(voicePackController.isLangEnabled(lang1)); assertTrue(voicePackController.isLangEnabled(lang2)); assertTrue(voicePackController.isLangEnabled(lang3)); + assertTrue(onEnabledLangsChange); }); // </if>
diff --git a/chrome/test/data/webui/side_panel/read_anything/voice_pack_model_test.ts b/chrome/test/data/webui/side_panel/read_anything/voice_pack_model_test.ts index 69cbfc58..4bf8428 100644 --- a/chrome/test/data/webui/side_panel/read_anything/voice_pack_model_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/voice_pack_model_test.ts
@@ -44,9 +44,9 @@ voicePackModel.enableLang(lang1); voicePackModel.enableLang(lang2); voicePackModel.enableLang(lang3); - assertTrue(voicePackModel.disableLang(lang1)); - assertTrue(voicePackModel.disableLang(lang2)); - assertFalse(voicePackModel.disableLang('random')); + voicePackModel.disableLang(lang1); + voicePackModel.disableLang(lang2); + voicePackModel.disableLang('random'); assertEquals(1, voicePackModel.getEnabledLangs().size); assertTrue(voicePackModel.getEnabledLangs().has(lang3));
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index af91de2..67198ae 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -809,8 +809,7 @@ } #endif // BUILDFLAG(IS_ANDROID) -std::vector<std::unique_ptr<content::NavigationThrottle>> -CastContentBrowserClient::CreateThrottlesForNavigation( +void CastContentBrowserClient::CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) { if (chromecast::IsFeatureEnabled(kEnableGeneralAudienceBrowsing)) { registry.AddThrottle( @@ -818,8 +817,6 @@ ®istry.GetNavigationHandle(), general_audience_browsing_service_.get())); } - - return {}; } void CastContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h index bec64fa..e4e91e6 100644 --- a/chromecast/browser/cast_content_browser_client.h +++ b/chromecast/browser/cast_content_browser_client.h
@@ -241,8 +241,7 @@ std::unique_ptr<content::NavigationUIData> GetNavigationUIData( content::NavigationHandle* navigation_handle) override; bool ShouldEnableStrictSiteIsolation() override; - std::vector<std::unique_ptr<content::NavigationThrottle>> - CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override; void RegisterNonNetworkSubresourceURLLoaderFactories( int render_process_id,
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 9b100b3..dfae418 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -16275.0.0-1068679 \ No newline at end of file +16276.0.0-1068685 \ No newline at end of file
diff --git a/chromeos/ash/components/audio/audio_device.cc b/chromeos/ash/components/audio/audio_device.cc index e514342..0a59988a 100644 --- a/chromeos/ash/components/audio/audio_device.cc +++ b/chromeos/ash/components/audio/audio_device.cc
@@ -27,11 +27,11 @@ case AudioDeviceType::kUsb: case AudioDeviceType::kBluetooth: return 3; + case AudioDeviceType::kHdmi: + return 2; case AudioDeviceType::kInternalSpeaker: case AudioDeviceType::kInternalMic: case AudioDeviceType::kFrontMic: - return 2; - case AudioDeviceType::kHdmi: return 1; // Lower the priority of bluetooth mic to prevent unexpected bad eperience // to user because of bluetooth audio profile switching. Make priority to
diff --git a/chromeos/ash/components/audio/audio_device_selection_generated_unittest.cc b/chromeos/ash/components/audio/audio_device_selection_generated_unittest.cc index 99ba780..99b94c39 100644 --- a/chromeos/ash/components/audio/audio_device_selection_generated_unittest.cc +++ b/chromeos/ash/components/audio/audio_device_selection_generated_unittest.cc
@@ -582,13 +582,13 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] usb3 headphone4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] usb3 headphone4 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(usb3); // Devices: [internal1 hdmi2 usb3*] headphone4 - // List: internal1 < usb3 + // List: internal1 < hdmi2 < usb3 EXPECT_EQ(ActiveOutputNodeId(), usb3.id); Select(hdmi2); @@ -628,33 +628,38 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi3); + // Devices: [internal1 hdmi3*] headphone2 + // List: internal1 < hdmi3 < headphone2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); + + Select(internal1); // Devices: [internal1* hdmi3] headphone2 - // List: internal1 < headphone2 + // List: hdmi3 < internal1 < headphone2 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Unplug(hdmi3); // Devices: [internal1*] headphone2 hdmi3 - // List: internal1 < headphone2 + // List: hdmi3 < internal1 < headphone2 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(headphone2); // Devices: [internal1 headphone2*] hdmi3 - // List: internal1 < headphone2 + // List: hdmi3 < internal1 < headphone2 EXPECT_EQ(ActiveOutputNodeId(), headphone2.id); Unplug(headphone2); // Devices: [internal1*] headphone2 hdmi3 - // List: internal1 < headphone2 + // List: hdmi3 < internal1 < headphone2 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi3); // Devices: [internal1* hdmi3] headphone2 - // List: internal1 < headphone2 + // List: hdmi3 < internal1 < headphone2 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Unplug(hdmi3); // Devices: [internal1*] headphone2 hdmi3 - // List: internal1 < headphone2 + // List: hdmi3 < internal1 < headphone2 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); } @@ -670,88 +675,88 @@ EXPECT_EQ(ActiveOutputNodeId(), internal4.id); Plug(hdmi1); - // Devices: [hdmi1 internal4*] hdmi2 headphone3 - // List: internal4 - EXPECT_EQ(ActiveOutputNodeId(), internal4.id); - - Plug(hdmi2); - // Devices: [hdmi1 hdmi2 internal4*] headphone3 - // List: internal4 - EXPECT_EQ(ActiveOutputNodeId(), internal4.id); - - Select(hdmi1); - // Devices: [hdmi1* hdmi2 internal4] headphone3 - // List: internal4 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), hdmi1.id); - - Unplug(hdmi1); - // Devices: [hdmi2 internal4*] hdmi1 headphone3 - // List: internal4 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), internal4.id); - - Unplug(hdmi2); - // Devices: [internal4*] hdmi1 hdmi2 headphone3 - // List: internal4 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), internal4.id); - - Plug(headphone3); - // Devices: [headphone3* internal4] hdmi1 hdmi2 - // List: internal4 < headphone3 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); - - Unplug(headphone3); - // Devices: [internal4*] hdmi1 hdmi2 headphone3 - // List: internal4 < headphone3 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), internal4.id); - - Plug(hdmi2); - // Devices: [hdmi2 internal4*] hdmi1 headphone3 - // List: internal4 < headphone3 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), internal4.id); - - Plug(hdmi1); - // Devices: [hdmi1* hdmi2 internal4] headphone3 - // List: internal4 < headphone3 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), hdmi1.id); - - Unplug(hdmi1); - // Devices: [hdmi2 internal4*] hdmi1 headphone3 - // List: internal4 < headphone3 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), internal4.id); - - Unplug(hdmi2); - // Devices: [internal4*] hdmi1 hdmi2 headphone3 - // List: internal4 < headphone3 < hdmi1 - EXPECT_EQ(ActiveOutputNodeId(), internal4.id); - - Plug(hdmi1); // Devices: [hdmi1* internal4] hdmi2 headphone3 - // List: internal4 < headphone3 < hdmi1 + // List: internal4 < hdmi1 EXPECT_EQ(ActiveOutputNodeId(), hdmi1.id); Plug(hdmi2); // Devices: [hdmi1 hdmi2* internal4] headphone3 - // List: internal4 < headphone3 < hdmi1 < hdmi2 + // List: internal4 < hdmi1 < hdmi2 EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + Select(hdmi1); + // Devices: [hdmi1* hdmi2 internal4] headphone3 + // List: internal4 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), hdmi1.id); + Unplug(hdmi1); // Devices: [hdmi2* internal4] hdmi1 headphone3 - // List: internal4 < headphone3 < hdmi1 < hdmi2 + // List: internal4 < hdmi2 < hdmi1 EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Unplug(hdmi2); // Devices: [internal4*] hdmi1 hdmi2 headphone3 - // List: internal4 < headphone3 < hdmi1 < hdmi2 + // List: internal4 < hdmi2 < hdmi1 EXPECT_EQ(ActiveOutputNodeId(), internal4.id); Plug(headphone3); // Devices: [headphone3* internal4] hdmi1 hdmi2 - // List: internal4 < headphone3 < hdmi1 < hdmi2 + // List: internal4 < headphone3 < hdmi2 < hdmi1 EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); Unplug(headphone3); // Devices: [internal4*] hdmi1 hdmi2 headphone3 - // List: internal4 < headphone3 < hdmi1 < hdmi2 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), internal4.id); + + Plug(hdmi2); + // Devices: [hdmi2* internal4] hdmi1 headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Plug(hdmi1); + // Devices: [hdmi1* hdmi2 internal4] headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), hdmi1.id); + + Unplug(hdmi1); + // Devices: [hdmi2* internal4] hdmi1 headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Unplug(hdmi2); + // Devices: [internal4*] hdmi1 hdmi2 headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), internal4.id); + + Plug(hdmi1); + // Devices: [hdmi1* internal4] hdmi2 headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), hdmi1.id); + + Plug(hdmi2); + // Devices: [hdmi1* hdmi2 internal4] headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), hdmi1.id); + + Unplug(hdmi1); + // Devices: [hdmi2* internal4] hdmi1 headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Unplug(hdmi2); + // Devices: [internal4*] hdmi1 hdmi2 headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), internal4.id); + + Plug(headphone3); + // Devices: [headphone3* internal4] hdmi1 hdmi2 + // List: internal4 < headphone3 < hdmi2 < hdmi1 + EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); + + Unplug(headphone3); + // Devices: [internal4*] hdmi1 hdmi2 headphone3 + // List: internal4 < headphone3 < hdmi2 < hdmi1 EXPECT_EQ(ActiveOutputNodeId(), internal4.id); } @@ -766,18 +771,23 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); + // Devices: [internal1 hdmi2*] headphone3 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Select(internal1); // Devices: [internal1* hdmi2] headphone3 - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(headphone3); // Devices: [internal1 hdmi2 headphone3*] - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); Unplug(headphone3); // Devices: [internal1* hdmi2] headphone3 - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); } @@ -793,13 +803,13 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] headphone3 hdmi4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] headphone3 hdmi4 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(headphone3); // Devices: [internal1 hdmi2 headphone3*] hdmi4 - // List: internal1 < headphone3 + // List: internal1 < hdmi2 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); Select(hdmi2); @@ -831,13 +841,13 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] headphone3 hdmi4 hdmi5 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] headphone3 hdmi4 hdmi5 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(headphone3); // Devices: [internal1 hdmi2 headphone3*] hdmi4 hdmi5 - // List: internal1 < headphone3 + // List: internal1 < hdmi2 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); Select(hdmi2); @@ -888,33 +898,38 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] hdmi3 hdmi4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] hdmi3 hdmi4 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(hdmi4); - // Devices: [internal1* hdmi2 hdmi4] hdmi3 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2 hdmi4*] hdmi3 + // List: internal1 < hdmi2 < hdmi4 + EXPECT_EQ(ActiveOutputNodeId(), hdmi4.id); Plug(hdmi3); - // Devices: [internal1* hdmi2 hdmi3 hdmi4] - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2 hdmi3* hdmi4] + // List: internal1 < hdmi2 < hdmi4 < hdmi3 + EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); Select(hdmi4); // Devices: [internal1 hdmi2 hdmi3 hdmi4*] - // List: internal1 < hdmi4 + // List: internal1 < hdmi2 < hdmi3 < hdmi4 EXPECT_EQ(ActiveOutputNodeId(), hdmi4.id); Unplug(hdmi4); + // Devices: [internal1 hdmi2 hdmi3*] hdmi4 + // List: internal1 < hdmi2 < hdmi3 < hdmi4 + EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); + + Select(internal1); // Devices: [internal1* hdmi2 hdmi3] hdmi4 - // List: internal1 < hdmi4 + // List: hdmi2 < hdmi3 < internal1 < hdmi4 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi4); // Devices: [internal1 hdmi2 hdmi3 hdmi4*] - // List: internal1 < hdmi4 + // List: hdmi2 < hdmi3 < internal1 < hdmi4 EXPECT_EQ(ActiveOutputNodeId(), hdmi4.id); } @@ -985,23 +1000,28 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); + // Devices: [internal1 hdmi2*] usb3 + // List: internal1 < hdmi2 < usb3 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Select(internal1); // Devices: [internal1* hdmi2] usb3 - // List: internal1 < usb3 + // List: hdmi2 < internal1 < usb3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Unplug(hdmi2); // Devices: [internal1*] hdmi2 usb3 - // List: internal1 < usb3 + // List: hdmi2 < internal1 < usb3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(usb3); // Devices: [internal1 usb3*] hdmi2 - // List: internal1 < usb3 + // List: hdmi2 < internal1 < usb3 EXPECT_EQ(ActiveOutputNodeId(), usb3.id); Plug(hdmi2); // Devices: [internal1 hdmi2 usb3*] - // List: internal1 < usb3 + // List: hdmi2 < internal1 < usb3 EXPECT_EQ(ActiveOutputNodeId(), usb3.id); } @@ -1017,28 +1037,23 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] hdmi3 usb4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] hdmi3 usb4 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(hdmi3); - // Devices: [internal1* hdmi2 hdmi3] usb4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); - - Select(hdmi3); // Devices: [internal1 hdmi2 hdmi3*] usb4 - // List: internal1 < hdmi3 + // List: internal1 < hdmi2 < hdmi3 EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); Plug(usb4); // Devices: [internal1 hdmi2 hdmi3 usb4*] - // List: internal1 < hdmi3 < usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 EXPECT_EQ(ActiveOutputNodeId(), usb4.id); Unplug(usb4); // Devices: [internal1 hdmi2 hdmi3*] usb4 - // List: internal1 < hdmi3 < usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); } @@ -1054,48 +1069,48 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] hdmi3 usb4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] hdmi3 usb4 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(hdmi3); - // Devices: [internal1* hdmi2 hdmi3] usb4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2 hdmi3*] usb4 + // List: internal1 < hdmi2 < hdmi3 + EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); Plug(usb4); // Devices: [internal1 hdmi2 hdmi3 usb4*] - // List: internal1 < usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 EXPECT_EQ(ActiveOutputNodeId(), usb4.id); Unplug(hdmi2); // Devices: [internal1 hdmi3 usb4*] hdmi2 - // List: internal1 < usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 EXPECT_EQ(ActiveOutputNodeId(), usb4.id); Unplug(hdmi3); // Devices: [internal1 usb4*] hdmi2 hdmi3 - // List: internal1 < usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 EXPECT_EQ(ActiveOutputNodeId(), usb4.id); Unplug(usb4); // Devices: [internal1*] hdmi2 hdmi3 usb4 - // List: internal1 < usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] hdmi3 usb4 - // List: internal1 < usb4 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] hdmi3 usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(hdmi3); - // Devices: [internal1* hdmi2 hdmi3] usb4 - // List: internal1 < usb4 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2 hdmi3*] usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 + EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); Plug(usb4); // Devices: [internal1 hdmi2 hdmi3 usb4*] - // List: internal1 < usb4 + // List: internal1 < hdmi2 < hdmi3 < usb4 EXPECT_EQ(ActiveOutputNodeId(), usb4.id); } @@ -1110,31 +1125,6 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] hdmi3 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); - - Plug(hdmi3); - // Devices: [internal1* hdmi2 hdmi3] - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); - - Select(hdmi2); - // Devices: [internal1 hdmi2* hdmi3] - // List: internal1 < hdmi2 - EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); - - Unplug(hdmi2); - // Devices: [internal1* hdmi3] hdmi2 - // List: internal1 < hdmi2 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); - - Unplug(hdmi3); - // Devices: [internal1*] hdmi2 hdmi3 - // List: internal1 < hdmi2 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); - - Plug(hdmi2); // Devices: [internal1 hdmi2*] hdmi3 // List: internal1 < hdmi2 EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); @@ -1143,6 +1133,31 @@ // Devices: [internal1 hdmi2 hdmi3*] // List: internal1 < hdmi2 < hdmi3 EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); + + Select(hdmi2); + // Devices: [internal1 hdmi2* hdmi3] + // List: internal1 < hdmi3 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Unplug(hdmi2); + // Devices: [internal1 hdmi3*] hdmi2 + // List: internal1 < hdmi3 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); + + Unplug(hdmi3); + // Devices: [internal1*] hdmi2 hdmi3 + // List: internal1 < hdmi3 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + + Plug(hdmi2); + // Devices: [internal1 hdmi2*] hdmi3 + // List: internal1 < hdmi3 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Plug(hdmi3); + // Devices: [internal1 hdmi2* hdmi3] + // List: internal1 < hdmi3 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); } TEST_F(AudioDeviceSelectionGeneratedTest, FeedbackComment8Output) { @@ -1156,18 +1171,23 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); + // Devices: [internal1 hdmi2*] headphone3 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Select(internal1); // Devices: [internal1* hdmi2] headphone3 - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(headphone3); // Devices: [internal1 hdmi2 headphone3*] - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); Unplug(headphone3); // Devices: [internal1* hdmi2] headphone3 - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); } @@ -1181,18 +1201,23 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); + // Devices: [internal1 hdmi2*] + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Select(internal1); // Devices: [internal1* hdmi2] - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Unplug(hdmi2); // Devices: [internal1*] hdmi2 - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); // Devices: [internal1* hdmi2] - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); } @@ -1207,18 +1232,23 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); + // Devices: [internal1 hdmi2*] headphone3 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Select(internal1); // Devices: [internal1* hdmi2] headphone3 - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(headphone3); // Devices: [internal1 hdmi2 headphone3*] - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); Unplug(headphone3); // Devices: [internal1* hdmi2] headphone3 - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); } @@ -1233,14 +1263,14 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] hdmi3 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] hdmi3 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(hdmi3); - // Devices: [internal1* hdmi2 hdmi3] - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2 hdmi3*] + // List: internal1 < hdmi2 < hdmi3 + EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); } TEST_F(AudioDeviceSelectionGeneratedTest, GreendocM3Output) { @@ -1255,28 +1285,28 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); - // Devices: [internal1* hdmi2] hdmi3 headphone4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2*] hdmi3 headphone4 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(hdmi3); - // Devices: [internal1* hdmi2 hdmi3] headphone4 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); + // Devices: [internal1 hdmi2 hdmi3*] headphone4 + // List: internal1 < hdmi2 < hdmi3 + EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); Select(hdmi2); // Devices: [internal1 hdmi2* hdmi3] headphone4 - // List: internal1 < hdmi2 + // List: internal1 < hdmi3 < hdmi2 EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); Plug(headphone4); // Devices: [internal1 hdmi2 hdmi3 headphone4*] - // List: internal1 < hdmi2 < headphone4 + // List: internal1 < hdmi3 < hdmi2 < headphone4 EXPECT_EQ(ActiveOutputNodeId(), headphone4.id); Unplug(headphone4); // Devices: [internal1 hdmi2* hdmi3] headphone4 - // List: internal1 < hdmi2 < headphone4 + // List: internal1 < hdmi3 < hdmi2 < headphone4 EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); } @@ -1291,33 +1321,33 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); + // Devices: [internal1 hdmi2*] hdmi3 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Select(internal1); // Devices: [internal1* hdmi2] hdmi3 - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Unplug(hdmi2); // Devices: [internal1*] hdmi2 hdmi3 - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi3); - // Devices: [internal1* hdmi3] hdmi2 - // List: internal1 - EXPECT_EQ(ActiveOutputNodeId(), internal1.id); - - Select(hdmi3); // Devices: [internal1 hdmi3*] hdmi2 - // List: internal1 < hdmi3 + // List: hdmi2 < internal1 < hdmi3 EXPECT_EQ(ActiveOutputNodeId(), hdmi3.id); Unplug(hdmi3); // Devices: [internal1*] hdmi2 hdmi3 - // List: internal1 < hdmi3 + // List: hdmi2 < internal1 < hdmi3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); // Devices: [internal1* hdmi2] hdmi3 - // List: internal1 < hdmi3 + // List: hdmi2 < internal1 < hdmi3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); } @@ -1332,28 +1362,33 @@ EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); + // Devices: [internal1 hdmi2*] headphone3 + // List: internal1 < hdmi2 + EXPECT_EQ(ActiveOutputNodeId(), hdmi2.id); + + Select(internal1); // Devices: [internal1* hdmi2] headphone3 - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Unplug(hdmi2); // Devices: [internal1*] hdmi2 headphone3 - // List: internal1 + // List: hdmi2 < internal1 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(headphone3); // Devices: [internal1 headphone3*] hdmi2 - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), headphone3.id); Unplug(headphone3); // Devices: [internal1*] hdmi2 headphone3 - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); Plug(hdmi2); // Devices: [internal1* hdmi2] headphone3 - // List: internal1 < headphone3 + // List: hdmi2 < internal1 < headphone3 EXPECT_EQ(ActiveOutputNodeId(), internal1.id); }
diff --git a/chromeos/ash/components/audio/cras_audio_handler_unittest.cc b/chromeos/ash/components/audio/cras_audio_handler_unittest.cc index d8a0e87..7ea8961 100644 --- a/chromeos/ash/components/audio/cras_audio_handler_unittest.cc +++ b/chromeos/ash/components/audio/cras_audio_handler_unittest.cc
@@ -1187,7 +1187,7 @@ SetupAudioNodesAndExpectActiveNodes( /*initial_nodes=*/{kInternalSpeaker, kHDMIOutput}, /*expected_active_input_node=*/nullptr, - /*expected_active_output_node=*/kInternalSpeaker, + /*expected_active_output_node=*/kHDMIOutput, /*expected_has_alternative_input=*/std::nullopt, /*expected_has_alternative_output=*/true); } @@ -1219,21 +1219,16 @@ cras_audio_handler_->GetAudioDevices(&audio_devices); EXPECT_EQ(2u, audio_devices.size()); - // Verify the active output device is not switched to hdmi output, and - // ActiveOutputChanged event is not fired. - EXPECT_EQ(0, test_observer_->active_output_node_changed_count()); - ExpectActiveDevice(/*is_input=*/false, - /*expected_active_device=*/kInternalSpeaker, + // Verify the active output device is switched to hdmi output, and + // ActiveOutputChanged event is fired. + EXPECT_EQ(1, test_observer_->active_output_node_changed_count()); + ExpectActiveDevice(/*is_input=*/false, /*expected_active_device=*/kHDMIOutput, /*has_alternative_device=*/true); system_monitor_observer_.reset_count(); // Disconnect hdmi headset. audio_nodes.clear(); - { - AudioNode active_internal_speaker = GenerateAudioNode(kInternalSpeaker); - active_internal_speaker.active = true; - audio_nodes.push_back(active_internal_speaker); - } + audio_nodes.push_back(GenerateAudioNode(kInternalSpeaker)); ChangeAudioNodes(audio_nodes); // Verify the AudioNodesChanged event is fired and one audio device is @@ -1243,9 +1238,9 @@ cras_audio_handler_->GetAudioDevices(&audio_devices); EXPECT_EQ(1u, audio_devices.size()); - // Verify the active output device is still the internal speaker, and - // ActiveOutputChanged event is not fired. - EXPECT_EQ(0, test_observer_->active_output_node_changed_count()); + // Verify the active output device is switched to internal speaker, and + // ActiveOutputChanged event is fired. + EXPECT_EQ(2, test_observer_->active_output_node_changed_count()); ExpectActiveDevice(/*is_input=*/false, /*expected_active_device=*/kInternalSpeaker, /*has_alternative_device=*/false); @@ -1344,11 +1339,10 @@ cras_audio_handler_->GetAudioDevices(&audio_devices); EXPECT_EQ(2u, audio_devices.size()); - // Verify the active output device is switched to internal speaker, and + // Verify the active output device is switched to HDMI output, and // ActiveOutputChanged event is fired. EXPECT_EQ(1, test_observer_->active_output_node_changed_count()); - ExpectActiveDevice(/*is_input=*/false, - /*expected_active_device=*/kInternalSpeaker, + ExpectActiveDevice(/*is_input=*/false, /*expected_active_device=*/kHDMIOutput, /*has_alternative_device=*/true); } @@ -5029,7 +5023,7 @@ // priority // output devices already plugged and user has manually selected an active // output. -TEST_P(CrasAudioHandlerTest, HotPlugHDMINotChangeActiveOutput) { +TEST_P(CrasAudioHandlerTest, HotPlugHDMIChangeActiveOutput) { AudioNodeList audio_nodes; AudioNode internal_speaker = GenerateAudioNode(kInternalSpeaker); audio_nodes.push_back(internal_speaker); @@ -5069,10 +5063,9 @@ audio_nodes.push_back(hdmi); ChangeAudioNodes(audio_nodes); - // The active output does not change to hdmi as it has lower built-in priority - // than the internal speaker. - EXPECT_EQ(kInternalSpeakerId, - cras_audio_handler_->GetPrimaryActiveOutputNode()); + // The active output change to hdmi as it has higher built-in priority than + // the internal speaker. + EXPECT_EQ(kHDMIOutputId, cras_audio_handler_->GetPrimaryActiveOutputNode()); } TEST_P(CrasAudioHandlerTest, @@ -5152,18 +5145,24 @@ // if it has a higher priority than the current active node. // crbug.com/443014. TEST_P(CrasAudioHandlerTest, HDMIRemainInactiveAfterSuspendResume) { - // Verify the internal speaker is selected as the active output since it has a - // higher priority. + // Verify the hdmi is selected as the active output since it has a higher + // priority. SetupAudioNodesAndExpectActiveNodes( /*initial_nodes=*/{kInternalSpeaker, kHDMIOutput}, /*expected_active_input_node=*/nullptr, - /*expected_active_output_node=*/kInternalSpeaker, + /*expected_active_output_node=*/kHDMIOutput, /*expected_has_alternative_input=*/std::nullopt, /*expected_has_alternative_output=*/true); + // Manually set the active output to internal speaker. + AudioNode internal_speaker = GenerateAudioNode(kInternalSpeaker); + cras_audio_handler_->SwitchToDevice(AudioDevice(internal_speaker), true, + DeviceActivateType::kActivateByUser); + EXPECT_EQ(internal_speaker.id, + cras_audio_handler_->GetPrimaryActiveOutputNode()); + // Simulate the suspend and resume of the device during mirror mode. The HDMI // node will be lost first. - AudioNode internal_speaker = GenerateAudioNode(kInternalSpeaker); AudioNodeList audio_nodes; internal_speaker.active = true; audio_nodes.push_back(internal_speaker); @@ -5231,19 +5230,15 @@ // This test HDMI output rediscovering case in crbug.com/503667. TEST_P(CrasAudioHandlerTest, HDMIOutputRediscover) { - // Prepare and switch to HDMI, and verify audio output is not muted. + // Verify the HDMI device has been selected as the active output, and audio + // output is not muted. SetupAudioNodesAndExpectActiveNodes( /*initial_nodes=*/{kInternalSpeaker, kHDMIOutput}, /*expected_active_input_node=*/nullptr, - /*expected_active_output_node=*/kInternalSpeaker, + /*expected_active_output_node=*/kHDMIOutput, /*expected_has_alternative_input=*/std::nullopt, /*expected_has_alternative_output=*/true); - // Manually set the active output to HDMI. - AudioNode hdmi_output = GenerateAudioNode(kHDMIOutput); - cras_audio_handler_->SwitchToDevice(AudioDevice(hdmi_output), true, - DeviceActivateType::kActivateByUser); - EXPECT_FALSE(cras_audio_handler_->IsOutputMuted()); // Trigger HDMI rediscovering grace period, and remove the HDMI node. @@ -5284,19 +5279,15 @@ // This tests the case of output unmuting event is not notified after the hdmi // output re-discover grace period ends. TEST_P(CrasAudioHandlerTest, HDMIOutputUnplugDuringSuspension) { - // Prepare and switch to HDMI, and verify audio output is not muted. + // Verify the HDMI device has been selected as the active output, and audio + // output is not muted. SetupAudioNodesAndExpectActiveNodes( /*initial_nodes=*/{kInternalSpeaker, kHDMIOutput}, /*expected_active_input_node=*/nullptr, - /*expected_active_output_node=*/kInternalSpeaker, + /*expected_active_output_node=*/kHDMIOutput, /*expected_has_alternative_input=*/std::nullopt, /*expected_has_alternative_output=*/true); - // Manually set the active output to HDMI. - AudioNode hdmi_output = GenerateAudioNode(kHDMIOutput); - cras_audio_handler_->SwitchToDevice(AudioDevice(hdmi_output), true, - DeviceActivateType::kActivateByUser); - EXPECT_FALSE(cras_audio_handler_->IsOutputMuted()); // Trigger HDMI rediscovering grace period, and remove the HDMI node. @@ -6979,9 +6970,9 @@ TEST_P(CrasAudioHandlerTest, AlternativeInputDeviceWithOneInternalAndOneExternalOutputDevice) { SetupAudioNodesAndExpectActiveNodes( - /*initial_nodes=*/{kInternalSpeaker, kUSBHeadphone1}, + /*initial_nodes=*/{kInternalSpeaker, kHDMIOutput}, /*expected_active_input_node=*/nullptr, - /*expected_active_output_node=*/kUSBHeadphone1, + /*expected_active_output_node=*/kHDMIOutput, /*expected_has_alternative_input=*/std::nullopt, /*expected_has_alternative_output=*/true); }
diff --git a/chromeos/ash/components/audio/device_selection_test_gen/dsp.py b/chromeos/ash/components/audio/device_selection_test_gen/dsp.py index 6285032..95a3186 100644 --- a/chromeos/ash/components/audio/device_selection_test_gen/dsp.py +++ b/chromeos/ash/components/audio/device_selection_test_gen/dsp.py
@@ -32,8 +32,8 @@ class T: Headphone = Type("Headphone", 4, False) USB = Type("USB", 3, False) - Internal = Type("Internal", 2, True) - HDMI = Type("HDMI", 1, True) + HDMI = Type("HDMI", 2, True) + Internal = Type("Internal", 1, True) @dataclasses.dataclass(frozen=True)
diff --git a/chromeos/ash/components/kcer/kcer_nss/kcer_nss_fuzzer.cc b/chromeos/ash/components/kcer/kcer_nss/kcer_nss_fuzzer.cc index a45b75f08..5ea7cb8 100644 --- a/chromeos/ash/components/kcer/kcer_nss/kcer_nss_fuzzer.cc +++ b/chromeos/ash/components/kcer/kcer_nss/kcer_nss_fuzzer.cc
@@ -883,6 +883,12 @@ if (!cert) { return; } + net::ScopedCERTCertificate nss_cert = + net::x509_util::CreateCERTCertificateFromX509Certificate(cert.get()); + if (!nss_cert) { + // NSS doesn't consider the cert valid. + return; + } base::span<const uint8_t> cert_data = GetCertData(cert); CertDer cert_der(std::vector<uint8_t>(cert_data.begin(), cert_data.end()));
diff --git a/chromeos/ash/components/policy/device_local_account/BUILD.gn b/chromeos/ash/components/policy/device_local_account/BUILD.gn new file mode 100644 index 0000000..c75baca --- /dev/null +++ b/chromeos/ash/components/policy/device_local_account/BUILD.gn
@@ -0,0 +1,23 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +assert(is_chromeos, "Non-Chrome-OS builds must not depend on //chromeos") + +component("device_local_account") { + defines = [ "IS_CHROMEOS_ASH_COMPONENTS_POLICY_DEVICE_LOCAL_ACCOUNT_IMPL" ] + + sources = [ + "device_local_account_type.cc", + "device_local_account_type.h", + ] + + deps = [ + "//base", + "//google_apis", + + # TODO(crbug.com/408460168): Only for a feature flag. + # Remove after the feature is released. + "//ash/constants", + ] +}
diff --git a/chromeos/ash/components/policy/device_local_account/DEPS b/chromeos/ash/components/policy/device_local_account/DEPS new file mode 100644 index 0000000..c1a9d257 --- /dev/null +++ b/chromeos/ash/components/policy/device_local_account/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + # This package must not depend on policy to avoid circular deps. + # We expect some of the policy implementation uses device local account + # concepts, instead. (i.e., dependency from other policy code to here). + "-components/policy", +]
diff --git a/components/policy/core/common/device_local_account_type.cc b/chromeos/ash/components/policy/device_local_account/device_local_account_type.cc similarity index 94% rename from components/policy/core/common/device_local_account_type.cc rename to chromeos/ash/components/policy/device_local_account/device_local_account_type.cc index 1146819d..be2c0243 100644 --- a/components/policy/core/common/device_local_account_type.cc +++ b/chromeos/ash/components/policy/device_local_account/device_local_account_type.cc
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/policy/core/common/device_local_account_type.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include <string_view> +#include "ash/constants/ash_features.h" #include "base/containers/fixed_flat_map.h" #include "base/notreached.h" #include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "components/policy/core/common/features.h" #include "google_apis/gaia/gaia_auth_util.h" namespace policy { @@ -25,7 +25,6 @@ {DeviceLocalAccountType::kSamlPublicSession, "saml-public-accounts"}, {DeviceLocalAccountType::kWebKioskApp, "web-kiosk-apps"}, {DeviceLocalAccountType::kKioskIsolatedWebApp, "isolated-kiosk-apps"}, - }); constexpr char kDeviceLocalAccountDomainSuffix[] = ".device-local.localhost"; @@ -41,7 +40,7 @@ case DeviceLocalAccountType::kKioskIsolatedWebApp: return true; case DeviceLocalAccountType::kArcvmKioskApp: - return policy::features::IsHeliumArcvmKioskEnabled(); + return ash::features::IsHeliumArcvmKioskEnabled(); } return false; }
diff --git a/components/policy/core/common/device_local_account_type.h b/chromeos/ash/components/policy/device_local_account/device_local_account_type.h similarity index 65% rename from components/policy/core/common/device_local_account_type.h rename to chromeos/ash/components/policy/device_local_account/device_local_account_type.h index a62c153..c8e3052 100644 --- a/components/policy/core/common/device_local_account_type.h +++ b/chromeos/ash/components/policy/device_local_account/device_local_account_type.h
@@ -2,14 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_POLICY_CORE_COMMON_DEVICE_LOCAL_ACCOUNT_TYPE_H_ -#define COMPONENTS_POLICY_CORE_COMMON_DEVICE_LOCAL_ACCOUNT_TYPE_H_ +#ifndef CHROMEOS_ASH_COMPONENTS_POLICY_DEVICE_LOCAL_ACCOUNT_DEVICE_LOCAL_ACCOUNT_TYPE_H_ +#define CHROMEOS_ASH_COMPONENTS_POLICY_DEVICE_LOCAL_ACCOUNT_DEVICE_LOCAL_ACCOUNT_TYPE_H_ #include <string> #include <string_view> +#include "base/component_export.h" #include "base/types/expected.h" -#include "components/policy/policy_export.h" namespace policy { @@ -42,11 +42,12 @@ }; // Returns whether the given value is valid DeviceLocalAccountType. -POLICY_EXPORT bool IsValidDeviceLocalAccountType(int value); +COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_POLICY_DEVICE_LOCAL_ACCOUNT) +bool IsValidDeviceLocalAccountType(int value); -POLICY_EXPORT std::string GenerateDeviceLocalAccountUserId( - std::string_view account_id, - DeviceLocalAccountType type); +COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_POLICY_DEVICE_LOCAL_ACCOUNT) +std::string GenerateDeviceLocalAccountUserId(std::string_view account_id, + DeviceLocalAccountType type); enum class GetDeviceLocalAccountTypeError { kNoDeviceLocalAccountUser, @@ -54,15 +55,16 @@ }; // Returns the type of device-local account. -POLICY_EXPORT +COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_POLICY_DEVICE_LOCAL_ACCOUNT) base::expected<DeviceLocalAccountType, GetDeviceLocalAccountTypeError> GetDeviceLocalAccountType(std::string_view user_id); // Returns whether |user_id| belongs to a device-local account. // This is equivalent to that GetDeviceLocalAccountType does not return // kNoDeviceLocalAccountUser error. -POLICY_EXPORT bool IsDeviceLocalAccountUser(std::string_view user_id); +COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_POLICY_DEVICE_LOCAL_ACCOUNT) +bool IsDeviceLocalAccountUser(std::string_view user_id); } // namespace policy -#endif // COMPONENTS_POLICY_CORE_COMMON_DEVICE_LOCAL_ACCOUNT_TYPE_H_ +#endif // CHROMEOS_ASH_COMPONENTS_POLICY_DEVICE_LOCAL_ACCOUNT_DEVICE_LOCAL_ACCOUNT_TYPE_H_
diff --git a/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.cc b/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.cc index 4986140..4fe31b5c 100644 --- a/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.cc +++ b/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.cc
@@ -13,6 +13,12 @@ namespace policy { +void RegisterDisabledSystemFeaturesPrefs(PrefRegistrySimple* registry) { + registry->RegisterListPref(policy_prefs::kSystemFeaturesDisableList); + registry->RegisterStringPref(policy_prefs::kSystemFeaturesDisableMode, + kSystemFeaturesDisableModeBlocked); +} + bool IsDisabledAppsModeHidden(const PrefService& local_state) { const bool is_disabled_apps_mode_hidden_pref = local_state.GetString(policy::policy_prefs::kSystemFeaturesDisableMode) ==
diff --git a/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.h b/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.h index b942f2f3..c8ae8232 100644 --- a/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.h +++ b/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils.h
@@ -6,10 +6,16 @@ #define CHROMEOS_ASH_COMPONENTS_POLICY_SYSTEM_FEATURES_DISABLE_LIST_SYSTEM_FEATURES_DISABLE_LIST_POLICY_UTILS_H_ #include "base/component_export.h" +#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" namespace policy { +// Registers prefs corresponding to the SystemFeaturesDisableList and +// SystemFeaturesDisableMode policies. +COMPONENT_EXPORT(CHROMEOS_ASH_COMPONENTS_POLICY) +void RegisterDisabledSystemFeaturesPrefs(PrefRegistrySimple* registry); + // Whether the icons of apps disabled by the SystemFeaturesDisableList policy // are hidden or blocked. // In managed guest sessions (MGS), this is configured by policy
diff --git a/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils_unittest.cc b/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils_unittest.cc index 7658617..979cbfd 100644 --- a/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils_unittest.cc +++ b/chromeos/ash/components/policy/system_features_disable_list/system_features_disable_list_policy_utils_unittest.cc
@@ -8,11 +8,11 @@ #include "base/functional/callback_helpers.h" #include "base/test/scoped_feature_list.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/fake_cros_settings_provider.h" #include "chromeos/constants/chromeos_features.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/core/common/policy_pref_names.h" #include "components/policy/core/common/system_features_disable_list_constants.h" #include "components/prefs/pref_registry_simple.h" @@ -73,13 +73,7 @@ cros_settings_->AddSettingsProvider(std::move(provider)); user_manager::UserManagerImpl::RegisterPrefs(local_state_.registry()); - // TODO(414768321): Share pref registration with prod code in - // SystemFeaturesDisableListPolicyHandler. - local_state_.registry()->RegisterListPref( - policy_prefs::kSystemFeaturesDisableList); - local_state_.registry()->RegisterStringPref( - policy_prefs::kSystemFeaturesDisableMode, - kSystemFeaturesDisableModeBlocked); + RegisterDisabledSystemFeaturesPrefs(local_state_.registry()); // Register users const auto user_account_id =
diff --git a/chromeos/ash/experiences/arc/arc_export.h b/chromeos/ash/experiences/arc/arc_export.h index 12a58a9..4dd237d 100644 --- a/chromeos/ash/experiences/arc/arc_export.h +++ b/chromeos/ash/experiences/arc/arc_export.h
@@ -9,10 +9,6 @@ static_assert(BUILDFLAG(IS_CHROMEOS), "ARC can be built only for ChromeOS."); -#if defined(COMPONENT_BUILD) && defined(ARC_IMPLEMENTATION) #define ARC_EXPORT __attribute__((visibility("default"))) -#else // !defined(COMPONENT_BUILD) || !defined(ARC_IMPLEMENTATION) -#define ARC_EXPORT -#endif #endif // CHROMEOS_ASH_EXPERIENCES_ARC_ARC_EXPORT_H_
diff --git a/chromeos/ash/services/BUILD.gn b/chromeos/ash/services/BUILD.gn index dae95a9..4049f4e 100644 --- a/chromeos/ash/services/BUILD.gn +++ b/chromeos/ash/services/BUILD.gn
@@ -17,7 +17,6 @@ testonly = true deps = [ "//ash:test_support", - "//chromeos/ash/services/assistant:tests", "//chromeos/ash/services/bluetooth_config:unit_tests", "//chromeos/ash/services/boca/babelorca/cpp:unit_tests", "//chromeos/ash/services/cellular_setup:unit_tests", @@ -40,11 +39,4 @@ "//chromeos/ash/services/wifi_direct:unit_tests", "//chromeos/services/machine_learning/public/cpp:ash_unit_tests", ] - - if (enable_cros_libassistant) { - deps += [ - "//chromeos/ash/services/libassistant:unit_tests", - "//chromeos/ash/services/libassistant/grpc:unit_tests", - ] - } }
diff --git a/chromeos/ash/services/assistant/BUILD.gn b/chromeos/ash/services/assistant/BUILD.gn index d1ce8ce..c9570e0d 100644 --- a/chromeos/ash/services/assistant/BUILD.gn +++ b/chromeos/ash/services/assistant/BUILD.gn
@@ -6,168 +6,14 @@ assert(is_chromeos) -component("lib") { - output_name = "assistant_service" - - friend = [ - ":tests", - ":test_support", - ] - - defines = [ "IS_ASSISTANT_SERVICE_IMPL" ] - - sources = [ - "assistant_host.cc", - "assistant_host.h", - "assistant_interaction_logger.cc", - "assistant_interaction_logger.h", - "assistant_manager_service.cc", - "assistant_manager_service.h", - "assistant_manager_service_impl.cc", - "assistant_manager_service_impl.h", - "assistant_settings_impl.cc", - "assistant_settings_impl.h", - "device_settings_host.cc", - "device_settings_host.h", - "libassistant_service_host.h", - "libassistant_service_host_impl.cc", - "libassistant_service_host_impl.h", - "media_host.cc", - "media_host.h", - "media_session/assistant_media_session.cc", - "media_session/assistant_media_session.h", - "platform/audio_devices.cc", - "platform/audio_devices.h", - "platform/audio_input_host.h", - "platform/audio_input_host_impl.cc", - "platform/audio_input_host_impl.h", - "platform/audio_output_delegate_impl.cc", - "platform/audio_output_delegate_impl.h", - "platform/platform_delegate_impl.cc", - "platform/platform_delegate_impl.h", - "service.cc", - "service.h", - "service_context.h", - "timer_host.cc", - "timer_host.h", - ] - - deps = [ - "//ash/constants", - "//base", - "//chromeos/ash/components/assistant:buildflags", - "//chromeos/ash/components/audio", - "//chromeos/ash/components/dbus", - "//chromeos/ash/services/assistant/public/proto", - "//chromeos/ash/services/libassistant/public/cpp:loader", - "//chromeos/ash/services/libassistant/public/mojom", - "//chromeos/dbus/power", - "//chromeos/dbus/power:power_manager_proto", - "//chromeos/strings", - "//chromeos/version", - "//components/account_id", - "//components/prefs", - "//components/signin/public/identity_manager", - "//components/user_manager", - "//media/mojo/mojom", - "//services/media_session/public/cpp", - "//ui/accessibility:ax_assistant", - ] - - if (enable_cros_libassistant) { - deps += [ - "//chromeos/ash/services/assistant/public/cpp", - "//chromeos/ash/services/libassistant", - "//chromeos/ash/services/libassistant:constants", - "//chromeos/ash/services/libassistant:loader", - ] - } else { - sources += - [ "//chromeos/ash/services/assistant/libassistant_loader_stub.cc" ] - } - - public_deps = [ - "//ash/public/cpp:cpp", - "//chromeos/ash/services/assistant/public/cpp", - "//chromeos/ash/services/assistant/public/mojom", - "//chromeos/services/assistant/public/shared", - "//mojo/public/cpp/bindings", - "//services/audio/public/cpp", - ] -} - -source_set("tests") { - testonly = true - deps = [ - ":lib", - ":test_support", - "//ash/constants", - "//ash/public/cpp/assistant/test_support", - "//base", - "//base/test:test_support", - "//chromeos/ash/components/assistant:buildflags", - "//chromeos/ash/components/assistant/test_support", - "//chromeos/ash/components/audio", - "//chromeos/ash/components/dbus:test_support", - "//chromeos/ash/components/dbus/audio", - "//chromeos/ash/services/assistant/public/cpp", - "//chromeos/ash/services/assistant/public/mojom", - "//chromeos/ash/services/libassistant/public/mojom", - "//chromeos/dbus/power", - "//components/prefs:test_support", - "//components/signin/public/identity_manager", - "//components/signin/public/identity_manager:test_support", - "//mojo/public/cpp/bindings", - "//services/device/public/mojom", - "//services/media_session/public/cpp/test:test_support", - "//services/media_session/public/mojom", - "//services/network:test_support", - "//testing/gmock", - "//testing/gtest", - ] - - sources = [ - "assistant_manager_service_impl_unittest.cc", - "media_host_unittest.cc", - "media_session/assistant_media_session_unittest.cc", - "platform/audio_devices_unittest.cc", - "platform/audio_input_host_unittest.cc", - "service_unittest.cc", - "test_support/fake_service_context.cc", - "test_support/fake_service_context.h", - "test_support/scoped_device_actions.cc", - "test_support/scoped_device_actions.h", - ] - - if (enable_cros_libassistant) { - deps += [ "//chromeos/assistant/internal:tests" ] - } -} - static_library("test_support") { testonly = true sources = [ - "test_support/fake_assistant_manager_service_impl.cc", - "test_support/fake_assistant_manager_service_impl.h", - "test_support/fake_assistant_settings_impl.cc", - "test_support/fake_assistant_settings_impl.h", - "test_support/fake_libassistant_service.cc", - "test_support/fake_libassistant_service.h", - "test_support/fake_service_controller.cc", - "test_support/fake_service_controller.h", - "test_support/fully_initialized_assistant_state.cc", - "test_support/fully_initialized_assistant_state.h", - "test_support/libassistant_media_controller_mock.cc", - "test_support/libassistant_media_controller_mock.h", - "test_support/mock_assistant.cc", - "test_support/mock_assistant.h", - "test_support/mock_assistant_interaction_subscriber.cc", - "test_support/mock_assistant_interaction_subscriber.h", "test_support/scoped_assistant_browser_delegate.cc", "test_support/scoped_assistant_browser_delegate.h", ] deps = [ - ":lib", + "//ash/public/cpp:cpp", "//ash/public/cpp/resources:ash_public_unscaled_resources", "//base", "//chromeos/ash/components/assistant:buildflags",
diff --git a/chromeos/ash/services/assistant/assistant_host.cc b/chromeos/ash/services/assistant/assistant_host.cc deleted file mode 100644 index 23a961b..0000000 --- a/chromeos/ash/services/assistant/assistant_host.cc +++ /dev/null
@@ -1,258 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/assistant_host.h" - -#include <memory> - -#include "base/check.h" -#include "base/functional/bind.h" -#include "base/task/single_thread_task_runner.h" -#include "chromeos/ash/services/assistant/assistant_manager_service_impl.h" -#include "chromeos/ash/services/assistant/libassistant_service_host.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/libassistant/public/mojom/service_controller.mojom.h" - -namespace ash::assistant { - -AssistantHost::AssistantHost(AssistantManagerServiceImpl* service) - : service_(service) { - if (!assistant::features::IsLibAssistantSandboxEnabled()) { - background_thread_.Start(); - } -} - -AssistantHost::~AssistantHost() { - if (libassistant_service_) { - StopLibassistantService(); - } -} - -void AssistantHost::StartLibassistantService(LibassistantServiceHost* host) { - DCHECK(host); - - libassistant_service_host_ = host; - LaunchLibassistantService(); - - BindControllers(); -} - -void AssistantHost::LaunchLibassistantService() { - if (assistant::features::IsLibAssistantSandboxEnabled()) { - libassistant_service_host_->Launch( - libassistant_service_.BindNewPipeAndPassReceiver()); - } else { - // A Mojom service runs on the thread where its receiver was bound. - // So to make |libassistant_service_| run on the background thread, we must - // create it on the background thread, as it binds its receiver in its - // constructor. - background_task_runner()->PostTask( - FROM_HERE, - base::BindOnce( - &AssistantHost::LaunchLibassistantServiceOnBackgroundThread, - // This is safe because we own the background thread, - // so when we're deleted the background thread is stopped. - base::Unretained(this), - // |libassistant_service_| runs on the current thread, so must - // be bound here and not on the background thread. - libassistant_service_.BindNewPipeAndPassReceiver())); - } - - libassistant_service_.set_disconnect_handler(base::BindOnce( - &AssistantHost::OnRemoteDisconnected, base::Unretained(this))); -} - -void AssistantHost::LaunchLibassistantServiceOnBackgroundThread( - mojo::PendingReceiver<libassistant::mojom::LibassistantService> client) { - DCHECK(background_task_runner()->BelongsToCurrentThread()); - DCHECK(libassistant_service_host_); - libassistant_service_host_->Launch(std::move(client)); -} - -void AssistantHost::StopLibassistantService() { - ResetRemote(); - - if (assistant::features::IsLibAssistantSandboxEnabled()) { - libassistant_service_host_->Stop(); - } else { - // |libassistant_service_| is launched on the background thread, so we have - // to stop it there as well. - background_task_runner()->PostTask( - FROM_HERE, - base::BindOnce( - &AssistantHost::StopLibassistantServiceOnBackgroundThread, - base::Unretained(this))); - } -} - -void AssistantHost::StopLibassistantServiceOnBackgroundThread() { - DCHECK(background_task_runner()->BelongsToCurrentThread()); - libassistant_service_host_->Stop(); -} - -void AssistantHost::OnRemoteDisconnected() { - ResetRemote(); - service_->OnStateChanged(libassistant::mojom::ServiceState::kDisconnected); -} - -void AssistantHost::BindControllers() { - mojo::PendingRemote<libassistant::mojom::AudioInputController> - pending_audio_input_controller_remote; - mojo::PendingRemote<libassistant::mojom::AudioOutputDelegate> - pending_audio_output_delegate_remote; - mojo::PendingRemote<libassistant::mojom::DeviceSettingsDelegate> - pending_device_settings_delegate_remote; - mojo::PendingRemote<libassistant::mojom::MediaDelegate> - pending_media_delegate_remote; - mojo::PendingRemote<libassistant::mojom::NotificationDelegate> - pending_notification_delegate_remote; - mojo::PendingRemote<libassistant::mojom::PlatformDelegate> - pending_platform_delegate_remote; - mojo::PendingRemote<libassistant::mojom::SpeakerIdEnrollmentController> - pending_speaker_id_enrollment_controller_remote; - mojo::PendingRemote<libassistant::mojom::TimerDelegate> - pending_timer_delegate_remote; - - media_delegate_ = - pending_media_delegate_remote.InitWithNewPipeAndPassReceiver(); - notification_delegate_ = - pending_notification_delegate_remote.InitWithNewPipeAndPassReceiver(); - platform_delegate_ = - pending_platform_delegate_remote.InitWithNewPipeAndPassReceiver(); - timer_delegate_ = - pending_timer_delegate_remote.InitWithNewPipeAndPassReceiver(); - - pending_audio_output_delegate_receiver_ = - pending_audio_output_delegate_remote.InitWithNewPipeAndPassReceiver(); - pending_device_settings_delegate_receiver_ = - pending_device_settings_delegate_remote.InitWithNewPipeAndPassReceiver(); - libassistant_service_->Bind( - pending_audio_input_controller_remote.InitWithNewPipeAndPassReceiver(), - conversation_controller_.BindNewPipeAndPassReceiver(), - display_controller_.BindNewPipeAndPassReceiver(), - media_controller_.BindNewPipeAndPassReceiver(), - service_controller_.BindNewPipeAndPassReceiver(), - settings_controller_.BindNewPipeAndPassReceiver(), - pending_speaker_id_enrollment_controller_remote - .InitWithNewPipeAndPassReceiver(), - timer_controller_.BindNewPipeAndPassReceiver(), - std::move(pending_audio_output_delegate_remote), - std::move(pending_device_settings_delegate_remote), - std::move(pending_media_delegate_remote), - std::move(pending_notification_delegate_remote), - std::move(pending_platform_delegate_remote), - std::move(pending_timer_delegate_remote)); - - audio_input_controller_ = std::move(pending_audio_input_controller_remote); - speaker_id_enrollment_controller_ = - std::move(pending_speaker_id_enrollment_controller_remote); -} - -scoped_refptr<base::SingleThreadTaskRunner> -AssistantHost::background_task_runner() { - return background_thread_.task_runner(); -} - -mojo::PendingRemote<libassistant::mojom::AudioInputController> -AssistantHost::ExtractAudioInputController() { - DCHECK(audio_input_controller_.is_valid()); - return std::move(audio_input_controller_); -} - -mojo::PendingReceiver<libassistant::mojom::AudioOutputDelegate> -AssistantHost::ExtractAudioOutputDelegate() { - DCHECK(pending_audio_output_delegate_receiver_.is_valid()); - return std::move(pending_audio_output_delegate_receiver_); -} - -mojo::PendingReceiver<libassistant::mojom::DeviceSettingsDelegate> -AssistantHost::ExtractDeviceSettingsDelegate() { - DCHECK(pending_device_settings_delegate_receiver_.is_valid()); - return std::move(pending_device_settings_delegate_receiver_); -} - -mojo::PendingReceiver<libassistant::mojom::MediaDelegate> -AssistantHost::ExtractMediaDelegate() { - DCHECK(media_delegate_.is_valid()); - return std::move(media_delegate_); -} - -mojo::PendingReceiver<libassistant::mojom::NotificationDelegate> -AssistantHost::ExtractNotificationDelegate() { - DCHECK(notification_delegate_.is_valid()); - return std::move(notification_delegate_); -} - -mojo::PendingReceiver<libassistant::mojom::PlatformDelegate> -AssistantHost::ExtractPlatformDelegate() { - DCHECK(platform_delegate_.is_valid()); - return std::move(platform_delegate_); -} - -mojo::PendingRemote<libassistant::mojom::SpeakerIdEnrollmentController> -AssistantHost::ExtractSpeakerIdEnrollmentController() { - DCHECK(speaker_id_enrollment_controller_.is_valid()); - return std::move(speaker_id_enrollment_controller_); -} - -mojo::PendingReceiver<libassistant::mojom::TimerDelegate> -AssistantHost::ExtractTimerDelegate() { - DCHECK(timer_delegate_.is_valid()); - return std::move(timer_delegate_); -} - -libassistant::mojom::ConversationController& -AssistantHost::conversation_controller() { - DCHECK(conversation_controller_.is_bound()); - return *conversation_controller_; -} - -libassistant::mojom::DisplayController& AssistantHost::display_controller() { - DCHECK(display_controller_.is_bound()); - return *display_controller_.get(); -} - -libassistant::mojom::ServiceController& AssistantHost::service_controller() { - DCHECK(service_controller_.is_bound()); - return *service_controller_.get(); -} - -libassistant::mojom::MediaController& AssistantHost::media_controller() { - DCHECK(media_controller_.is_bound()); - return *media_controller_.get(); -} - -libassistant::mojom::SettingsController& AssistantHost::settings_controller() { - DCHECK(settings_controller_.is_bound()); - return *settings_controller_; -} - -libassistant::mojom::TimerController& AssistantHost::timer_controller() { - DCHECK(timer_controller_.is_bound()); - return *timer_controller_.get(); -} - -void AssistantHost::AddSpeechRecognitionObserver( - mojo::PendingRemote<libassistant::mojom::SpeechRecognitionObserver> - observer) { - libassistant_service_->AddSpeechRecognitionObserver(std::move(observer)); -} - -void AssistantHost::AddAuthenticationStateObserver( - mojo::PendingRemote<libassistant::mojom::AuthenticationStateObserver> - observer) { - libassistant_service_->AddAuthenticationStateObserver(std::move(observer)); -} - -void AssistantHost::ResetRemote() { - libassistant_service_.reset(); - conversation_controller_.reset(); - display_controller_.reset(); - media_controller_.reset(); - service_controller_.reset(); - settings_controller_.reset(); - timer_controller_.reset(); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/assistant_host.h b/chromeos/ash/services/assistant/assistant_host.h deleted file mode 100644 index 9ca5ab8..0000000 --- a/chromeos/ash/services/assistant/assistant_host.h +++ /dev/null
@@ -1,158 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_HOST_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_HOST_H_ - -#include "base/memory/raw_ptr.h" -#include "base/task/single_thread_task_runner.h" -#include "base/threading/thread.h" -#include "base/time/time.h" -#include "chromeos/ash/services/libassistant/public/mojom/audio_input_controller.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/conversation_controller.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/display_controller.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/media_controller.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/notification_delegate.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/platform_delegate.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/service.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/service_controller.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/speaker_id_enrollment_controller.mojom-forward.h" -#include "chromeos/ash/services/libassistant/public/mojom/timer_controller.mojom.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/remote.h" - -namespace chromeos { -namespace libassistant { -class LibassistantService; -} // namespace libassistant -} // namespace chromeos - -namespace ash::assistant { - -class AssistantManagerServiceImpl; -class LibassistantServiceHost; - -// The proxy to the Assistant service, which serves as the main -// access point to the entire Assistant API. -class AssistantHost { - public: - explicit AssistantHost(AssistantManagerServiceImpl* service); - AssistantHost(AssistantHost&) = delete; - AssistantHost& operator=(AssistantHost&) = delete; - ~AssistantHost(); - - void StartLibassistantService(LibassistantServiceHost* host); - void StopLibassistantService(); - - // Returns the controller that manages conversations with Libassistant. - libassistant::mojom::ConversationController& conversation_controller(); - - // Returns the controller that manages display related settings. - libassistant::mojom::DisplayController& display_controller(); - - // Returns the controller that manages media related settings. - libassistant::mojom::MediaController& media_controller(); - - // Returns the controller that manages the lifetime of the service. - libassistant::mojom::ServiceController& service_controller(); - - // Returns the controller that manages Libassistant settings. - libassistant::mojom::SettingsController& settings_controller(); - - // Returns the controller that manages timers. - libassistant::mojom::TimerController& timer_controller(); - - // The background thread is temporary exposed until the entire Libassistant - // API is hidden behind this proxy API. - base::Thread& background_thread() { return background_thread_; } - - // Add an observer that will be informed of all speech recognition related - // updates. - void AddSpeechRecognitionObserver( - mojo::PendingRemote<libassistant::mojom::SpeechRecognitionObserver> - observer); - - void AddAuthenticationStateObserver( - mojo::PendingRemote<libassistant::mojom::AuthenticationStateObserver> - observer); - - mojo::PendingRemote<libassistant::mojom::AudioInputController> - ExtractAudioInputController(); - mojo::PendingReceiver<libassistant::mojom::AudioOutputDelegate> - ExtractAudioOutputDelegate(); - mojo::PendingReceiver<libassistant::mojom::DeviceSettingsDelegate> - ExtractDeviceSettingsDelegate(); - mojo::PendingReceiver<libassistant::mojom::MediaDelegate> - ExtractMediaDelegate(); - mojo::PendingReceiver<libassistant::mojom::NotificationDelegate> - ExtractNotificationDelegate(); - mojo::PendingReceiver<libassistant::mojom::PlatformDelegate> - ExtractPlatformDelegate(); - mojo::PendingRemote<libassistant::mojom::SpeakerIdEnrollmentController> - ExtractSpeakerIdEnrollmentController(); - mojo::PendingReceiver<libassistant::mojom::TimerDelegate> - ExtractTimerDelegate(); - - private: - scoped_refptr<base::SingleThreadTaskRunner> background_task_runner(); - - void LaunchLibassistantService(); - void LaunchLibassistantServiceOnBackgroundThread( - mojo::PendingReceiver<libassistant::mojom::LibassistantService>); - void StopLibassistantServiceOnBackgroundThread(); - - void BindControllers(); - - // Callback when `LibassistantService` has disconnected, e.g. process crashes. - void OnRemoteDisconnected(); - - // Reset remote controllers etc. for restarts. - void ResetRemote(); - - // Owned by |Service|. - raw_ptr<AssistantManagerServiceImpl> service_; - - // Owned by |AssistantManagerServiceImpl|. - raw_ptr<LibassistantServiceHost> libassistant_service_host_; - - mojo::Remote<libassistant::mojom::LibassistantService> libassistant_service_; - - mojo::Remote<libassistant::mojom::ConversationController> - conversation_controller_; - mojo::Remote<libassistant::mojom::DisplayController> display_controller_; - mojo::Remote<libassistant::mojom::MediaController> media_controller_; - mojo::Remote<libassistant::mojom::ServiceController> service_controller_; - mojo::Remote<libassistant::mojom::SettingsController> settings_controller_; - mojo::Remote<libassistant::mojom::TimerController> timer_controller_; - - // Will be unbound after they are extracted. - mojo::PendingRemote<libassistant::mojom::AudioInputController> - audio_input_controller_; - mojo::PendingReceiver<libassistant::mojom::AudioOutputDelegate> - pending_audio_output_delegate_receiver_; - mojo::PendingReceiver<libassistant::mojom::DeviceSettingsDelegate> - pending_device_settings_delegate_receiver_; - mojo::PendingReceiver<libassistant::mojom::MediaDelegate> media_delegate_; - mojo::PendingReceiver<libassistant::mojom::NotificationDelegate> - notification_delegate_; - mojo::PendingReceiver<libassistant::mojom::PlatformDelegate> - platform_delegate_; - mojo::PendingRemote<libassistant::mojom::SpeakerIdEnrollmentController> - speaker_id_enrollment_controller_; - mojo::PendingReceiver<libassistant::mojom::TimerDelegate> timer_delegate_; - - // The thread on which the Libassistant service runs. - // Only used to run LibAssistant service without sandbox for development, e.g. - // with `--no-sandbox`. Background thread is needed because there are blocking - // calls when start LibAssistant service, e.g. creating directories. - // Warning: must be the last object, so it is destroyed (and flushed) first. - // This will prevent use-after-free issues where the background thread would - // access other member variables after they have been destroyed. - base::Thread background_thread_{"Assistant background thread"}; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_HOST_H_
diff --git a/chromeos/ash/services/assistant/assistant_interaction_logger.cc b/chromeos/ash/services/assistant/assistant_interaction_logger.cc deleted file mode 100644 index acd95e1..0000000 --- a/chromeos/ash/services/assistant/assistant_interaction_logger.cc +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/assistant_interaction_logger.h" - -#include <utility> - -#include "chromeos/ash/services/assistant/public/cpp/features.h" - -namespace ash::assistant { - -namespace { - -std::string ResolutionToString(AssistantInteractionResolution resolution) { - std::stringstream result; - result << static_cast<int>(resolution); - return result.str(); -} - -bool IsPIILoggingAllowed() { - return features::IsAssistantDebuggingEnabled(); -} - -std::string HidePiiMaybe(const std::string& value) { - if (IsPIILoggingAllowed()) - return "[PII](" + value + ")"; - else - return "[Redacted PII]"; -} - -#define LOG_INTERACTION() \ - LOG_INTERACTION_AT_LEVEL(AssistantInteractionLogger::kVLogLevel) - -#define LOG_INTERACTION_AT_LEVEL(_level) \ - VLOG(_level) << "Assistant: " << __func__ << ": " - -} // namespace - -bool AssistantInteractionLogger::IsLoggingEnabled() { - return VLOG_IS_ON(kVLogLevel); -} - -AssistantInteractionLogger::AssistantInteractionLogger() = default; - -AssistantInteractionLogger::~AssistantInteractionLogger() = default; - -void AssistantInteractionLogger::OnInteractionStarted( - const AssistantInteractionMetadata& metadata) { - switch (metadata.type) { - case AssistantInteractionType::kText: - LOG_INTERACTION() << "Text interaction with query " - << HidePiiMaybe(metadata.query); - break; - case AssistantInteractionType::kVoice: - LOG_INTERACTION() << "Voice interaction"; - break; - } -} - -void AssistantInteractionLogger::OnInteractionFinished( - AssistantInteractionResolution resolution) { - LOG_INTERACTION() << "with resolution " << ResolutionToString(resolution); -} - -void AssistantInteractionLogger::OnHtmlResponse(const std::string& response, - const std::string& fallback) { - // Displaying fallback instead of the response as the response is filled with - // HTML tags and rather large. - LOG_INTERACTION() << "with fallback '" << fallback << "'"; - // Display HTML at highest verbosity. - LOG_INTERACTION_AT_LEVEL(3) << "with HTML: " << HidePiiMaybe(response); -} - -void AssistantInteractionLogger::OnSuggestionsResponse( - const std::vector<assistant::AssistantSuggestion>& response) { - std::stringstream suggestions; - for (const auto& suggestion : response) - suggestions << "'" << suggestion.text << "', "; - LOG_INTERACTION() << "{ " << suggestions.str() << " }"; -} - -void AssistantInteractionLogger::OnTextResponse(const std::string& response) { - LOG_INTERACTION() << HidePiiMaybe(response); -} - -void AssistantInteractionLogger::OnOpenUrlResponse(const GURL& url, - bool in_background) { - LOG_INTERACTION() << "with url '" << url.possibly_invalid_spec() << "'"; -} - -void AssistantInteractionLogger::OnOpenAppResponse( - const AndroidAppInfo& app_info) { - LOG_INTERACTION() << "with app '" << app_info.package_name << "'"; -} - -void AssistantInteractionLogger::OnSpeechRecognitionStarted() { - LOG_INTERACTION(); -} - -void AssistantInteractionLogger::OnSpeechRecognitionIntermediateResult( - const std::string& high_confidence_text, - const std::string& low_confidence_text) { - // Not logged until we have a use for this (and this might spam the log). -} - -void AssistantInteractionLogger::OnSpeechRecognitionEndOfUtterance() { - LOG_INTERACTION(); -} - -void AssistantInteractionLogger::OnSpeechRecognitionFinalResult( - const std::string& final_result) { - LOG_INTERACTION() << "with final result '" << final_result << "'"; -} - -void AssistantInteractionLogger::OnSpeechLevelUpdated(float speech_level) { - // Not logged until we have a use for this and this might spam the log. -} - -void AssistantInteractionLogger::OnTtsStarted(bool due_to_error) { - LOG_INTERACTION() << (due_to_error ? "not" : "") << "due to error"; -} - -void AssistantInteractionLogger::OnWaitStarted() { - LOG_INTERACTION(); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/assistant_interaction_logger.h b/chromeos/ash/services/assistant/assistant_interaction_logger.h deleted file mode 100644 index 9acf16b1a..0000000 --- a/chromeos/ash/services/assistant/assistant_interaction_logger.h +++ /dev/null
@@ -1,70 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_INTERACTION_LOGGER_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_INTERACTION_LOGGER_H_ - -#include <string> -#include <vector> - -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" - -namespace ash::assistant { - -// A subscriber that will log all Assistant interactions. -// The interactions will be logged using -// VLOG(AssistantInteractionLogger::kVLogLevel) -class AssistantInteractionLogger : public AssistantInteractionSubscriber { - public: - // VLog level used for logging interactions. - constexpr static const int kVLogLevel = 1; - - // Returns if the current logging level is high enough so that the traces - // will be printed. If not, there is no point in creating this class. - static bool IsLoggingEnabled(); - - AssistantInteractionLogger(); - AssistantInteractionLogger(AssistantInteractionLogger&) = delete; - AssistantInteractionLogger& operator=(AssistantInteractionLogger&) = delete; - ~AssistantInteractionLogger() override; - - // AssistantInteractionSubscriber implementation: - void OnInteractionStarted( - const AssistantInteractionMetadata& metadata) override; - - void OnInteractionFinished( - AssistantInteractionResolution resolution) override; - - void OnHtmlResponse(const std::string& response, - const std::string& fallback) override; - - void OnSuggestionsResponse( - const std::vector<AssistantSuggestion>& response) override; - - void OnTextResponse(const std::string& response) override; - - void OnOpenUrlResponse(const GURL& url, bool in_background) override; - - void OnOpenAppResponse(const AndroidAppInfo& app_info) override; - - void OnSpeechRecognitionStarted() override; - - void OnSpeechRecognitionIntermediateResult( - const std::string& high_confidence_text, - const std::string& low_confidence_text) override; - - void OnSpeechRecognitionEndOfUtterance() override; - - void OnSpeechRecognitionFinalResult(const std::string& final_result) override; - - void OnSpeechLevelUpdated(float speech_level) override; - - void OnTtsStarted(bool due_to_error) override; - - void OnWaitStarted() override; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_INTERACTION_LOGGER_H_
diff --git a/chromeos/ash/services/assistant/assistant_manager_service.cc b/chromeos/ash/services/assistant/assistant_manager_service.cc deleted file mode 100644 index e0a578c6..0000000 --- a/chromeos/ash/services/assistant/assistant_manager_service.cc +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/assistant_manager_service.h" - -namespace ash::assistant { - -AuthenticationStateObserver::AuthenticationStateObserver() = default; - -AuthenticationStateObserver::~AuthenticationStateObserver() = default; - -mojo::PendingRemote<libassistant::mojom::AuthenticationStateObserver> -AuthenticationStateObserver::BindNewPipeAndPassRemote() { - return receiver_.BindNewPipeAndPassRemote(); -} - -void AuthenticationStateObserver::ResetAuthenticationStateObserver() { - receiver_.reset(); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/assistant_manager_service.h b/chromeos/ash/services/assistant/assistant_manager_service.h deleted file mode 100644 index 282fee6..0000000 --- a/chromeos/ash/services/assistant/assistant_manager_service.h +++ /dev/null
@@ -1,144 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_MANAGER_SERVICE_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_MANAGER_SERVICE_H_ - -#include <memory> -#include <string> - -#include "base/component_export.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_settings.h" -#include "chromeos/ash/services/libassistant/public/mojom/authentication_state_observer.mojom.h" -#include "google_apis/gaia/gaia_id.h" -#include "services/media_session/public/mojom/media_session.mojom-shared.h" - -namespace ash::assistant { - -class AuthenticationStateObserver; - -// Interface class that defines all assistant functionalities. -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantManagerService - : public Assistant { - public: - class StateObserver; - - struct UserInfo { - UserInfo(const GaiaId& gaia_id, const std::string& access_token) - : gaia_id(gaia_id), access_token(access_token) {} - - GaiaId gaia_id; - std::string access_token; - }; - - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // If any value is added, please update enums.xml - // `AssistantServiceState`. - // Enumeration of possible assistant manager service states. - enum State { - // Initial state, the service is created but not started yet. - STOPPED = 0, - // Start has been called but libassistant creation is still in progress. - // Calling |assistant_manager()| will still return a nullptr. - // TODO(b/171748795): I think we no longer need this state once - // Libassistant has migrated to a mojom service (in fact, we should be able - // to remove this enum and use ash::libassistant::mojom::ServiceState). - STARTING = 1, - // The service is started, libassistant has been created, but libassistant - // is not ready yet to take requests. - STARTED = 2, - // The service is fully running and ready to take requests. - RUNNING = 3, - // Stop has been called but `assistant_manager` has not been destroyed. It - // is possible that some functions will call back to the browser thread, - // e.g. the audio output. - STOPPING = 4, - // The libassistant mojom service is disconnected, e.g. process crashes. - DISCONNECTED = 5, - - kMaxValue = DISCONNECTED - }; - - ~AssistantManagerService() override = default; - - // Start the Assistant in the background with the given |user|. - // If the user is nullopt, the service will be started in signed-out mode. - // If you want to know when the service is started, use - // |AddAndFireStateObserver| to add an observer. - virtual void Start(const std::optional<UserInfo>& user, - bool enable_hotword) = 0; - - // Stop the Assistant. - virtual void Stop() = 0; - - // Return the current state. - virtual State GetState() const = 0; - - // Set user information for Assistant. Passing a nullopt will reconfigure - // Libassistant to run in signed-out mode, and passing a valid non-empty value - // will switch the mode back to normal. - virtual void SetUser(const std::optional<UserInfo>& user) = 0; - - // Turn on / off all listening, including hotword and voice query. - virtual void EnableListening(bool enable) = 0; - - // Turn on / off hotword listening. - virtual void EnableHotword(bool enable) = 0; - - // Enable/disable ARC play store. - virtual void SetArcPlayStoreEnabled(bool enabled) = 0; - - // Enable/disable Assistant Context. - virtual void SetAssistantContextEnabled(bool enable) = 0; - - // Return a pointer of AssistantSettings. - virtual AssistantSettings* GetAssistantSettings() = 0; - - virtual void AddAuthenticationStateObserver( - AuthenticationStateObserver* observer) = 0; - - // Add/Remove an observer that is invoked when there is a change in the - // |AssistantManagerService::State| value. - // When adding an observer it will immediately be triggered with the current - // state value. - virtual void AddAndFireStateObserver(StateObserver* observer) = 0; - virtual void RemoveStateObserver(const StateObserver* observer) = 0; - - // Sync the device apps user consent status. - virtual void SyncDeviceAppsStatus() = 0; - - // Update and sync the internal media player status to Libassistant. - virtual void UpdateInternalMediaPlayerStatus( - media_session::mojom::MediaSessionAction action) = 0; -}; - -// Observes all state changes made to the |AssistantManagerService::State|. -class AssistantManagerService::StateObserver : public base::CheckedObserver { - public: - StateObserver() = default; - ~StateObserver() override = default; - - virtual void OnStateChanged(AssistantManagerService::State new_state) = 0; -}; - -class AuthenticationStateObserver - : public libassistant::mojom::AuthenticationStateObserver { - public: - AuthenticationStateObserver(); - ~AuthenticationStateObserver() override; - - mojo::PendingRemote<libassistant::mojom::AuthenticationStateObserver> - BindNewPipeAndPassRemote(); - void ResetAuthenticationStateObserver(); - - private: - mojo::Receiver<libassistant::mojom::AuthenticationStateObserver> receiver_{ - this}; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_MANAGER_SERVICE_H_
diff --git a/chromeos/ash/services/assistant/assistant_manager_service_impl.cc b/chromeos/ash/services/assistant/assistant_manager_service_impl.cc deleted file mode 100644 index 2f1b5a7..0000000 --- a/chromeos/ash/services/assistant/assistant_manager_service_impl.cc +++ /dev/null
@@ -1,789 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/assistant_manager_service_impl.h" - -#include <algorithm> -#include <memory> -#include <optional> -#include <utility> - -#include "ash/constants/ash_features.h" -#include "ash/constants/ash_switches.h" -#include "ash/public/cpp/assistant/assistant_state.h" -#include "ash/public/cpp/assistant/assistant_state_base.h" -#include "ash/public/cpp/assistant/controller/assistant_notification_controller.h" -#include "base/barrier_closure.h" -#include "base/check.h" -#include "base/command_line.h" -#include "base/containers/contains.h" -#include "base/feature_list.h" -#include "base/functional/bind.h" -#include "base/i18n/rtl.h" -#include "base/logging.h" -#include "base/memory/raw_ref.h" -#include "base/metrics/histogram_macros.h" -#include "base/notreached.h" -#include "base/run_loop.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/task/sequenced_task_runner.h" -#include "base/time/time.h" -#include "base/unguessable_token.h" -#include "chromeos/ash/services/assistant/device_settings_host.h" -#include "chromeos/ash/services/assistant/libassistant_service_host_impl.h" -#include "chromeos/ash/services/assistant/media_host.h" -#include "chromeos/ash/services/assistant/platform/audio_input_host_impl.h" -#include "chromeos/ash/services/assistant/platform/audio_output_delegate_impl.h" -#include "chromeos/ash/services/assistant/platform/platform_delegate_impl.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_enums.h" -#include "chromeos/ash/services/assistant/public/cpp/device_actions.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/assistant/service.h" -#include "chromeos/ash/services/assistant/service_context.h" -#include "chromeos/ash/services/assistant/timer_host.h" -#include "chromeos/ash/services/libassistant/public/mojom/android_app_info.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/speech_recognition_observer.mojom.h" -#include "chromeos/services/assistant/public/shared/utils.h" -#include "chromeos/strings/grit/chromeos_strings.h" -#include "chromeos/version/version_loader.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "ui/accessibility/mojom/ax_assistant_structure.mojom.h" -#include "ui/base/l10n/l10n_util.h" -#include "url/gurl.h" - -using media_session::mojom::MediaSessionAction; - -namespace ash::assistant { -namespace { - -static base::OnceCallback<void()> initialized_internal_callback_for_testing; -static bool is_first_init = true; - -constexpr char kAndroidSettingsAppPackage[] = "com.android.settings"; - -std::vector<libassistant::mojom::AuthenticationTokenPtr> ToAuthenticationTokens( - const std::optional<AssistantManagerService::UserInfo>& user) { - std::vector<libassistant::mojom::AuthenticationTokenPtr> result; - - if (user.has_value()) { - DCHECK(!user.value().gaia_id.empty()); - DCHECK(!user.value().access_token.empty()); - result.emplace_back(libassistant::mojom::AuthenticationToken::New( - /*gaia_id=*/user.value().gaia_id.ToString(), - /*access_token=*/user.value().access_token)); - } - - return result; -} - -libassistant::mojom::BootupConfigPtr CreateBootupConfig( - const std::optional<std::string>& s3_server_uri_override, - const std::optional<std::string>& device_id_override) { - auto result = libassistant::mojom::BootupConfig::New(); - result->s3_server_uri_override = s3_server_uri_override; - result->device_id_override = device_id_override; - return result; -} - -} // namespace - -// Observer that will receive all speech recognition related events, -// and forwards them to all |AssistantInteractionSubscriber|. -class SpeechRecognitionObserverWrapper - : public libassistant::mojom::SpeechRecognitionObserver { - public: - explicit SpeechRecognitionObserverWrapper( - const base::ObserverList<AssistantInteractionSubscriber>* observers) - : interaction_subscribers_(*observers) { - DCHECK(observers); - } - SpeechRecognitionObserverWrapper(const SpeechRecognitionObserverWrapper&) = - delete; - SpeechRecognitionObserverWrapper& operator=( - const SpeechRecognitionObserverWrapper&) = delete; - ~SpeechRecognitionObserverWrapper() override = default; - - mojo::PendingRemote<libassistant::mojom::SpeechRecognitionObserver> - BindNewPipeAndPassRemote() { - return receiver_.BindNewPipeAndPassRemote(); - } - - void Stop() { receiver_.reset(); } - - // libassistant::mojom::SpeechRecognitionObserver implementation: - void OnSpeechLevelUpdated(float speech_level_in_decibels) override { - for (auto& it : *interaction_subscribers_) { - it.OnSpeechLevelUpdated(speech_level_in_decibels); - } - } - - void OnSpeechRecognitionStart() override { - for (auto& it : *interaction_subscribers_) { - it.OnSpeechRecognitionStarted(); - } - } - - void OnIntermediateResult(const std::string& high_confidence_text, - const std::string& low_confidence_text) override { - for (auto& it : *interaction_subscribers_) { - it.OnSpeechRecognitionIntermediateResult(high_confidence_text, - low_confidence_text); - } - } - - void OnSpeechRecognitionEnd() override { - for (auto& it : *interaction_subscribers_) { - it.OnSpeechRecognitionEndOfUtterance(); - } - } - - void OnFinalResult(const std::string& recognized_text) override { - for (auto& it : *interaction_subscribers_) { - it.OnSpeechRecognitionFinalResult(recognized_text); - } - } - - private: - // Owned by our parent, |AssistantManagerServiceImpl|. - const raw_ref<const base::ObserverList<AssistantInteractionSubscriber>> - interaction_subscribers_; - - mojo::Receiver<libassistant::mojom::SpeechRecognitionObserver> receiver_{ - this}; -}; - -// static -void AssistantManagerServiceImpl::SetInitializedInternalCallbackForTesting( - base::OnceCallback<void()> callback) { - CHECK(initialized_internal_callback_for_testing.is_null()); - // We expect that the callback is set when AssistantStatus is NOT_READY to - // confirm that AssistantStatus has changed from NOT_READY to READY. See more - // details at a comment in AssistantManagerServiceImpl::OnDeviceAppsEnabled. - CHECK(AssistantState::Get()->assistant_status() == - AssistantStatus::NOT_READY); - initialized_internal_callback_for_testing = std::move(callback); -} - -// static -void AssistantManagerServiceImpl::ResetIsFirstInitFlagForTesting() { - is_first_init = true; -} - -AssistantManagerServiceImpl::AssistantManagerServiceImpl( - ServiceContext* context, - std::unique_ptr<network::PendingSharedURLLoaderFactory> - pending_url_loader_factory, - std::optional<std::string> s3_server_uri_override, - std::optional<std::string> device_id_override, - std::unique_ptr<LibassistantServiceHost> libassistant_service_host) - : assistant_settings_(std::make_unique<AssistantSettingsImpl>(context)), - assistant_host_(std::make_unique<AssistantHost>(this)), - platform_delegate_(std::make_unique<PlatformDelegateImpl>()), - context_(context), - device_settings_host_(std::make_unique<DeviceSettingsHost>(context)), - media_host_(std::make_unique<MediaHost>(AssistantBrowserDelegate::Get(), - &interaction_subscribers_)), - timer_host_(std::make_unique<TimerHost>(context)), - audio_output_delegate_(std::make_unique<AudioOutputDelegateImpl>( - &media_host_->media_session())), - speech_recognition_observer_( - std::make_unique<SpeechRecognitionObserverWrapper>( - &interaction_subscribers_)), - bootup_config_( - CreateBootupConfig(s3_server_uri_override, device_id_override)), - url_loader_factory_(network::SharedURLLoaderFactory::Create( - std::move(pending_url_loader_factory))), - weak_factory_(this) { - if (libassistant_service_host) { - // During unittests a custom host is passed in, so we'll use that one. - libassistant_service_host_ = std::move(libassistant_service_host); - } else { - // Use the default service host if none was provided. - libassistant_service_host_ = - std::make_unique<LibassistantServiceHostImpl>(); - } -} - -AssistantManagerServiceImpl::~AssistantManagerServiceImpl() { - // Destroy the Assistant Proxy first so the background thread is flushed - // before any of the other objects are destroyed. - assistant_host_ = nullptr; -} - -void AssistantManagerServiceImpl::Start(const std::optional<UserInfo>& user, - bool enable_hotword) { - DCHECK(!IsServiceStarted()); - DCHECK(GetState() == State::STOPPED || GetState() == State::DISCONNECTED); - - Initialize(); - - // Set the flag to avoid starting the service multiple times. - SetStateAndInformObservers(State::STARTING); - - started_time_ = base::TimeTicks::Now(); - - EnableHotword(enable_hotword); - InitAssistant(user); -} - -void AssistantManagerServiceImpl::Stop() { - // We cannot cleanly stop the service if it is in the process of starting up. - DCHECK_NE(GetState(), State::STARTING); - - // During shutdown, this could be called when the libassistant - // service is not started. - if (!IsServiceStarted()) { - return; - } - - weak_factory_.InvalidateWeakPtrs(); - SetStateAndInformObservers(State::STOPPING); - - // We stop observing media events before we destroy `AssistantManagerImpl`, - // otherwise notification may happen any time after it is destroyed. - media_host_->Stop(); - // For similar reason, stop observing app_list events. - scoped_app_list_event_subscriber_.Reset(); - - // When user disables the feature, we also delete all data. - if (!assistant_state()->settings_enabled().value()) - service_controller().ResetAllDataAndStop(); - else - service_controller().Stop(); -} - -AssistantManagerService::State AssistantManagerServiceImpl::GetState() const { - return state_; -} - -void AssistantManagerServiceImpl::SetUser(const std::optional<UserInfo>& user) { - if (!IsServiceStarted()) - return; - - VLOG(1) << "Set user information (Gaia ID and access token)."; - settings_controller().SetAuthenticationTokens(ToAuthenticationTokens(user)); -} - -void AssistantManagerServiceImpl::EnableListening(bool enable) { - // Could be called when the libassistant service is not started. - if (!IsServiceStarted()) - return; - - settings_controller().SetListeningEnabled(enable); -} - -void AssistantManagerServiceImpl::EnableHotword(bool enable) { - // Could be called when the libassistant service is not started. - if (!IsServiceStarted()) - return; - - audio_input_host_->OnHotwordEnabled(enable); -} - -void AssistantManagerServiceImpl::SetArcPlayStoreEnabled(bool enable) { - DCHECK(GetState() == State::RUNNING); - if (assistant::features::IsAppSupportEnabled()) - display_controller().SetArcPlayStoreEnabled(enable); -} - -void AssistantManagerServiceImpl::SetAssistantContextEnabled(bool enable) { - DCHECK(GetState() == State::RUNNING); - - media_host_->SetRelatedInfoEnabled(enable); - display_controller().SetRelatedInfoEnabled(enable); -} - -AssistantSettings* AssistantManagerServiceImpl::GetAssistantSettings() { - return assistant_settings_.get(); -} - -void AssistantManagerServiceImpl::AddAuthenticationStateObserver( - AuthenticationStateObserver* observer) { - DCHECK(observer); - assistant_host_->AddAuthenticationStateObserver( - observer->BindNewPipeAndPassRemote()); -} - -void AssistantManagerServiceImpl::AddAndFireStateObserver( - AssistantManagerService::StateObserver* observer) { - state_observers_.AddObserver(observer); - observer->OnStateChanged(GetState()); -} - -void AssistantManagerServiceImpl::RemoveStateObserver( - const AssistantManagerService::StateObserver* observer) { - state_observers_.RemoveObserver(observer); -} - -void AssistantManagerServiceImpl::SyncDeviceAppsStatus() { - assistant_settings_->SyncDeviceAppsStatus( - base::BindOnce(&AssistantManagerServiceImpl::OnDeviceAppsEnabled, - weak_factory_.GetWeakPtr())); -} - -void AssistantManagerServiceImpl::UpdateInternalMediaPlayerStatus( - MediaSessionAction action) { - if (action == MediaSessionAction::kPause) { - media_host_->PauseInternalMediaPlayer(); - } else if (action == MediaSessionAction::kPlay) { - media_host_->ResumeInternalMediaPlayer(); - } -} - -void AssistantManagerServiceImpl::StartVoiceInteraction() { - DVLOG(1) << __func__; - - audio_input_host_->SetMicState(true); - conversation_controller().StartVoiceInteraction(); -} - -void AssistantManagerServiceImpl::StopActiveInteraction( - bool cancel_conversation) { - DVLOG(1) << __func__; - - audio_input_host_->SetMicState(false); - conversation_controller().StopActiveInteraction(cancel_conversation); -} - -void AssistantManagerServiceImpl::StartEditReminderInteraction( - const std::string& client_id) { - conversation_controller().StartEditReminderInteraction(client_id); -} - -void AssistantManagerServiceImpl::StartTextInteraction( - const std::string& query, - AssistantQuerySource source, - bool allow_tts) { - DVLOG(1) << __func__; - - conversation_controller().SendTextQuery(query, source, allow_tts); -} - -void AssistantManagerServiceImpl::AddAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) { - // For now, this function is handling events registration for both Mojom - // side and Assistant service side. All native AssistantInteractionSubscriber - // should be deprecated and replaced with |ConversationObserver| once the - // migration is done. - interaction_subscribers_.AddObserver(subscriber); - AddRemoteConversationObserver(subscriber); -} - -void AssistantManagerServiceImpl::RemoveAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) { - interaction_subscribers_.RemoveObserver(subscriber); -} - -void AssistantManagerServiceImpl::RetrieveNotification( - const AssistantNotification& notification, - int action_index) { - conversation_controller().RetrieveNotification(notification, action_index); -} - -void AssistantManagerServiceImpl::DismissNotification( - const AssistantNotification& notification) { - conversation_controller().DismissNotification(notification); -} - -void AssistantManagerServiceImpl::OnInteractionStarted( - const AssistantInteractionMetadata& metadata) { - audio_input_host_->OnConversationTurnStarted(); -} - -void AssistantManagerServiceImpl::OnInteractionFinished( - AssistantInteractionResolution resolution) { - switch (resolution) { - case AssistantInteractionResolution::kNormal: - RecordQueryResponseTypeUMA(); - return; - case AssistantInteractionResolution::kInterruption: - if (HasReceivedQueryResponse()) - RecordQueryResponseTypeUMA(); - return; - case AssistantInteractionResolution::kMicTimeout: - case AssistantInteractionResolution::kError: - case AssistantInteractionResolution::kMultiDeviceHotwordLoss: - // No action needed. - return; - } -} - -void AssistantManagerServiceImpl::OnHtmlResponse(const std::string& html, - const std::string& fallback) { - receive_inline_response_ = true; -} - -void AssistantManagerServiceImpl::OnTextResponse(const std::string& reponse) { - receive_inline_response_ = true; -} - -void AssistantManagerServiceImpl::OnOpenUrlResponse(const GURL& url, - bool in_background) { - receive_url_response_ = url.spec(); -} - -void AssistantManagerServiceImpl::OnStateChanged( - libassistant::mojom::ServiceState new_state) { - using libassistant::mojom::ServiceState; - - DVLOG(1) << "Libassistant service state changed to " << new_state; - switch (new_state) { - case ServiceState::kStarted: - OnServiceStarted(); - break; - case ServiceState::kRunning: - OnServiceRunning(); - break; - case ServiceState::kDisconnected: - OnServiceDisconnected(); - break; - case ServiceState::kStopped: - OnServiceStopped(); - break; - } -} - -void AssistantManagerServiceImpl::Initialize() { - assistant_host_->StartLibassistantService(libassistant_service_host_.get()); - - service_controller().AddAndFireStateObserver( - state_observer_receiver_.BindNewPipeAndPassRemote()); - assistant_host_->AddSpeechRecognitionObserver( - speech_recognition_observer_->BindNewPipeAndPassRemote()); - AddRemoteConversationObserver(this); - - audio_output_delegate_->Bind(assistant_host_->ExtractAudioOutputDelegate()); - platform_delegate_->Bind(assistant_host_->ExtractPlatformDelegate()); - audio_input_host_ = std::make_unique<AudioInputHostImpl>( - assistant_host_->ExtractAudioInputController(), - context_->cras_audio_handler(), context_->power_manager_client(), - context_->assistant_state()->locale().value()); - - assistant_settings_->Initialize( - assistant_host_->ExtractSpeakerIdEnrollmentController(), - &assistant_host_->settings_controller()); - - media_host_->Initialize(&assistant_host_->media_controller(), - assistant_host_->ExtractMediaDelegate()); - timer_host_->Initialize(&assistant_host_->timer_controller(), - assistant_host_->ExtractTimerDelegate()); - - device_settings_host_->Bind(assistant_host_->ExtractDeviceSettingsDelegate()); -} - -void AssistantManagerServiceImpl::InitAssistant( - const std::optional<UserInfo>& user) { - DCHECK(!IsServiceStarted()); - - auto bootup_config = bootup_config_.Clone(); - bootup_config->authentication_tokens = ToAuthenticationTokens(user); - bootup_config->hotword_enabled = assistant_state()->hotword_enabled().value(); - bootup_config->locale = assistant_state()->locale().value(); - bootup_config->spoken_feedback_enabled = spoken_feedback_enabled_; - bootup_config->dark_mode_enabled = dark_mode_enabled_; - - service_controller().Initialize(std::move(bootup_config), - BindURLLoaderFactory()); - service_controller().Start(); -} - -base::Thread& AssistantManagerServiceImpl::GetBackgroundThreadForTesting() { - return background_thread(); -} - -void AssistantManagerServiceImpl::OnServiceStarted() { - DCHECK_EQ(GetState(), State::STARTING); - - const base::TimeDelta time_since_started = - base::TimeTicks::Now() - started_time_; - UMA_HISTOGRAM_TIMES("Assistant.ServiceStartTime", time_since_started); - - SetStateAndInformObservers(State::STARTED); -} - -bool AssistantManagerServiceImpl::IsServiceStarted() const { - switch (state_) { - case State::STOPPED: - case State::STOPPING: - case State::STARTING: - case State::DISCONNECTED: - return false; - case State::STARTED: - case State::RUNNING: - return true; - } -} - -mojo::PendingRemote<network::mojom::URLLoaderFactory> -AssistantManagerServiceImpl::BindURLLoaderFactory() { - mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote; - url_loader_factory_->Clone(pending_remote.InitWithNewPipeAndPassReceiver()); - return pending_remote; -} - -void AssistantManagerServiceImpl::OnServiceRunning() { - // Try to avoid double run by checking |GetState()|. - if (GetState() == State::RUNNING) - return; - - SetStateAndInformObservers(State::RUNNING); - - if (is_first_init) { - is_first_init = false; - // Only sync status at the first init to prevent unexpected corner cases. - if (assistant_state()->hotword_enabled().value()) - assistant_settings_->SyncSpeakerIdEnrollmentStatus(); - } - - const base::TimeDelta time_since_started = - base::TimeTicks::Now() - started_time_; - UMA_HISTOGRAM_TIMES("Assistant.ServiceReadyTime", time_since_started); - - SyncDeviceAppsStatus(); - - SetAssistantContextEnabled(assistant_state()->IsScreenContextAllowed()); - - if (assistant_state()->arc_play_store_enabled().has_value()) - SetArcPlayStoreEnabled(assistant_state()->arc_play_store_enabled().value()); - - if (base::FeatureList::IsEnabled(assistant::features::kAssistantAppSupport)) - scoped_app_list_event_subscriber_.Observe(device_actions()); -} - -void AssistantManagerServiceImpl::OnServiceStopped() { - // Valid `STOPPED` will only be called after `STOPPING`. - // However, a false `STOPPED` may be received. - // An ideal situation would be: - // 1. `AddAndFireStateObserver()` is called. - // 2. `ServiceController` sends the current state, e.g. STOPPED. - // However, since it takes a longer time (through mojom to another thread), - // the `state_` in this class could be temporary out of sync. For example: - // 1. `AddAndFireStateObserver()` is called when the `state_` is STOPPED. - // 2. `Start()`: sets `state_` to STARTING. - // 3. `ServiceController` sends the current state inside it, which is STOPPED. - // 4. `OnStateChanged()` receives STOPPED, but the `state_` is STARTING. - // We will ignore the invalid STOPPED signal. - if (GetState() != State::STOPPING) - return; - - SetStateAndInformObservers(State::STOPPED); - - // Stop after the `assistant_manager` was destroyed. - assistant_host_->StopLibassistantService(); - ClearAfterStop(); -} - -void AssistantManagerServiceImpl::OnServiceDisconnected() { - SetStateAndInformObservers(State::DISCONNECTED); - ClearAfterStop(); -} - -void AssistantManagerServiceImpl::OnAndroidAppListRefreshed( - const std::vector<AndroidAppInfo>& apps_info) { - DCHECK(GetState() == State::RUNNING); - - std::vector<AndroidAppInfo> filtered_apps_info; - for (const auto& app_info : apps_info) { - // TODO(b/146355799): Remove the special handling for Android settings app. - if (app_info.package_name == kAndroidSettingsAppPackage) - continue; - - filtered_apps_info.push_back(app_info); - } - display_controller().SetAndroidAppList(std::move(filtered_apps_info)); -} - -void AssistantManagerServiceImpl::OnAccessibilityStatusChanged( - bool spoken_feedback_enabled) { - if (spoken_feedback_enabled_ == spoken_feedback_enabled) - return; - - spoken_feedback_enabled_ = spoken_feedback_enabled; - - // When |spoken_feedback_enabled_| changes we need to update our internal - // options to turn on/off A11Y features in LibAssistant. - if (IsServiceStarted()) - settings_controller().SetSpokenFeedbackEnabled(spoken_feedback_enabled_); -} - -void AssistantManagerServiceImpl::OnColorModeChanged(bool dark_mode_enabled) { - if (dark_mode_enabled_ == dark_mode_enabled) - return; - - dark_mode_enabled_ = dark_mode_enabled; - - if (IsServiceStarted()) - settings_controller().SetDarkModeEnabled(dark_mode_enabled_); -} - -void AssistantManagerServiceImpl::OnDeviceAppsEnabled(bool enabled) { - // The device apps state sync should only be sent after service is running. - // Check state here to prevent timing issue when the service is restarting. - if (GetState() != State::RUNNING) - return; - - display_controller().SetDeviceAppsEnabled(enabled); - - // You can set initialized_internal callback only when AssistantStatus is - // NOT_READY. Also this line reaches only after GetState() becomes RUNNING - // (i.e. READY). From that reason, test code can assume that status has - // changed from NOT_READY to READY between those two points. - // - // Test code expects those things when Assistant gets initialized: - // - // - Status becomes READY. - // - All necessary settings are passed to LibAssistant. - // - // We update necessary settings after status becomes READY. For now, - // DeviceAppsEnabled is the only settings update which involves async call. - // As other settings are sync, if this async call gets completed, we can also - // assume that all necessary settings are passed to LibAssistant, i.e. - // initialized. - if (!initialized_internal_callback_for_testing.is_null()) { - std::move(initialized_internal_callback_for_testing).Run(); - } -} - -void AssistantManagerServiceImpl::AddTimeToTimer(const std::string& id, - base::TimeDelta duration) { - timer_host_->AddTimeToTimer(id, duration); -} - -void AssistantManagerServiceImpl::PauseTimer(const std::string& id) { - timer_host_->PauseTimer(id); -} - -void AssistantManagerServiceImpl::RemoveAlarmOrTimer(const std::string& id) { - timer_host_->RemoveTimer(id); -} - -void AssistantManagerServiceImpl::ResumeTimer(const std::string& id) { - timer_host_->ResumeTimer(id); -} - -void AssistantManagerServiceImpl::AddRemoteConversationObserver( - ConversationObserver* observer) { - conversation_controller().AddRemoteObserver( - observer->BindNewPipeAndPassRemote()); -} - -mojo::PendingReceiver<libassistant::mojom::NotificationDelegate> -AssistantManagerServiceImpl::GetPendingNotificationDelegate() { - return assistant_host_->ExtractNotificationDelegate(); -} - -void AssistantManagerServiceImpl::RecordQueryResponseTypeUMA() { - AssistantQueryResponseType response_type = GetQueryResponseType(); - - UMA_HISTOGRAM_ENUMERATION("Assistant.QueryResponseType", response_type); - - // Reset the flags. - receive_url_response_.clear(); - receive_inline_response_ = false; - device_settings_host_->reset_has_setting_changed(); -} - -bool AssistantManagerServiceImpl::HasReceivedQueryResponse() const { - return GetQueryResponseType() != AssistantQueryResponseType::kUnspecified; -} - -AssistantQueryResponseType AssistantManagerServiceImpl::GetQueryResponseType() - const { - if (device_settings_host_->has_setting_changed()) { - return AssistantQueryResponseType::kDeviceAction; - } else if (!receive_url_response_.empty()) { - if (base::Contains(receive_url_response_, "www.google.com/search?")) { - return AssistantQueryResponseType::kSearchFallback; - } else { - return AssistantQueryResponseType::kTargetedAction; - } - } else if (receive_inline_response_) { - return AssistantQueryResponseType::kInlineElement; - } - - return AssistantQueryResponseType::kUnspecified; -} - -void AssistantManagerServiceImpl::SendAssistantFeedback( - const AssistantFeedback& assistant_feedback) { - conversation_controller().SendAssistantFeedback(assistant_feedback); -} - -AssistantNotificationController* -AssistantManagerServiceImpl::assistant_notification_controller() { - return context_->assistant_notification_controller(); -} - -AssistantStateBase* AssistantManagerServiceImpl::assistant_state() { - return context_->assistant_state(); -} - -DeviceActions* AssistantManagerServiceImpl::device_actions() { - return context_->device_actions(); -} - -scoped_refptr<base::SequencedTaskRunner> -AssistantManagerServiceImpl::main_task_runner() { - return context_->main_task_runner(); -} - -libassistant::mojom::DisplayController& -AssistantManagerServiceImpl::display_controller() { - return assistant_host_->display_controller(); -} - -libassistant::mojom::ServiceController& -AssistantManagerServiceImpl::service_controller() { - return assistant_host_->service_controller(); -} - -void AssistantManagerServiceImpl::SetMicState(bool mic_open) { - DCHECK(audio_input_host_); - audio_input_host_->SetMicState(mic_open); -} - -libassistant::mojom::ConversationController& -AssistantManagerServiceImpl::conversation_controller() { - return assistant_host_->conversation_controller(); -} - -libassistant::mojom::SettingsController& -AssistantManagerServiceImpl::settings_controller() { - return assistant_host_->settings_controller(); -} - -base::Thread& AssistantManagerServiceImpl::background_thread() { - return assistant_host_->background_thread(); -} - -void AssistantManagerServiceImpl::SetStateAndInformObservers(State new_state) { - state_ = new_state; - - for (auto& observer : state_observers_) - observer.OnStateChanged(state_); -} - -void AssistantManagerServiceImpl::ClearAfterStop() { - weak_factory_.InvalidateWeakPtrs(); - - state_observer_receiver_.reset(); - speech_recognition_observer_->Stop(); - audio_output_delegate_->Stop(); - platform_delegate_->Stop(); - audio_input_host_.reset(); - assistant_settings_->Stop(); - media_host_->Stop(); - timer_host_->Stop(); - device_settings_host_->Stop(); - - scoped_app_list_event_subscriber_.Reset(); - interaction_subscribers_.Clear(); - state_observers_.Clear(); - - is_first_init = true; -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/assistant_manager_service_impl.h b/chromeos/ash/services/assistant/assistant_manager_service_impl.h deleted file mode 100644 index 9098c214..0000000 --- a/chromeos/ash/services/assistant/assistant_manager_service_impl.h +++ /dev/null
@@ -1,283 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_MANAGER_SERVICE_IMPL_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_MANAGER_SERVICE_IMPL_H_ - -#include <map> -#include <memory> -#include <optional> -#include <string> -#include <vector> - -#include "base/cancelable_callback.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/scoped_refptr.h" -#include "base/observer_list.h" -#include "base/scoped_observation.h" -#include "base/synchronization/lock.h" -#include "base/task/sequenced_task_runner.h" -#include "base/threading/thread.h" -#include "base/time/time.h" -#include "chromeos/ash/services/assistant/assistant_host.h" -#include "chromeos/ash/services/assistant/assistant_manager_service.h" -#include "chromeos/ash/services/assistant/assistant_settings_impl.h" -#include "chromeos/ash/services/assistant/libassistant_service_host.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "chromeos/ash/services/assistant/public/cpp/conversation_observer.h" -#include "chromeos/ash/services/assistant/public/cpp/device_actions.h" -#include "chromeos/ash/services/libassistant/public/cpp/assistant_notification.h" -#include "chromeos/ash/services/libassistant/public/mojom/notification_delegate.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/service_controller.mojom-forward.h" -#include "chromeos/services/assistant/public/shared/utils.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "services/device/public/mojom/battery_monitor.mojom.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "ui/accessibility/ax_assistant_structure.h" -#include "ui/accessibility/mojom/ax_assistant_structure.mojom.h" - -namespace ash { - -class AssistantNotificationController; -class AssistantStateBase; - -namespace assistant { - -class AssistantHost; -class AssistantMediaSession; -class AudioInputHost; -class AudioOutputDelegateImpl; -class DeviceSettingsHost; -class MediaHost; -class PlatformDelegateImpl; -class ServiceContext; -class SpeechRecognitionObserverWrapper; -class TimerHost; - -// Enumeration of Assistant query response type, also recorded in histograms. -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. Only append to this enum is allowed -// if the possible type grows. -enum class AssistantQueryResponseType { - // Query without response. - kUnspecified = 0, - // Query results in device actions (e.g. turn on bluetooth/WiFi). - kDeviceAction = 1, - // Query results in answer cards with contents rendered inside the - // Assistant UI. - kInlineElement = 2, - // Query results in searching on Google, indicating that Assistant - // doesn't know what to do. - kSearchFallback = 3, - // Query results in specific actions (e.g. opening a web app such as YouTube - // or Facebook, some deeplink actions such as opening chrome settings page), - // indicating that Assistant knows what to do. - kTargetedAction = 4, - // Special enumerator value used by histogram macros. - kMaxValue = kTargetedAction -}; - -// Implementation of AssistantManagerService based on LibAssistant. -// This is the main class that interacts with LibAssistant. -// Since LibAssistant is a standalone library, all callbacks come from it -// running on threads not owned by Chrome. Thus we need to post the callbacks -// onto the main thread. -// NOTE: this class may start/stop LibAssistant multiple times throughout its -// lifetime. This may occur, for example, if the user manually toggles Assistant -// enabled/disabled in settings or switches to a non-primary profile. -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantManagerServiceImpl - : public AssistantManagerService, - public AppListEventSubscriber, - private libassistant::mojom::StateObserver, - public ConversationObserver { - public: - // |callback| is called when AssistantManagerServiceImpl got initialized - // internally. This waits DeviceApps config value sync. - static void SetInitializedInternalCallbackForTesting( - base::OnceCallback<void()> callback); - static void ResetIsFirstInitFlagForTesting(); - - // |service| owns this class and must outlive this class. - AssistantManagerServiceImpl( - ServiceContext* context, - std::unique_ptr<network::PendingSharedURLLoaderFactory> - pending_url_loader_factory, - std::optional<std::string> s3_server_uri_override, - std::optional<std::string> device_id_override, - // Allows to inect a custom |LibassistantServiceHost| during unittests. - std::unique_ptr<LibassistantServiceHost> libassistant_service_host = - nullptr); - - AssistantManagerServiceImpl(const AssistantManagerServiceImpl&) = delete; - AssistantManagerServiceImpl& operator=(const AssistantManagerServiceImpl&) = - delete; - - ~AssistantManagerServiceImpl() override; - - // assistant::AssistantManagerService overrides: - void Start(const std::optional<UserInfo>& user, bool enable_hotword) override; - void Stop() override; - State GetState() const override; - void SetUser(const std::optional<UserInfo>& user) override; - void EnableListening(bool enable) override; - void EnableHotword(bool enable) override; - void SetArcPlayStoreEnabled(bool enable) override; - void SetAssistantContextEnabled(bool enable) override; - AssistantSettings* GetAssistantSettings() override; - void AddAuthenticationStateObserver( - AuthenticationStateObserver* observer) override; - void AddAndFireStateObserver( - AssistantManagerService::StateObserver* observer) override; - void RemoveStateObserver( - const AssistantManagerService::StateObserver* observer) override; - void SyncDeviceAppsStatus() override; - void UpdateInternalMediaPlayerStatus( - media_session::mojom::MediaSessionAction action) override; - - // Assistant overrides: - void StartEditReminderInteraction(const std::string& client_id) override; - void StartTextInteraction(const std::string& query, - AssistantQuerySource source, - bool allow_tts) override; - void StartVoiceInteraction() override; - void StopActiveInteraction(bool cancel_conversation) override; - void AddAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) override; - void RemoveAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) override; - void RetrieveNotification(const AssistantNotification& notification, - int action_index) override; - void DismissNotification(const AssistantNotification& notification) override; - void OnAccessibilityStatusChanged(bool spoken_feedback_enabled) override; - void OnColorModeChanged(bool dark_mode_enabled) override; - void SendAssistantFeedback(const AssistantFeedback& feedback) override; - void AddTimeToTimer(const std::string& id, base::TimeDelta duration) override; - void PauseTimer(const std::string& id) override; - void RemoveAlarmOrTimer(const std::string& id) override; - void ResumeTimer(const std::string& id) override; - void AddRemoteConversationObserver(ConversationObserver* observer) override; - mojo::PendingReceiver<libassistant::mojom::NotificationDelegate> - GetPendingNotificationDelegate() override; - - // ConversationObserver overrides: - void OnInteractionStarted( - const AssistantInteractionMetadata& metadata) override; - void OnInteractionFinished( - AssistantInteractionResolution resolution) override; - void OnHtmlResponse(const std::string& response, - const std::string& fallback) override; - void OnTextResponse(const std::string& reponse) override; - void OnOpenUrlResponse(const GURL& url, bool in_background) override; - - // AppListEventSubscriber overrides: - void OnAndroidAppListRefreshed( - const std::vector<AndroidAppInfo>& apps_info) override; - - // libassistant::mojom::StateObserver implementation: - void OnStateChanged(libassistant::mojom::ServiceState new_state) override; - - void SetMicState(bool mic_open); - - base::Thread& GetBackgroundThreadForTesting(); - - private: - void Initialize(); - void InitAssistant(const std::optional<UserInfo>& user); - void OnServiceStarted(); - void OnServiceRunning(); - void OnServiceStopped(); - void OnServiceDisconnected(); - bool IsServiceStarted() const; - - mojo::PendingRemote<network::mojom::URLLoaderFactory> BindURLLoaderFactory(); - - void OnModifySettingsAction(const std::string& modify_setting_args_proto); - - void OnDeviceAppsEnabled(bool enabled); - - void FillServerExperimentIds(std::vector<std::string>* server_experiment_ids); - - // Record the response type for each query. Note that query on device - // actions (e.g. turn on Bluetooth, turn on WiFi) will cause duplicate - // record because it interacts with server twice on on the same query. - // The first round interaction checks if a setting is supported with no - // responses sent back and ends normally (will be recorded as kUnspecified), - // and settings modification proto along with any text/voice responses would - // be sent back in the second round (recorded as kDeviceAction). - void RecordQueryResponseTypeUMA(); - bool HasReceivedQueryResponse() const; - AssistantQueryResponseType GetQueryResponseType() const; - - std::string NewPendingInteraction(AssistantInteractionType interaction_type, - AssistantQuerySource source, - const std::string& query); - - void SendVoicelessInteraction(const std::string& interaction, - const std::string& description, - bool is_user_initiated); - - AssistantNotificationController* assistant_notification_controller(); - AssistantStateBase* assistant_state(); - DeviceActions* device_actions(); - scoped_refptr<base::SequencedTaskRunner> main_task_runner(); - - libassistant::mojom::ConversationController& conversation_controller(); - libassistant::mojom::DisplayController& display_controller(); - libassistant::mojom::ServiceController& service_controller(); - libassistant::mojom::SettingsController& settings_controller(); - base::Thread& background_thread(); - - void SetStateAndInformObservers(State new_state); - - void ClearAfterStop(); - - State state_ = State::STOPPED; - - std::unique_ptr<AssistantSettingsImpl> assistant_settings_; - - std::unique_ptr<AssistantHost> assistant_host_; - std::unique_ptr<PlatformDelegateImpl> platform_delegate_; - std::unique_ptr<AudioInputHost> audio_input_host_; - - base::ObserverList<AssistantInteractionSubscriber> interaction_subscribers_; - - // Owned by the parent |Service| which will destroy |this| before |context_|. - const raw_ptr<ServiceContext> context_; - - std::unique_ptr<LibassistantServiceHost> libassistant_service_host_; - std::unique_ptr<DeviceSettingsHost> device_settings_host_; - std::unique_ptr<MediaHost> media_host_; - std::unique_ptr<TimerHost> timer_host_; - std::unique_ptr<AudioOutputDelegateImpl> audio_output_delegate_; - std::unique_ptr<SpeechRecognitionObserverWrapper> - speech_recognition_observer_; - mojo::Receiver<libassistant::mojom::StateObserver> state_observer_receiver_{ - this}; - - bool spoken_feedback_enabled_ = false; - bool dark_mode_enabled_ = false; - - base::TimeTicks started_time_; - - bool receive_inline_response_ = false; - std::string receive_url_response_; - - // Configuration passed to libassistant. - libassistant::mojom::BootupConfigPtr bootup_config_; - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; - - base::ScopedObservation<DeviceActions, AppListEventSubscriber> - scoped_app_list_event_subscriber_{this}; - base::ObserverList<AssistantManagerService::StateObserver> state_observers_; - - base::WeakPtrFactory<AssistantManagerServiceImpl> weak_factory_; -}; - -} // namespace assistant -} // namespace ash - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_MANAGER_SERVICE_IMPL_H_
diff --git a/chromeos/ash/services/assistant/assistant_manager_service_impl_unittest.cc b/chromeos/ash/services/assistant/assistant_manager_service_impl_unittest.cc deleted file mode 100644 index 35a2796..0000000 --- a/chromeos/ash/services/assistant/assistant_manager_service_impl_unittest.cc +++ /dev/null
@@ -1,785 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/assistant_manager_service_impl.h" - -#include <optional> -#include <string> -#include <utility> - -#include "ash/public/cpp/assistant/controller/assistant_alarm_timer_controller.h" -#include "base/json/json_reader.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/run_loop.h" -#include "base/test/bind.h" -#include "base/test/task_environment.h" -#include "base/values.h" -#include "chromeos/ash/components/assistant/test_support/expect_utils.h" -#include "chromeos/ash/components/audio/cras_audio_handler.h" -#include "chromeos/ash/services/assistant/assistant_manager_service.h" -#include "chromeos/ash/services/assistant/libassistant_service_host.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/assistant/service_context.h" -#include "chromeos/ash/services/assistant/test_support/fake_libassistant_service.h" -#include "chromeos/ash/services/assistant/test_support/fake_service_context.h" -#include "chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.h" -#include "chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.h" -#include "chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.h" -#include "chromeos/ash/services/assistant/test_support/scoped_assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/test_support/scoped_device_actions.h" -#include "chromeos/ash/services/libassistant/public/cpp/assistant_timer.h" -#include "chromeos/ash/services/libassistant/public/mojom/speaker_id_enrollment_controller.mojom.h" -#include "chromeos/dbus/power/fake_power_manager_client.h" -#include "google_apis/gaia/gaia_id.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "services/media_session/public/mojom/media_session.mojom-shared.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" -#include "services/network/test/test_url_loader_factory.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash::assistant { - -using libassistant::mojom::ServiceState; -using libassistant::mojom::SpeakerIdEnrollmentStatus; -using media_session::mojom::MediaSessionAction; -using testing::_; -using testing::ElementsAre; -using testing::Invoke; -using testing::NiceMock; -using testing::StrictMock; -using UserInfo = AssistantManagerService::UserInfo; - -namespace { - -const char* kNoValue = FakeServiceController::kNoValue; -#define EXPECT_STATE(_state) \ - EXPECT_EQ(_state, assistant_manager_service()->GetState()); - -class AssistantAlarmTimerControllerMock : public AssistantAlarmTimerController { - public: - AssistantAlarmTimerControllerMock() = default; - AssistantAlarmTimerControllerMock(const AssistantAlarmTimerControllerMock&) = - delete; - AssistantAlarmTimerControllerMock& operator=( - const AssistantAlarmTimerControllerMock&) = delete; - ~AssistantAlarmTimerControllerMock() override = default; - - // AssistantAlarmTimerController: - MOCK_METHOD((const AssistantAlarmTimerModel*), - GetModel, - (), - (const, override)); - - MOCK_METHOD(void, - OnTimerStateChanged, - (const std::vector<AssistantTimer>&), - (override)); -}; - -class FakeLibassistantServiceHost : public LibassistantServiceHost { - public: - explicit FakeLibassistantServiceHost(FakeLibassistantService* service) - : service_(service) {} - - void Launch(mojo::PendingReceiver<libassistant::mojom::LibassistantService> - receiver) override { - service_->Bind(std::move(receiver)); - } - void Stop() override { service_->Unbind(); } - - private: - raw_ptr<FakeLibassistantService> service_; -}; - -class StateObserverMock : public AssistantManagerService::StateObserver { - public: - StateObserverMock() = default; - - StateObserverMock(const StateObserverMock&) = delete; - StateObserverMock& operator=(const StateObserverMock&) = delete; - - ~StateObserverMock() override = default; - - MOCK_METHOD(void, OnStateChanged, (AssistantManagerService::State new_state)); -}; - -class AssistantManagerServiceImplTest : public testing::Test { - public: - AssistantManagerServiceImplTest() = default; - - AssistantManagerServiceImplTest(const AssistantManagerServiceImplTest&) = - delete; - AssistantManagerServiceImplTest& operator=( - const AssistantManagerServiceImplTest&) = delete; - - ~AssistantManagerServiceImplTest() override = default; - - void SetUp() override { - chromeos::PowerManagerClient::InitializeFake(); - chromeos::FakePowerManagerClient::Get()->SetTabletMode( - chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks()); - - mojo::PendingRemote<device::mojom::BatteryMonitor> battery_monitor; - delegate_.RequestBatteryMonitor( - battery_monitor.InitWithNewPipeAndPassReceiver()); - - shared_url_loader_factory_ = - base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &url_loader_factory_); - - alarm_timer_controller_ = - std::make_unique<NiceMock<AssistantAlarmTimerControllerMock>>(); - - service_context_ = std::make_unique<FakeServiceContext>(); - service_context_ - ->set_main_task_runner(task_environment().GetMainThreadTaskRunner()) - .set_power_manager_client(chromeos::PowerManagerClient::Get()) - .set_assistant_state(&assistant_state_) - .set_cras_audio_handler(&cras_audio_handler_.Get()) - .set_assistant_alarm_timer_controller(alarm_timer_controller_.get()); - - CreateAssistantManagerServiceImpl(); - - // Flushes the background thread to let Mojom finish all its work (i.e. - // binding controllers) before moving formard. - RunUntilIdle(); - } - - void TearDown() override { - assistant_manager_service_.reset(); - chromeos::PowerManagerClient::Shutdown(); - } - - void CreateAssistantManagerServiceImpl( - std::optional<std::string> s3_server_uri_override = std::nullopt, - std::optional<std::string> device_id_override = std::nullopt) { - // We can not have 2 instances of |AssistantManagerServiceImpl| at the same - // time, so we must destroy the old one before creating a new one. - assistant_manager_service_.reset(); - - assistant_manager_service_ = std::make_unique<AssistantManagerServiceImpl>( - service_context_.get(), shared_url_loader_factory_->Clone(), - s3_server_uri_override, device_id_override, - std::make_unique<FakeLibassistantServiceHost>(&libassistant_service_)); - } - - FakeServiceController& mojom_service_controller() { - return libassistant_service_.service_controller(); - } - - FakeLibassistantService& mojom_libassistant_service() { - return libassistant_service_; - } - - AssistantManagerServiceImpl* assistant_manager_service() { - return assistant_manager_service_.get(); - } - - AssistantSettings& assistant_settings() { - auto* result = assistant_manager_service()->GetAssistantSettings(); - DCHECK(result); - return *result; - } - - FullyInitializedAssistantState& assistant_state() { return assistant_state_; } - - void SetAssistantStateContext(bool enabled) { - assistant_state_.SetContextEnabled(enabled); - } - - FakeServiceContext* fake_service_context() { return service_context_.get(); } - - base::test::TaskEnvironment& task_environment() { return task_environment_; } - - void Start() { - assistant_manager_service()->Start( - UserInfo(GaiaId("<user-id>"), "<access-token>"), - /*enable_hotword=*/false); - } - - // Start Libassistant, and wait until it is running. - void StartAndWaitForRunning() { - Start(); - WaitForState(AssistantManagerService::STARTED); - mojom_service_controller().SetState(ServiceState::kRunning); - WaitForState(AssistantManagerService::RUNNING); - } - - void RunUntilIdle() { - // First ensure our mojom thread is finished. - FlushForTesting(); - // Then handle any callbacks. - base::RunLoop().RunUntilIdle(); - } - - void FlushForTesting() { - libassistant_service_.FlushForTesting(); - background_thread().FlushForTesting(); - } - - // Adds a state observer mock, and add the expectation for the fact that it - // auto-fires the observer. - void AddStateObserver(StateObserverMock* observer) { - EXPECT_CALL(*observer, - OnStateChanged(assistant_manager_service()->GetState())); - assistant_manager_service()->AddAndFireStateObserver(observer); - } - - void WaitForState(AssistantManagerService::State expected_state) { - test::ExpectResult( - expected_state, - base::BindRepeating(&AssistantManagerServiceImpl::GetState, - base::Unretained(assistant_manager_service())), - "AssistantManagerStateImpl"); - } - - private: - base::Thread& background_thread() { - return assistant_manager_service()->GetBackgroundThreadForTesting(); - } - - base::test::SingleThreadTaskEnvironment task_environment_; - - ScopedAssistantBrowserDelegate delegate_; - ScopedCrasAudioHandlerForTesting cras_audio_handler_; - ScopedDeviceActions device_actions_; - FullyInitializedAssistantState assistant_state_; - - // Fake implementation of the Libassistant Mojom service. - FakeLibassistantService libassistant_service_; - - std::unique_ptr<AssistantAlarmTimerControllerMock> alarm_timer_controller_; - std::unique_ptr<FakeServiceContext> service_context_; - - network::TestURLLoaderFactory url_loader_factory_; - scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_; - - std::unique_ptr<AssistantManagerServiceImpl> assistant_manager_service_; -}; - -class SpeakerIdEnrollmentControllerMock - : public libassistant::mojom::SpeakerIdEnrollmentController { - public: - SpeakerIdEnrollmentControllerMock() = default; - SpeakerIdEnrollmentControllerMock(const SpeakerIdEnrollmentControllerMock&) = - delete; - SpeakerIdEnrollmentControllerMock& operator=( - const SpeakerIdEnrollmentControllerMock&) = delete; - ~SpeakerIdEnrollmentControllerMock() override = default; - - // libassistant::mojom::SpeakerIdEnrollmentController implementation: - MOCK_METHOD( - void, - StartSpeakerIdEnrollment, - (const std::string& user_gaia_id, - bool skip_cloud_enrollment, - mojo::PendingRemote<libassistant::mojom::SpeakerIdEnrollmentClient> - client)); - MOCK_METHOD(void, StopSpeakerIdEnrollment, ()); - MOCK_METHOD(void, - GetSpeakerIdEnrollmentStatus, - (const std::string& user_gaia_id, - GetSpeakerIdEnrollmentStatusCallback callback)); - - void Bind( - mojo::PendingReceiver<libassistant::mojom::SpeakerIdEnrollmentController> - pending_receiver) { - receiver_.Bind(std::move(pending_receiver)); - } - - void Bind(FakeLibassistantService& service) { - Bind(service.GetSpeakerIdEnrollmentControllerPendingReceiver()); - } - - void FlushForTesting() { receiver_.FlushForTesting(); } - - private: - mojo::Receiver<SpeakerIdEnrollmentController> receiver_{this}; -}; - -class SpeakerIdEnrollmentClientMock : public SpeakerIdEnrollmentClient { - public: - SpeakerIdEnrollmentClientMock() = default; - SpeakerIdEnrollmentClientMock(const SpeakerIdEnrollmentClientMock&) = delete; - SpeakerIdEnrollmentClientMock& operator=( - const SpeakerIdEnrollmentClientMock&) = delete; - ~SpeakerIdEnrollmentClientMock() override = default; - - base::WeakPtr<SpeakerIdEnrollmentClientMock> GetWeakPtr() { - return weak_factory_.GetWeakPtr(); - } - - // SpeakerIdEnrollmentClient implementation: - MOCK_METHOD(void, OnListeningHotword, ()); - MOCK_METHOD(void, OnProcessingHotword, ()); - MOCK_METHOD(void, OnSpeakerIdEnrollmentDone, ()); - MOCK_METHOD(void, OnSpeakerIdEnrollmentFailure, ()); - - private: - base::WeakPtrFactory<SpeakerIdEnrollmentClientMock> weak_factory_{this}; -}; - -} // namespace - -TEST_F(AssistantManagerServiceImplTest, StateShouldStartAsStopped) { - EXPECT_STATE(AssistantManagerService::STOPPED); -} - -TEST_F(AssistantManagerServiceImplTest, - StateShouldChangeToStartingAfterCallingStart) { - Start(); - - EXPECT_STATE(AssistantManagerService::STARTING); -} - -TEST_F(AssistantManagerServiceImplTest, - StateShouldRemainStartingUntilLibassistantServiceIsStarted) { - mojom_service_controller().BlockStartCalls(); - - Start(); - WaitForState(AssistantManagerService::STARTING); - - mojom_service_controller().UnblockStartCalls(); - WaitForState(AssistantManagerService::STARTED); -} - -TEST_F(AssistantManagerServiceImplTest, - StateShouldBecomeRunningAfterLibassistantSignalsRunningState) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - mojom_service_controller().SetState(ServiceState::kRunning); - - WaitForState(AssistantManagerService::RUNNING); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldSetStateToStoppedAfterStopping) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_manager_service()->Stop(); - WaitForState(AssistantManagerService::STOPPED); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldSetStateToDisconnected) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - mojom_service_controller().SetState(ServiceState::kDisconnected); - WaitForState(AssistantManagerService::DISCONNECTED); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldAllowRestartingAfterStopping) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_manager_service()->Stop(); - WaitForState(AssistantManagerService::STOPPED); - - Start(); - WaitForState(AssistantManagerService::STARTED); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldNotResetDataWhenStopping) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_manager_service()->Stop(); - WaitForState(AssistantManagerService::STOPPED); - RunUntilIdle(); - - EXPECT_EQ(false, mojom_service_controller().has_data_been_reset()); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldResetDataWhenAssistantIsDisabled) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_state().SetAssistantEnabled(false); - assistant_manager_service()->Stop(); - WaitForState(AssistantManagerService::STOPPED); - RunUntilIdle(); - - EXPECT_EQ(true, mojom_service_controller().has_data_been_reset()); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldPassUserInfoToAssistantManagerWhenStarting) { - assistant_manager_service()->Start( - UserInfo(GaiaId("<user-id>"), "<access-token>"), - /*enable_hotword=*/false); - - WaitForState(AssistantManagerService::STARTED); - - EXPECT_EQ(GaiaId("<user-id>"), mojom_service_controller().gaia_id()); - EXPECT_EQ("<access-token>", mojom_service_controller().access_token()); -} - -// TODO(crbug.com/40902244): Re-enable this test -TEST_F(AssistantManagerServiceImplTest, - DISABLED_ShouldPassUserInfoToAssistantManager) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_manager_service()->SetUser( - UserInfo(GaiaId("<new-user-id>"), "<new-access-token>")); - RunUntilIdle(); - - EXPECT_EQ(GaiaId("<new-user-id>"), mojom_service_controller().gaia_id()); - EXPECT_EQ("<new-access-token>", mojom_service_controller().access_token()); -} - -TEST_F(AssistantManagerServiceImplTest, - // TODO(crbug.com/40902244): Re-enable this test - DISABLED_ShouldPassEmptyUserInfoToAssistantManager) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_manager_service()->SetUser(std::nullopt); - RunUntilIdle(); - - EXPECT_EQ(GaiaId(kNoValue), mojom_service_controller().gaia_id()); - EXPECT_EQ(kNoValue, mojom_service_controller().access_token()); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldNotCrashWhenSettingUserInfoBeforeStartIsFinished) { - EXPECT_STATE(AssistantManagerService::STOPPED); - assistant_manager_service()->SetUser( - UserInfo(GaiaId("<user-id>"), "<access-token>")); - - Start(); - EXPECT_STATE(AssistantManagerService::STARTING); - assistant_manager_service()->SetUser( - UserInfo(GaiaId("<user-id>"), "<access-token>")); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldPassS3ServerUriOverrideToMojomService) { - CreateAssistantManagerServiceImpl("the-uri-override"); - - Start(); - WaitForState(AssistantManagerService::STARTED); - - EXPECT_EQ(mojom_service_controller() - .libassistant_config() - .s3_server_uri_override.value_or("<none>"), - "the-uri-override"); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldPassDeviceIdOverrideToMojomService) { - CreateAssistantManagerServiceImpl( - /*s3_server_uri_override=*/std::nullopt, "the-device-id-override"); - - Start(); - WaitForState(AssistantManagerService::STARTED); - - EXPECT_EQ(mojom_service_controller() - .libassistant_config() - .device_id_override.value_or("<none>"), - "the-device-id-override"); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldPauseMediaManagerOnPause) { - StrictMock<LibassistantMediaControllerMock> mock; - - StartAndWaitForRunning(); - - mock.Bind(mojom_libassistant_service().GetMediaControllerPendingReceiver()); - - EXPECT_CALL(mock, PauseInternalMediaPlayer); - - assistant_manager_service()->UpdateInternalMediaPlayerStatus( - MediaSessionAction::kPause); - mock.FlushForTesting(); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldResumeMediaManagerOnPlay) { - StrictMock<LibassistantMediaControllerMock> mock; - - StartAndWaitForRunning(); - - mock.Bind(mojom_libassistant_service().GetMediaControllerPendingReceiver()); - - EXPECT_CALL(mock, ResumeInternalMediaPlayer); - - assistant_manager_service()->UpdateInternalMediaPlayerStatus( - MediaSessionAction::kPlay); - mock.FlushForTesting(); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldIgnoreOtherMediaManagerActions) { - StrictMock<LibassistantMediaControllerMock> mock; - - const auto unsupported_media_session_actions = { - MediaSessionAction::kPreviousTrack, MediaSessionAction::kNextTrack, - MediaSessionAction::kSeekBackward, MediaSessionAction::kSeekForward, - MediaSessionAction::kSkipAd, MediaSessionAction::kStop, - MediaSessionAction::kSeekTo, MediaSessionAction::kScrubTo, - }; - - StartAndWaitForRunning(); - - mock.Bind(mojom_libassistant_service().GetMediaControllerPendingReceiver()); - - for (auto action : unsupported_media_session_actions) { - // If this is not ignored, |mock| will complain about an uninterested call. - assistant_manager_service()->UpdateInternalMediaPlayerStatus(action); - } - - mock.FlushForTesting(); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldNotCrashWhenMediaManagerIsAbsent) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_manager_service()->UpdateInternalMediaPlayerStatus( - media_session::mojom::MediaSessionAction::kPlay); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldFireStateObserverWhenAddingIt) { - StrictMock<StateObserverMock> observer; - EXPECT_CALL(observer, - OnStateChanged(AssistantManagerService::State::STARTED)); - - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_manager_service()->AddAndFireStateObserver(&observer); - - assistant_manager_service()->RemoveStateObserver(&observer); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldFireStateObserverWhenStarting) { - StrictMock<StateObserverMock> observer; - AddStateObserver(&observer); - - mojom_service_controller().BlockStartCalls(); - - EXPECT_CALL(observer, - OnStateChanged(AssistantManagerService::State::STARTING)); - Start(); - - assistant_manager_service()->RemoveStateObserver(&observer); - mojom_service_controller().UnblockStartCalls(); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldFireStateObserverWhenStarted) { - StrictMock<StateObserverMock> observer; - AddStateObserver(&observer); - - EXPECT_CALL(observer, - OnStateChanged(AssistantManagerService::State::STARTING)); - EXPECT_CALL(observer, - OnStateChanged(AssistantManagerService::State::STARTED)); - Start(); - WaitForState(AssistantManagerService::STARTED); - - assistant_manager_service()->RemoveStateObserver(&observer); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldFireStateObserverWhenLibAssistantServiceIsRunning) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - StrictMock<StateObserverMock> observer; - AddStateObserver(&observer); - EXPECT_CALL(observer, - OnStateChanged(AssistantManagerService::State::RUNNING)); - - mojom_service_controller().SetState(ServiceState::kRunning); - WaitForState(AssistantManagerService::RUNNING); - - assistant_manager_service()->RemoveStateObserver(&observer); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldFireStateObserverWhenStopping) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - StrictMock<StateObserverMock> observer; - AddStateObserver(&observer); - EXPECT_CALL(observer, - OnStateChanged(AssistantManagerService::State::STOPPING)); - EXPECT_CALL(observer, - OnStateChanged(AssistantManagerService::State::STOPPED)); - - assistant_manager_service()->Stop(); - WaitForState(AssistantManagerService::STOPPING); - WaitForState(AssistantManagerService::STOPPED); - - assistant_manager_service()->RemoveStateObserver(&observer); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldNotFireStateObserverAfterItIsRemoved) { - StrictMock<StateObserverMock> observer; - AddStateObserver(&observer); - - assistant_manager_service()->RemoveStateObserver(&observer); - EXPECT_CALL(observer, OnStateChanged).Times(0); - - Start(); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldStartSpeakerIdEnrollmentWhenRequested) { - NiceMock<SpeakerIdEnrollmentClientMock> client_mock; - Start(); - WaitForState(AssistantManagerService::STARTED); - - StrictMock<SpeakerIdEnrollmentControllerMock> mojom_mock; - mojom_mock.Bind(mojom_libassistant_service()); - - EXPECT_CALL(mojom_mock, StartSpeakerIdEnrollment); - - assistant_settings().StartSpeakerIdEnrollment(/*skip_cloud_enrollment=*/false, - client_mock.GetWeakPtr()); - - mojom_mock.FlushForTesting(); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldSendGaiaIdDuringSpeakerIdEnrollment) { - NiceMock<SpeakerIdEnrollmentClientMock> client_mock; - fake_service_context()->set_primary_account_gaia_id(GaiaId("gaia user id")); - Start(); - WaitForState(AssistantManagerService::STARTED); - - StrictMock<SpeakerIdEnrollmentControllerMock> mojom_mock; - mojom_mock.Bind(mojom_libassistant_service()); - - EXPECT_CALL(mojom_mock, StartSpeakerIdEnrollment("gaia user id", _, _)); - - assistant_settings().StartSpeakerIdEnrollment(/*skip_cloud_enrollment=*/false, - client_mock.GetWeakPtr()); - - mojom_mock.FlushForTesting(); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldSendSkipCloudEnrollmentDuringSpeakerIdEnrollment) { - Start(); - WaitForState(AssistantManagerService::STARTED); - - StrictMock<SpeakerIdEnrollmentControllerMock> mojom_mock; - mojom_mock.Bind(mojom_libassistant_service()); - - { - NiceMock<SpeakerIdEnrollmentClientMock> client_mock; - - EXPECT_CALL(mojom_mock, StartSpeakerIdEnrollment(_, true, _)); - - assistant_settings().StartSpeakerIdEnrollment( - /*skip_cloud_enrollment=*/true, client_mock.GetWeakPtr()); - mojom_mock.FlushForTesting(); - } - - { - NiceMock<SpeakerIdEnrollmentClientMock> client_mock; - - EXPECT_CALL(mojom_mock, StartSpeakerIdEnrollment(_, false, _)); - - assistant_settings().StartSpeakerIdEnrollment( - /*skip_cloud_enrollment=*/false, client_mock.GetWeakPtr()); - mojom_mock.FlushForTesting(); - } -} - -TEST_F(AssistantManagerServiceImplTest, ShouldSendStopSpeakerIdEnrollment) { - NiceMock<SpeakerIdEnrollmentClientMock> client_mock; - Start(); - WaitForState(AssistantManagerService::STARTED); - - StrictMock<SpeakerIdEnrollmentControllerMock> mojom_mock; - mojom_mock.Bind(mojom_libassistant_service()); - - EXPECT_CALL(mojom_mock, StopSpeakerIdEnrollment); - - assistant_settings().StopSpeakerIdEnrollment(); - mojom_mock.FlushForTesting(); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldSyncSpeakerIdEnrollmentStatus) { - StrictMock<SpeakerIdEnrollmentClientMock> client_mock; - Start(); - WaitForState(AssistantManagerService::STARTED); - - StrictMock<SpeakerIdEnrollmentControllerMock> mojom_mock; - mojom_mock.Bind(mojom_libassistant_service()); - - EXPECT_CALL(mojom_mock, GetSpeakerIdEnrollmentStatus) - .WillOnce([](const std::string& user_gaia_id, - SpeakerIdEnrollmentControllerMock:: - GetSpeakerIdEnrollmentStatusCallback callback) { - std::move(callback).Run( - SpeakerIdEnrollmentStatus::New(/*user_model_exists=*/true)); - }); - - assistant_settings().SyncSpeakerIdEnrollmentStatus(); - mojom_mock.FlushForTesting(); -} - -TEST_F(AssistantManagerServiceImplTest, - ShouldSyncSpeakerIdEnrollmentStatusWhenRunning) { - AssistantManagerServiceImpl::ResetIsFirstInitFlagForTesting(); - StartAndWaitForRunning(); - - StrictMock<SpeakerIdEnrollmentClientMock> client_mock; - StrictMock<SpeakerIdEnrollmentControllerMock> mojom_mock; - - mojom_mock.Bind(mojom_libassistant_service()); - - EXPECT_CALL(mojom_mock, GetSpeakerIdEnrollmentStatus) - .WillOnce([](const std::string& user_gaia_id, - SpeakerIdEnrollmentControllerMock:: - GetSpeakerIdEnrollmentStatusCallback callback) { - std::move(callback).Run( - SpeakerIdEnrollmentStatus::New(/*user_model_exists=*/true)); - }); - - mojom_mock.FlushForTesting(); -} - -// TODO(crbug.com/40902244): Re-enable this test -TEST_F(AssistantManagerServiceImplTest, DISABLED_ShouldPropagateColorMode) { - ASSERT_FALSE(mojom_service_controller().dark_mode_enabled().has_value()); - - StartAndWaitForRunning(); - - ASSERT_TRUE(mojom_service_controller().dark_mode_enabled().has_value()); - EXPECT_FALSE(mojom_service_controller().dark_mode_enabled().value()); - - assistant_manager_service()->OnColorModeChanged(true); - FlushForTesting(); - - ASSERT_TRUE(mojom_service_controller().dark_mode_enabled().has_value()); - EXPECT_TRUE(mojom_service_controller().dark_mode_enabled().value()); -} - -TEST_F(AssistantManagerServiceImplTest, ShouldNotCrashRunningAfterStopped) { - Start(); - SetAssistantStateContext(/*enabled=*/false); - WaitForState(AssistantManagerService::STARTED); - - // http://crbug.com/1414264: calling Stop() before Running is set, should not - // crash. - assistant_manager_service()->Stop(); - WaitForState(AssistantManagerService::STOPPING); - - mojom_service_controller().SetState(ServiceState::kRunning); - WaitForState(AssistantManagerService::RUNNING); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/assistant_settings_impl.cc b/chromeos/ash/services/assistant/assistant_settings_impl.cc deleted file mode 100644 index e1a25c28..0000000 --- a/chromeos/ash/services/assistant/assistant_settings_impl.cc +++ /dev/null
@@ -1,162 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/assistant_settings_impl.h" - -#include <utility> - -#include "ash/public/cpp/assistant/assistant_state_base.h" -#include "ash/public/cpp/assistant/controller/assistant_controller.h" -#include "base/functional/bind.h" -#include "base/functional/callback_helpers.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/assistant/public/proto/settings_ui.pb.h" -#include "chromeos/ash/services/assistant/service_context.h" -#include "chromeos/ash/services/libassistant/public/mojom/settings_controller.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/speaker_id_enrollment_controller.mojom.h" -#include "chromeos/version/version_loader.h" - -namespace ash::assistant { - -AssistantSettingsImpl::AssistantSettingsImpl(ServiceContext* context) - : context_(context) {} - -AssistantSettingsImpl::~AssistantSettingsImpl() = default; - -void AssistantSettingsImpl::Initialize( - mojo::PendingRemote<libassistant::mojom::SpeakerIdEnrollmentController> - remote, - libassistant::mojom::SettingsController* settings_controller) { - DCHECK(!settings_controller_); - - speaker_id_enrollment_remote_.Bind(std::move(remote)); - settings_controller_ = settings_controller; -} - -void AssistantSettingsImpl::Stop() { - speaker_id_enrollment_remote_.reset(); - settings_controller_ = nullptr; -} - -void AssistantSettingsImpl::GetSettings(const std::string& selector, - GetSettingsCallback callback) { - settings_controller().GetSettings(selector, /*include_header=*/false, - std::move(callback)); -} - -void AssistantSettingsImpl::GetSettingsWithHeader( - const std::string& selector, - GetSettingsCallback callback) { - settings_controller().GetSettings(selector, /*include_header=*/true, - std::move(callback)); -} - -void AssistantSettingsImpl::UpdateSettings(const std::string& update, - GetSettingsCallback callback) { - settings_controller().UpdateSettings(update, std::move(callback)); -} - -void AssistantSettingsImpl::StartSpeakerIdEnrollment( - bool skip_cloud_enrollment, - base::WeakPtr<SpeakerIdEnrollmentClient> client) { - DCHECK(speaker_id_enrollment_remote_.is_bound()); - - speaker_id_enrollment_remote_->StartSpeakerIdEnrollment( - context_->primary_account_gaia_id().ToString(), skip_cloud_enrollment, - client->BindNewPipeAndPassRemote()); -} - -void AssistantSettingsImpl::StopSpeakerIdEnrollment() { - DCHECK(speaker_id_enrollment_remote_.is_bound()); - - speaker_id_enrollment_remote_->StopSpeakerIdEnrollment(); -} - -void AssistantSettingsImpl::SyncSpeakerIdEnrollmentStatus() { - if (assistant_state()->allowed_state() != AssistantAllowedState::ALLOWED || - features::IsVoiceMatchDisabled()) { - return; - } - - DCHECK(speaker_id_enrollment_remote_.is_bound()); - - speaker_id_enrollment_remote_->GetSpeakerIdEnrollmentStatus( - context_->primary_account_gaia_id().ToString(), - base::BindOnce( - &AssistantSettingsImpl::HandleSpeakerIdEnrollmentStatusSync, - weak_factory_.GetWeakPtr())); -} - -void AssistantSettingsImpl::SyncDeviceAppsStatus( - base::OnceCallback<void(bool)> callback) { - SettingsUiSelector selector; - ConsentFlowUiSelector* consent_flow_ui = - selector.mutable_consent_flow_ui_selector(); - consent_flow_ui->set_flow_id( - ActivityControlSettingsUiSelector::ASSISTANT_SUW_ONBOARDING_ON_CHROME_OS); - selector.set_gaia_user_context_ui(true); - GetSettings(selector.SerializeAsString(), - base::BindOnce(&AssistantSettingsImpl::HandleDeviceAppsStatusSync, - weak_factory_.GetWeakPtr(), std::move(callback))); -} - -void AssistantSettingsImpl::HandleSpeakerIdEnrollmentStatusSync( - libassistant::mojom::SpeakerIdEnrollmentStatusPtr status) { - if (!status->user_model_exists) { - // If hotword is enabled but there is no voice model found, launch the - // enrollment flow. - if (assistant_state()->hotword_enabled().value()) - assistant_controller()->StartSpeakerIdEnrollmentFlow(); - } -} - -void AssistantSettingsImpl::HandleDeviceAppsStatusSync( - base::OnceCallback<void(bool)> callback, - const std::string& settings) { - if (settings.empty()) { - // Note: we deliberately do not log an error here, as this happens quite - // regularly when there is a network issue during signup. See b/151321970. - DVLOG(1) << "Assistant: Error while syncing device apps status."; - std::move(callback).Run(false); - return; - } - - SettingsUi settings_ui; - if (!settings_ui.ParseFromString(settings)) { - LOG(ERROR) << "Failed to parse the response proto, set the DA bit to false"; - std::move(callback).Run(false); - return; - } - - if (!settings_ui.has_gaia_user_context_ui()) { - LOG(ERROR) << "Failed to get gaia user context, set the DA bit to false"; - std::move(callback).Run(false); - return; - } - - const auto& gaia_user_context_ui = settings_ui.gaia_user_context_ui(); - if (!gaia_user_context_ui.has_device_apps_enabled()) { - LOG(ERROR) << "Failed to get the device apps bit, set it to false"; - std::move(callback).Run(false); - return; - } - - std::move(callback).Run(gaia_user_context_ui.device_apps_enabled()); -} - -AssistantStateBase* AssistantSettingsImpl::assistant_state() { - return context_->assistant_state(); -} - -AssistantController* AssistantSettingsImpl::assistant_controller() { - return context_->assistant_controller(); -} - -libassistant::mojom::SettingsController& -AssistantSettingsImpl::settings_controller() { - DCHECK(settings_controller_); - return *settings_controller_; -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/assistant_settings_impl.h b/chromeos/ash/services/assistant/assistant_settings_impl.h deleted file mode 100644 index 4340e9a..0000000 --- a/chromeos/ash/services/assistant/assistant_settings_impl.h +++ /dev/null
@@ -1,82 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_SETTINGS_IMPL_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_SETTINGS_IMPL_H_ - -#include <memory> -#include <string> - -#include "base/memory/raw_ptr.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_settings.h" -#include "chromeos/ash/services/libassistant/public/mojom/settings_controller.mojom-forward.h" -#include "chromeos/ash/services/libassistant/public/mojom/speaker_id_enrollment_controller.mojom-forward.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver_set.h" -#include "mojo/public/cpp/bindings/remote.h" - -namespace ash { - -class AssistantController; -class AssistantStateBase; - -namespace assistant { - -class ServiceContext; - -class AssistantSettingsImpl : public AssistantSettings { - public: - explicit AssistantSettingsImpl(ServiceContext* context); - - AssistantSettingsImpl(const AssistantSettingsImpl&) = delete; - AssistantSettingsImpl& operator=(const AssistantSettingsImpl&) = delete; - - ~AssistantSettingsImpl() override; - - void Initialize( - mojo::PendingRemote<libassistant::mojom::SpeakerIdEnrollmentController> - enrollment_controller_remote, - libassistant::mojom::SettingsController* settings_controller); - void Stop(); - - // AssistantSettings overrides: - void GetSettings(const std::string& selector, - GetSettingsCallback callback) override; - void GetSettingsWithHeader(const std::string& selector, - GetSettingsCallback callback) override; - void UpdateSettings(const std::string& update, - UpdateSettingsCallback callback) override; - void StartSpeakerIdEnrollment( - bool skip_cloud_enrollment, - base::WeakPtr<SpeakerIdEnrollmentClient> client) override; - void StopSpeakerIdEnrollment() override; - void SyncSpeakerIdEnrollmentStatus() override; - - void SyncDeviceAppsStatus(base::OnceCallback<void(bool)> callback); - - private: - void HandleSpeakerIdEnrollmentStatusSync( - libassistant::mojom::SpeakerIdEnrollmentStatusPtr status); - void HandleDeviceAppsStatusSync(base::OnceCallback<void(bool)> callback, - const std::string& settings); - - AssistantStateBase* assistant_state(); - AssistantController* assistant_controller(); - libassistant::mojom::SettingsController& settings_controller(); - - const raw_ptr<ServiceContext> context_; - raw_ptr<libassistant::mojom::SettingsController, DanglingUntriaged> - settings_controller_ = nullptr; - - mojo::Remote<libassistant::mojom::SpeakerIdEnrollmentController> - speaker_id_enrollment_remote_; - - base::WeakPtrFactory<AssistantSettingsImpl> weak_factory_{this}; -}; - -} // namespace assistant -} // namespace ash - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_ASSISTANT_SETTINGS_IMPL_H_
diff --git a/chromeos/ash/services/assistant/audio_decoder/BUILD.gn b/chromeos/ash/services/assistant/audio_decoder/BUILD.gn deleted file mode 100644 index 4f1e14d..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/BUILD.gn +++ /dev/null
@@ -1,29 +0,0 @@ -# Copyright 2018 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//chromeos/ash/components/assistant/assistant.gni") - -assert(is_chromeos, "Non Chrome OS builds cannot depend on //chromeos/ash") -assert(enable_cros_libassistant) - -source_set("lib") { - sources = [ - "assistant_audio_decoder.cc", - "assistant_audio_decoder.h", - "assistant_audio_decoder_factory.cc", - "assistant_audio_decoder_factory.h", - "ipc_data_source.cc", - "ipc_data_source.h", - ] - - deps = [ - "//base", - "//chromeos/ash/services/assistant/public/mojom", - ] - - public_deps = [ - "//media", - "//mojo/public/cpp/bindings", - ] -}
diff --git a/chromeos/ash/services/assistant/audio_decoder/DEPS b/chromeos/ash/services/assistant/audio_decoder/DEPS deleted file mode 100644 index 386e0fef..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/DEPS +++ /dev/null
@@ -1,5 +0,0 @@ -include_rules = [ - "+media/filters", - "+media/formats", - "+media/mojo", -]
diff --git a/chromeos/ash/services/assistant/audio_decoder/README.md b/chromeos/ash/services/assistant/audio_decoder/README.md deleted file mode 100644 index 3a4b337..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/README.md +++ /dev/null
@@ -1,3 +0,0 @@ -This directory contains audio decoder service for the Chrome OS native Assistant -to decode the audio output by Libassistant, before connecting to AudioService. -We cannot use the standard media service, which does not have the demuxer.
diff --git a/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.cc b/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.cc deleted file mode 100644 index 3aad9b4..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.cc +++ /dev/null
@@ -1,170 +0,0 @@ -// Copyright 2018 The Chromium Authors -// 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/374320451): Fix and remove. -#pragma allow_unsafe_buffers -#endif - -#include "chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.h" - -#include <utility> -#include <vector> - -#include "base/functional/bind.h" -#include "base/task/sequenced_task_runner.h" -#include "base/threading/thread.h" -#include "chromeos/ash/services/assistant/audio_decoder/ipc_data_source.h" -#include "media/base/audio_bus.h" -#include "media/base/data_source.h" -#include "media/filters/audio_file_reader.h" -#include "media/filters/blocking_url_protocol.h" - -namespace ash::assistant { - -namespace { - -// Preferred bytes per sample when get interleaved data from AudioBus. -constexpr int kBytesPerSample = 2; - -} // namespace - -AssistantAudioDecoder::AssistantAudioDecoder( - mojo::PendingRemote<mojom::AssistantAudioDecoderClient> client, - mojo::PendingRemote<mojom::AssistantMediaDataSource> data_source) - : client_(std::move(client)), - task_runner_(base::SequencedTaskRunner::GetCurrentDefault()), - data_source_(std::make_unique<IPCDataSource>(std::move(data_source))), - media_thread_(std::make_unique<base::Thread>("media_thread")), - weak_factory_(this) { - weak_this_ = weak_factory_.GetWeakPtr(); - CHECK(media_thread_->Start()); - client_.set_disconnect_handler(base::BindOnce( - &AssistantAudioDecoder::OnConnectionError, base::Unretained(this))); -} - -AssistantAudioDecoder::~AssistantAudioDecoder() = default; - -void AssistantAudioDecoder::Decode() { - media_thread_->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&AssistantAudioDecoder::DecodeOnMediaThread, - base::Unretained(this))); -} - -void AssistantAudioDecoder::OpenDecoder(OpenDecoderCallback callback) { - DCHECK(!open_callback_); - open_callback_ = std::move(callback); - media_thread_->task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&AssistantAudioDecoder::OpenDecoderOnMediaThread, - base::Unretained(this))); -} - -void AssistantAudioDecoder::CloseDecoder(CloseDecoderCallback callback) { - DCHECK(!close_callback_); - close_callback_ = std::move(callback); - media_thread_->task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&AssistantAudioDecoder::CloseDecoderOnMediaThread, - base::Unretained(this))); -} - -void AssistantAudioDecoder::OnDataReadError() { - read_error_ = true; -} - -void AssistantAudioDecoder::OpenDecoderOnMediaThread() { - protocol_ = std::make_unique<media::BlockingUrlProtocol>( - data_source_.get(), - base::BindRepeating(&AssistantAudioDecoder::OnDataReadError, - base::Unretained(this))); - decoder_ = std::make_unique<media::AudioFileReader>(protocol_.get()); - - if (closed_ || !decoder_->Open() || read_error_) { - CloseDecoderOnMediaThread(); - return; - } - - task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&AssistantAudioDecoder::OnDecoderInitializedOnThread, - weak_this_, decoder_->sample_rate(), - decoder_->channels())); -} - -void AssistantAudioDecoder::DecodeOnMediaThread() { - std::vector<std::unique_ptr<media::AudioBus>> decoded_audio_packets; - // Experimental number of decoded packets before sending to |client_|. - constexpr int kPacketsToRead = 16; - DCHECK(decoder_); - // The client expects to be called |OnNewBuffers()| so that to return - // AudioDeviceOwner's |FillBuffer()| call. If |closed_| is true, still return - // empty |decoded_audio_packets| to indicate no more data available. - if (!closed_) - decoder_->Read(&decoded_audio_packets, kPacketsToRead); - - task_runner_->PostTask( - FROM_HERE, base::BindOnce(&AssistantAudioDecoder::OnBufferDecodedOnThread, - weak_this_, std::move(decoded_audio_packets))); -} - -void AssistantAudioDecoder::CloseDecoderOnMediaThread() { - // |decoder_| may not be initialized. - if (decoder_) - decoder_->Close(); - - closed_ = true; - task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&AssistantAudioDecoder::RunCallbacksAsClosed, weak_this_)); -} - -void AssistantAudioDecoder::OnDecoderInitializedOnThread( - int sample_rate, - int channels) { - DCHECK(open_callback_); - std::move(open_callback_) - .Run(/*success=*/true, kBytesPerSample, sample_rate, channels); -} - -void AssistantAudioDecoder::OnBufferDecodedOnThread( - const std::vector<std::unique_ptr<media::AudioBus>>& - decoded_audio_packets) { - if (!client_) - return; - - std::vector<std::vector<uint8_t>> buffers; - for (const auto& audio_bus : decoded_audio_packets) { - const int bytes_to_alloc = - audio_bus->frames() * kBytesPerSample * audio_bus->channels(); - std::vector<uint8_t> buffer(bytes_to_alloc); - audio_bus->ToInterleaved<media::SignedInt16SampleTypeTraits>( - audio_bus->frames(), reinterpret_cast<int16_t*>(buffer.data())); - buffers.emplace_back(buffer); - } - client_->OnNewBuffers(buffers); -} - -void AssistantAudioDecoder::OnConnectionError() { - client_.reset(); - media_thread_->task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&AssistantAudioDecoder::CloseDecoderOnMediaThread, - base::Unretained(this))); -} - -void AssistantAudioDecoder::RunCallbacksAsClosed() { - if (open_callback_) { - std::move(open_callback_) - .Run(/*success=*/false, - /*bytes_per_sample=*/0, - /*samples_per_second=*/0, - /*channels=*/0); - } - - if (close_callback_) - std::move(close_callback_).Run(); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.h b/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.h deleted file mode 100644 index 8fbd0359..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.h +++ /dev/null
@@ -1,84 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_H_ - -#include <memory> - -#include "base/memory/weak_ptr.h" -#include "base/task/sequenced_task_runner.h" -#include "base/threading/thread.h" -#include "chromeos/ash/services/assistant/public/mojom/assistant_audio_decoder.mojom.h" -#include "media/filters/blocking_url_protocol.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/remote.h" - -namespace media { -class AudioFileReader; -class AudioBus; -class DataSource; -} // namespace media - -namespace ash::assistant { - -class AssistantAudioDecoder : public mojom::AssistantAudioDecoder { - public: - AssistantAudioDecoder( - mojo::PendingRemote<mojom::AssistantAudioDecoderClient> client, - mojo::PendingRemote<mojom::AssistantMediaDataSource> data_source); - - AssistantAudioDecoder(const AssistantAudioDecoder&) = delete; - AssistantAudioDecoder& operator=(const AssistantAudioDecoder&) = delete; - - ~AssistantAudioDecoder() override; - - // Called by |client_| on main thread. - void OpenDecoder(OpenDecoderCallback callback) override; - void Decode() override; - void CloseDecoder(CloseDecoderCallback callback) override; - - private: - // Calls |decoder_| to decode on media thread. - void OpenDecoderOnMediaThread(); - void DecodeOnMediaThread(); - void CloseDecoderOnMediaThread(); - - // Calls |client_| methods on main thread. - void OnDecoderInitializedOnThread(int sample_rate, int channels); - void OnBufferDecodedOnThread( - const std::vector<std::unique_ptr<media::AudioBus>>& - decoded_audio_buffers); - - // Error callback for media::BlockingUrlProtocol. Only run on media thread. - void OnDataReadError(); - - void OnConnectionError(); - void RunCallbacksAsClosed(); - - mojo::Remote<mojom::AssistantAudioDecoderClient> client_; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - - OpenDecoderCallback open_callback_; - CloseDecoderCallback close_callback_; - bool closed_ = false; - bool read_error_ = false; - - // Weak reference to |this| for use by the media thread. Note, ordering is - // important here. This _must_ appear before |media_thread_| so that the media - // thread is destroyed (and joined) first, and hence any attempt to copy - // |weak_this_| happens before it is destroyed. - base::WeakPtr<AssistantAudioDecoder> weak_this_; - - std::unique_ptr<media::DataSource> data_source_; - std::unique_ptr<media::BlockingUrlProtocol> protocol_; - std::unique_ptr<media::AudioFileReader> decoder_; - std::unique_ptr<base::Thread> media_thread_; - - base::WeakPtrFactory<AssistantAudioDecoder> weak_factory_; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_H_
diff --git a/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder_factory.cc b/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder_factory.cc deleted file mode 100644 index 21f7591..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder_factory.cc +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder_factory.h" - -#include "chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder.h" -#include "mojo/public/cpp/bindings/self_owned_receiver.h" - -namespace ash::assistant { - -AssistantAudioDecoderFactory::AssistantAudioDecoderFactory( - mojo::PendingReceiver<mojom::AssistantAudioDecoderFactory> receiver) - : receiver_(this, std::move(receiver)) {} - -AssistantAudioDecoderFactory::~AssistantAudioDecoderFactory() = default; - -void AssistantAudioDecoderFactory::CreateAssistantAudioDecoder( - mojo::PendingReceiver<mojom::AssistantAudioDecoder> receiver, - mojo::PendingRemote<mojom::AssistantAudioDecoderClient> client, - mojo::PendingRemote<mojom::AssistantMediaDataSource> data_source) { - mojo::MakeSelfOwnedReceiver(std::make_unique<AssistantAudioDecoder>( - std::move(client), std::move(data_source)), - std::move(receiver)); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder_factory.h b/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder_factory.h deleted file mode 100644 index 85b48ab6..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/assistant_audio_decoder_factory.h +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_FACTORY_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_FACTORY_H_ - -#include "chromeos/ash/services/assistant/public/mojom/assistant_audio_decoder.mojom.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver.h" - -namespace ash::assistant { - -class AssistantAudioDecoderFactory - : public mojom::AssistantAudioDecoderFactory { - public: - explicit AssistantAudioDecoderFactory( - mojo::PendingReceiver<mojom::AssistantAudioDecoderFactory> receiver); - - AssistantAudioDecoderFactory(const AssistantAudioDecoderFactory&) = delete; - AssistantAudioDecoderFactory& operator=(const AssistantAudioDecoderFactory&) = - delete; - - ~AssistantAudioDecoderFactory() override; - - private: - // mojom::AssistantAudioDecoderFactory: - void CreateAssistantAudioDecoder( - mojo::PendingReceiver<mojom::AssistantAudioDecoder> receiver, - mojo::PendingRemote<mojom::AssistantAudioDecoderClient> client, - mojo::PendingRemote<mojom::AssistantMediaDataSource> data_source) - override; - - mojo::Receiver<mojom::AssistantAudioDecoderFactory> receiver_; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_ASSISTANT_AUDIO_DECODER_FACTORY_H_
diff --git a/chromeos/ash/services/assistant/audio_decoder/ipc_data_source.cc b/chromeos/ash/services/assistant/audio_decoder/ipc_data_source.cc deleted file mode 100644 index a85f491..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/ipc_data_source.cc +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/audio_decoder/ipc_data_source.h" - -#include <algorithm> -#include <utility> -#include <vector> - -#include "base/functional/bind.h" -#include "base/task/sequenced_task_runner.h" -#include "mojo/public/cpp/bindings/message.h" - -namespace ash::assistant { - -IPCDataSource::IPCDataSource( - mojo::PendingRemote<mojom::AssistantMediaDataSource> media_data_source) - : media_data_source_(std::move(media_data_source)), - utility_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) { - DETACH_FROM_THREAD(data_source_thread_checker_); -} - -IPCDataSource::~IPCDataSource() { - DCHECK_CALLED_ON_VALID_THREAD(utility_thread_checker_); -} - -void IPCDataSource::Stop() { - DCHECK_CALLED_ON_VALID_THREAD(data_source_thread_checker_); -} - -void IPCDataSource::Abort() { - DCHECK_CALLED_ON_VALID_THREAD(data_source_thread_checker_); -} - -void IPCDataSource::Read(int64_t position, - int size, - uint8_t* destination, - DataSource::ReadCB callback) { - DCHECK_CALLED_ON_VALID_THREAD(data_source_thread_checker_); - - utility_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&IPCDataSource::ReadMediaData, base::Unretained(this), - destination, std::move(callback), size)); -} - -bool IPCDataSource::GetSize(int64_t* size_out) { - DCHECK_CALLED_ON_VALID_THREAD(data_source_thread_checker_); - *size_out = 0; - return false; -} - -bool IPCDataSource::IsStreaming() { - DCHECK_CALLED_ON_VALID_THREAD(data_source_thread_checker_); - return true; -} - -void IPCDataSource::SetBitrate(int bitrate) { - DCHECK_CALLED_ON_VALID_THREAD(data_source_thread_checker_); -} - -bool IPCDataSource::PassedTimingAllowOriginCheck() { - // The mojo ipc channel doesn't support this yet, so cautiously return false, - // for now. - // TODO(crbug.com/40243452): Rework this method to be asynchronous, if - // possible, so that the mojo interface can be queried. - return false; -} - -bool IPCDataSource::WouldTaintOrigin() { - // The mojo ipc channel doesn't support this yet, so cautiously return true, - // for now. - // TODO(crbug.com/40243452): Rework this method to be asynchronous, if - // possible, so that the mojo interface can be queried. - return true; -} - -void IPCDataSource::ReadMediaData(uint8_t* destination, - DataSource::ReadCB callback, - int size) { - DCHECK_CALLED_ON_VALID_THREAD(utility_thread_checker_); - CHECK_GE(size, 0); - - media_data_source_->Read( - size, base::BindOnce(&IPCDataSource::ReadDone, base::Unretained(this), - destination, std::move(callback), size)); -} - -void IPCDataSource::ReadDone(uint8_t* destination, - DataSource::ReadCB callback, - uint32_t requested_size, - const std::vector<uint8_t>& data) { - DCHECK_CALLED_ON_VALID_THREAD(utility_thread_checker_); - if (data.size() > requested_size) { - mojo::ReportBadMessage("IPCDataSource::ReadDone: Unexpected data size."); - std::move(callback).Run(0); - return; - } - - std::ranges::copy(data, destination); - std::move(callback).Run(data.size()); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/audio_decoder/ipc_data_source.h b/chromeos/ash/services/assistant/audio_decoder/ipc_data_source.h deleted file mode 100644 index 360f445..0000000 --- a/chromeos/ash/services/assistant/audio_decoder/ipc_data_source.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_IPC_DATA_SOURCE_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_IPC_DATA_SOURCE_H_ - -#include <stdint.h> - -#include "base/task/sequenced_task_runner.h" -#include "base/threading/thread_checker.h" -#include "chromeos/ash/services/assistant/public/mojom/assistant_audio_decoder.mojom.h" -#include "media/base/data_source.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/remote.h" - -namespace ash::assistant { - -// Provides data source to the audio stream decoder. Class must be created and -// destroyed on a same thread. The thread must not be blocked for read -// operations to succeed. -class IPCDataSource : public media::DataSource { - public: - // May only be called on the utility thread. - explicit IPCDataSource( - mojo::PendingRemote<mojom::AssistantMediaDataSource> media_data_source); - - IPCDataSource(const IPCDataSource&) = delete; - IPCDataSource& operator=(const IPCDataSource&) = delete; - - ~IPCDataSource() override; - - // media::DataSource implementation. The methods may be called on any single - // thread. First usage of these methods attaches a thread checker. - void Stop() override; - void Abort() override; - void Read(int64_t position, - int size, - uint8_t* destination, - ReadCB callback) override; - bool GetSize(int64_t* size_out) override; - bool IsStreaming() override; - void SetBitrate(int bitrate) override; - bool PassedTimingAllowOriginCheck() override; - bool WouldTaintOrigin() override; - - private: - // Media data read helpers: must be run on the utility thread. - void ReadMediaData(uint8_t* destination, ReadCB callback, int size); - void ReadDone(uint8_t* destination, - ReadCB callback, - uint32_t requested_size, - const std::vector<uint8_t>& data); - - mojo::Remote<mojom::AssistantMediaDataSource> media_data_source_; - - scoped_refptr<base::SequencedTaskRunner> utility_task_runner_; - - THREAD_CHECKER(utility_thread_checker_); - - // Enforces that the DataSource methods are called on one other thread only. - THREAD_CHECKER(data_source_thread_checker_); -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_AUDIO_DECODER_IPC_DATA_SOURCE_H_
diff --git a/chromeos/ash/services/assistant/device_settings_host.cc b/chromeos/ash/services/assistant/device_settings_host.cc deleted file mode 100644 index d227ce3..0000000 --- a/chromeos/ash/services/assistant/device_settings_host.cc +++ /dev/null
@@ -1,98 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/device_settings_host.h" - -#include "ash/public/cpp/assistant/controller/assistant_notification_controller.h" -#include "chromeos/ash/services/assistant/public/cpp/device_actions.h" -#include "chromeos/ash/services/assistant/service_context.h" - -namespace ash::assistant { - -namespace { - -using libassistant::mojom::GetBrightnessResult; -using GetScreenBrightnessLevelCallback = libassistant::mojom:: - DeviceSettingsDelegate::GetScreenBrightnessLevelCallback; - -void HandleScreenBrightnessCallback(GetScreenBrightnessLevelCallback callback, - bool success, - double level) { - if (success) { - std::move(callback).Run(GetBrightnessResult::New(level)); - } else { - std::move(callback).Run(nullptr); - } -} - -} // namespace - -DeviceSettingsHost::DeviceSettingsHost(ServiceContext* context) - : context_(*context) {} - -DeviceSettingsHost::~DeviceSettingsHost() = default; - -void DeviceSettingsHost::Bind( - mojo::PendingReceiver<DeviceSettingsDelegate> pending_receiver) { - receiver_.Bind(std::move(pending_receiver)); -} - -void DeviceSettingsHost::Stop() { - receiver_.reset(); -} - -void DeviceSettingsHost::GetScreenBrightnessLevel( - GetScreenBrightnessLevelCallback callback) { - device_actions().GetScreenBrightnessLevel( - base::BindOnce(&HandleScreenBrightnessCallback, std::move(callback))); -} - -void DeviceSettingsHost::SetBluetoothEnabled(bool enabled) { - has_setting_changed_ = true; - device_actions().SetBluetoothEnabled(enabled); -} - -void DeviceSettingsHost::SetDoNotDisturbEnabled(bool enabled) { - has_setting_changed_ = true; - assistant_notification_controller().SetQuietMode(enabled); -} - -void DeviceSettingsHost::SetNightLightEnabled(bool enabled) { - has_setting_changed_ = true; - device_actions().SetNightLightEnabled(enabled); -} - -void DeviceSettingsHost::SetScreenBrightnessLevel(double level, bool gradual) { - has_setting_changed_ = true; - device_actions().SetScreenBrightnessLevel(level, gradual); -} - -void DeviceSettingsHost::SetSwitchAccessEnabled(bool enabled) { - has_setting_changed_ = true; - device_actions().SetSwitchAccessEnabled(enabled); -} - -void DeviceSettingsHost::SetWifiEnabled(bool enabled) { - has_setting_changed_ = true; - device_actions().SetWifiEnabled(enabled); -} - -void DeviceSettingsHost::reset_has_setting_changed() { - has_setting_changed_ = false; -} - -DeviceActions& DeviceSettingsHost::device_actions() { - auto* result = context_->device_actions(); - DCHECK(result); - return *result; -} - -AssistantNotificationController& -DeviceSettingsHost::assistant_notification_controller() { - auto* result = context_->assistant_notification_controller(); - DCHECK(result); - return *result; -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/device_settings_host.h b/chromeos/ash/services/assistant/device_settings_host.h deleted file mode 100644 index a42e7ec..0000000 --- a/chromeos/ash/services/assistant/device_settings_host.h +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_DEVICE_SETTINGS_HOST_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_DEVICE_SETTINGS_HOST_H_ - -#include "base/component_export.h" -#include "base/memory/raw_ref.h" -#include "chromeos/ash/services/libassistant/public/mojom/device_settings_delegate.mojom.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/receiver.h" - -namespace ash { - -class AssistantNotificationController; - -namespace assistant { - -class DeviceActions; -class ServiceContext; - -class COMPONENT_EXPORT(ASSISTANT_SERVICE) DeviceSettingsHost - : public libassistant::mojom::DeviceSettingsDelegate { - public: - explicit DeviceSettingsHost(ServiceContext* context); - DeviceSettingsHost(const DeviceSettingsHost&) = delete; - DeviceSettingsHost& operator=(const DeviceSettingsHost&) = delete; - ~DeviceSettingsHost() override; - - void Bind(mojo::PendingReceiver<DeviceSettingsDelegate> pending_receiver); - void Stop(); - - // libassistant::mojom::DeviceSettingsDelegate implementation: - void GetScreenBrightnessLevel( - GetScreenBrightnessLevelCallback callback) override; - void SetBluetoothEnabled(bool enabled) override; - void SetDoNotDisturbEnabled(bool enabled) override; - void SetNightLightEnabled(bool enabled) override; - void SetScreenBrightnessLevel(double level, bool gradual) override; - void SetSwitchAccessEnabled(bool enabled) override; - void SetWifiEnabled(bool enabled) override; - - // Return if any setting has been modified. - bool has_setting_changed() const { return has_setting_changed_; } - void reset_has_setting_changed(); - - private: - const raw_ref<ServiceContext> context_; - - DeviceActions& device_actions(); - AssistantNotificationController& assistant_notification_controller(); - - bool has_setting_changed_ = false; - - mojo::Receiver<DeviceSettingsDelegate> receiver_{this}; -}; -} // namespace assistant -} // namespace ash - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_DEVICE_SETTINGS_HOST_H_
diff --git a/chromeos/ash/services/assistant/libassistant_loader_stub.cc b/chromeos/ash/services/assistant/libassistant_loader_stub.cc deleted file mode 100644 index e2384ef..0000000 --- a/chromeos/ash/services/assistant/libassistant_loader_stub.cc +++ /dev/null
@@ -1,14 +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 "chromeos/ash/services/libassistant/public/cpp/libassistant_loader.h" - -namespace ash::libassistant { - -// static -void LibassistantLoader::Load(LoadCallback callback) { - std::move(callback).Run(/*success=*/true); -} - -} // namespace ash::libassistant
diff --git a/chromeos/ash/services/assistant/libassistant_service_host.h b/chromeos/ash/services/assistant/libassistant_service_host.h deleted file mode 100644 index 56c6c5c..0000000 --- a/chromeos/ash/services/assistant/libassistant_service_host.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_LIBASSISTANT_SERVICE_HOST_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_LIBASSISTANT_SERVICE_HOST_H_ - -#include "chromeos/ash/services/libassistant/public/mojom/service.mojom-forward.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" - -namespace ash::assistant { - -// Interface which can be implemented to control launching and the lifetime of -// the Libassistant service. The API is losely inspired by -// ServiceProcessHost::Launch(), to make it easier to migrate to a real mojom -// service running in its own process. -class LibassistantServiceHost { - public: - virtual ~LibassistantServiceHost() = default; - - // Launch the mojom service. Barring crashes, the service will remain running - // as long as both the receiver and this host class remain alive, or until - // |Stop| is called. - virtual void Launch( - mojo::PendingReceiver<libassistant::mojom::LibassistantService> - receiver) = 0; - - // Stop the mojom service. - virtual void Stop() = 0; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_LIBASSISTANT_SERVICE_HOST_H_
diff --git a/chromeos/ash/services/assistant/libassistant_service_host_impl.cc b/chromeos/ash/services/assistant/libassistant_service_host_impl.cc deleted file mode 100644 index 06d92bd4..0000000 --- a/chromeos/ash/services/assistant/libassistant_service_host_impl.cc +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/libassistant_service_host_impl.h" - -#include "base/check.h" -#include "base/sequence_checker.h" -#include "build/buildflag.h" -#include "chromeos/ash/components/assistant/buildflags.h" - -#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT) -#include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/libassistant/libassistant_service.h" -#include "chromeos/ash/services/libassistant/public/mojom/service.mojom-forward.h" -#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT) - -namespace ash::assistant { - -#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT) - -LibassistantServiceHostImpl::LibassistantServiceHostImpl() { - DETACH_FROM_SEQUENCE(sequence_checker_); -} - -LibassistantServiceHostImpl::~LibassistantServiceHostImpl() = default; - -void LibassistantServiceHostImpl::Launch( - mojo::PendingReceiver<libassistant::mojom::LibassistantService> receiver) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (assistant::features::IsLibAssistantSandboxEnabled()) { - AssistantBrowserDelegate::Get()->RequestLibassistantService( - std::move(receiver)); - } else { - DCHECK(!libassistant_service_); - libassistant_service_ = std::make_unique<libassistant::LibassistantService>( - std::move(receiver)); - } -} - -void LibassistantServiceHostImpl::Stop() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - libassistant_service_ = nullptr; -} - -#else - -LibassistantServiceHostImpl::LibassistantServiceHostImpl() = default; -LibassistantServiceHostImpl::~LibassistantServiceHostImpl() = default; - -void LibassistantServiceHostImpl::Launch( - mojo::PendingReceiver<libassistant::mojom::LibassistantService> receiver) {} - -void LibassistantServiceHostImpl::Stop() {} - -#endif - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/libassistant_service_host_impl.h b/chromeos/ash/services/assistant/libassistant_service_host_impl.h deleted file mode 100644 index e37e6ae..0000000 --- a/chromeos/ash/services/assistant/libassistant_service_host_impl.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_LIBASSISTANT_SERVICE_HOST_IMPL_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_LIBASSISTANT_SERVICE_HOST_IMPL_H_ - -#include <memory> - -#include "base/thread_annotations.h" -#include "build/buildflag.h" -#include "chromeos/ash/components/assistant/buildflags.h" -#include "chromeos/ash/services/assistant/libassistant_service_host.h" - -namespace ash { - -namespace libassistant { -class LibassistantService; -} - -namespace assistant { - -// Host class controlling the lifetime of the Libassistant service. -// The implementation will be stubbed out in the unbranded build. -class LibassistantServiceHostImpl : public LibassistantServiceHost { - public: - LibassistantServiceHostImpl(); - LibassistantServiceHostImpl(LibassistantServiceHostImpl&) = delete; - LibassistantServiceHostImpl& operator=(LibassistantServiceHostImpl&) = delete; - ~LibassistantServiceHostImpl() override; - - // LibassistantServiceHost implementation: - void Launch(mojo::PendingReceiver<libassistant::mojom::LibassistantService> - receiver) override; - void Stop() override; - - private: -#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT) - SEQUENCE_CHECKER(sequence_checker_); - std::unique_ptr<libassistant::LibassistantService> libassistant_service_ - GUARDED_BY_CONTEXT(sequence_checker_); -#endif -}; - -} // namespace assistant -} // namespace ash - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_LIBASSISTANT_SERVICE_HOST_IMPL_H_
diff --git a/chromeos/ash/services/assistant/media_host.cc b/chromeos/ash/services/assistant/media_host.cc deleted file mode 100644 index d7fd220..0000000 --- a/chromeos/ash/services/assistant/media_host.cc +++ /dev/null
@@ -1,297 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/media_host.h" - -#include "base/memory/raw_ptr.h" -#include "base/strings/utf_string_conversions.h" -#include "chromeos/ash/services/assistant/media_session/assistant_media_session.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/libassistant/public/mojom/media_controller.mojom.h" -#include "chromeos/services/assistant/public/shared/utils.h" - -namespace ash::assistant { - -namespace { -using libassistant::mojom::PlaybackState; -using media_session::mojom::MediaSessionAction; -using media_session::mojom::MediaSessionInfo; -using media_session::mojom::MediaSessionInfoPtr; - -constexpr char kIntentActionView[] = "android.intent.action.VIEW"; - -} // namespace - -//////////////////////////////////////////////////////////////////////////////// -// MediaHost::ChromeosMediaStateObserver -//////////////////////////////////////////////////////////////////////////////// - -// Helper class that will observe media changes on ChromeOS and sync them to -// |MediaHost::UpdateMediaState| (which will sync them to -// Libassistant). -class MediaHost::ChromeosMediaStateObserver - : private media_session::mojom::MediaControllerObserver { - public: - explicit ChromeosMediaStateObserver(MediaHost* parent) : parent_(parent) { - DCHECK(parent_); - } - ChromeosMediaStateObserver(const ChromeosMediaStateObserver&) = delete; - ChromeosMediaStateObserver& operator=(const ChromeosMediaStateObserver&) = - delete; - ~ChromeosMediaStateObserver() override = default; - - mojo::PendingRemote<MediaControllerObserver> BindNewPipeAndPassRemote() { - return receiver_.BindNewPipeAndPassRemote(); - } - - private: - // media_session::mojom::MediaControllerObserver overrides: - void MediaSessionInfoChanged(MediaSessionInfoPtr info) override { - media_session_info_ptr_ = std::move(info); - UpdateMediaState(); - } - void MediaSessionMetadataChanged( - const std::optional<media_session::MediaMetadata>& metadata) override { - media_metadata_ = std::move(metadata); - UpdateMediaState(); - } - void MediaSessionActionsChanged( - const std::vector<MediaSessionAction>& action) override {} - void MediaSessionChanged( - const std::optional<base::UnguessableToken>& request_id) override { - if (request_id.has_value()) - media_session_audio_focus_id_ = std::move(request_id.value()); - } - void MediaSessionPositionChanged( - const std::optional<media_session::MediaPosition>& position) override {} - - void UpdateMediaState() { - if (media_session_info_ptr_) { - if (media_session_info_ptr_->state == - MediaSessionInfo::SessionState::kSuspended && - media_session_info_ptr_->playback_state == - media_session::mojom::MediaPlaybackState::kPlaying) { - // It is an intermediate state caused by some providers override the - // playback state. We considered it as invalid and skip reporting the - // state. - return; - } - } - - libassistant::mojom::MediaStatePtr media_state = - libassistant::mojom::MediaState::New(); - media_state->metadata = libassistant::mojom::MediaMetadata::New(); - - // Set media metadata. - if (media_metadata_.has_value()) { - media_state->metadata->title = - base::UTF16ToUTF8(media_metadata_.value().title); - } - - // Set playback state. - media_state->playback_state = PlaybackState::kIdle; - if (media_session_info_ptr_ && - media_session_info_ptr_->state != - MediaSessionInfo::SessionState::kInactive) { - switch (media_session_info_ptr_->playback_state) { - case media_session::mojom::MediaPlaybackState::kPlaying: - media_state->playback_state = PlaybackState::kPlaying; - break; - case media_session::mojom::MediaPlaybackState::kPaused: - media_state->playback_state = PlaybackState::kPaused; - break; - } - } - - parent_->UpdateMediaState(media_session_audio_focus_id_, - std::move(media_state)); - } - - const raw_ptr<MediaHost> parent_; - mojo::Receiver<media_session::mojom::MediaControllerObserver> receiver_{this}; - - // Info associated to the active media session. - MediaSessionInfoPtr media_session_info_ptr_; - // The metadata for the active media session. It can be null to be reset, - // e.g. the media that was being played has been stopped. - std::optional<media_session::MediaMetadata> media_metadata_ = std::nullopt; - - base::UnguessableToken media_session_audio_focus_id_ = - base::UnguessableToken::Null(); -}; - -//////////////////////////////////////////////////////////////////////////////// -// MediaHost::LibassistantMediaStateObserver -//////////////////////////////////////////////////////////////////////////////// - -// Helper class that will observe media changes in Libassisstant and sync them -// to either |MediaHost::interaction_subscribers_|, -// |MediaHost::chromeos_media_controller_| or -// |MediaHost::media_session_|. -class MediaHost::LibassistantMediaDelegate - : public libassistant::mojom::MediaDelegate { - public: - explicit LibassistantMediaDelegate( - MediaHost* parent, - mojo::PendingReceiver<MediaDelegate> pending_receiver) - : parent_(parent), receiver_(this, std::move(pending_receiver)) {} - - LibassistantMediaDelegate(const LibassistantMediaDelegate&) = delete; - LibassistantMediaDelegate& operator=(const LibassistantMediaDelegate&) = - delete; - ~LibassistantMediaDelegate() override = default; - - private: - // libassistant::mojom::MediaDelegate implementation: - void OnPlaybackStateChanged( - libassistant::mojom::MediaStatePtr new_state) override { - parent_->media_session_->NotifyMediaSessionMetadataChanged(*new_state); - } - - void PlayAndroidMedia(const AndroidAppInfo& app_info) override { - // This is the only action that can be executed when we play android media. - DCHECK_EQ(app_info.action, kIntentActionView); - // Status is meaningless when playing android media. - DCHECK_EQ(app_info.status, AppStatus::kUnknown); - - for (auto& subscriber : interaction_subscribers()) - subscriber.OnOpenAppResponse(app_info); - } - - void PlayWebMedia(const std::string& url) override { - const GURL gurl = GURL(url); - for (auto& it : interaction_subscribers()) - it.OnOpenUrlResponse(gurl, /*in_background=*/false); - } - - void NextTrack() override { media_controller().NextTrack(); } - - void PreviousTrack() override { media_controller().PreviousTrack(); } - - void Pause() override { media_controller().Suspend(); } - - void Resume() override { media_controller().Resume(); } - - void Stop() override { - // Note: we intentionally use 'suspend' here so the user can later resume; - // if we issued 'stop' there would be no way to resume. - // See b/140945356. - media_controller().Suspend(); - } - - const base::ObserverList<AssistantInteractionSubscriber>& - interaction_subscribers() { - return *parent_->interaction_subscribers_; - } - - media_session::mojom::MediaController& media_controller() { - return *parent_->chromeos_media_controller_; - } - - const raw_ptr<MediaHost> parent_; - mojo::Receiver<MediaDelegate> receiver_; -}; - -//////////////////////////////////////////////////////////////////////////////// -// MediaHost -//////////////////////////////////////////////////////////////////////////////// - -MediaHost::MediaHost(AssistantBrowserDelegate* delegate, - const base::ObserverList<AssistantInteractionSubscriber>* - interaction_subscribers) - : interaction_subscribers_(interaction_subscribers), - media_session_(std::make_unique<AssistantMediaSession>(this)) { - DCHECK(delegate); - - mojo::Remote<media_session::mojom::MediaControllerManager> - media_controller_manager; - delegate->RequestMediaControllerManager( - media_controller_manager.BindNewPipeAndPassReceiver()); - media_controller_manager->CreateActiveMediaController( - chromeos_media_controller_.BindNewPipeAndPassReceiver()); -} - -MediaHost::~MediaHost() = default; - -void MediaHost::Initialize( - libassistant::mojom::MediaController* libassistant_controller, - mojo::PendingReceiver<libassistant::mojom::MediaDelegate> media_delegate) { - DCHECK(!libassistant_media_controller_); - - libassistant_media_controller_ = libassistant_controller; - libassistant_media_delegate_ = std::make_unique<LibassistantMediaDelegate>( - this, std::move(media_delegate)); -} - -void MediaHost::Stop() { - libassistant_media_controller_ = nullptr; - StopObservingMediaController(); -} - -void MediaHost::ResumeInternalMediaPlayer() { - if (!libassistant_media_controller_) { - return; - } - libassistant_media_controller_->ResumeInternalMediaPlayer(); -} - -void MediaHost::PauseInternalMediaPlayer() { - if (!libassistant_media_controller_) { - return; - } - libassistant_media_controller_->PauseInternalMediaPlayer(); -} - -void MediaHost::SetRelatedInfoEnabled(bool enable) { - if (enable) { - StartObservingMediaController(); - } else { - StopObservingMediaController(); - ResetMediaState(); - } -} - -void MediaHost::UpdateMediaState( - const base::UnguessableToken& media_session_id, - libassistant::mojom::MediaStatePtr media_state) { - // MediaSession Integrated providers (include the libassistant internal - // media provider) will trigger media state change event. Only update the - // external media status if the state changes is triggered by external - // providers. - if (media_session_->internal_audio_focus_id() == media_session_id) { - return; - } - - if (!libassistant_media_controller_) { - return; - } - libassistant_media_controller_->SetExternalPlaybackState( - std::move(media_state)); -} - -void MediaHost::ResetMediaState() { - if (!libassistant_media_controller_) { - return; - } - libassistant_media_controller_->SetExternalPlaybackState( - libassistant::mojom::MediaState::New()); -} - -void MediaHost::StartObservingMediaController() { - if (chromeos_media_state_observer_) - return; - - chromeos_media_state_observer_ = - std::make_unique<ChromeosMediaStateObserver>(this); - chromeos_media_controller_->AddObserver( - chromeos_media_state_observer_->BindNewPipeAndPassRemote()); -} - -void MediaHost::StopObservingMediaController() { - chromeos_media_state_observer_.reset(); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/media_host.h b/chromeos/ash/services/assistant/media_host.h deleted file mode 100644 index e31df05..0000000 --- a/chromeos/ash/services/assistant/media_host.h +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_MEDIA_HOST_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_MEDIA_HOST_H_ - -#include "base/component_export.h" -#include "base/memory/raw_ptr.h" -#include "base/observer_list.h" -#include "base/unguessable_token.h" -#include "chromeos/ash/services/libassistant/public/mojom/media_controller.mojom-forward.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "services/media_session/public/mojom/media_controller.mojom.h" -#include "services/media_session/public/mojom/media_session.mojom.h" - -namespace ash::assistant { - -class AssistantBrowserDelegate; -class AssistantInteractionSubscriber; -class AssistantManagerServiceImpl; -class AssistantMediaSession; - -// Handles all media related interactions with Libassistant, which can broadly -// be separated in 2 responsibilities: -// 1) Let Libassistant know about the currently playing media. -// 1) Let Libassistant control media (start/stop/open spotify). -class COMPONENT_EXPORT(ASSISTANT_SERVICE) MediaHost { - public: - MediaHost(AssistantBrowserDelegate* delegate, - const base::ObserverList<AssistantInteractionSubscriber>* - interaction_subscribers); - MediaHost(const MediaHost&) = delete; - MediaHost& operator=(const MediaHost&) = delete; - ~MediaHost(); - - void Initialize( - libassistant::mojom::MediaController* libassistant_controller, - mojo::PendingReceiver<libassistant::mojom::MediaDelegate> media_delegate); - - // Stop observing ChromeOS media state. - void Stop(); - - // Pause/resume playback of Libassistant media player (which plays podcasts - // and news). - void ResumeInternalMediaPlayer(); - void PauseInternalMediaPlayer(); - - // Called when the user allows/disallows related info. - // We only observe the current playing audio when related info is allowed. - void SetRelatedInfoEnabled(bool enable); - - AssistantMediaSession& media_session() { return *media_session_; } - - private: - class LibassistantMediaDelegate; - class ChromeosMediaStateObserver; - - void UpdateMediaState(const base::UnguessableToken& media_session_id, - libassistant::mojom::MediaStatePtr media_state); - void ResetMediaState(); - - void StartObservingMediaController(); - void StopObservingMediaController(); - - // Owned by our parent |AssistantManagerServiceImpl|. - const raw_ptr<const base::ObserverList<AssistantInteractionSubscriber>> - interaction_subscribers_; - // Owned by our parent |AssistantManagerServiceImpl|. - raw_ptr<libassistant::mojom::MediaController, DanglingUntriaged> - libassistant_media_controller_ = nullptr; - - std::unique_ptr<AssistantMediaSession> media_session_; - mojo::Remote<media_session::mojom::MediaController> - chromeos_media_controller_; - - // Helper class that will observe media changes on ChromeOS and sync them - // to Libassistant. - std::unique_ptr<ChromeosMediaStateObserver> chromeos_media_state_observer_; - // Helper class that will observe media changes in Libassistant and - // sync/apply them in ChromeOS. - std::unique_ptr<LibassistantMediaDelegate> libassistant_media_delegate_; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_MEDIA_HOST_H_
diff --git a/chromeos/ash/services/assistant/media_host_unittest.cc b/chromeos/ash/services/assistant/media_host_unittest.cc deleted file mode 100644 index a7df6335..0000000 --- a/chromeos/ash/services/assistant/media_host_unittest.cc +++ /dev/null
@@ -1,458 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/media_host.h" - -#include "base/notreached.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/task_environment.h" -#include "chromeos/ash/services/assistant/media_session/assistant_media_session.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.h" -#include "chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.h" -#include "chromeos/ash/services/assistant/test_support/scoped_assistant_browser_delegate.h" -#include "chromeos/ash/services/libassistant/public/mojom/android_app_info.mojom-shared.h" -#include "chromeos/ash/services/libassistant/public/mojom/android_app_info.mojom.h" -#include "chromeos/services/assistant/public/shared/utils.h" -#include "services/media_session/public/cpp/test/mock_media_session.h" -#include "services/media_session/public/cpp/test/test_media_controller.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace ash::assistant { - -namespace { - -using libassistant::mojom::MediaState; -using libassistant::mojom::MediaStatePtr; -using libassistant::mojom::PlaybackState; -using media_session::mojom::MediaSessionInfo; -using media_session::test::MockMediaSessionMojoObserver; -using media_session::test::TestMediaController; -using ::testing::_; - -constexpr char kPlayAndroidMediaAction[] = "android.intent.action.VIEW"; - -#define EXPECT_NO_CALLS(args...) EXPECT_CALL(args).Times(0); - -MATCHER_P(PlaybackStateIs, expected_state, "") { - if (arg.is_null()) { - *result_listener << "MediaStatePtr is nullptr"; - return false; - } - - if (arg->playback_state != expected_state) { - *result_listener << "Expected " << expected_state << " but got " - << arg->playback_state; - return false; - } - return true; -} - -std::string AndroidAppInfoToString(const AndroidAppInfo& app_info) { - return base::StringPrintf(R"( - AndroidAppInfo { - package_name '%s' - version '%i' - localized_app_name '%s' - action '%s' - intent '%s' - status '%i' - )", - app_info.package_name.c_str(), app_info.version, - app_info.localized_app_name.c_str(), - app_info.action.c_str(), app_info.intent.c_str(), - static_cast<int>(app_info.status)); -} - -MATCHER_P(MatchesAndroidAppInfo, expected, "") { - if (AndroidAppInfoToString(arg) == AndroidAppInfoToString(expected)) - return true; - - *result_listener << "\nExpected: " << AndroidAppInfoToString(expected); - *result_listener << "\nActual: " << AndroidAppInfoToString(arg); - return false; -} - -class FakeMediaControllerManager - : public media_session::mojom::MediaControllerManager { - public: - FakeMediaControllerManager() { - media_controller_ = std::make_unique<TestMediaController>(); - } - FakeMediaControllerManager(const FakeMediaControllerManager&) = delete; - FakeMediaControllerManager& operator=(const FakeMediaControllerManager&) = - delete; - ~FakeMediaControllerManager() override = default; - - mojo::Receiver<media_session::mojom::MediaControllerManager>& receiver() { - return receiver_; - } - - TestMediaController* media_controller() const { - return media_controller_.get(); - } - - // media_session::mojom::MediaControllerManager implementation: - void CreateMediaControllerForSession( - mojo::PendingReceiver<media_session::mojom::MediaController> receiver, - const ::base::UnguessableToken& request_id) override { - NOTIMPLEMENTED(); - } - void CreateActiveMediaController( - mojo::PendingReceiver<media_session::mojom::MediaController> receiver) - override { - media_controller_->BindMediaControllerReceiver(std::move(receiver)); - } - void SuspendAllSessions() override { NOTIMPLEMENTED(); } - - private: - mojo::Receiver<media_session::mojom::MediaControllerManager> receiver_{this}; - std::unique_ptr<TestMediaController> media_controller_; -}; - -} // namespace - -class MediaHostTest : public testing::Test { - public: - MediaHostTest() = default; - MediaHostTest(const MediaHostTest&) = delete; - MediaHostTest& operator=(const MediaHostTest&) = delete; - ~MediaHostTest() override = default; - - void SetUp() override { - delegate_.SetMediaControllerManager(&media_controller_manager_.receiver()); - - media_host_ = std::make_unique<MediaHost>(AssistantBrowserDelegate::Get(), - &interaction_subscribers_); - media_host().Initialize( - &libassistant_controller_, - libassistant_media_delegate_.BindNewPipeAndPassReceiver()); - } - - LibassistantMediaControllerMock& libassistant_controller_mock() { - return libassistant_controller_; - } - - libassistant::mojom::MediaDelegate& libassistant_media_delegate() { - return *libassistant_media_delegate_; - } - - MediaHost& media_host() { return *media_host_; } - - AssistantMediaSession& media_session() { - return media_host().media_session(); - } - - TestMediaController* media_controller() const { - return media_controller_manager_.media_controller(); - } - - void FlushMojomPipes() { - media_controller_manager_.receiver().FlushForTesting(); - libassistant_media_delegate_.FlushForTesting(); - } - - void SetRelatedInfoEnabled(bool enabled) { - media_host().SetRelatedInfoEnabled(enabled); - FlushMojomPipes(); - } - - void StartMediaSession( - base::UnguessableToken token = base::UnguessableToken::Create()) { - media_controller()->SimulateMediaSessionChanged(token); - media_controller()->Flush(); - } - - void MediaSessionInfoChanged( - media_session::mojom::MediaSessionInfoPtr session_info) { - media_controller()->SimulateMediaSessionInfoChanged( - std::move(session_info)); - media_controller()->Flush(); - } - - void MediaSessionMetadataChanged( - const media_session::MediaMetadata& meta_data) { - media_controller()->SimulateMediaSessionMetadataChanged(meta_data); - media_controller()->Flush(); - } - - void AddAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) { - interaction_subscribers_.AddObserver(subscriber); - } - - void ClearAssistantInteractionSubscribers() { - interaction_subscribers_.Clear(); - } - - private: - base::test::SingleThreadTaskEnvironment environment_; - - base::ObserverList<AssistantInteractionSubscriber> interaction_subscribers_; - FakeMediaControllerManager media_controller_manager_; - ScopedAssistantBrowserDelegate delegate_; - testing::StrictMock<LibassistantMediaControllerMock> libassistant_controller_; - mojo::Remote<libassistant::mojom::MediaDelegate> libassistant_media_delegate_; - std::unique_ptr<MediaHost> media_host_; -}; - -TEST_F(MediaHostTest, ShouldSupportResumePlaying) { - EXPECT_CALL(libassistant_controller_mock(), ResumeInternalMediaPlayer); - - media_host().ResumeInternalMediaPlayer(); -} - -TEST_F(MediaHostTest, ShouldSupportPausePlaying) { - EXPECT_CALL(libassistant_controller_mock(), PauseInternalMediaPlayer); - - media_host().PauseInternalMediaPlayer(); -} - -TEST_F(MediaHostTest, ShouldInitiallyNotObserveMediaChanges) { - EXPECT_EQ(0, media_controller()->add_observer_count()); -} - -TEST_F(MediaHostTest, - ShouldStartObservingMediaChangesWhenRelatedInfoIsEnabled) { - SetRelatedInfoEnabled(true); - EXPECT_EQ(1, media_controller()->add_observer_count()); - EXPECT_EQ(1, media_controller()->GetActiveObserverCount()); -} - -TEST_F(MediaHostTest, - ShouldStopObservingMediaChangesAndFlushStateWhenRelatedInfoIsDisabled) { - SetRelatedInfoEnabled(true); - - EXPECT_CALL(libassistant_controller_mock(), SetExternalPlaybackState); - SetRelatedInfoEnabled(false); - - // Note the observer is not unbound, but the connection is severed. - EXPECT_EQ(1, media_controller()->add_observer_count()); - EXPECT_EQ(0, media_controller()->GetActiveObserverCount()); -} - -TEST_F(MediaHostTest, ShouldSetTitleWhenCallingSetExternalPlaybackState) { - SetRelatedInfoEnabled(true); - StartMediaSession(); - - MediaStatePtr actual_state; - EXPECT_CALL(libassistant_controller_mock(), SetExternalPlaybackState) - .WillOnce([&](MediaStatePtr state) { actual_state = std::move(state); }); - - media_session::MediaMetadata meta_data; - meta_data.title = u"the title"; - MediaSessionMetadataChanged(meta_data); - - ASSERT_FALSE(actual_state.is_null()); - ASSERT_FALSE(actual_state->metadata.is_null()); - EXPECT_EQ(actual_state->metadata->title, "the title"); -} - -TEST_F(MediaHostTest, ShouldDropInvalidStates) { - SetRelatedInfoEnabled(true); - StartMediaSession(); - - auto session_info = MediaSessionInfo::New(); - session_info->state = MediaSessionInfo::SessionState::kSuspended; - session_info->playback_state = - media_session::mojom::MediaPlaybackState::kPlaying; - MediaSessionInfoChanged(std::move(session_info)); - - EXPECT_NO_CALLS(libassistant_controller_mock(), SetExternalPlaybackState); - - media_session::MediaMetadata meta_data; - MediaSessionMetadataChanged(meta_data); -} - -TEST_F(MediaHostTest, ShouldSetPlaybackState) { - SetRelatedInfoEnabled(true); - StartMediaSession(); - - // State is idle if MediaSessionInfo is never set. - { - EXPECT_CALL( - libassistant_controller_mock(), - SetExternalPlaybackState(PlaybackStateIs(PlaybackState::kIdle))); - media_session::MediaMetadata meta_data; - MediaSessionMetadataChanged(meta_data); - } - - // State kPlaying. - { - EXPECT_CALL( - libassistant_controller_mock(), - SetExternalPlaybackState(PlaybackStateIs(PlaybackState::kPlaying))); - - auto session_info = MediaSessionInfo::New(); - session_info->playback_state = - media_session::mojom::MediaPlaybackState::kPlaying; - MediaSessionInfoChanged(std::move(session_info)); - } - - // State kPaused. - { - EXPECT_CALL( - libassistant_controller_mock(), - SetExternalPlaybackState(PlaybackStateIs(PlaybackState::kPaused))); - - auto session_info = MediaSessionInfo::New(); - session_info->playback_state = - media_session::mojom::MediaPlaybackState::kPaused; - MediaSessionInfoChanged(std::move(session_info)); - } - - // State is kInvalid if session is inactive - { - EXPECT_CALL( - libassistant_controller_mock(), - SetExternalPlaybackState(PlaybackStateIs(PlaybackState::kIdle))); - - auto session_info = MediaSessionInfo::New(); - session_info->state = MediaSessionInfo::SessionState::kInactive; - session_info->playback_state = - media_session::mojom::MediaPlaybackState::kPaused; - MediaSessionInfoChanged(std::move(session_info)); - } -} - -TEST_F(MediaHostTest, ShouldResetPlaybackStateWhenDisablingRelatedInfo) { - SetRelatedInfoEnabled(true); - StartMediaSession(); - - MediaStatePtr actual_state; - EXPECT_CALL(libassistant_controller_mock(), SetExternalPlaybackState) - .WillOnce([&](MediaStatePtr state) { actual_state = std::move(state); }); - - SetRelatedInfoEnabled(false); - - const MediaStatePtr empty_state = MediaState::New(); - EXPECT_EQ(actual_state, empty_state); -} - -TEST_F(MediaHostTest, - ShouldIgnorePlaybackStateUpdatesWhenRelatedInfoIsDisabled) { - SetRelatedInfoEnabled(true); - StartMediaSession(); - - // Playback state is updated when disabling related info. - EXPECT_CALL(libassistant_controller_mock(), SetExternalPlaybackState); - SetRelatedInfoEnabled(false); - - // But not for any consecutive changes. - EXPECT_NO_CALLS(libassistant_controller_mock(), SetExternalPlaybackState); - media_session::MediaMetadata meta_data; - MediaSessionMetadataChanged(meta_data); -} - -TEST_F(MediaHostTest, - ShouldIgnorePlaybackStateUpdatesForLibassistantInternalSessions) { - SetRelatedInfoEnabled(true); - - const auto session_id = base::UnguessableToken::Create(); - StartMediaSession(session_id); - media_session().SetInternalAudioFocusIdForTesting(session_id); - - EXPECT_NO_CALLS(libassistant_controller_mock(), SetExternalPlaybackState); - - media_session::MediaMetadata meta_data; - MediaSessionMetadataChanged(meta_data); -} - -TEST_F(MediaHostTest, ShouldForwardLibassistantMediaSessionUpdates) { - MockMediaSessionMojoObserver media_session_observer(media_session()); - media_session_observer.WaitForEmptyMetadata(); - - auto input = MediaState::New(); - input->metadata = libassistant::mojom::MediaMetadata::New(); - input->metadata->title = "the title"; - input->metadata->artist = "the artist"; - input->metadata->album = "the album"; - libassistant_media_delegate().OnPlaybackStateChanged(std::move(input)); - FlushMojomPipes(); - - media_session::MediaMetadata expected_output; - expected_output.title = u"the title"; - expected_output.artist = u"the artist"; - expected_output.album = u"the album"; - media_session_observer.WaitForExpectedMetadata(expected_output); -} - -TEST_F(MediaHostTest, ShouldForwardLibassistantOpenAndroidMediaUpdates) { - testing::StrictMock<MockAssistantInteractionSubscriber> mock; - AddAssistantInteractionSubscriber(&mock); - - AndroidAppInfo output_app_info; - output_app_info.package_name = "the package name"; - output_app_info.version = 111; - output_app_info.localized_app_name = "the localized name"; - output_app_info.action = kPlayAndroidMediaAction; - output_app_info.intent = "the intent"; - output_app_info.status = AppStatus::kUnknown; - - EXPECT_CALL(mock, OnOpenAppResponse(MatchesAndroidAppInfo(output_app_info))); - - AndroidAppInfo input_app_info; - input_app_info.package_name = "the package name"; - input_app_info.version = 111; - input_app_info.localized_app_name = "the localized name"; - input_app_info.intent = "the intent"; - input_app_info.status = AppStatus::kUnknown; - input_app_info.action = kPlayAndroidMediaAction; - - libassistant_media_delegate().PlayAndroidMedia(std::move(input_app_info)); - - FlushMojomPipes(); - ClearAssistantInteractionSubscribers(); -} - -TEST_F(MediaHostTest, ShouldOpenWebMediaUrl) { - testing::StrictMock<MockAssistantInteractionSubscriber> mock; - AddAssistantInteractionSubscriber(&mock); - - EXPECT_CALL( - mock, OnOpenUrlResponse(GURL("http://the.url"), /*in_background=*/false)); - - libassistant_media_delegate().PlayWebMedia("http://the.url"); - - FlushMojomPipes(); - ClearAssistantInteractionSubscribers(); -} - -TEST_F(MediaHostTest, ShouldPlayNextTrack) { - EXPECT_EQ(0, media_controller()->next_track_count()); - libassistant_media_delegate().NextTrack(); - FlushMojomPipes(); - EXPECT_EQ(1, media_controller()->next_track_count()); -} - -TEST_F(MediaHostTest, ShouldPlayPreviousTrack) { - EXPECT_EQ(0, media_controller()->previous_track_count()); - libassistant_media_delegate().PreviousTrack(); - FlushMojomPipes(); - EXPECT_EQ(1, media_controller()->previous_track_count()); -} - -TEST_F(MediaHostTest, ShouldPause) { - EXPECT_EQ(0, media_controller()->suspend_count()); - libassistant_media_delegate().Pause(); - FlushMojomPipes(); - EXPECT_EQ(1, media_controller()->suspend_count()); -} - -TEST_F(MediaHostTest, ShouldResume) { - EXPECT_EQ(0, media_controller()->resume_count()); - libassistant_media_delegate().Resume(); - FlushMojomPipes(); - EXPECT_EQ(1, media_controller()->resume_count()); -} - -TEST_F(MediaHostTest, ShouldStop) { - EXPECT_EQ(0, media_controller()->suspend_count()); - libassistant_media_delegate().Stop(); - FlushMojomPipes(); - EXPECT_EQ(1, media_controller()->suspend_count()); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/media_session/assistant_media_session.cc b/chromeos/ash/services/assistant/media_session/assistant_media_session.cc deleted file mode 100644 index 41e0a13..0000000 --- a/chromeos/ash/services/assistant/media_session/assistant_media_session.cc +++ /dev/null
@@ -1,247 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/media_session/assistant_media_session.h" - -#include <utility> - -#include "base/functional/bind.h" -#include "base/memory/scoped_refptr.h" -#include "base/strings/utf_string_conversions.h" -#include "base/task/sequenced_task_runner.h" -#include "chromeos/ash/services/assistant/media_host.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" -#include "chromeos/ash/services/libassistant/public/mojom/media_controller.mojom.h" -#include "services/media_session/public/cpp/features.h" - -// A macro which ensures we are running on the main thread. -#define ENSURE_MAIN_THREAD(method, ...) \ - if (!main_task_runner_->RunsTasksInCurrentSequence()) { \ - main_task_runner_->PostTask( \ - FROM_HERE, \ - base::BindOnce(method, weak_factory_.GetWeakPtr(), ##__VA_ARGS__)); \ - return; \ - } - -namespace ash::assistant { - -namespace { - -using media_session::mojom::AudioFocusType; -using media_session::mojom::MediaPlaybackState; -using media_session::mojom::MediaSessionInfo; - -const char kAudioFocusSourceName[] = "assistant"; - -} // namespace - -AssistantMediaSession::AssistantMediaSession(MediaHost* host) - : host_(host), - main_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()) {} - -AssistantMediaSession::~AssistantMediaSession() { - AbandonAudioFocusIfNeeded(); -} - -void AssistantMediaSession::GetMediaSessionInfo( - GetMediaSessionInfoCallback callback) { - std::move(callback).Run(session_info_.Clone()); -} - -void AssistantMediaSession::AddObserver( - mojo::PendingRemote<media_session::mojom::MediaSessionObserver> observer) { - ENSURE_MAIN_THREAD(&AssistantMediaSession::AddObserver, std::move(observer)); - mojo::Remote<media_session::mojom::MediaSessionObserver> - media_session_observer(std::move(observer)); - media_session_observer->MediaSessionInfoChanged(session_info_.Clone()); - media_session_observer->MediaSessionMetadataChanged(metadata_); - observers_.Add(std::move(media_session_observer)); -} - -void AssistantMediaSession::GetDebugInfo(GetDebugInfoCallback callback) { - std::move(callback).Run(media_session::mojom::MediaSessionDebugInfo::New()); -} - -void AssistantMediaSession::GetVisibility(GetVisibilityCallback callback) { - std::move(callback).Run(false); -} - -void AssistantMediaSession::StartDucking() { - if (!IsSessionStateActive()) - return; - SetAudioFocusInfo(MediaSessionInfo::SessionState::kDucking, - audio_focus_type_); -} - -void AssistantMediaSession::StopDucking() { - if (!IsSessionStateDucking()) - return; - SetAudioFocusInfo(MediaSessionInfo::SessionState::kActive, audio_focus_type_); -} - -void AssistantMediaSession::Suspend(SuspendType suspend_type) { - if (!IsSessionStateActive() && !IsSessionStateDucking()) - return; - SetAudioFocusInfo(MediaSessionInfo::SessionState::kSuspended, - audio_focus_type_); - host_->PauseInternalMediaPlayer(); -} - -void AssistantMediaSession::Resume(SuspendType suspend_type) { - if (!IsSessionStateSuspended()) - return; - SetAudioFocusInfo(MediaSessionInfo::SessionState::kActive, audio_focus_type_); - host_->ResumeInternalMediaPlayer(); -} - -void AssistantMediaSession::RequestAudioFocus(AudioFocusType audio_focus_type) { - if (!base::FeatureList::IsEnabled( - media_session::features::kMediaSessionService)) { - return; - } - - if (audio_focus_request_client_.is_bound()) { - // We have an existing request so we should request an updated focus type. - audio_focus_request_client_->RequestAudioFocus( - session_info_.Clone(), audio_focus_type, - base::BindOnce(&AssistantMediaSession::FinishAudioFocusRequest, - base::Unretained(this), audio_focus_type)); - return; - } - - EnsureServiceConnection(); - - // Create a mojo interface pointer to our media session. - receiver_.reset(); - audio_focus_manager_->RequestAudioFocus( - audio_focus_request_client_.BindNewPipeAndPassReceiver(), - receiver_.BindNewPipeAndPassRemote(), session_info_.Clone(), - audio_focus_type, - base::BindOnce(&AssistantMediaSession::FinishInitialAudioFocusRequest, - base::Unretained(this), audio_focus_type)); -} - -void AssistantMediaSession::AbandonAudioFocusIfNeeded() { - if (!base::FeatureList::IsEnabled( - media_session::features::kMediaSessionService)) { - return; - } - - if (IsSessionStateInactive()) - return; - - SetAudioFocusInfo(MediaSessionInfo::SessionState::kInactive, - audio_focus_type_); - - if (!audio_focus_request_client_.is_bound()) - return; - - audio_focus_request_client_->AbandonAudioFocus(); - audio_focus_request_client_.reset(); - audio_focus_manager_.reset(); - internal_audio_focus_id_ = base::UnguessableToken::Null(); -} - -void AssistantMediaSession::NotifyMediaSessionMetadataChanged( - const libassistant::mojom::MediaState& status) { - media_session::MediaMetadata metadata; - - if (!status.metadata.is_null()) { - metadata.title = base::UTF8ToUTF16(status.metadata->title); - metadata.artist = base::UTF8ToUTF16(status.metadata->artist); - metadata.album = base::UTF8ToUTF16(status.metadata->album); - } - - bool metadata_changed = metadata_ != metadata; - if (!metadata_changed) - return; - - metadata_ = metadata; - - for (auto& observer : observers_) - observer->MediaSessionMetadataChanged(this->metadata_); -} - -base::WeakPtr<AssistantMediaSession> AssistantMediaSession::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - -bool AssistantMediaSession::IsSessionStateActive() const { - return session_info_.state == MediaSessionInfo::SessionState::kActive; -} - -bool AssistantMediaSession::IsSessionStateDucking() const { - return session_info_.state == MediaSessionInfo::SessionState::kDucking; -} - -bool AssistantMediaSession::IsSessionStateSuspended() const { - return session_info_.state == MediaSessionInfo::SessionState::kSuspended; -} - -bool AssistantMediaSession::IsSessionStateInactive() const { - return session_info_.state == MediaSessionInfo::SessionState::kInactive; -} - -void AssistantMediaSession::SetInternalAudioFocusIdForTesting( - const base::UnguessableToken& token) { - internal_audio_focus_id_ = token; -} - -void AssistantMediaSession::EnsureServiceConnection() { - DCHECK(base::FeatureList::IsEnabled( - media_session::features::kMediaSessionService)); - - if (audio_focus_manager_.is_bound() && audio_focus_manager_.is_connected()) - return; - - audio_focus_manager_.reset(); - - AssistantBrowserDelegate::Get()->RequestAudioFocusManager( - audio_focus_manager_.BindNewPipeAndPassReceiver()); - audio_focus_manager_->SetSource(base::UnguessableToken::Create(), - kAudioFocusSourceName); -} - -void AssistantMediaSession::FinishAudioFocusRequest( - AudioFocusType audio_focus_type) { - DCHECK(audio_focus_request_client_.is_bound()); - - SetAudioFocusInfo(MediaSessionInfo::SessionState::kActive, audio_focus_type); -} - -void AssistantMediaSession::FinishInitialAudioFocusRequest( - AudioFocusType audio_focus_type, - const base::UnguessableToken& request_id) { - internal_audio_focus_id_ = request_id; - FinishAudioFocusRequest(audio_focus_type); -} - -void AssistantMediaSession::SetAudioFocusInfo( - MediaSessionInfo::SessionState audio_focus_state, - AudioFocusType audio_focus_type) { - if (audio_focus_state == session_info_.state && - audio_focus_type == audio_focus_type_) { - return; - } - - // Update |session_info_| and |audio_focus_type_|. - session_info_.state = audio_focus_state; - audio_focus_type_ = audio_focus_type; - session_info_.is_controllable = - !IsSessionStateInactive() && - (audio_focus_type != AudioFocusType::kGainTransient); - - NotifyMediaSessionInfoChanged(); -} - -void AssistantMediaSession::NotifyMediaSessionInfoChanged() { - ENSURE_MAIN_THREAD(&AssistantMediaSession::NotifyMediaSessionInfoChanged); - if (audio_focus_request_client_.is_bound()) - audio_focus_request_client_->MediaSessionInfoChanged(session_info_.Clone()); - - for (auto& observer : observers_) - observer->MediaSessionInfoChanged(session_info_.Clone()); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/media_session/assistant_media_session.h b/chromeos/ash/services/assistant/media_session/assistant_media_session.h deleted file mode 100644 index fa9f2d7d..0000000 --- a/chromeos/ash/services/assistant/media_session/assistant_media_session.h +++ /dev/null
@@ -1,146 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_MEDIA_SESSION_ASSISTANT_MEDIA_SESSION_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_MEDIA_SESSION_ASSISTANT_MEDIA_SESSION_H_ - -#include "base/memory/raw_ptr.h" -#include "base/memory/scoped_refptr.h" -#include "base/task/sequenced_task_runner.h" -#include "base/timer/timer.h" -#include "base/unguessable_token.h" -#include "chromeos/ash/services/libassistant/public/mojom/media_controller.mojom-forward.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote_set.h" -#include "services/media_session/public/mojom/audio_focus.mojom.h" -#include "services/media_session/public/mojom/media_session.mojom.h" - -namespace ash::assistant { - -class MediaHost; - -// MediaSession manages the media session and audio focus for Assistant. -// MediaSession allows clients to observe its changes via MediaSessionObserver, -// and allows clients to resume/suspend/stop the managed players. -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AssistantMediaSession - : public media_session::mojom::MediaSession { - public: - explicit AssistantMediaSession(MediaHost* host); - - AssistantMediaSession(const AssistantMediaSession&) = delete; - AssistantMediaSession& operator=(const AssistantMediaSession&) = delete; - - ~AssistantMediaSession() override; - - // media_session.mojom.MediaSession overrides: - void Suspend(SuspendType suspend_type) override; - void Resume(SuspendType suspend_type) override; - void StartDucking() override; - void StopDucking() override; - void GetMediaSessionInfo(GetMediaSessionInfoCallback callback) override; - void GetDebugInfo(GetDebugInfoCallback callback) override; - void AddObserver( - mojo::PendingRemote<media_session::mojom::MediaSessionObserver> observer) - override; - void PreviousTrack() override {} - void NextTrack() override {} - void SkipAd() override {} - void PreviousSlide() override {} - void NextSlide() override {} - void Seek(base::TimeDelta seek_time) override {} - void Stop(SuspendType suspend_type) override {} - void GetMediaImageBitmap(const media_session::MediaImage& image, - int minimum_size_px, - int desired_size_px, - GetMediaImageBitmapCallback callback) override {} - void SeekTo(base::TimeDelta seek_time) override {} - void ScrubTo(base::TimeDelta seek_time) override {} - void EnterPictureInPicture() override {} - void ExitPictureInPicture() override {} - void GetVisibility(GetVisibilityCallback callback) override; - void SetAudioSinkId(const std::optional<std::string>& sink_id) override {} - void ToggleMicrophone() override {} - void ToggleCamera() override {} - void HangUp() override {} - void Raise() override {} - void SetMute(bool mute) override {} - void RequestMediaRemoting() override {} - void EnterAutoPictureInPicture() override {} - - // Requests/abandons audio focus to the AudioFocusManager. - void RequestAudioFocus(media_session::mojom::AudioFocusType audio_focus_type); - void AbandonAudioFocusIfNeeded(); - - void NotifyMediaSessionMetadataChanged( - const libassistant::mojom::MediaState& status); - - base::WeakPtr<AssistantMediaSession> GetWeakPtr(); - - // Returns if the session is currently active. - bool IsSessionStateActive() const; - // Returns if the session is currently ducking. - bool IsSessionStateDucking() const; - // Returns if the session is currently suspended. - bool IsSessionStateSuspended() const; - // Returns if the session is currently inactive. - bool IsSessionStateInactive() const; - - // Returns internal audio focus id. - base::UnguessableToken internal_audio_focus_id() { - return internal_audio_focus_id_; - } - - void SetInternalAudioFocusIdForTesting(const base::UnguessableToken& token); - - private: - // Ensures that |audio_focus_ptr_| is connected. - void EnsureServiceConnection(); - - // Called by AudioFocusManager when an async audio focus request is completed. - void FinishAudioFocusRequest(media_session::mojom::AudioFocusType type); - void FinishInitialAudioFocusRequest(media_session::mojom::AudioFocusType type, - const base::UnguessableToken& request_id); - - // Sets |session_info_|, |audio_focus_type_| and notifies observers about - // the state change. - void SetAudioFocusInfo( - media_session::mojom::MediaSessionInfo::SessionState audio_focus_state, - media_session::mojom::AudioFocusType audio_focus_type); - - // Notifies mojo observers that the MediaSessionInfo has changed. - void NotifyMediaSessionInfoChanged(); - - // The current metadata associated with the current media session. - media_session::MediaMetadata metadata_; - - const raw_ptr<MediaHost> host_; - - scoped_refptr<base::SequencedTaskRunner> main_task_runner_; - // Binding for Mojo pointer to |this| held by AudioFocusManager. - mojo::Receiver<media_session::mojom::MediaSession> receiver_{this}; - - mojo::RemoteSet<media_session::mojom::MediaSessionObserver> observers_; - - // Holds a pointer to the MediaSessionService. - mojo::Remote<media_session::mojom::AudioFocusManager> audio_focus_manager_; - - // If the media session has acquired audio focus then this will contain a - // pointer to that requests AudioFocusRequestClient. - mojo::Remote<media_session::mojom::AudioFocusRequestClient> - audio_focus_request_client_; - - media_session::mojom::MediaSessionInfo session_info_; - - media_session::mojom::AudioFocusType audio_focus_type_; - - // Audio focus request Id for the internal media which is playing. - base::UnguessableToken internal_audio_focus_id_ = - base::UnguessableToken::Null(); - - base::WeakPtrFactory<AssistantMediaSession> weak_factory_{this}; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_MEDIA_SESSION_ASSISTANT_MEDIA_SESSION_H_
diff --git a/chromeos/ash/services/assistant/media_session/assistant_media_session_unittest.cc b/chromeos/ash/services/assistant/media_session/assistant_media_session_unittest.cc deleted file mode 100644 index fa330ca5..0000000 --- a/chromeos/ash/services/assistant/media_session/assistant_media_session_unittest.cc +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/media_session/assistant_media_session.h" - -#include <memory> - -#include "base/test/task_environment.h" -#include "chromeos/ash/services/assistant/media_host.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.h" -#include "chromeos/ash/services/assistant/test_support/scoped_assistant_browser_delegate.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash::assistant { - -namespace { - -using media_session::mojom::MediaSession; -using media_session::mojom::MediaSessionAction; -using media_session::mojom::MediaSessionInfo; - -} // namespace - -class AssistantMediaSessionTest : public testing::Test { - public: - AssistantMediaSessionTest() = default; - ~AssistantMediaSessionTest() override = default; - - void SetUp() override { - media_host().Initialize( - &libassistant_media_controller_, - libassistant_media_delegate_.BindNewPipeAndPassReceiver()); - } - - AssistantMediaSession* assistant_media_session() { - return &assistant_media_session_; - } - - MediaHost& media_host() { return media_host_; } - - LibassistantMediaControllerMock& libassistant_media_controller_mock() { - return libassistant_media_controller_; - } - - private: - // Needed for a test environment to support post tasks and should outlive - // other class members. - base::test::SingleThreadTaskEnvironment task_environment_; - - ScopedAssistantBrowserDelegate delegate_; - testing::StrictMock<LibassistantMediaControllerMock> - libassistant_media_controller_; - mojo::Remote<libassistant::mojom::MediaDelegate> libassistant_media_delegate_; - MediaHost media_host_{AssistantBrowserDelegate::Get(), - /*interaction_subscribers=*/nullptr}; - AssistantMediaSession assistant_media_session_{&media_host_}; -}; - -TEST_F(AssistantMediaSessionTest, ShouldUpdateSessionStateOnStartStopDucking) { - assistant_media_session()->StartDucking(); - EXPECT_TRUE(assistant_media_session()->IsSessionStateDucking()); - - assistant_media_session()->StopDucking(); - EXPECT_TRUE(assistant_media_session()->IsSessionStateActive()); -} - -TEST_F(AssistantMediaSessionTest, - ShouldUpdateSessionStateAndSendActionOnSuspendResumePlaying) { - // Suspend. - EXPECT_CALL(libassistant_media_controller_mock(), PauseInternalMediaPlayer); - assistant_media_session()->Suspend(MediaSession::SuspendType::kSystem); - EXPECT_TRUE(assistant_media_session()->IsSessionStateSuspended()); - - // Then resume. - EXPECT_CALL(libassistant_media_controller_mock(), ResumeInternalMediaPlayer); - assistant_media_session()->Resume(MediaSession::SuspendType::kSystem); - EXPECT_TRUE(assistant_media_session()->IsSessionStateActive()); - - // And pause again. - EXPECT_CALL(libassistant_media_controller_mock(), PauseInternalMediaPlayer); - assistant_media_session()->Suspend(MediaSession::SuspendType::kSystem); - EXPECT_TRUE(assistant_media_session()->IsSessionStateSuspended()); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/platform/audio_devices.cc b/chromeos/ash/services/assistant/platform/audio_devices.cc deleted file mode 100644 index 80c62307..0000000 --- a/chromeos/ash/services/assistant/platform/audio_devices.cc +++ /dev/null
@@ -1,301 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/platform/audio_devices.h" - -#include <optional> - -#include "base/memory/raw_ptr.h" -#include "base/metrics/histogram_functions.h" -#include "base/scoped_observation.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_split.h" -#include "base/strings/string_util.h" -#include "base/system/sys_info.h" -#include "chromeos/ash/components/audio/audio_device.h" -#include "chromeos/ash/components/audio/cras_audio_handler.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" - -namespace ash::assistant { - -namespace { - -constexpr const char kDefaultLocale[] = "en_us"; - -// Hotword model is expected to have <language>_<region> format with lower -// case, while the locale in pref is stored as <language>-<region> with region -// code in capital letters. So we need to convert the pref locale to the -// correct format. -// Examples: -// "fr" -> "fr_fr" -// "nl-BE" -> "nl_be" -std::optional<std::string> ToHotwordModel(std::string pref_locale) { - std::vector<std::string> code_strings = base::SplitString( - pref_locale, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - if (code_strings.size() == 0) { - // Note: I am not sure this happens during real operations, but it - // definitely happens during the ChromeOS performance tests. - return std::nullopt; - } - - DCHECK_LT(code_strings.size(), 3u); - - // For locales with language code "en", use "en_all" hotword model. - if (code_strings[0] == "en") - return "en_all"; - - // If the language code and country code happen to be the same, e.g. - // France (FR) and French (fr), the locale will be stored as "fr" instead - // of "fr-FR" in the profile on Chrome OS. - if (code_strings.size() == 1) - return code_strings[0] + "_" + code_strings[0]; - - return code_strings[0] + "_" + base::ToLowerASCII(code_strings[1]); -} - -const AudioDevice* GetHighestPriorityDevice(const AudioDevice* left, - const AudioDevice* right) { - if (!left) - return right; - if (!right) - return left; - return left->priority < right->priority ? right : left; -} - -std::optional<uint64_t> IdToOptional(const AudioDevice* device) { - if (!device) - return std::nullopt; - return device->id; -} - -std::optional<uint64_t> GetHotwordDeviceId(const AudioDeviceList& devices) { - const AudioDevice* result = nullptr; - - for (const AudioDevice& device : devices) { - if (!device.is_input) - continue; - - switch (device.type) { - case AudioDeviceType::kHotword: - result = GetHighestPriorityDevice(result, &device); - break; - default: - // ignore other devices - break; - } - } - - return IdToOptional(result); -} - -std::optional<uint64_t> GetPreferredDeviceId(const AudioDeviceList& devices) { - const AudioDevice* result = nullptr; - - for (const AudioDevice& device : devices) { - if (!device.is_input) - continue; - - switch (device.type) { - case AudioDeviceType::kMic: - case AudioDeviceType::kUsb: - case AudioDeviceType::kHeadphone: - case AudioDeviceType::kInternalMic: - case AudioDeviceType::kFrontMic: - case AudioDeviceType::kRearMic: - case AudioDeviceType::kKeyboardMic: - result = GetHighestPriorityDevice(result, &device); - break; - default: - // Ignore other devices. Note that we ignore bluetooth devices due to - // battery consumption concerns. - break; - } - } - - return IdToOptional(result); -} - -std::optional<std::string> ToString(std::optional<uint64_t> int_value) { - if (!int_value) - return std::nullopt; - return base::NumberToString(int_value.value()); -} - -} // namespace - -// Observer that will report all changes to the audio devices. -// It will unsubscribe from |CrasAudioHandler| in its destructor. -class AudioDevices::ScopedCrasAudioHandlerObserver - : private CrasAudioHandler::AudioObserver { - public: - ScopedCrasAudioHandlerObserver(CrasAudioHandler* cras_audio_handler, - AudioDevices* parent) - : parent_(parent), cras_audio_handler_(cras_audio_handler) {} - ScopedCrasAudioHandlerObserver(const ScopedCrasAudioHandlerObserver&) = - delete; - ScopedCrasAudioHandlerObserver& operator=( - const ScopedCrasAudioHandlerObserver&) = delete; - ~ScopedCrasAudioHandlerObserver() override = default; - - // Start the observer, which means it will - // - Subscribe for changes - // - Fetch the current state. - void StartObserving() { - scoped_observer_.Observe(cras_audio_handler_.get()); - FetchAudioNodes(); - } - - private: - // CrasAudioHandler::AudioObserver implementation: - void OnAudioNodesChanged() override { FetchAudioNodes(); } - - void FetchAudioNodes() { - if (!base::SysInfo::IsRunningOnChromeOS()) - return; - - AudioDeviceList audio_devices; - cras_audio_handler_->GetAudioDevices(&audio_devices); - parent_->SetAudioDevices(audio_devices); - } - - const raw_ptr<AudioDevices> parent_; - // Owned by |AssistantManagerServiceImpl|. - const raw_ptr<CrasAudioHandler> cras_audio_handler_; - base::ScopedObservation<CrasAudioHandler, CrasAudioHandler::AudioObserver> - scoped_observer_{this}; -}; - -// Sends the new hotword model to |cras_audio_handler|. If that fails this class -// will attempt to set the hotword model to |kDefaultLocale|. -class AudioDevices::HotwordModelUpdater { - public: - HotwordModelUpdater(CrasAudioHandler* cras_audio_handler, - uint64_t hotword_device, - const std::string& locale) - : cras_audio_handler_(cras_audio_handler), - hotword_device_(hotword_device), - locale_(locale) { - SendUpdate(); - } - - HotwordModelUpdater(const HotwordModelUpdater&) = delete; - HotwordModelUpdater& operator=(const HotwordModelUpdater&) = delete; - ~HotwordModelUpdater() = default; - - private: - void SendUpdate() { - std::string hotword_model = - ToHotwordModel(locale_).value_or(kDefaultLocale); - - VLOG(2) << "Changing audio hotword model of device " << hotword_device_ - << " to '" << hotword_model << "'"; - - cras_audio_handler_->SetHotwordModel( - hotword_device_, hotword_model, - base::BindOnce(&HotwordModelUpdater::SetDspHotwordLocaleCallback, - weak_factory_.GetWeakPtr(), hotword_model)); - } - - void SetDspHotwordLocaleCallback(std::string pref_locale, bool success) { - base::UmaHistogramBoolean("Assistant.SetDspHotwordLocale", success); - if (success) { - VLOG(2) << "Successfully changed audio hotword model"; - return; - } - - LOG(ERROR) << "Set " << pref_locale - << " hotword model failed, fallback to default locale."; - // Reset the locale to the default value if we failed to sync it to the - // locale stored in user's pref. - cras_audio_handler_->SetHotwordModel( - hotword_device_, /* hotword_model */ kDefaultLocale, - base::BindOnce([](bool success) { - if (!success) - LOG(ERROR) << "Reset to default hotword model failed."; - })); - } - - const raw_ptr<CrasAudioHandler> cras_audio_handler_; - uint64_t hotword_device_; - std::string locale_; - - base::WeakPtrFactory<HotwordModelUpdater> weak_factory_{this}; -}; - -AudioDevices::AudioDevices(CrasAudioHandler* cras_audio_handler, - const std::string& locale) - : cras_audio_handler_(cras_audio_handler), - locale_(locale), - scoped_cras_audio_handler_observer_( - std::make_unique<ScopedCrasAudioHandlerObserver>(cras_audio_handler, - this)) { - // Note we can only start the observer here, at the end of the constructor, - // to ensure this class is properly initialized when we receive the current - // list of audio devices. - scoped_cras_audio_handler_observer_->StartObserving(); -} - -AudioDevices::~AudioDevices() = default; - -void AudioDevices::AddAndFireObserver(Observer* observer) { - DCHECK(observer); - observers_.AddObserver(observer); - - observer->SetHotwordDeviceId(ToString(hotword_device_id_)); - observer->SetDeviceId(ToString(device_id_)); -} - -void AudioDevices::RemoveObserver(Observer* observer) { - observers_.RemoveObserver(observer); -} - -void AudioDevices::SetLocale(const std::string& locale) { - locale_ = locale; - UpdateHotwordModel(); -} - -void AudioDevices::SetAudioDevicesForTest( - const AudioDeviceList& audio_devices) { - SetAudioDevices(audio_devices); -} - -void AudioDevices::SetAudioDevices(const AudioDeviceList& devices) { - UpdateHotwordDeviceId(devices); - UpdateDeviceId(devices); - UpdateHotwordModel(); -} - -void AudioDevices::UpdateHotwordDeviceId(const AudioDeviceList& devices) { - hotword_device_id_ = GetHotwordDeviceId(devices); - - VLOG(2) << "Changed audio hotword input device to " - << ToString(hotword_device_id_).value_or("<none>"); - - for (auto& observer : observers_) - observer.SetHotwordDeviceId(ToString(hotword_device_id_)); -} - -void AudioDevices::UpdateDeviceId(const AudioDeviceList& devices) { - device_id_ = GetPreferredDeviceId(devices); - - VLOG(2) << "Changed audio input device to " - << ToString(device_id_).value_or("<none>"); - - for (auto& observer : observers_) - observer.SetDeviceId(ToString(device_id_)); -} - -void AudioDevices::UpdateHotwordModel() { - if (!hotword_device_id_) - return; - - if (!features::IsDspHotwordEnabled()) - return; - - hotword_model_updater_ = std::make_unique<HotwordModelUpdater>( - cras_audio_handler_, hotword_device_id_.value(), locale_); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/platform/audio_devices.h b/chromeos/ash/services/assistant/platform/audio_devices.h deleted file mode 100644 index a51c773..0000000 --- a/chromeos/ash/services/assistant/platform/audio_devices.h +++ /dev/null
@@ -1,105 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICES_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICES_H_ - -#include <cstdint> -#include <optional> - -#include "base/component_export.h" -#include "base/memory/raw_ptr.h" -#include "base/observer_list.h" -#include "base/scoped_observation_traits.h" -#include "chromeos/ash/components/audio/audio_device.h" - -namespace ash { - -class CrasAudioHandler; - -namespace assistant { - -// This class will monitor the available audio devices (through -// |CrasAudioHandler|), and select the devices to use for audio input (both -// regular input and hotword detection). -// When the selected devices change, this class will: -// - Inform the observers. -// - Find the hotword model to use, and send it to -// CrasAudioHandler::SetHotwordModel(). -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioDevices { - public: - class Observer : public base::CheckedObserver { - public: - ~Observer() override = default; - - // Set the input device to use for audio capture. - virtual void SetDeviceId(const std::optional<std::string>& device_id) = 0; - // Set the input device to use for hardware based hotword detection. - virtual void SetHotwordDeviceId( - const std::optional<std::string>& device_id) = 0; - }; - - AudioDevices(CrasAudioHandler* cras_audio_handler, const std::string& locale); - AudioDevices(const AudioDevices&) = delete; - AudioDevices& operator=(const AudioDevices&) = delete; - ~AudioDevices(); - - void AddAndFireObserver(Observer*); - void RemoveObserver(Observer*); - - void SetLocale(const std::string& locale); - - // Used during unittests to simulate an update to the list of available audio - // devices. - void SetAudioDevicesForTest(const AudioDeviceList& audio_devices); - - private: - class ScopedCrasAudioHandlerObserver; - class HotwordModelUpdater; - - void SetAudioDevices(const AudioDeviceList& audio_devices); - void UpdateHotwordDeviceId(const AudioDeviceList& devices); - void UpdateDeviceId(const AudioDeviceList& devices); - void UpdateHotwordModel(); - - // Handles the asynchronous nature of sending a new hotword model to - // |cras_audio_handler_|. - std::unique_ptr<HotwordModelUpdater> hotword_model_updater_; - - base::ObserverList<Observer> observers_; - - // Owned by |AssistantManagerServiceImpl|. - const raw_ptr<CrasAudioHandler> cras_audio_handler_; - - std::string locale_; - std::optional<uint64_t> hotword_device_id_; - std::optional<uint64_t> device_id_; - - // Observes changes to the available audio devices, and sends the list of - // devices to SetAudioDevices(). - std::unique_ptr<ScopedCrasAudioHandlerObserver> - scoped_cras_audio_handler_observer_; -}; - -} // namespace assistant -} // namespace ash - -namespace base { - -template <> -struct ScopedObservationTraits<ash::assistant::AudioDevices, - ash::assistant::AudioDevices::Observer> { - static void AddObserver(ash::assistant::AudioDevices* source, - ash::assistant::AudioDevices::Observer* observer) { - source->AddAndFireObserver(observer); - } - static void RemoveObserver(ash::assistant::AudioDevices* source, - ash::assistant::AudioDevices::Observer* observer) { - source->RemoveObserver(observer); - } -}; - -} // namespace base - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICES_H_
diff --git a/chromeos/ash/services/assistant/platform/audio_devices_unittest.cc b/chromeos/ash/services/assistant/platform/audio_devices_unittest.cc deleted file mode 100644 index a5b2982a..0000000 --- a/chromeos/ash/services/assistant/platform/audio_devices_unittest.cc +++ /dev/null
@@ -1,433 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/platform/audio_devices.h" - -#include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" -#include "chromeos/ash/components/audio/audio_device.h" -#include "chromeos/ash/components/audio/cras_audio_handler.h" -#include "chromeos/ash/components/dbus/audio/fake_cras_audio_client.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash::assistant { - -namespace { - -using ::testing::_; - -constexpr const char kDefaultLocale[] = "en_us"; - -class FakeAudioDevicesObserver : public AudioDevices::Observer { - public: - FakeAudioDevicesObserver() = default; - FakeAudioDevicesObserver(const FakeAudioDevicesObserver&) = delete; - FakeAudioDevicesObserver& operator=(const FakeAudioDevicesObserver&) = delete; - ~FakeAudioDevicesObserver() override = default; - - // AudioDevices::Observer implementation - void SetDeviceId(const std::optional<std::string>& device_id) override { - preferred_device_id_ = device_id; - } - void SetHotwordDeviceId( - const std::optional<std::string>& device_id) override { - hotword_device_id_ = device_id; - } - - std::string preferred_device_id() { - return preferred_device_id_.value_or("<none>"); - } - - std::string hotword_device_id() { - return hotword_device_id_.value_or("<none>"); - } - - private: - std::optional<std::string> preferred_device_id_; - std::optional<std::string> hotword_device_id_; -}; - -class DeviceBuilder { - public: - explicit DeviceBuilder(AudioDeviceType type) { - result_.type = type; - result_.is_input = true; - } - DeviceBuilder(const DeviceBuilder&) = delete; - DeviceBuilder& operator=(const DeviceBuilder&) = delete; - ~DeviceBuilder() = default; - - DeviceBuilder& WithId(int id) { - result_.id = id; - return *this; - } - - DeviceBuilder& WithPriority(int priority) { - result_.priority = priority; - return *this; - } - - DeviceBuilder& WithIsInput(bool is_input) { - result_.is_input = is_input; - return *this; - } - - AudioDevice Build() const { return result_; } - - private: - AudioDevice result_; -}; - -// Mock for |CrosAudioClient|. This inherits from |FakeCrasAudioClient| so we -// only have to mock the methods we're interested in. -// It will automatically be installed as the global singleton in its -// constructor, and removed in the destructor. -class ScopedCrasAudioClientMock : public FakeCrasAudioClient { - public: - ScopedCrasAudioClientMock() = default; - ScopedCrasAudioClientMock(ScopedCrasAudioClientMock&) = delete; - ScopedCrasAudioClientMock& operator=(ScopedCrasAudioClientMock&) = delete; - ~ScopedCrasAudioClientMock() override = default; - - MOCK_METHOD(void, - SetHotwordModel, - (uint64_t node_id, - const std::string& hotword_model, - chromeos::VoidDBusMethodCallback callback)); -}; - -class ScopedCrasAudioHandler { - public: - ScopedCrasAudioHandler() { CrasAudioHandler::InitializeForTesting(); } - ScopedCrasAudioHandler(const ScopedCrasAudioHandler&) = delete; - ScopedCrasAudioHandler& operator=(const ScopedCrasAudioHandler&) = delete; - ~ScopedCrasAudioHandler() { CrasAudioHandler::Shutdown(); } - - CrasAudioHandler* Get() { return CrasAudioHandler::Get(); } -}; - -} // namespace - -class AssistantAudioDevicesTest : public testing::Test { - public: - AssistantAudioDevicesTest() - : audio_devices_(cras_audio_handler_.Get(), "pref-locale") { - // Enable DSP feature flag. - scoped_feature_list_.InitAndEnableFeature(features::kEnableDspHotword); - } - - AssistantAudioDevicesTest(const AssistantAudioDevicesTest&) = delete; - AssistantAudioDevicesTest& operator=(const AssistantAudioDevicesTest&) = - delete; - ~AssistantAudioDevicesTest() override = default; - - AudioDevices& audio_devices() { return audio_devices_; } - - ScopedCrasAudioClientMock& cras_audio_client_mock() { - return cras_audio_client_mock_; - } - - void UpdateDeviceList(const AudioDeviceList& devices) { - audio_devices().SetAudioDevicesForTest(devices); - } - - private: - base::test::TaskEnvironment task_environment_; - base::test::ScopedFeatureList scoped_feature_list_; - testing::NiceMock<ScopedCrasAudioClientMock> cras_audio_client_mock_; - ScopedCrasAudioHandler cras_audio_handler_; - AudioDevices audio_devices_; -}; - -TEST_F(AssistantAudioDevicesTest, ShouldSendHotwordDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList( - {DeviceBuilder(AudioDeviceType::kHotword).WithId(111).Build()}); - - EXPECT_EQ("111", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendMicDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({DeviceBuilder(AudioDeviceType::kMic).WithId(221).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("221", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendUsbDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({DeviceBuilder(AudioDeviceType::kUsb).WithId(222).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("222", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendHeadphonesDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList( - {DeviceBuilder(AudioDeviceType::kHeadphone).WithId(333).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("333", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendInternalMicDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList( - {DeviceBuilder(AudioDeviceType::kInternalMic).WithId(444).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("444", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendFrontMicDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList( - {DeviceBuilder(AudioDeviceType::kFrontMic).WithId(555).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("555", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendRearMicDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList( - {DeviceBuilder(AudioDeviceType::kRearMic).WithId(666).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("666", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldSendKeyboardMicDeviceToObserver) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList( - {DeviceBuilder(AudioDeviceType::kKeyboardMic).WithId(777).Build()}); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("777", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldUseHighestPriorityHotwordDevice) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AudioDeviceType::kHotword) - .WithId(111) - .WithPriority(1) - .Build(), - DeviceBuilder(AudioDeviceType::kHotword) - .WithId(555) - .WithPriority(5) - .Build(), - DeviceBuilder(AudioDeviceType::kHotword) - .WithId(222) - .WithPriority(2) - .Build(), - }); - - EXPECT_EQ("555", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldIgnoreNonInputHotwordDevices) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AudioDeviceType::kHotword) - .WithId(111) - .WithIsInput(false) - .Build(), - DeviceBuilder(AudioDeviceType::kHotword) - .WithId(222) - .WithIsInput(true) - .Build(), - DeviceBuilder(AudioDeviceType::kHotword) - .WithId(333) - .WithIsInput(false) - .Build(), - }); - - EXPECT_EQ("222", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldUseHighestPriorityDevice) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AudioDeviceType::kUsb).WithId(111).WithPriority(1).Build(), - DeviceBuilder(AudioDeviceType::kUsb).WithId(555).WithPriority(5).Build(), - DeviceBuilder(AudioDeviceType::kUsb).WithId(222).WithPriority(2).Build(), - }); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("555", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldIgnoreNonInputDevices) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AudioDeviceType::kUsb) - .WithId(111) - .WithIsInput(false) - .Build(), - DeviceBuilder(AudioDeviceType::kUsb) - .WithId(222) - .WithIsInput(true) - .Build(), - DeviceBuilder(AudioDeviceType::kUsb) - .WithId(333) - .WithIsInput(false) - .Build(), - }); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("222", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldIgnoreUnsupportedDeviceTypes) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AudioDeviceType::kBluetooth).WithId(2).Build(), - DeviceBuilder(AudioDeviceType::kBluetoothNbMic).WithId(3).Build(), - DeviceBuilder(AudioDeviceType::kHdmi).WithId(4).Build(), - DeviceBuilder(AudioDeviceType::kInternalSpeaker).WithId(5).Build(), - DeviceBuilder(AudioDeviceType::kLineout).WithId(8).Build(), - DeviceBuilder(AudioDeviceType::kPostMixLoopback).WithId(9).Build(), - DeviceBuilder(AudioDeviceType::kPostDspLoopback).WithId(10).Build(), - DeviceBuilder(AudioDeviceType::kAlsaLoopback).WithId(11).Build(), - DeviceBuilder(AudioDeviceType::kOther).WithId(12).Build(), - }); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldFireObserverWhenAdded) { - UpdateDeviceList({ - DeviceBuilder(AudioDeviceType::kHotword).WithId(111).Build(), - DeviceBuilder(AudioDeviceType::kUsb).WithId(222).Build(), - }); - - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - - EXPECT_EQ("111", observer.hotword_device_id()); - EXPECT_EQ("222", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, ShouldNotFireObserverAfterItsRemoved) { - FakeAudioDevicesObserver observer; - audio_devices().AddAndFireObserver(&observer); - audio_devices().RemoveObserver(&observer); - - UpdateDeviceList({ - DeviceBuilder(AudioDeviceType::kHotword).WithId(111).Build(), - DeviceBuilder(AudioDeviceType::kUsb).WithId(222).Build(), - }); - - EXPECT_EQ("<none>", observer.hotword_device_id()); - EXPECT_EQ("<none>", observer.preferred_device_id()); -} - -TEST_F(AssistantAudioDevicesTest, - ShouldUpdateHotwordModelWhenHotwordDeviceIsAdded) { - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel); - - UpdateDeviceList({DeviceBuilder(AudioDeviceType::kHotword).Build()}); -} - -TEST_F(AssistantAudioDevicesTest, ShouldFormatLocaleToHotwordModel) { - UpdateDeviceList( - {DeviceBuilder(AudioDeviceType::kHotword).WithId(111).Build()}); - - // Normal case - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "nl_be", _)); - audio_devices().SetLocale("nl-BE"); - base::RunLoop().RunUntilIdle(); - - // Handle the case where country code and language code are the same - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "fr_fr", _)); - audio_devices().SetLocale("fr"); - base::RunLoop().RunUntilIdle(); - - // use "en_all" for all english locales - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(111, "en_all", _)); - audio_devices().SetLocale("en-US"); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(AssistantAudioDevicesTest, ShouldUseDefaultLocaleIfUserPrefIsRejected) { - UpdateDeviceList( - {DeviceBuilder(AudioDeviceType::kHotword).WithId(222).Build()}); - - EXPECT_CALL(cras_audio_client_mock(), - SetHotwordModel(_, "rejected_locale", _)) - .WillOnce([](uint64_t node_id, const std::string&, - chromeos::VoidDBusMethodCallback callback) { - // Report failure to change the locale - std::move(callback).Run(/*success=*/false); - }); - - EXPECT_CALL(cras_audio_client_mock(), - SetHotwordModel(222, kDefaultLocale, _)); - - audio_devices().SetLocale("rejected-LOCALE"); -} - -TEST_F(AssistantAudioDevicesTest, ShouldUseDefaultLocaleIfUserPrefIsEmpty) { - UpdateDeviceList({DeviceBuilder(AudioDeviceType::kHotword).Build()}); - - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(_, kDefaultLocale, _)); - - audio_devices().SetLocale(""); -} - -TEST_F(AssistantAudioDevicesTest, ShouldDoNothingIfUserPrefIsAccepted) { - UpdateDeviceList({DeviceBuilder(AudioDeviceType::kHotword).Build()}); - - EXPECT_CALL(cras_audio_client_mock(), - SetHotwordModel(_, "accepted_locale", _)) - .WillOnce([](uint64_t node_id, const std::string&, - chromeos::VoidDBusMethodCallback callback) { - // Accept the change to the locale. - std::move(callback).Run(/*success=*/true); - }); - - // Do not expect a second call if change of locale is accepted - EXPECT_CALL(cras_audio_client_mock(), SetHotwordModel(_, kDefaultLocale, _)) - .Times(0); - - audio_devices().SetLocale("accepted-LOCALE"); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/platform/audio_input_host.h b/chromeos/ash/services/assistant/platform/audio_input_host.h deleted file mode 100644 index bb3c023b..0000000 --- a/chromeos/ash/services/assistant/platform/audio_input_host.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_ - -namespace ash::assistant { - -// Class that provides the bridge between the ChromeOS UI thread and the -// Libassistant audio input class. -class AudioInputHost { - public: - virtual ~AudioInputHost() = default; - - // Called when the mic state associated with the interaction is changed. - virtual void SetMicState(bool mic_open) = 0; - - // Called when hotword enabled status changed. - virtual void OnHotwordEnabled(bool enable) = 0; - - virtual void OnConversationTurnStarted() = 0; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_H_
diff --git a/chromeos/ash/services/assistant/platform/audio_input_host_impl.cc b/chromeos/ash/services/assistant/platform/audio_input_host_impl.cc deleted file mode 100644 index 8002d25..0000000 --- a/chromeos/ash/services/assistant/platform/audio_input_host_impl.cc +++ /dev/null
@@ -1,97 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/platform/audio_input_host_impl.h" - -#include <optional> - -#include "base/check.h" -#include "chromeos/ash/services/assistant/platform/audio_devices.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" - -namespace ash::assistant { - -namespace { - -using MojomLidState = libassistant::mojom::LidState; - -MojomLidState ConvertLidState(chromeos::PowerManagerClient::LidState state) { - switch (state) { - case chromeos::PowerManagerClient::LidState::CLOSED: - return MojomLidState::kClosed; - case chromeos::PowerManagerClient::LidState::OPEN: - return MojomLidState::kOpen; - case chromeos::PowerManagerClient::LidState::NOT_PRESENT: - // If there is no lid, it can't be closed. - return MojomLidState::kOpen; - } -} - -} // namespace - -AudioInputHostImpl::AudioInputHostImpl( - mojo::PendingRemote<libassistant::mojom::AudioInputController> - pending_remote, - CrasAudioHandler* cras_audio_handler, - chromeos::PowerManagerClient* power_manager_client, - const std::string& locale) - : remote_(std::move(pending_remote)), - power_manager_client_(power_manager_client), - power_manager_client_observer_(this), - audio_devices_(cras_audio_handler, locale) { - DCHECK(power_manager_client_); - - audio_devices_observation_.Observe(&audio_devices_); - power_manager_client_observer_.Observe(power_manager_client_.get()); - power_manager_client_->GetSwitchStates( - base::BindOnce(&AudioInputHostImpl::OnInitialLidStateReceived, - weak_factory_.GetWeakPtr())); -} - -AudioInputHostImpl::~AudioInputHostImpl() = default; - -void AudioInputHostImpl::SetMicState(bool mic_open) { - remote_->SetMicOpen(mic_open); -} - -void AudioInputHostImpl::SetDeviceId( - const std::optional<std::string>& device_id) { - remote_->SetDeviceId(device_id); -} - -void AudioInputHostImpl::OnConversationTurnStarted() { - remote_->OnConversationTurnStarted(); - // Inform power manager of a wake notification when Libassistant - // recognized hotword and started a conversation. We intentionally - // avoid using |NotifyUserActivity| because it is not suitable for - // this case according to the Platform team. - power_manager_client_->NotifyWakeNotification(); -} - -void AudioInputHostImpl::OnHotwordEnabled(bool enable) { - remote_->SetHotwordEnabled(enable); -} - -void AudioInputHostImpl::SetHotwordDeviceId( - const std::optional<std::string>& device_id) { - remote_->SetHotwordDeviceId(device_id); -} - -void AudioInputHostImpl::LidEventReceived( - chromeos::PowerManagerClient::LidState state, - base::TimeTicks timestamp) { - // Lid switch event still gets fired during system suspend, which enables - // us to stop DSP recording correctly when user closes lid after the device - // goes to sleep. - remote_->SetLidState(ConvertLidState(state)); -} - -void AudioInputHostImpl::OnInitialLidStateReceived( - std::optional<chromeos::PowerManagerClient::SwitchStates> switch_states) { - if (switch_states.has_value()) - remote_->SetLidState(ConvertLidState(switch_states->lid_state)); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/platform/audio_input_host_impl.h b/chromeos/ash/services/assistant/platform/audio_input_host_impl.h deleted file mode 100644 index 10d6708..0000000 --- a/chromeos/ash/services/assistant/platform/audio_input_host_impl.h +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_ - -#include <optional> -#include <string> - -#include "base/component_export.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/scoped_observation.h" -#include "base/time/time.h" -#include "chromeos/ash/services/assistant/platform/audio_devices.h" -#include "chromeos/ash/services/assistant/platform/audio_input_host.h" -#include "chromeos/ash/services/libassistant/public/mojom/audio_input_controller.mojom.h" -#include "chromeos/dbus/power/power_manager_client.h" -#include "mojo/public/cpp/bindings/remote.h" - -namespace ash::assistant { - -// Class that provides the bridge between the ChromeOS Browser thread and the -// Libassistant audio input mojom service. -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioInputHostImpl - : public AudioInputHost, - private chromeos::PowerManagerClient::Observer, - private AudioDevices::Observer { - public: - AudioInputHostImpl( - mojo::PendingRemote<libassistant::mojom::AudioInputController> - pending_remote, - CrasAudioHandler* cras_audio_handler, - chromeos::PowerManagerClient* power_manager_client, - const std::string& locale); - AudioInputHostImpl(const AudioInputHost&) = delete; - AudioInputHostImpl& operator=(const AudioInputHostImpl&) = delete; - ~AudioInputHostImpl() override; - - // AudioInputHost implementation: - void SetMicState(bool mic_open) override; - void OnHotwordEnabled(bool enable) override; - void OnConversationTurnStarted() override; - - // AudioDevices::Observer implementation: - void SetDeviceId(const std::optional<std::string>& device_id) override; - void SetHotwordDeviceId(const std::optional<std::string>& device_id) override; - - private: - // chromeos::PowerManagerClient::Observer overrides: - void LidEventReceived(chromeos::PowerManagerClient::LidState state, - base::TimeTicks timestamp) override; - - void OnInitialLidStateReceived( - std::optional<chromeos::PowerManagerClient::SwitchStates> switch_states); - - mojo::Remote<libassistant::mojom::AudioInputController> remote_; - const raw_ptr<chromeos::PowerManagerClient> power_manager_client_; - base::ScopedObservation<chromeos::PowerManagerClient, - chromeos::PowerManagerClient::Observer> - power_manager_client_observer_; - - // Observes available audio devices and will set device-id/hotword-device-id - // accordingly. - AudioDevices audio_devices_; - base::ScopedObservation<AudioDevices, AudioDevices::Observer> - audio_devices_observation_{this}; - - base::WeakPtrFactory<AudioInputHostImpl> weak_factory_{this}; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_INPUT_HOST_IMPL_H_
diff --git a/chromeos/ash/services/assistant/platform/audio_input_host_unittest.cc b/chromeos/ash/services/assistant/platform/audio_input_host_unittest.cc deleted file mode 100644 index 7c37ec88..0000000 --- a/chromeos/ash/services/assistant/platform/audio_input_host_unittest.cc +++ /dev/null
@@ -1,228 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <optional> - -#include "base/run_loop.h" -#include "base/test/mock_callback.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" -#include "chromeos/ash/components/audio/cras_audio_handler.h" -#include "chromeos/ash/services/assistant/platform/audio_input_host_impl.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/libassistant/public/mojom/audio_input_controller.mojom.h" -#include "chromeos/dbus/power/fake_power_manager_client.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash::assistant { - -namespace { - -using LidState = chromeos::PowerManagerClient::LidState; -using MojomLidState = libassistant::mojom::LidState; -using MojomAudioInputController = libassistant::mojom::AudioInputController; -using ::testing::_; -using ::testing::NiceMock; - -class AudioInputControllerMock : public MojomAudioInputController { - public: - AudioInputControllerMock() = default; - AudioInputControllerMock(const AudioInputControllerMock&) = delete; - AudioInputControllerMock& operator=(const AudioInputControllerMock&) = delete; - ~AudioInputControllerMock() override = default; - - mojo::PendingRemote<MojomAudioInputController> BindNewPipeAndPassRemote() { - receiver_.reset(); - return receiver_.BindNewPipeAndPassRemote(); - } - - MOCK_METHOD(void, SetMicOpen, (bool mic_open)); - MOCK_METHOD(void, SetHotwordEnabled, (bool enable)); - MOCK_METHOD(void, SetDeviceId, (const std::optional<std::string>& device_id)); - MOCK_METHOD(void, - SetHotwordDeviceId, - (const std::optional<std::string>& device_id)); - MOCK_METHOD(void, SetLidState, (MojomLidState new_state)); - MOCK_METHOD(void, OnConversationTurnStarted, ()); - - private: - mojo::Receiver<MojomAudioInputController> receiver_{this}; -}; - -class AssistantAudioInputHostTest : public testing::Test { - public: - AssistantAudioInputHostTest() { - chromeos::PowerManagerClient::InitializeFake(); - } - - AssistantAudioInputHostTest(const AssistantAudioInputHostTest&) = delete; - AssistantAudioInputHostTest& operator=(const AssistantAudioInputHostTest&) = - delete; - ~AssistantAudioInputHostTest() override { - // |audio_input_host_| uses the fake power manager client, so must be - // destroyed before the power manager client. - audio_input_host_.reset(); - chromeos::PowerManagerClient::Shutdown(); - } - - void SetUp() override { - // Enable DSP Hotword - scoped_feature_list_.InitAndEnableFeature(features::kEnableDspHotword); - - CreateNewAudioInputHost(); - } - - AudioInputControllerMock& mojom_audio_input_controller() { - return audio_input_controller_; - } - - AudioInputHostImpl& audio_input_host() { - CHECK(audio_input_host_); - return *audio_input_host_; - } - - void CreateNewAudioInputHost() { - audio_input_host_ = std::make_unique<AudioInputHostImpl>( - audio_input_controller_.BindNewPipeAndPassRemote(), - &cras_audio_handler_.Get(), chromeos::FakePowerManagerClient::Get(), - "default-locale"); - - FlushPendingMojomCalls(); - } - - void DestroyAudioInputHost() { audio_input_host_ = nullptr; } - - void ReportLidEvent(LidState state) { - chromeos::FakePowerManagerClient::Get()->SetLidState( - state, base::TimeTicks::UnixEpoch()); - FlushPendingMojomCalls(); - } - - void SetLidState(LidState state) { ReportLidEvent(state); } - - void SetDeviceId(const std::optional<std::string>& device_id) { - audio_input_host().SetDeviceId(device_id); - FlushPendingMojomCalls(); - } - - void SetHotwordDeviceId(const std::optional<std::string>& device_id) { - audio_input_host().SetHotwordDeviceId(device_id); - FlushPendingMojomCalls(); - } - - void OnHotwordEnabled(bool enabled) { - audio_input_host().OnHotwordEnabled(enabled); - FlushPendingMojomCalls(); - } - - void SetMicState(bool mic_open) { - audio_input_host().SetMicState(mic_open); - FlushPendingMojomCalls(); - } - - void OnConversationTurnStarted() { - audio_input_host().OnConversationTurnStarted(); - FlushPendingMojomCalls(); - } - - void FlushPendingMojomCalls() { base::RunLoop().RunUntilIdle(); } - - private: - base::test::TaskEnvironment task_environment_; - base::test::ScopedFeatureList scoped_feature_list_; - ScopedCrasAudioHandlerForTesting cras_audio_handler_; - NiceMock<AudioInputControllerMock> audio_input_controller_; - std::unique_ptr<AudioInputHostImpl> audio_input_host_; -}; - -} // namespace - -TEST_F(AssistantAudioInputHostTest, ShouldSendLidOpenEventsToMojom) { - EXPECT_CALL(mojom_audio_input_controller(), - SetLidState(MojomLidState::kOpen)); - ReportLidEvent(LidState::OPEN); -} - -TEST_F(AssistantAudioInputHostTest, ShouldSendLidClosedEventsToMojom) { - EXPECT_CALL(mojom_audio_input_controller(), - SetLidState(MojomLidState::kClosed)); - ReportLidEvent(LidState::CLOSED); -} - -TEST_F(AssistantAudioInputHostTest, ShouldSendLidNotPresentEventsToMojom) { - // If there is no lid it can not be closed by the user so we consider it to be - // open. - EXPECT_CALL(mojom_audio_input_controller(), - SetLidState(MojomLidState::kOpen)); - ReportLidEvent(LidState::NOT_PRESENT); -} - -TEST_F(AssistantAudioInputHostTest, ShouldReadCurrentLidStateWhenLaunching) { - DestroyAudioInputHost(); - SetLidState(LidState::OPEN); - EXPECT_CALL(mojom_audio_input_controller(), - SetLidState(MojomLidState::kOpen)); - CreateNewAudioInputHost(); - - DestroyAudioInputHost(); - SetLidState(LidState::CLOSED); - EXPECT_CALL(mojom_audio_input_controller(), - SetLidState(MojomLidState::kClosed)); - CreateNewAudioInputHost(); -} - -TEST_F(AssistantAudioInputHostTest, ShouldSendDeviceIdToMojom) { - EXPECT_CALL(mojom_audio_input_controller(), - SetDeviceId(std::optional<std::string>("device-id"))); - SetDeviceId("device-id"); -} - -TEST_F(AssistantAudioInputHostTest, ShouldUnsetDeviceIdWhenItsEmpty) { - // Note this variable is required as directly passing std::nullopt into the - // EXPECT_CALL doesn't compile. - const std::optional<std::string> expected = std::nullopt; - EXPECT_CALL(mojom_audio_input_controller(), SetDeviceId(expected)); - - SetDeviceId(std::nullopt); -} - -TEST_F(AssistantAudioInputHostTest, ShouldSendHotwordDeviceIdToMojom) { - EXPECT_CALL( - mojom_audio_input_controller(), - SetHotwordDeviceId(std::optional<std::string>("hotword-device-id"))); - SetHotwordDeviceId("hotword-device-id"); -} - -TEST_F(AssistantAudioInputHostTest, ShouldUnsetHotwordDeviceIdWhenItsEmpty) { - // Note this variable is required as directly passing std::nullopt into the - // EXPECT_CALL doesn't compile. - const std::optional<std::string> expected = std::nullopt; - EXPECT_CALL(mojom_audio_input_controller(), SetHotwordDeviceId(expected)); - - SetHotwordDeviceId(std::nullopt); -} -TEST_F(AssistantAudioInputHostTest, ShouldSendHotwordEnabledToMojom) { - EXPECT_CALL(mojom_audio_input_controller(), SetHotwordEnabled(true)); - OnHotwordEnabled(true); - - EXPECT_CALL(mojom_audio_input_controller(), SetHotwordEnabled(false)); - OnHotwordEnabled(false); -} - -TEST_F(AssistantAudioInputHostTest, ShouldSendMicOpenToMojom) { - EXPECT_CALL(mojom_audio_input_controller(), SetMicOpen(true)); - SetMicState(/*mic_open=*/true); - - EXPECT_CALL(mojom_audio_input_controller(), SetMicOpen(false)); - SetMicState(/*mic_open=*/false); -} - -TEST_F(AssistantAudioInputHostTest, - ShouldSendOnConversationTurnStartedToMojom) { - EXPECT_CALL(mojom_audio_input_controller(), OnConversationTurnStarted); - OnConversationTurnStarted(); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/platform/audio_output_delegate_impl.cc b/chromeos/ash/services/assistant/platform/audio_output_delegate_impl.cc deleted file mode 100644 index 2045798..0000000 --- a/chromeos/ash/services/assistant/platform/audio_output_delegate_impl.cc +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/platform/audio_output_delegate_impl.h" -#include "chromeos/ash/services/assistant/media_session/assistant_media_session.h" - -namespace ash::assistant { - -AudioOutputDelegateImpl::AudioOutputDelegateImpl( - AssistantMediaSession* media_session) - : media_session_(media_session) {} - -AudioOutputDelegateImpl::~AudioOutputDelegateImpl() = default; - -void AudioOutputDelegateImpl::Bind( - mojo::PendingReceiver<AudioOutputDelegate> pending_receiver) { - receiver_.Bind(std::move(pending_receiver)); -} - -void AudioOutputDelegateImpl::Stop() { - receiver_.reset(); -} - -void AudioOutputDelegateImpl::RequestAudioFocus( - libassistant::mojom::AudioOutputStreamType stream_type) { - // TODO(wutao): Fix the libassistant behavior. - // Currently this is called with |STREAM_TTS| and |STREAM_ALARM| when - // requesting focus. When releasing focus it calls with |STREAM_MEDIA|. - // libassistant media code path does not request focus. - switch (stream_type) { - case libassistant::mojom::AudioOutputStreamType::kAlarmStream: - media_session_->RequestAudioFocus( - media_session::mojom::AudioFocusType::kGainTransientMayDuck); - break; - case libassistant::mojom::AudioOutputStreamType::kTtsStream: - media_session_->RequestAudioFocus( - media_session::mojom::AudioFocusType::kGainTransient); - break; - case libassistant::mojom::AudioOutputStreamType::kMediaStream: - media_session_->AbandonAudioFocusIfNeeded(); - break; - } -} - -void AudioOutputDelegateImpl::AbandonAudioFocusIfNeeded() { - media_session_->AbandonAudioFocusIfNeeded(); -} - -void AudioOutputDelegateImpl::AddMediaSessionObserver( - mojo::PendingRemote<::media_session::mojom::MediaSessionObserver> - observer) { - media_session_->AddObserver(std::move(observer)); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/platform/audio_output_delegate_impl.h b/chromeos/ash/services/assistant/platform/audio_output_delegate_impl.h deleted file mode 100644 index 59450826..0000000 --- a/chromeos/ash/services/assistant/platform/audio_output_delegate_impl.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_OUTPUT_DELEGATE_IMPL_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_OUTPUT_DELEGATE_IMPL_H_ - -#include "base/memory/raw_ptr.h" -#include "chromeos/ash/services/libassistant/public/mojom/audio_output_delegate.mojom.h" - -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver.h" - -namespace ash::assistant { - -class AssistantMediaSession; - -class AudioOutputDelegateImpl - : public libassistant::mojom::AudioOutputDelegate { - public: - explicit AudioOutputDelegateImpl(AssistantMediaSession* media_session); - AudioOutputDelegateImpl(const AudioOutputDelegateImpl&) = delete; - AudioOutputDelegateImpl& operator=(const AudioOutputDelegateImpl&) = delete; - ~AudioOutputDelegateImpl() override; - - void Bind(mojo::PendingReceiver<AudioOutputDelegate> pending_receiver); - void Stop(); - - // libassistant::mojom::AudioOutputDelegate implementation: - void RequestAudioFocus( - libassistant::mojom::AudioOutputStreamType stream_type) override; - void AbandonAudioFocusIfNeeded() override; - void AddMediaSessionObserver( - mojo::PendingRemote<::media_session::mojom::MediaSessionObserver> - observer) override; - - private: - mojo::Receiver<AudioOutputDelegate> receiver_{this}; - const raw_ptr<AssistantMediaSession> media_session_; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_AUDIO_OUTPUT_DELEGATE_IMPL_H_
diff --git a/chromeos/ash/services/assistant/platform/platform_delegate_impl.cc b/chromeos/ash/services/assistant/platform/platform_delegate_impl.cc deleted file mode 100644 index bd214d3..0000000 --- a/chromeos/ash/services/assistant/platform/platform_delegate_impl.cc +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/platform/platform_delegate_impl.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" - -namespace ash::assistant { - -PlatformDelegateImpl::~PlatformDelegateImpl() = default; -PlatformDelegateImpl::PlatformDelegateImpl() = default; - -void PlatformDelegateImpl::Bind( - mojo::PendingReceiver<PlatformDelegate> pending_receiver) { - receiver_.Bind(std::move(pending_receiver)); -} - -void PlatformDelegateImpl::Stop() { - receiver_.reset(); -} - -void PlatformDelegateImpl::BindAudioStreamFactory( - mojo::PendingReceiver<media::mojom::AudioStreamFactory> receiver) { - AssistantBrowserDelegate::Get()->RequestAudioStreamFactory( - std::move(receiver)); -} - -void PlatformDelegateImpl::BindAudioDecoderFactory( - mojo::PendingReceiver<mojom::AssistantAudioDecoderFactory> receiver) { - AssistantBrowserDelegate::Get()->RequestAudioDecoderFactory( - std::move(receiver)); -} - -void PlatformDelegateImpl::BindBatteryMonitor( - mojo::PendingReceiver<::device::mojom::BatteryMonitor> receiver) { - AssistantBrowserDelegate::Get()->RequestBatteryMonitor(std::move(receiver)); -} - -void PlatformDelegateImpl::BindNetworkConfig( - mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig> - receiver) { - AssistantBrowserDelegate::Get()->RequestNetworkConfig(std::move(receiver)); -} - -void PlatformDelegateImpl::BindAssistantVolumeControl( - mojo::PendingReceiver<::ash::mojom::AssistantVolumeControl> receiver) { - AssistantBrowserDelegate::Get()->RequestAssistantVolumeControl( - std::move(receiver)); -} - -void PlatformDelegateImpl::BindWakeLockProvider( - mojo::PendingReceiver<::device::mojom::WakeLockProvider> receiver) { - AssistantBrowserDelegate::Get()->RequestWakeLockProvider(std::move(receiver)); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/platform/platform_delegate_impl.h b/chromeos/ash/services/assistant/platform/platform_delegate_impl.h deleted file mode 100644 index 3372099..0000000 --- a/chromeos/ash/services/assistant/platform/platform_delegate_impl.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_PLATFORM_DELEGATE_IMPL_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_PLATFORM_DELEGATE_IMPL_H_ - -#include "chromeos/ash/services/libassistant/public/mojom/platform_delegate.mojom.h" -#include "mojo/public/cpp/bindings/receiver.h" - -namespace ash::assistant { - -// Delegate that will fetch all instances from the |AssistantBrowserDelegate|. -class PlatformDelegateImpl : public libassistant::mojom::PlatformDelegate { - public: - PlatformDelegateImpl(); - PlatformDelegateImpl(const PlatformDelegateImpl&) = delete; - PlatformDelegateImpl& operator=(const PlatformDelegateImpl&) = delete; - ~PlatformDelegateImpl() override; - - void Bind(mojo::PendingReceiver<PlatformDelegate> pending_receiver); - void Stop(); - - // libassistant::mojom::PlatformDelegate implementation: - void BindAudioStreamFactory( - mojo::PendingReceiver<media::mojom::AudioStreamFactory> receiver) - override; - void BindAudioDecoderFactory( - mojo::PendingReceiver<assistant::mojom::AssistantAudioDecoderFactory> - receiver) override; - void BindBatteryMonitor( - mojo::PendingReceiver<::device::mojom::BatteryMonitor> receiver) override; - void BindNetworkConfig( - mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig> - receiver) override; - void BindAssistantVolumeControl( - mojo::PendingReceiver<::ash::mojom::AssistantVolumeControl> receiver) - override; - void BindWakeLockProvider( - mojo::PendingReceiver<::device::mojom::WakeLockProvider> receiver) - override; - - private: - mojo::Receiver<PlatformDelegate> receiver_{this}; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_PLATFORM_PLATFORM_DELEGATE_IMPL_H_
diff --git a/chromeos/ash/services/assistant/service.cc b/chromeos/ash/services/assistant/service.cc deleted file mode 100644 index 53d115e..0000000 --- a/chromeos/ash/services/assistant/service.cc +++ /dev/null
@@ -1,812 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/service.h" - -#include <algorithm> -#include <memory> -#include <optional> -#include <utility> - -#include "ash/constants/ash_features.h" -#include "ash/constants/ash_switches.h" -#include "ash/public/cpp/assistant/assistant_state.h" -#include "ash/public/cpp/assistant/controller/assistant_alarm_timer_controller.h" -#include "ash/public/cpp/assistant/controller/assistant_controller.h" -#include "ash/public/cpp/assistant/controller/assistant_notification_controller.h" -#include "ash/public/cpp/session/session_controller.h" -#include "base/command_line.h" -#include "base/functional/bind.h" -#include "base/logging.h" -#include "base/memory/raw_ptr.h" -#include "base/metrics/histogram_functions.h" -#include "base/rand_util.h" -#include "base/task/sequenced_task_runner.h" -#include "base/task/single_thread_task_runner.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "build/buildflag.h" -#include "chromeos/ash/components/assistant/buildflags.h" -#include "chromeos/ash/components/audio/cras_audio_handler.h" -#include "chromeos/ash/components/dbus/dbus_thread_manager.h" -#include "chromeos/ash/services/assistant/assistant_interaction_logger.h" -#include "chromeos/ash/services/assistant/assistant_manager_service.h" -#include "chromeos/ash/services/assistant/assistant_manager_service_impl.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_prefs.h" -#include "chromeos/ash/services/assistant/public/cpp/device_actions.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/assistant/service_context.h" -#include "chromeos/ash/services/libassistant/public/cpp/libassistant_loader.h" -#include "chromeos/dbus/power_manager/power_supply_properties.pb.h" -#include "components/account_id/account_id.h" -#include "components/prefs/pref_service.h" -#include "components/signin/public/base/consent_level.h" -#include "components/signin/public/identity_manager/access_token_fetcher.h" -#include "components/signin/public/identity_manager/access_token_info.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/signin/public/identity_manager/scope_set.h" -#include "google_apis/gaia/gaia_constants.h" -#include "google_apis/gaia/google_service_auth_error.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" - -#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT) -#include "base/files/file_path.h" -#include "base/files/file_util.h" -#include "base/task/task_traits.h" -#include "base/task/thread_pool.h" -#include "chromeos/ash/services/libassistant/constants.h" -#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT) - -namespace ash::assistant { - -namespace { - -constexpr char kScopeAssistant[] = - "https://www.googleapis.com/auth/assistant-sdk-prototype"; - -constexpr char kServiceStateHistogram[] = "Assistant.ServiceState"; - -constexpr base::TimeDelta kMinTokenRefreshDelay = base::Milliseconds(1000); -constexpr base::TimeDelta kMaxTokenRefreshDelay = base::Milliseconds(60 * 1000); - -// Testing override for the URI used to contact the s3 server. -const char* g_s3_server_uri_override = nullptr; -// Testing override for the device-id used by Libassistant to identify this -// device. -const char* g_device_id_override = nullptr; - -#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT) -base::TaskTraits GetTaskTraits() { - return {base::MayBlock(), base::TaskPriority::USER_BLOCKING, - base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}; -} -#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT) - -// The max number of tries to start service. -// We decide whether to start service based on two counters: -// 1. the backoff `failure_count`, and -// 2. the pref value `kAssistantNumFailuresSinceLastServiceRun`. -// -// 1. Will not restart service if the `failure_count` is larger than -// `kMaxStartServiceRetries`. Note that the `failure_count` will change: -// 1.a. Increment by 1 for every service disconnected. -// 1.b. Reset to 0 when explicitly re-enable the Assistant from the Settings. -// 1.c. Reset to 0 when re-login the device. -// 1.d. Decrement by 1 when it has been `kAutoRecoverTime`. -// -// 2. Will not restart service if the pref value -// `kAssistantNumFailuresSinceLastServiceRun` is larger than -// `kMaxStartServiceRetries`, unless `failure_count` is 0, e.g. the first -// time login. Note that the `kAssistantNumFailuresSinceLastServiceRun` -// will change: -// 2.a. Increment by 1 for every service disconnected. -// 2.b. Reset to 0 when every service running. -constexpr int kMaxStartServiceRetries = 1; - -// An interval used to gradually reduce the failure_count so that we could -// restart. -constexpr base::TimeDelta kAutoRecoverTime = base::Hours(24); - -constexpr net::BackoffEntry::Policy kRetryStartServiceBackoffPolicy = { - 0, // Number of initial errors to ignore. - 1000, // Initial delay in ms. - 2.0, // Factor by which the waiting time will be multiplied. - 0.2, // Fuzzing percentage. - 60 * 1000, // Maximum delay in ms. - -1, // Never discard the entry. - true, // Use initial delay. -}; - -AssistantStatus ToAssistantStatus(AssistantManagerService::State state) { - using State = AssistantManagerService::State; - - switch (state) { - case State::STOPPED: - case State::STOPPING: - case State::STARTING: - case State::STARTED: - case State::DISCONNECTED: - return AssistantStatus::NOT_READY; - case State::RUNNING: - return AssistantStatus::READY; - } -} - -std::optional<std::string> GetS3ServerUriOverride() { - if (g_s3_server_uri_override) - return g_s3_server_uri_override; - return std::nullopt; -} - -std::optional<std::string> GetDeviceIdOverride() { - if (g_device_id_override) - return g_device_id_override; - return std::nullopt; -} - -// In the signed-out mode, we are going to run Assistant service without -// using user's signed in account information. -bool IsSignedOutMode() { - // One example of using fake gaia login is in our automation tests, i.e. - // Assistant Tast tests. - return base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableGaiaServices); -} - -void RecordServiceState(AssistantManagerService::State state) { - base::UmaHistogramEnumeration(kServiceStateHistogram, state); -} - -} // namespace - -// Scoped observer that will subscribe |Service| as an Ash session observer, -// and will unsubscribe in its destructor. -class ScopedAshSessionObserver { - public: - ScopedAshSessionObserver(SessionActivationObserver* observer, - const AccountId& account_id) - : observer_(observer), account_id_(account_id) { - DCHECK(account_id_.is_valid()); - DCHECK(controller()); - controller()->AddSessionActivationObserverForAccountId(account_id_, - observer_); - } - - ~ScopedAshSessionObserver() { - if (controller()) - controller()->RemoveSessionActivationObserverForAccountId(account_id_, - observer_); - } - - private: - SessionController* controller() const { return SessionController::Get(); } - - const raw_ptr<SessionActivationObserver> observer_; - const AccountId account_id_; -}; - -class Service::Context : public ServiceContext { - public: - explicit Context(Service* parent) : parent_(parent) {} - - Context(const Context&) = delete; - Context& operator=(const Context&) = delete; - - ~Context() override = default; - - // ServiceContext: - AssistantAlarmTimerController* assistant_alarm_timer_controller() override { - return AssistantAlarmTimerController::Get(); - } - - AssistantController* assistant_controller() override { - return AssistantController::Get(); - } - - AssistantNotificationController* assistant_notification_controller() - override { - return AssistantNotificationController::Get(); - } - - AssistantScreenContextController* assistant_screen_context_controller() - override { - return AssistantScreenContextController::Get(); - } - - AssistantStateBase* assistant_state() override { - return AssistantState::Get(); - } - - CrasAudioHandler* cras_audio_handler() override { - return CrasAudioHandler::Get(); - } - - DeviceActions* device_actions() override { return DeviceActions::Get(); } - - scoped_refptr<base::SequencedTaskRunner> main_task_runner() override { - return parent_->main_task_runner_; - } - - chromeos::PowerManagerClient* power_manager_client() override { - return chromeos::PowerManagerClient::Get(); - } - - GaiaId primary_account_gaia_id() override { - return parent_->RetrievePrimaryAccountInfo().gaia; - } - - private: - const raw_ptr<Service> parent_; // |this| is owned by |parent_|. -}; - -Service::Service(std::unique_ptr<network::PendingSharedURLLoaderFactory> - pending_url_loader_factory, - signin::IdentityManager* identity_manager, - PrefService* pref_service) - : context_(std::make_unique<Context>(this)), - identity_manager_(identity_manager), - pref_service_(pref_service), - token_refresh_timer_(std::make_unique<base::OneShotTimer>()), - main_task_runner_(base::SequencedTaskRunner::GetCurrentDefault()), - pending_url_loader_factory_(std::move(pending_url_loader_factory)), - start_service_retry_backoff_(&kRetryStartServiceBackoffPolicy), - auto_service_recover_timer_(std::make_unique<base::OneShotTimer>()) { - DCHECK(identity_manager_); - chromeos::PowerManagerClient* power_manager_client = - context_->power_manager_client(); - power_manager_observation_.Observe(power_manager_client); - power_manager_client->RequestStatusUpdate(); -} - -Service::~Service() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - AssistantState::Get()->RemoveObserver(this); - AssistantController::Get()->SetAssistant(nullptr); -} - -// static -void Service::OverrideS3ServerUriForTesting(const char* uri) { - g_s3_server_uri_override = uri; -} - -// static -void Service::OverrideDeviceIdForTesting(const char* device_id) { - g_device_id_override = device_id; -} - -void Service::SetAssistantManagerServiceForTesting( - std::unique_ptr<AssistantManagerService> assistant_manager_service) { - DCHECK(assistant_manager_service_ == nullptr); - assistant_manager_service_for_testing_ = std::move(assistant_manager_service); -} - -void Service::Init() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - AssistantState::Get()->AddObserver(this); - - DCHECK(!assistant_manager_service_); - - RequestAccessToken(); - LoadLibassistant(); -} - -void Service::Shutdown() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (assistant_manager_service_) - StopAssistantManagerService(); -} - -Assistant* Service::GetAssistant() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(assistant_manager_service_); - return assistant_manager_service_.get(); -} - -void Service::PowerChanged(const power_manager::PowerSupplyProperties& prop) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const bool power_source_connected = - prop.external_power() == power_manager::PowerSupplyProperties::AC; - if (power_source_connected == power_source_connected_) - return; - - power_source_connected_ = power_source_connected; - UpdateAssistantManagerState(); -} - -void Service::SuspendDone(base::TimeDelta sleep_duration) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // |token_refresh_timer_| may become stale during sleeping, so we immediately - // request a new token to make sure it is fresh. - if (token_refresh_timer_->IsRunning()) { - token_refresh_timer_->Stop(); - RequestAccessToken(); - } -} - -void Service::OnSessionActivated(bool activated) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - session_active_ = activated; - - AssistantBrowserDelegate::Get()->OnAssistantStatusChanged( - ToAssistantStatus(assistant_manager_service_->GetState())); - UpdateListeningState(); -} - -void Service::OnLockStateChanged(bool locked) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - locked_ = locked; - UpdateListeningState(); -} - -void Service::OnAssistantConsentStatusChanged(int consent_status) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Notify device apps status when user accepts activity control. - if (assistant_manager_service_ && - assistant_manager_service_->GetState() == - AssistantManagerService::State::RUNNING) { - assistant_manager_service_->SyncDeviceAppsStatus(); - } -} - -void Service::OnAssistantContextEnabled(bool enabled) { - UpdateAssistantManagerState(); -} - -void Service::OnAssistantHotwordAlwaysOn(bool hotword_always_on) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // No need to update hotword status if power source is connected. - if (power_source_connected_) - return; - - UpdateAssistantManagerState(); -} - -void Service::OnAssistantSettingsEnabled(bool enabled) { - // Reset the failure count and backoff delay when the Settings is re-enabled. - start_service_retry_backoff_.Reset(); - UpdateAssistantManagerState(); -} - -void Service::OnAssistantHotwordEnabled(bool enabled) { - UpdateAssistantManagerState(); -} - -void Service::OnLocaleChanged(const std::string& locale) { - UpdateAssistantManagerState(); -} - -void Service::OnArcPlayStoreEnabledChanged(bool enabled) { - UpdateAssistantManagerState(); -} - -void Service::OnLockedFullScreenStateChanged(bool enabled) { - UpdateListeningState(); -} - -void Service::OnAuthenticationError() { - RequestAccessToken(); -} - -void Service::OnStateChanged(AssistantManagerService::State new_state) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - switch (new_state) { - case AssistantManagerService::State::STARTED: - FinalizeAssistantManagerService(); - break; - case AssistantManagerService::State::RUNNING: - OnLibassistantServiceRunning(); - break; - case AssistantManagerService::State::STOPPED: - OnLibassistantServiceStopped(); - break; - case AssistantManagerService::State::DISCONNECTED: - OnLibassistantServiceDisconnected(); - break; - case AssistantManagerService::State::STARTING: - case AssistantManagerService::State::STOPPING: - // No action. - break; - } - - RecordServiceState(new_state); - AssistantBrowserDelegate::Get()->OnAssistantStatusChanged( - ToAssistantStatus(new_state)); - - UpdateListeningState(); -} - -void Service::UpdateAssistantManagerState() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - auto* assistant_state = AssistantState::Get(); - - if (!assistant_state->hotword_enabled().has_value() || - !assistant_state->settings_enabled().has_value() || - !assistant_state->locale().has_value() || - (!access_token_.has_value() && !IsSignedOutMode()) || - !assistant_state->arc_play_store_enabled().has_value() || - !libassistant_loaded_ || is_deleting_data_) { - // Assistant state has not finished initialization, let's wait. - return; - } - - if (IsSignedOutMode()) { - // Clear |access_token_| in signed-out mode to keep it synced with what we - // will pass to the |assistant_manager_service_|. - access_token_ = std::nullopt; - } - - if (!assistant_manager_service_) - CreateAssistantManagerService(); - - auto state = assistant_manager_service_->GetState(); - switch (state) { - case AssistantManagerService::State::STOPPED: - case AssistantManagerService::State::DISCONNECTED: - if (!CanStartService()) { - return; - } - - if (assistant_state->settings_enabled().value()) { - assistant_manager_service_->Start(GetUserInfo(), ShouldEnableHotword()); - - // Re-add observers every time when starting. - assistant_manager_service_->AddAuthenticationStateObserver(this); - assistant_manager_service_->AddAndFireStateObserver(this); - - if (AssistantInteractionLogger::IsLoggingEnabled()) { - interaction_logger_ = std::make_unique<AssistantInteractionLogger>(); - assistant_manager_service_->AddAssistantInteractionSubscriber( - interaction_logger_.get()); - } - - DVLOG(1) << "Request Assistant start"; - } - break; - case AssistantManagerService::State::STARTING: - case AssistantManagerService::State::STARTED: - // If the Assistant is disabled by domain policy, the libassistant will - // never becomes ready. Stop waiting for the state change and stop the - // service. - if (assistant_state->allowed_state() == - AssistantAllowedState::DISALLOWED_BY_POLICY) { - StopAssistantManagerService(); - return; - } - // Wait if |assistant_manager_service_| is not at a stable state. - ScheduleUpdateAssistantManagerState(/*should_backoff=*/false); - break; - case AssistantManagerService::State::STOPPING: - ScheduleUpdateAssistantManagerState(/*should_backoff=*/false); - break; - case AssistantManagerService::State::RUNNING: - if (assistant_state->settings_enabled().value()) { - assistant_manager_service_->SetUser(GetUserInfo()); - assistant_manager_service_->EnableHotword(ShouldEnableHotword()); - assistant_manager_service_->SetArcPlayStoreEnabled( - assistant_state->arc_play_store_enabled().value()); - assistant_manager_service_->SetAssistantContextEnabled( - assistant_state->IsScreenContextAllowed()); - } else { - StopAssistantManagerService(); - } - break; - } -} - -void Service::ScheduleUpdateAssistantManagerState(bool should_backoff) { - update_assistant_manager_callback_.Cancel(); - update_assistant_manager_callback_.Reset(base::BindOnce( - &Service::UpdateAssistantManagerState, weak_ptr_factory_.GetWeakPtr())); - - base::TimeDelta delay = - should_backoff ? start_service_retry_backoff_.GetTimeUntilRelease() - : kUpdateAssistantManagerDelay; - main_task_runner_->PostDelayedTask( - FROM_HERE, update_assistant_manager_callback_.callback(), delay); -} - -CoreAccountInfo Service::RetrievePrimaryAccountInfo() const { - CoreAccountInfo account_info = - identity_manager_->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin); - CHECK(!account_info.account_id.empty()); - CHECK(!account_info.gaia.empty()); - return account_info; -} - -void Service::RequestAccessToken() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Bypass access token fetching when service is running in signed-out mode. - if (IsSignedOutMode()) { - VLOG(1) << "Signed out mode detected, bypass access token fetching."; - return; - } - - if (access_token_fetcher_) { - LOG(WARNING) << "Access token already requested."; - return; - } - - VLOG(1) << "Start requesting access token."; - CoreAccountInfo account_info = RetrievePrimaryAccountInfo(); - if (!identity_manager_->HasAccountWithRefreshToken(account_info.account_id)) { - LOG(ERROR) << "Failed to retrieve primary account info. Retrying."; - RetryRefreshToken(); - return; - } - - signin::ScopeSet scopes; - scopes.insert(kScopeAssistant); - scopes.insert(GaiaConstants::kGCMGroupServerOAuth2Scope); - - access_token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount( - account_info.account_id, "cros_assistant", scopes, - base::BindOnce(&Service::GetAccessTokenCallback, base::Unretained(this)), - signin::AccessTokenFetcher::Mode::kImmediate); -} - -void Service::GetAccessTokenCallback( - GoogleServiceAuthError error, - signin::AccessTokenInfo access_token_info) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // It's safe to delete AccessTokenFetcher from inside its own callback. - access_token_fetcher_.reset(); - - if (error.state() != GoogleServiceAuthError::NONE) { - LOG(ERROR) << "Failed to retrieve token, error: " << error.ToString(); - RetryRefreshToken(); - return; - } - - access_token_ = access_token_info.token; - UpdateAssistantManagerState(); - token_refresh_timer_->Start( - FROM_HERE, access_token_info.expiration_time - base::Time::Now(), this, - &Service::RequestAccessToken); -} - -void Service::RetryRefreshToken() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - base::TimeDelta backoff_delay = - std::min(kMinTokenRefreshDelay * - (1 << (token_refresh_error_backoff_factor - 1)), - kMaxTokenRefreshDelay) + - base::RandDouble() * kMinTokenRefreshDelay; - if (backoff_delay < kMaxTokenRefreshDelay) - ++token_refresh_error_backoff_factor; - token_refresh_timer_->Start(FROM_HERE, backoff_delay, this, - &Service::RequestAccessToken); -} - -void Service::CreateAssistantManagerService() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - assistant_manager_service_ = CreateAndReturnAssistantManagerService(); -} - -std::unique_ptr<AssistantManagerService> -Service::CreateAndReturnAssistantManagerService() { - if (assistant_manager_service_for_testing_) - return std::move(assistant_manager_service_for_testing_); - - // |assistant_manager_service_| is only created once. - DCHECK(pending_url_loader_factory_); - return std::make_unique<AssistantManagerServiceImpl>( - context(), std::move(pending_url_loader_factory_), - GetS3ServerUriOverride(), GetDeviceIdOverride()); -} - -void Service::FinalizeAssistantManagerService() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(assistant_manager_service_->GetState() == - AssistantManagerService::STARTED || - assistant_manager_service_->GetState() == - AssistantManagerService::RUNNING); - - // Ensure one-time mojom initialization. - if (is_assistant_manager_service_finalized_) - return; - is_assistant_manager_service_finalized_ = true; - - AddAshSessionObserver(); - AssistantController::Get()->SetAssistant(assistant_manager_service_.get()); -} - -void Service::StopAssistantManagerService() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - assistant_manager_service_->Stop(); - weak_ptr_factory_.InvalidateWeakPtrs(); -} - -void Service::OnLibassistantServiceRunning() { - DVLOG(1) << "Assistant is running"; - pref_service_->SetInteger(prefs::kAssistantNumFailuresSinceLastServiceRun, 0); -} - -void Service::OnLibassistantServiceStopped() { - ClearAfterStop(); -} - -void Service::OnLibassistantServiceDisconnected() { - ClearAfterStop(); - - if (auto_service_recover_timer_->IsRunning()) { - auto_service_recover_timer_->Stop(); - } - - // Increase the failure count for both the backoff and pref. - start_service_retry_backoff_.InformOfRequest(/*succeeded=*/false); - int num_failures = pref_service_->GetInteger( - prefs::kAssistantNumFailuresSinceLastServiceRun); - pref_service_->SetInteger(prefs::kAssistantNumFailuresSinceLastServiceRun, - num_failures + 1); - if (CanStartService()) { - LOG(WARNING) << "LibAssistant service disconnected. Re-starting..."; - - // Restarts LibassistantService. - ScheduleUpdateAssistantManagerState(/*should_backoff=*/true); - } else { - // Start auto recover timer. - auto delay = GetAutoRecoverTime(); - auto_service_recover_timer_->Start(FROM_HERE, delay, this, - &Service::DecreaseStartServiceBackoff); - LOG(ERROR) - << "LibAssistant service keeps disconnected. All retries attempted."; - } -} - -void Service::AddAshSessionObserver() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // No session controller in unittest. - if (SessionController::Get()) { - // Note that this account can either be a regular account using real gaia, - // or a fake gaia account. - CoreAccountInfo account_info = RetrievePrimaryAccountInfo(); - AccountId account_id = AccountId::FromNonCanonicalEmail( - account_info.email, account_info.gaia, AccountType::GOOGLE); - scoped_ash_session_observer_ = - std::make_unique<ScopedAshSessionObserver>(this, account_id); - } -} - -void Service::UpdateListeningState() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (!assistant_manager_service_) { - return; - } - - bool should_listen = - !locked_ && - !AssistantState::Get()->locked_full_screen_enabled().value_or(false) && - session_active_; - DVLOG(1) << "Update assistant listening state: " << should_listen; - assistant_manager_service_->EnableListening(should_listen); - assistant_manager_service_->EnableHotword(should_listen && - ShouldEnableHotword()); -} - -std::optional<AssistantManagerService::UserInfo> Service::GetUserInfo() const { - if (access_token_) { - return AssistantManagerService::UserInfo(RetrievePrimaryAccountInfo().gaia, - access_token_.value()); - } - return std::nullopt; -} - -bool Service::ShouldEnableHotword() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - bool dsp_available = context()->cras_audio_handler()->HasHotwordDevice(); - auto* assistant_state = AssistantState::Get(); - - // Disable hotword if hotword is not set to always on and power source is not - // connected. - if (!dsp_available && !assistant_state->hotword_always_on().value_or(false) && - !power_source_connected_) { - return false; - } - - return assistant_state->hotword_enabled().value(); -} - -void Service::LoadLibassistant() { - libassistant::LibassistantLoader::Load(base::BindOnce( - &Service::OnLibassistantLoaded, weak_ptr_factory_.GetWeakPtr())); -} - -void Service::OnLibassistantLoaded(bool success) { - libassistant_loaded_ = success; - - if (success) { - UpdateAssistantManagerState(); - } -} - -void Service::ClearAfterStop() { - is_assistant_manager_service_finalized_ = false; - scoped_ash_session_observer_.reset(); - -#if BUILDFLAG(ENABLE_CROS_LIBASSISTANT) - // When user disables the Assistant, we also delete all data. - if (!AssistantState::Get()->settings_enabled().value()) { - is_deleting_data_ = true; - base::ThreadPool::CreateSequencedTaskRunner(GetTaskTraits()) - ->PostTaskAndReply( - FROM_HERE, base::BindOnce([]() { - base::DeletePathRecursively(base::FilePath( - FILE_PATH_LITERAL(libassistant::kAssistantBaseDirPath))); - }), - base::BindOnce(&Service::OnDataDeleted, - weak_ptr_factory_.GetWeakPtr())); - } -#endif // BUILDFLAG(ENABLE_CROS_LIBASSISTANT) - - ResetAuthenticationStateObserver(); -} - -void Service::DecreaseStartServiceBackoff() { - // Reduce the failure_count by one to allow restart. - start_service_retry_backoff_.InformOfRequest(/*succeeded=*/true); - - // It is ok to try to reset service if the service is running. - ScheduleUpdateAssistantManagerState(/*should_backoff=*/true); - - // Start auto recover timer. - if (start_service_retry_backoff_.failure_count() > 0) { - auto delay = GetAutoRecoverTime(); - auto_service_recover_timer_->Start(FROM_HERE, delay, this, - &Service::DecreaseStartServiceBackoff); - } -} - -base::TimeDelta Service::GetAutoRecoverTime() { - if (!auto_recover_time_for_testing_.is_zero()) { - return auto_recover_time_for_testing_; - } - return kAutoRecoverTime; -} - -bool Service::CanStartService() const { - // Please see comments on `kMaxStartServiceRetries`. - // We can start service if the failure count is zero: - // 1.b. Reset to 0 when explicitly re-enable the Assistant from the Settings. - // 1.c. Reset to 0 when re-login the device. - // 1.d. Decrement by 1 when it has been `kAutoRecoverTime`. - if (start_service_retry_backoff_.failure_count() == 0) { - return true; - } - - // Do not start service if it has retried `kMaxStartServiceRetries` times in - // one chrome session or since the last time enable in Settings. - if (start_service_retry_backoff_.failure_count() > kMaxStartServiceRetries) { - return false; - } - - // Do not start service if `kAssistantNumFailuresSinceLastServiceRun` failed - // `kMaxStartServiceRetries` times. - int num_failures_since_last_service_run = pref_service_->GetInteger( - prefs::kAssistantNumFailuresSinceLastServiceRun); - if (num_failures_since_last_service_run > kMaxStartServiceRetries) { - return false; - } - - return true; -} - -void Service::OnDataDeleted() { - is_deleting_data_ = false; - UpdateAssistantManagerState(); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/service.h b/chromeos/ash/services/assistant/service.h deleted file mode 100644 index 4f1cb51d..0000000 --- a/chromeos/ash/services/assistant/service.h +++ /dev/null
@@ -1,244 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_SERVICE_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_SERVICE_H_ - -#include <memory> -#include <optional> -#include <string> - -#include "ash/public/cpp/assistant/assistant_state.h" -#include "ash/public/cpp/session/session_activation_observer.h" -#include "base/cancelable_callback.h" -#include "base/component_export.h" -#include "base/functional/callback.h" -#include "base/memory/raw_ptr.h" -#include "base/memory/weak_ptr.h" -#include "base/scoped_observation.h" -#include "base/sequence_checker.h" -#include "base/task/sequenced_task_runner.h" -#include "base/task/single_thread_task_runner.h" -#include "base/time/time.h" -#include "chromeos/ash/services/assistant/assistant_manager_service.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "chromeos/dbus/power/power_manager_client.h" -#include "components/signin/public/identity_manager/account_info.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "net/base/backoff_entry.h" - -class GoogleServiceAuthError; -class PrefService; - -namespace base { -class OneShotTimer; -} // namespace base - -namespace network { -class PendingSharedURLLoaderFactory; -} // namespace network - -namespace power_manager { -class PowerSupplyProperties; -} // namespace power_manager - -namespace signin { -class AccessTokenFetcher; -struct AccessTokenInfo; -class IdentityManager; -} // namespace signin - -namespace ash::assistant { - -class AssistantInteractionLogger; -class ScopedAshSessionObserver; -class ServiceContext; - -// |AssistantManagerService|'s state won't update if it's currently in the -// process of starting up. This is the delay before we will try to update -// |AssistantManagerService| again. -constexpr auto kUpdateAssistantManagerDelay = base::Seconds(1); - -class COMPONENT_EXPORT(ASSISTANT_SERVICE) Service - : public AssistantService, - public chromeos::PowerManagerClient::Observer, - public SessionActivationObserver, - public AssistantStateObserver, - public AssistantManagerService::StateObserver, - public AuthenticationStateObserver { - public: - Service(std::unique_ptr<network::PendingSharedURLLoaderFactory> - pending_url_loader_factory, - signin::IdentityManager* identity_manager, - PrefService* pref_service); - - Service(const Service&) = delete; - Service& operator=(const Service&) = delete; - - ~Service() override; - - // Allows tests to override the S3 server URI used by the service. - // The caller must ensure the memory passed in remains valid. - // This override can be removed by passing in a nullptr. - // Note: This would look nicer if it was a class method and not static, - // but unfortunately this must be called before |Service| tries to create the - // |AssistantManagerService|, which happens really soon after the service - // itself is created, so we do not have time in our tests to grab a handle - // to |Service| and set this before it is too late. - static void OverrideS3ServerUriForTesting(const char* uri); - static void OverrideDeviceIdForTesting(const char* device_id); - - void SetAssistantManagerServiceForTesting( - std::unique_ptr<AssistantManagerService> assistant_manager_service); - - // AssistantService overrides: - void Init() override; - void Shutdown() override; - Assistant* GetAssistant() override; - - private: - friend class AssistantServiceTest; - - class Context; - - // chromeos::PowerManagerClient::Observer overrides: - void PowerChanged(const power_manager::PowerSupplyProperties& prop) override; - void SuspendDone(base::TimeDelta sleep_duration) override; - - // SessionActivationObserver overrides: - void OnSessionActivated(bool activated) override; - void OnLockStateChanged(bool locked) override; - - // AssistantStateObserver overrides: - void OnAssistantConsentStatusChanged(int consent_status) override; - void OnAssistantContextEnabled(bool enabled) override; - void OnAssistantHotwordAlwaysOn(bool hotword_always_on) override; - void OnAssistantSettingsEnabled(bool enabled) override; - void OnAssistantHotwordEnabled(bool enabled) override; - void OnLocaleChanged(const std::string& locale) override; - void OnArcPlayStoreEnabledChanged(bool enabled) override; - void OnLockedFullScreenStateChanged(bool enabled) override; - - // AuthenticationStateObserver overrides: - void OnAuthenticationError() override; - - // AssistantManagerService::StateObserver overrides: - void OnStateChanged(AssistantManagerService::State new_state) override; - - void UpdateAssistantManagerState(); - void ScheduleUpdateAssistantManagerState(bool should_backoff); - - CoreAccountInfo RetrievePrimaryAccountInfo() const; - void RequestAccessToken(); - void GetAccessTokenCallback(GoogleServiceAuthError error, - signin::AccessTokenInfo access_token_info); - void RetryRefreshToken(); - - void CreateAssistantManagerService(); - std::unique_ptr<AssistantManagerService> - CreateAndReturnAssistantManagerService(); - - void FinalizeAssistantManagerService(); - - void StopAssistantManagerService(); - - void OnLibassistantServiceRunning(); - void OnLibassistantServiceStopped(); - void OnLibassistantServiceDisconnected(); - - void AddAshSessionObserver(); - - void UpdateListeningState(); - - std::optional<AssistantManagerService::UserInfo> GetUserInfo() const; - - ServiceContext* context() { return context_.get(); } - - // Returns the "actual" hotword status. In addition to the hotword pref, this - // method also take power status into account if dsp support is not available - // for the device. - bool ShouldEnableHotword(); - - void LoadLibassistant(); - void OnLibassistantLoaded(bool success); - - void ClearAfterStop(); - - void DecreaseStartServiceBackoff(); - - base::TimeDelta GetAutoRecoverTime(); - void SetAutoRecoverTimeForTesting(base::TimeDelta delay) { - auto_recover_time_for_testing_ = delay; - } - - bool CanStartService() const; - - void OnDataDeleted(); - - // |ServiceContext| object passed to child classes so they can access some of - // our functionality without depending on us. - // Note: this is used by the other members here, so it must be defined first - // so it is destroyed last. - std::unique_ptr<ServiceContext> context_; - - const raw_ptr<signin::IdentityManager> identity_manager_; - const raw_ptr<PrefService> pref_service_; - std::unique_ptr<ScopedAshSessionObserver> scoped_ash_session_observer_; - std::unique_ptr<AssistantManagerService> assistant_manager_service_; - std::unique_ptr<base::OneShotTimer> token_refresh_timer_; - int token_refresh_error_backoff_factor = 1; - scoped_refptr<base::SequencedTaskRunner> main_task_runner_; - base::ScopedObservation<chromeos::PowerManagerClient, - chromeos::PowerManagerClient::Observer> - power_manager_observation_{this}; - - // Flag to guard the one-time mojom initialization. - bool is_assistant_manager_service_finalized_ = false; - // Whether the current user session is active. - bool session_active_ = false; - // Whether the lock screen is on. - bool locked_ = false; - // Whether the power source is connected. - bool power_source_connected_ = false; - // Whether the libassistant library is loaded. - bool libassistant_loaded_ = false; - // Whether is deleting data. - bool is_deleting_data_ = false; - - // The value passed into |SetAssistantManagerServiceForTesting|. - // Will be moved into |assistant_manager_service_| when the service is - // supposed to be created. - std::unique_ptr<AssistantManagerService> - assistant_manager_service_for_testing_; - - std::optional<std::string> access_token_; - - // non-null until |assistant_manager_service_| is created. - std::unique_ptr<network::PendingSharedURLLoaderFactory> - pending_url_loader_factory_; - - // If Libassistant service is disconnected, will use this backoff entry to - // restart the service. - net::BackoffEntry start_service_retry_backoff_; - - // A timer used to slowly recover from previous crashes by reducing the - // `start_service_retry_backoff_` failure_count by one for every - // `kAutoRecoverTime`. - std::unique_ptr<base::OneShotTimer> auto_service_recover_timer_; - base::TimeDelta auto_recover_time_for_testing_; - - base::CancelableOnceClosure update_assistant_manager_callback_; - - std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_; - - std::unique_ptr<AssistantInteractionLogger> interaction_logger_; - - SEQUENCE_CHECKER(sequence_checker_); - - base::WeakPtrFactory<Service> weak_ptr_factory_{this}; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_SERVICE_H_
diff --git a/chromeos/ash/services/assistant/service_context.h b/chromeos/ash/services/assistant/service_context.h deleted file mode 100644 index aa9d7fdf..0000000 --- a/chromeos/ash/services/assistant/service_context.h +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_SERVICE_CONTEXT_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_SERVICE_CONTEXT_H_ - -#include "ash/public/cpp/assistant/controller/assistant_screen_context_controller.h" -#include "base/memory/scoped_refptr.h" -#include "google_apis/gaia/gaia_id.h" - -namespace base { -class SequencedTaskRunner; -} // namespace base - -namespace chromeos { -class PowerManagerClient; -} - -namespace ash { - -class AssistantAlarmTimerController; -class AssistantController; -class AssistantNotificationController; -class AssistantStateBase; -class CrasAudioHandler; -class DeviceActions; - -namespace assistant { - -// Context object passed around so classes can access some of the |Service| -// functionality without directly depending on the |Service| class. -class ServiceContext { - public: - virtual ~ServiceContext() = default; - - virtual AssistantAlarmTimerController* assistant_alarm_timer_controller() = 0; - - virtual AssistantController* assistant_controller() = 0; - - virtual AssistantNotificationController* - assistant_notification_controller() = 0; - - virtual AssistantScreenContextController* - assistant_screen_context_controller() = 0; - - virtual AssistantStateBase* assistant_state() = 0; - - virtual CrasAudioHandler* cras_audio_handler() = 0; - - virtual DeviceActions* device_actions() = 0; - - virtual scoped_refptr<base::SequencedTaskRunner> main_task_runner() = 0; - - virtual chromeos::PowerManagerClient* power_manager_client() = 0; - - // Returns the Gaia ID of the primary account (which is used by the - // Assistant). - virtual GaiaId primary_account_gaia_id() = 0; -}; -} // namespace assistant -} // namespace chromeos - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_SERVICE_CONTEXT_H_
diff --git a/chromeos/ash/services/assistant/service_unittest.cc b/chromeos/ash/services/assistant/service_unittest.cc deleted file mode 100644 index 3cedb50..0000000 --- a/chromeos/ash/services/assistant/service_unittest.cc +++ /dev/null
@@ -1,751 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/service.h" - -#include <memory> -#include <utility> -#include <vector> - -#include "ash/public/cpp/assistant/test_support/mock_assistant_controller.h" -#include "base/check.h" -#include "base/memory/scoped_refptr.h" -#include "base/run_loop.h" -#include "base/test/task_environment.h" -#include "base/test/test_mock_time_task_runner.h" -#include "base/time/tick_clock.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "chromeos/ash/components/audio/cras_audio_handler.h" -#include "chromeos/ash/services/assistant/public/cpp/assistant_prefs.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/assistant/test_support/fake_assistant_manager_service_impl.h" -#include "chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.h" -#include "chromeos/ash/services/assistant/test_support/scoped_assistant_browser_delegate.h" -#include "chromeos/ash/services/assistant/test_support/scoped_device_actions.h" -#include "chromeos/dbus/power/fake_power_manager_client.h" -#include "components/prefs/testing_pref_service.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/signin/public/identity_manager/identity_test_environment.h" -#include "google_apis/gaia/gaia_id.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "net/base/backoff_entry.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" -#include "services/network/test/test_url_loader_factory.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash::assistant { - -namespace { - -constexpr base::TimeDelta kDefaultTokenExpirationDelay = - base::Milliseconds(60000); - -constexpr base::TimeDelta kAutoRecoverTime = base::Seconds(60); - -#define EXPECT_STATE(_state) EXPECT_EQ(_state, assistant_manager()->GetState()) - -constexpr char kAccessToken[] = "fake access token"; -constexpr GaiaId::Literal kGaiaId("gaia_id_for_user_gmail.com"); -constexpr char kEmailAddress[] = "user@gmail.com"; - -// Should be the same value as the one in service.cc. -constexpr int kMaxStartServiceRetries = 1; - -} // namespace - -class ScopedFakeAssistantBrowserDelegate - : public ScopedAssistantBrowserDelegate { - public: - explicit ScopedFakeAssistantBrowserDelegate(AssistantState* assistant_state) - : status_(AssistantStatus::NOT_READY) {} - - AssistantStatus status() { return status_; } - - private: - // ScopedAssistantBrowserDelegate: - void OnAssistantStatusChanged(AssistantStatus new_status) override { - status_ = new_status; - } - - AssistantStatus status_; -}; - -class AssistantServiceTest : public testing::Test { - public: - AssistantServiceTest() = default; - AssistantServiceTest(const AssistantServiceTest&) = delete; - AssistantServiceTest& operator=(const AssistantServiceTest&) = delete; - ~AssistantServiceTest() override = default; - - void SetUp() override { - chromeos::PowerManagerClient::InitializeFake(); - chromeos::FakePowerManagerClient::Get()->SetTabletMode( - chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks()); - - shared_url_loader_factory_ = - base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &url_loader_factory_); - - prefs::RegisterProfilePrefs(pref_service_.registry()); - pref_service_.SetBoolean(prefs::kAssistantEnabled, true); - pref_service_.SetBoolean(prefs::kAssistantHotwordEnabled, true); - - assistant_state_.RegisterPrefChanges(&pref_service_); - - // In production the primary account is set before the service is created. - identity_test_env_.MakePrimaryAccountAvailable( - kEmailAddress, signin::ConsentLevel::kSignin); - - service_ = std::make_unique<Service>(shared_url_loader_factory_->Clone(), - identity_test_env_.identity_manager(), - pref_service()); - service_->SetAssistantManagerServiceForTesting( - std::make_unique<FakeAssistantManagerServiceImpl>()); - service_->SetAutoRecoverTimeForTesting(kAutoRecoverTime); - - service_->Init(); - // Wait for AssistantManagerService to be set. - base::RunLoop().RunUntilIdle(); - - IssueAccessToken(kAccessToken); - // Simulate that the DLC library is loaded. - service_->OnLibassistantLoaded(/*success=*/true); - } - - void TearDown() override { - service_.reset(); - chromeos::PowerManagerClient::Shutdown(); - CrasAudioHandler::Shutdown(); - } - - void StartAssistantAndWait() { - pref_service()->SetBoolean(prefs::kAssistantEnabled, true); - base::RunLoop().RunUntilIdle(); - } - - void StopAssistantAndWait() { - pref_service()->SetBoolean(prefs::kAssistantEnabled, false); - base::RunLoop().RunUntilIdle(); - } - - void IssueAccessToken(const std::string& access_token) { - identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - access_token, base::Time::Now() + kDefaultTokenExpirationDelay); - } - - Service* service() { return service_.get(); } - - FakeAssistantManagerServiceImpl* assistant_manager() { - auto* result = static_cast<FakeAssistantManagerServiceImpl*>( - service_->assistant_manager_service_.get()); - DCHECK(result); - return result; - } - - void ResetFakeAssistantManager() { - assistant_manager()->SetUser(std::nullopt); - } - - signin::IdentityTestEnvironment* identity_test_env() { - return &identity_test_env_; - } - - PrefService* pref_service() { return &pref_service_; } - - AssistantState* assistant_state() { return &assistant_state_; } - - ScopedFakeAssistantBrowserDelegate* client() { return &fake_delegate_; } - - base::test::TaskEnvironment* task_environment() { return &task_environment_; } - - net::BackoffEntry* GetRestartServiceBackoff() { - return &service_->start_service_retry_backoff_; - } - - void DecreaseStartServiceBackoff() { - service_->DecreaseStartServiceBackoff(); - } - - int GetNumberOfFailuresSinceLastServiceRun() { - return pref_service()->GetInteger( - prefs::kAssistantNumFailuresSinceLastServiceRun); - } - - void SetNumberOfFailuresSinceLastServiceRun(int number) { - pref_service()->SetInteger(prefs::kAssistantNumFailuresSinceLastServiceRun, - number); - } - - private: - base::test::TaskEnvironment task_environment_{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - - TestingPrefServiceSimple pref_service_; - - std::unique_ptr<Service> service_; - - ScopedCrasAudioHandlerForTesting cras_audio_handler_; - FullyInitializedAssistantState assistant_state_; - signin::IdentityTestEnvironment identity_test_env_; - ScopedFakeAssistantBrowserDelegate fake_delegate_{&assistant_state_}; - ScopedDeviceActions fake_device_actions_; - testing::NiceMock<MockAssistantController> mock_assistant_controller; - - network::TestURLLoaderFactory url_loader_factory_; - scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_; -}; - -TEST_F(AssistantServiceTest, RefreshTokenAfterExpire) { - ASSERT_FALSE(identity_test_env()->IsAccessTokenRequestPending()); - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay / 2); - - // Before token expire, should not request new token. - EXPECT_FALSE(identity_test_env()->IsAccessTokenRequestPending()); - - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay); - - // After token expire, should request once. - EXPECT_TRUE(identity_test_env()->IsAccessTokenRequestPending()); -} - -TEST_F(AssistantServiceTest, RetryRefreshTokenAfterFailure) { - ASSERT_FALSE(identity_test_env()->IsAccessTokenRequestPending()); - - // Let the first token expire. Another will be requested. - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay); - EXPECT_TRUE(identity_test_env()->IsAccessTokenRequestPending()); - - // Reply with an error. - identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( - GoogleServiceAuthError(GoogleServiceAuthError::State::CONNECTION_FAILED)); - EXPECT_FALSE(identity_test_env()->IsAccessTokenRequestPending()); - - // Token request automatically retry. - // The failure delay has jitter so fast forward a bit more, but before - // the returned token would expire again. - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay / 2); - - EXPECT_TRUE(identity_test_env()->IsAccessTokenRequestPending()); -} - -TEST_F(AssistantServiceTest, RetryRefreshTokenAfterDeviceWakeup) { - ASSERT_FALSE(identity_test_env()->IsAccessTokenRequestPending()); - - chromeos::FakePowerManagerClient::Get()->SendSuspendDone(); - // Token requested immediately after suspend done. - EXPECT_TRUE(identity_test_env()->IsAccessTokenRequestPending()); -} - -TEST_F(AssistantServiceTest, StopImmediatelyIfAssistantIsRunning) { - // Test is set up as |State::STARTED|. - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - - StopAssistantAndWait(); - - EXPECT_STATE(AssistantManagerService::State::STOPPED); -} - -TEST_F(AssistantServiceTest, StopDelayedIfAssistantNotFinishedStarting) { - EXPECT_STATE(AssistantManagerService::State::STARTING); - - // Turning settings off will trigger logic to try to stop it. - StopAssistantAndWait(); - - EXPECT_STATE(AssistantManagerService::State::STARTING); - - task_environment()->FastForwardBy(kUpdateAssistantManagerDelay); - - // No change of state because it is still starting. - EXPECT_STATE(AssistantManagerService::State::STARTING); - - assistant_manager()->FinishStart(); - - task_environment()->FastForwardBy(kUpdateAssistantManagerDelay); - - EXPECT_STATE(AssistantManagerService::State::STOPPED); -} - -TEST_F(AssistantServiceTest, ShouldSendUserInfoWhenStarting) { - // First stop the service and reset the AssistantManagerService - assistant_manager()->FinishStart(); - StopAssistantAndWait(); - ResetFakeAssistantManager(); - - // Now start the service - StartAssistantAndWait(); - - ASSERT_TRUE(assistant_manager()->access_token().has_value()); - EXPECT_EQ(kAccessToken, assistant_manager()->access_token().value()); - ASSERT_TRUE(assistant_manager()->gaia_id().has_value()); - EXPECT_EQ(kGaiaId, assistant_manager()->gaia_id()); -} - -TEST_F(AssistantServiceTest, ShouldSendUserInfoWhenAccessTokenIsRefreshed) { - assistant_manager()->FinishStart(); - - // Reset the AssistantManagerService so it forgets the user info sent when - // starting the service. - ResetFakeAssistantManager(); - - // Now force an access token refresh - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay); - IssueAccessToken("new token"); - - ASSERT_TRUE(assistant_manager()->access_token().has_value()); - EXPECT_EQ("new token", assistant_manager()->access_token()); - ASSERT_TRUE(assistant_manager()->gaia_id().has_value()); - EXPECT_EQ(kGaiaId, assistant_manager()->gaia_id()); -} - -TEST_F(AssistantServiceTest, ShouldSetClientStatusToNotReadyWhenStarting) { - assistant_manager()->SetStateAndInformObservers( - AssistantManagerService::State::STARTING); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(client()->status(), AssistantStatus::NOT_READY); -} - -TEST_F(AssistantServiceTest, ShouldKeepClientStatusNotReadyWhenStarted) { - // Note: even though we've started, we are not ready to handle the queries - // until LibAssistant tells us we are. - assistant_manager()->SetStateAndInformObservers( - AssistantManagerService::State::STARTED); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(client()->status(), AssistantStatus::NOT_READY); -} - -TEST_F(AssistantServiceTest, ShouldSetClientStatusToNewReadyWhenRunning) { - assistant_manager()->SetStateAndInformObservers( - AssistantManagerService::State::RUNNING); - base::RunLoop().RunUntilIdle(); - - EXPECT_EQ(client()->status(), AssistantStatus::READY); -} - -TEST_F(AssistantServiceTest, ShouldSetClientStatusToNotReadyWhenStopped) { - assistant_manager()->SetStateAndInformObservers( - AssistantManagerService::State::RUNNING); - base::RunLoop().RunUntilIdle(); - - StopAssistantAndWait(); - - EXPECT_EQ(client()->status(), AssistantStatus::NOT_READY); -} - -TEST_F(AssistantServiceTest, StopImmediatelyIfAssistantIsDisconnected) { - // Test is set up as |State::STARTED|. - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(client()->status(), AssistantStatus::NOT_READY); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::STARTING); -} - -TEST_F(AssistantServiceTest, - IncreaseBackoffIfAssistantIsDisconnectedAfterStarting) { - StartAssistantAndWait(); - EXPECT_STATE(AssistantManagerService::State::STARTING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 1); -} - -TEST_F(AssistantServiceTest, - IncreaseBackoffIfAssistantIsDisconnectedAfterStarted) { - assistant_manager()->SetStateAndInformObservers( - AssistantManagerService::State::STARTED); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 1); -} - -TEST_F(AssistantServiceTest, - IncreaseBackoffIfAssistantIsDisconnectedAfterRunning) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 1); -} - -TEST_F(AssistantServiceTest, WillRetryIfAssistantIsDisconnectedAfterRunning) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 1); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::STARTING); -} - -TEST_F(AssistantServiceTest, - WillNotRetryIfAssistantIsDisconnectedAfterRunning) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - - // Will retry start for the first `kMaxStartServiceRetries` times. - for (int i = 1; i <= kMaxStartServiceRetries; ++i) { - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), i); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::STARTING); - } - - // Will not retry start after disconnected `kMaxStartServiceRetries` times. - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries + 1); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); -} - -TEST_F(AssistantServiceTest, DecreaseBackoff) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - - for (int i = 1; i <= kMaxStartServiceRetries; ++i) { - GetRestartServiceBackoff()->InformOfRequest(/*succeeded=*/false); - } - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries + 1); - - for (int i = kMaxStartServiceRetries; i >= 0; --i) { - task_environment()->FastForwardBy(kAutoRecoverTime); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), i); - } - - // The `failure_count` will not be less than 0. - task_environment()->FastForwardBy(kAutoRecoverTime); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); -} - -TEST_F(AssistantServiceTest, WillRetryAfterDecreaseBackoff) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - - for (int i = 1; i <= kMaxStartServiceRetries; ++i) { - GetRestartServiceBackoff()->InformOfRequest(/*succeeded=*/false); - } - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries + 1); - - task_environment()->FastForwardBy(kAutoRecoverTime); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::STARTING); -} - -TEST_F(AssistantServiceTest, NoOpWhenRetryStartAfterDecreaseBackoff) { - for (int i = 1; i <= kMaxStartServiceRetries; ++i) { - GetRestartServiceBackoff()->InformOfRequest(/*succeeded=*/false); - } - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries); - - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - - DecreaseStartServiceBackoff(); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries - 1); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::RUNNING); -} - -TEST_F(AssistantServiceTest, ResetBackoffAfterReEnableSettings) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - - for (int i = 1; i <= kMaxStartServiceRetries; ++i) { - GetRestartServiceBackoff()->InformOfRequest(/*succeeded=*/false); - } - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries + 1); - - StopAssistantAndWait(); - StartAssistantAndWait(); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); -} - -TEST_F(AssistantServiceTest, WillStartAfterReEnableSettings) { - for (int i = 1; i <= kMaxStartServiceRetries + 1; ++i) { - GetRestartServiceBackoff()->InformOfRequest(/*succeeded=*/false); - } - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries + 1); - - StopAssistantAndWait(); - StartAssistantAndWait(); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - EXPECT_STATE(AssistantManagerService::State::STARTING); -} - -TEST_F(AssistantServiceTest, WillNotStartAfterMaxRetry_OnTokenRefreshed) { - ResetFakeAssistantManager(); - // Now force an access token refresh. - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay); - IssueAccessToken("new token"); - EXPECT_STATE(AssistantManagerService::State::STARTING); - - // Now force an access token refresh. - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay); - for (int i = 1; i <= kMaxStartServiceRetries; ++i) { - GetRestartServiceBackoff()->InformOfRequest(/*succeeded=*/false); - } - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries + 1); - - IssueAccessToken("new token"); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); -} - -TEST_F(AssistantServiceTest, - IncreaseFailuresPrefIfAssistantIsDisconnectedAfterStarting) { - StartAssistantAndWait(); - EXPECT_STATE(AssistantManagerService::State::STARTING); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 0); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 1); -} - -TEST_F(AssistantServiceTest, - IncreaseFailuresPrefIfAssistantIsDisconnectedAfterStarted) { - assistant_manager()->SetStateAndInformObservers( - AssistantManagerService::State::STARTED); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 0); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 1); -} - -TEST_F(AssistantServiceTest, - IncreaseFailuresPrefIfAssistantIsDisconnectedAfterRunning) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 0); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 1); -} - -TEST_F(AssistantServiceTest, ShouldRetryBasedOnNumberOfFailures) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 0); - - // Set pref kNumFailuresSinceLastServiceRun to `kMaxStartServiceRetries - 1`, - // disconnect will retry. - SetNumberOfFailuresSinceLastServiceRun(kMaxStartServiceRetries - 1); - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 1); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), kMaxStartServiceRetries); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::STARTING); - - // Pref kNumFailuresSinceLastServiceRun is kMaxStartServiceRetries now, - // disconnect will not retry. - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 2); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 1); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); -} - -TEST_F(AssistantServiceTest, - DecreaseBackoffRetryWillNotBasedOnNumberOfFailures) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 0); - - for (int i = 1; i <= kMaxStartServiceRetries; ++i) { - GetRestartServiceBackoff()->InformOfRequest(/*succeeded=*/false); - } - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries + 1); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 1); - - // Decreasing backoff will retry. - task_environment()->FastForwardBy(kAutoRecoverTime); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::STARTING); - - // Set pref kNumFailuresSinceLastServiceRun to > `kMaxStartServiceRetries`, - // decreasing backoff still will retry. - SetNumberOfFailuresSinceLastServiceRun(kMaxStartServiceRetries + 1); - task_environment()->FastForwardBy(kAutoRecoverTime); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), - kMaxStartServiceRetries - 1); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 1); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::STARTING); -} - -TEST_F(AssistantServiceTest, - WillNotResetNumberOfFailuresAfterReEnableSettings) { - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 0); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 1); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 1); - - StopAssistantAndWait(); - StartAssistantAndWait(); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 1); -} - -TEST_F(AssistantServiceTest, - WillStartAfterReEnableSettingsWithMaxNumberOfFailures) { - SetNumberOfFailuresSinceLastServiceRun(kMaxStartServiceRetries + 1); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 1); - - StopAssistantAndWait(); - StartAssistantAndWait(); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 1); - EXPECT_STATE(AssistantManagerService::State::STARTING); -} - -TEST_F(AssistantServiceTest, ResetNumberOfFailuresAfterRunning) { - SetNumberOfFailuresSinceLastServiceRun(kMaxStartServiceRetries + 1); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 1); - - assistant_manager()->FinishStart(); - EXPECT_STATE(AssistantManagerService::State::RUNNING); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), 0); -} - -TEST_F(AssistantServiceTest, - WillStartAfterMaxNumberOfFailures_OnTokenRefreshed) { - ResetFakeAssistantManager(); - // Now force an access token refresh. - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay); - IssueAccessToken("new token"); - EXPECT_STATE(AssistantManagerService::State::STARTING); - - // Now force an access token refresh. - task_environment()->FastForwardBy(kDefaultTokenExpirationDelay); - GetRestartServiceBackoff()->InformOfRequest(/*succeeded=*/false); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 1); - SetNumberOfFailuresSinceLastServiceRun(kMaxStartServiceRetries + 1); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 1); - - assistant_manager()->Disconnected(); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 2); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 2); - - IssueAccessToken("new token"); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - - // First decreasing backoff will not restart service. - task_environment()->FastForwardBy(kAutoRecoverTime); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 1); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 2); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::DISCONNECTED); - - // Second decreasing backoff will not restart service. - task_environment()->FastForwardBy(kAutoRecoverTime); - EXPECT_EQ(GetRestartServiceBackoff()->failure_count(), 0); - EXPECT_EQ(GetNumberOfFailuresSinceLastServiceRun(), - kMaxStartServiceRetries + 2); - - task_environment()->FastForwardBy( - GetRestartServiceBackoff()->GetTimeUntilRelease() * 1.2); - EXPECT_STATE(AssistantManagerService::State::STARTING); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/fake_assistant_manager_service_impl.cc b/chromeos/ash/services/assistant/test_support/fake_assistant_manager_service_impl.cc deleted file mode 100644 index cd3b94a..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_assistant_manager_service_impl.cc +++ /dev/null
@@ -1,162 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/fake_assistant_manager_service_impl.h" - -#include <utility> - -namespace ash::assistant { - -FakeAssistantManagerServiceImpl::FakeAssistantManagerServiceImpl() = default; - -FakeAssistantManagerServiceImpl::~FakeAssistantManagerServiceImpl() = default; - -void FakeAssistantManagerServiceImpl::FinishStart() { - SetStateAndInformObservers(State::RUNNING); -} - -void FakeAssistantManagerServiceImpl::Start(const std::optional<UserInfo>& user, - bool enable_hotword) { - SetStateAndInformObservers(State::STARTING); - SetUser(user); -} - -void FakeAssistantManagerServiceImpl::Stop() { - SetStateAndInformObservers(State::STOPPING); - SetStateAndInformObservers(State::STOPPED); - state_observers_.Clear(); -} - -void FakeAssistantManagerServiceImpl::Disconnected() { - SetStateAndInformObservers(State::DISCONNECTED); - state_observers_.Clear(); -} - -void FakeAssistantManagerServiceImpl::SetUser( - const std::optional<UserInfo>& user) { - if (user) { - gaia_id_ = user.value().gaia_id; - access_token_ = user.value().access_token; - } else { - gaia_id_ = std::nullopt; - access_token_ = std::nullopt; - } -} - -void FakeAssistantManagerServiceImpl::EnableListening(bool enable) {} - -void FakeAssistantManagerServiceImpl::EnableHotword(bool enable) {} - -void FakeAssistantManagerServiceImpl::SetArcPlayStoreEnabled(bool enabled) {} - -void FakeAssistantManagerServiceImpl::SetAssistantContextEnabled(bool enabled) { -} - -AssistantManagerService::State FakeAssistantManagerServiceImpl::GetState() - const { - return state_; -} - -AssistantSettings* FakeAssistantManagerServiceImpl::GetAssistantSettings() { - return &assistant_settings_; -} - -void FakeAssistantManagerServiceImpl::AddAndFireStateObserver( - StateObserver* observer) { - state_observers_.AddObserver(observer); - observer->OnStateChanged(GetState()); -} - -void FakeAssistantManagerServiceImpl::RemoveStateObserver( - const StateObserver* observer) { - state_observers_.RemoveObserver(observer); -} - -void FakeAssistantManagerServiceImpl::UpdateInternalMediaPlayerStatus( - MediaSessionAction action) {} - -void FakeAssistantManagerServiceImpl::StartEditReminderInteraction( - const std::string& client_id) {} - -void FakeAssistantManagerServiceImpl::StartTextInteraction( - const std::string& query, - AssistantQuerySource source, - bool allow_tts) {} - -void FakeAssistantManagerServiceImpl::StartVoiceInteraction() {} - -void FakeAssistantManagerServiceImpl::StopActiveInteraction( - bool cancel_conversation) {} - -void FakeAssistantManagerServiceImpl::AddAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) {} - -void FakeAssistantManagerServiceImpl::RemoveAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) {} - -mojo::PendingReceiver<libassistant::mojom::NotificationDelegate> -FakeAssistantManagerServiceImpl::GetPendingNotificationDelegate() { - return mojo::PendingReceiver<libassistant::mojom::NotificationDelegate>(); -} - -void FakeAssistantManagerServiceImpl::RetrieveNotification( - const AssistantNotification& notification, - int action_index) {} - -void FakeAssistantManagerServiceImpl::DismissNotification( - const AssistantNotification& notification) {} - -void FakeAssistantManagerServiceImpl::OnAccessibilityStatusChanged( - bool spoken_feedback_enabled) {} - -void FakeAssistantManagerServiceImpl::OnColorModeChanged( - bool dark_mode_enabled) {} - -void FakeAssistantManagerServiceImpl::SendAssistantFeedback( - const AssistantFeedback& feedback) {} - -void FakeAssistantManagerServiceImpl::AddTimeToTimer(const std::string& id, - base::TimeDelta duration) { -} - -void FakeAssistantManagerServiceImpl::PauseTimer(const std::string& id) {} - -void FakeAssistantManagerServiceImpl::RemoveAlarmOrTimer( - const std::string& id) {} - -void FakeAssistantManagerServiceImpl::ResumeTimer(const std::string& id) {} - -void FakeAssistantManagerServiceImpl::SetStateAndInformObservers( - State new_state) { - State old_state = state_; - state_ = new_state; - - // In reality we will not skip states, i.e. we will always get |STARTING| - // before ever encountering |STARTED|. As such our fake implementation will - // send out all intermediate states between |old_state| and |new_state|. - // |DISCONNECTED| is different, could be sent before |STARTED| and |RUNNING|. - if (new_state == State::DISCONNECTED) { - for (auto& observer : state_observers_) { - observer.OnStateChanged(state_); - } - return; - } - - MaybeSendStateChange(State::STOPPED, old_state, new_state); - MaybeSendStateChange(State::STARTING, old_state, new_state); - MaybeSendStateChange(State::STARTED, old_state, new_state); - MaybeSendStateChange(State::RUNNING, old_state, new_state); - MaybeSendStateChange(State::STOPPING, old_state, new_state); -} - -void FakeAssistantManagerServiceImpl::MaybeSendStateChange(State state, - State old_state, - State target_state) { - if (state > old_state && state <= target_state) { - for (auto& observer : state_observers_) - observer.OnStateChanged(state); - } -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/fake_assistant_manager_service_impl.h b/chromeos/ash/services/assistant/test_support/fake_assistant_manager_service_impl.h deleted file mode 100644 index 61ac3a4..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_assistant_manager_service_impl.h +++ /dev/null
@@ -1,109 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_ASSISTANT_MANAGER_SERVICE_IMPL_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_ASSISTANT_MANAGER_SERVICE_IMPL_H_ - -#include <memory> -#include <optional> -#include <string> -#include <vector> - -#include "base/component_export.h" -#include "base/observer_list.h" -#include "chromeos/ash/services/assistant/assistant_manager_service.h" -#include "chromeos/ash/services/assistant/test_support/fake_assistant_settings_impl.h" -#include "chromeos/ash/services/libassistant/public/mojom/notification_delegate.mojom-forward.h" -#include "google_apis/gaia/gaia_id.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" - -namespace ash::assistant { - -using media_session::mojom::MediaSessionAction; - -// Stub implementation of AssistantManagerService. -// Will return deterministic result for testing. -class COMPONENT_EXPORT(ASSISTANT_SERVICE) FakeAssistantManagerServiceImpl - : public AssistantManagerService { - public: - FakeAssistantManagerServiceImpl(); - - FakeAssistantManagerServiceImpl(const FakeAssistantManagerServiceImpl&) = - delete; - FakeAssistantManagerServiceImpl& operator=( - const FakeAssistantManagerServiceImpl&) = delete; - - ~FakeAssistantManagerServiceImpl() override; - - void FinishStart(); - - // assistant::AssistantManagerService overrides - void Start(const std::optional<UserInfo>& user, bool enable_hotword) override; - void Stop() override; - void SetUser(const std::optional<UserInfo>& user) override; - void EnableListening(bool enable) override; - void EnableHotword(bool enable) override; - void SetArcPlayStoreEnabled(bool enabled) override; - void SetAssistantContextEnabled(bool enable) override; - State GetState() const override; - AssistantSettings* GetAssistantSettings() override; - void AddAuthenticationStateObserver( - AuthenticationStateObserver* observer) override {} - void AddAndFireStateObserver(StateObserver* observer) override; - void RemoveStateObserver(const StateObserver* observer) override; - void SyncDeviceAppsStatus() override {} - void UpdateInternalMediaPlayerStatus(MediaSessionAction action) override; - - // Assistant overrides: - void StartEditReminderInteraction(const std::string& client_id) override; - void StartTextInteraction(const std::string& query, - AssistantQuerySource source, - bool allow_tts) override; - void StartVoiceInteraction() override; - void StopActiveInteraction(bool cancel_conversation) override; - void AddAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) override; - void AddRemoteConversationObserver(ConversationObserver* observer) override {} - void RemoveAssistantInteractionSubscriber( - AssistantInteractionSubscriber* subscriber) override; - mojo::PendingReceiver<libassistant::mojom::NotificationDelegate> - GetPendingNotificationDelegate() override; - void RetrieveNotification(const AssistantNotification& notification, - int action_index) override; - void DismissNotification(const AssistantNotification& notification) override; - void OnAccessibilityStatusChanged(bool spoken_feedback_enabled) override; - void OnColorModeChanged(bool dark_mode_enabled) override; - void SendAssistantFeedback(const AssistantFeedback& feedback) override; - void AddTimeToTimer(const std::string& id, base::TimeDelta duration) override; - void PauseTimer(const std::string& id) override; - void RemoveAlarmOrTimer(const std::string& id) override; - void ResumeTimer(const std::string& id) override; - - // Update the state to the corresponding value, and inform the - // |AssistantStateObserver| of the change. - void SetStateAndInformObservers(State new_state); - - // Return the access token that was passed to |SetUser|. - std::optional<std::string> access_token() { return access_token_; } - // Return the Gaia ID that was passed to |SetUser|. - const std::optional<GaiaId>& gaia_id() const { return gaia_id_; } - - void Disconnected(); - - private: - // Send out a |AssistantStateObserver::OnStateChange(state)| event if we are - // transitioning from a prior state to a later state. - void MaybeSendStateChange(State state, State old_state, State target_state); - - State state_ = State::STOPPED; - std::optional<GaiaId> gaia_id_; - std::optional<std::string> access_token_; - FakeAssistantSettingsImpl assistant_settings_; - base::ObserverList<StateObserver> state_observers_; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_ASSISTANT_MANAGER_SERVICE_IMPL_H_
diff --git a/chromeos/ash/services/assistant/test_support/fake_assistant_settings_impl.cc b/chromeos/ash/services/assistant/test_support/fake_assistant_settings_impl.cc deleted file mode 100644 index c33c8cb..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_assistant_settings_impl.cc +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/fake_assistant_settings_impl.h" - -#include <utility> - -#include "base/functional/callback.h" -#include "chromeos/ash/services/assistant/public/proto/get_settings_ui.pb.h" -#include "chromeos/ash/services/assistant/public/proto/settings_ui.pb.h" - -namespace ash::assistant { - -FakeAssistantSettingsImpl::FakeAssistantSettingsImpl() = default; - -FakeAssistantSettingsImpl::~FakeAssistantSettingsImpl() = default; - -void FakeAssistantSettingsImpl::GetSettings(const std::string& selector, - GetSettingsCallback callback) { - // Create a fake response - SettingsUi settings_ui; - settings_ui.mutable_consent_flow_ui()->set_consent_status( - ConsentFlowUi_ConsentStatus_ALREADY_CONSENTED); - std::move(callback).Run(settings_ui.SerializeAsString()); -} - -void FakeAssistantSettingsImpl::GetSettingsWithHeader( - const std::string& selector, - GetSettingsCallback callback) { - // Create a fake response - assistant::GetSettingsUiResponse response; - response.mutable_settings()->mutable_consent_flow_ui()->set_consent_status( - ConsentFlowUi_ConsentStatus_ALREADY_CONSENTED); - std::move(callback).Run(response.SerializeAsString()); -} - -void FakeAssistantSettingsImpl::UpdateSettings( - const std::string& update, - UpdateSettingsCallback callback) { - std::move(callback).Run(std::string()); -} - -void FakeAssistantSettingsImpl::StartSpeakerIdEnrollment( - bool skip_cloud_enrollment, - base::WeakPtr<SpeakerIdEnrollmentClient> client) { - client->OnSpeakerIdEnrollmentDone(); -} - -void FakeAssistantSettingsImpl::StopSpeakerIdEnrollment() {} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/fake_assistant_settings_impl.h b/chromeos/ash/services/assistant/test_support/fake_assistant_settings_impl.h deleted file mode 100644 index dcef2cd..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_assistant_settings_impl.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_ASSISTANT_SETTINGS_IMPL_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_ASSISTANT_SETTINGS_IMPL_H_ - -#include <memory> -#include <string> - -#include "chromeos/ash/services/assistant/public/cpp/assistant_settings.h" - -namespace ash::assistant { - -// TODO(jeroendh): Can be removed once FakeAssistantManagerServiceImpl is gone. -class FakeAssistantSettingsImpl : public AssistantSettings { - public: - FakeAssistantSettingsImpl(); - ~FakeAssistantSettingsImpl() override; - - // AssistantSettings overrides: - void GetSettings(const std::string& selector, - GetSettingsCallback callback) override; - void GetSettingsWithHeader(const std::string& selector, - GetSettingsCallback callback) override; - void UpdateSettings(const std::string& update, - UpdateSettingsCallback callback) override; - void StartSpeakerIdEnrollment( - bool skip_cloud_enrollment, - base::WeakPtr<SpeakerIdEnrollmentClient> client) override; - void StopSpeakerIdEnrollment() override; - void SyncSpeakerIdEnrollmentStatus() override {} -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_ASSISTANT_SETTINGS_IMPL_H_
diff --git a/chromeos/ash/services/assistant/test_support/fake_libassistant_service.cc b/chromeos/ash/services/assistant/test_support/fake_libassistant_service.cc deleted file mode 100644 index cfb593dd..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_libassistant_service.cc +++ /dev/null
@@ -1,89 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/fake_libassistant_service.h" - -#include "chromeos/ash/services/libassistant/public/mojom/notification_delegate.mojom-forward.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash::assistant { - -FakeLibassistantService::FakeLibassistantService() : receiver_(this) {} - -FakeLibassistantService::~FakeLibassistantService() = default; - -void FakeLibassistantService::Bind( - mojo::PendingReceiver<libassistant::mojom::LibassistantService> - pending_receiver) { - EXPECT_FALSE(receiver_.is_bound()) - << "Cannot bind the LibassistantService twice"; - receiver_.Bind(std::move(pending_receiver)); -} - -void FakeLibassistantService::Unbind() { - receiver_.reset(); - service_controller().Unbind(); -} - -mojo::PendingReceiver<libassistant::mojom::MediaController> -FakeLibassistantService::GetMediaControllerPendingReceiver() { - EXPECT_TRUE(media_controller_pending_receiver_.is_valid()); - return std::move(media_controller_pending_receiver_); -} - -mojo::PendingRemote<libassistant::mojom::MediaDelegate> -FakeLibassistantService::GetMediaDelegatePendingRemote() { - EXPECT_TRUE(media_delegate_pending_remote_.is_valid()); - return std::move(media_delegate_pending_remote_); -} - -mojo::PendingReceiver<libassistant::mojom::SpeakerIdEnrollmentController> -FakeLibassistantService::GetSpeakerIdEnrollmentControllerPendingReceiver() { - EXPECT_TRUE(speaker_id_enrollment_controller_pending_receiver_.is_valid()); - return std::move(speaker_id_enrollment_controller_pending_receiver_); -} - -void FakeLibassistantService::Bind( - mojo::PendingReceiver<libassistant::mojom::AudioInputController> - audio_input_controller, - mojo::PendingReceiver<libassistant::mojom::ConversationController> - conversation_controller, - mojo::PendingReceiver<libassistant::mojom::DisplayController> - display_controller, - mojo::PendingReceiver<libassistant::mojom::MediaController> - media_controller, - mojo::PendingReceiver<libassistant::mojom::ServiceController> - service_controller, - mojo::PendingReceiver<libassistant::mojom::SettingsController> - settings_controller, - mojo::PendingReceiver<libassistant::mojom::SpeakerIdEnrollmentController> - speaker_id_enrollment_controller, - mojo::PendingReceiver<libassistant::mojom::TimerController> - timer_controller, - mojo::PendingRemote<libassistant::mojom::AudioOutputDelegate> - audio_output_delegate, - mojo::PendingRemote<libassistant::mojom::DeviceSettingsDelegate> - device_settings_delegate, - mojo::PendingRemote<libassistant::mojom::MediaDelegate> media_delegate, - mojo::PendingRemote<libassistant::mojom::NotificationDelegate> - notification_delegate, - mojo::PendingRemote<libassistant::mojom::PlatformDelegate> - platform_delegate, - mojo::PendingRemote<libassistant::mojom::TimerDelegate> timer_delegate) { - service_controller_.Bind(std::move(service_controller), - std::move(settings_controller)); - media_controller_pending_receiver_ = std::move(media_controller); - media_delegate_pending_remote_ = std::move(media_delegate); - speaker_id_enrollment_controller_pending_receiver_ = - std::move(speaker_id_enrollment_controller); -} - -void FakeLibassistantService::FlushForTesting() { - if (receiver_.is_bound()) { - receiver_.FlushForTesting(); - } -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/fake_libassistant_service.h b/chromeos/ash/services/assistant/test_support/fake_libassistant_service.h deleted file mode 100644 index 335cd9a..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_libassistant_service.h +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_LIBASSISTANT_SERVICE_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_LIBASSISTANT_SERVICE_H_ - -#include "chromeos/ash/services/assistant/test_support/fake_service_controller.h" -#include "chromeos/ash/services/libassistant/public/mojom/notification_delegate.mojom-forward.h" -#include "chromeos/ash/services/libassistant/public/mojom/service.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/speaker_id_enrollment_controller.mojom-forward.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" -#include "mojo/public/cpp/bindings/pending_remote.h" -#include "mojo/public/cpp/bindings/receiver.h" - -namespace ash::assistant { - -// Fake implementation of the Libassistant Mojom service. -// It allows hooks to read and control the state of the service. -class FakeLibassistantService - : public libassistant::mojom::LibassistantService { - public: - FakeLibassistantService(); - FakeLibassistantService(FakeLibassistantService&) = delete; - FakeLibassistantService& operator=(FakeLibassistantService&) = delete; - ~FakeLibassistantService() override; - - void Bind(mojo::PendingReceiver<libassistant::mojom::LibassistantService> - pending_receiver); - void Unbind(); - - FakeServiceController& service_controller() { return service_controller_; } - FakeServiceController& settings_controller() { return service_controller_; } - - // Return the receiver that was passed into the last Bind() call. - mojo::PendingReceiver<libassistant::mojom::MediaController> - GetMediaControllerPendingReceiver(); - mojo::PendingRemote<libassistant::mojom::MediaDelegate> - GetMediaDelegatePendingRemote(); - mojo::PendingReceiver<libassistant::mojom::SpeakerIdEnrollmentController> - GetSpeakerIdEnrollmentControllerPendingReceiver(); - - // mojom::LibassistantService implementation: - void Bind( - mojo::PendingReceiver<libassistant::mojom::AudioInputController> - audio_input_controller, - mojo::PendingReceiver<libassistant::mojom::ConversationController> - conversation_controller, - mojo::PendingReceiver<libassistant::mojom::DisplayController> - display_controller, - mojo::PendingReceiver<libassistant::mojom::MediaController> - media_controller, - mojo::PendingReceiver<libassistant::mojom::ServiceController> - service_controller, - mojo::PendingReceiver<libassistant::mojom::SettingsController> - settings_controller, - mojo::PendingReceiver<libassistant::mojom::SpeakerIdEnrollmentController> - speaker_id_enrollment_controller, - mojo::PendingReceiver<libassistant::mojom::TimerController> - timer_controller, - mojo::PendingRemote<libassistant::mojom::AudioOutputDelegate> - audio_output_delegate, - mojo::PendingRemote<libassistant::mojom::DeviceSettingsDelegate> - device_settings_delegate, - mojo::PendingRemote<libassistant::mojom::MediaDelegate> media_delegate, - mojo::PendingRemote<libassistant::mojom::NotificationDelegate> - notification_delegate, - mojo::PendingRemote<libassistant::mojom::PlatformDelegate> - platform_delegate, - mojo::PendingRemote<libassistant::mojom::TimerDelegate> timer_delegate) - override; - void AddSpeechRecognitionObserver( - mojo::PendingRemote<libassistant::mojom::SpeechRecognitionObserver> - observer) override {} - void AddAuthenticationStateObserver( - mojo::PendingRemote<libassistant::mojom::AuthenticationStateObserver> - observer) override {} - - void FlushForTesting(); - - private: - mojo::Receiver<libassistant::mojom::LibassistantService> receiver_; - - mojo::PendingReceiver<libassistant::mojom::MediaController> - media_controller_pending_receiver_; - mojo::PendingReceiver<libassistant::mojom::SpeakerIdEnrollmentController> - speaker_id_enrollment_controller_pending_receiver_; - mojo::PendingRemote<libassistant::mojom::MediaDelegate> - media_delegate_pending_remote_; - - FakeServiceController service_controller_; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_LIBASSISTANT_SERVICE_H_
diff --git a/chromeos/ash/services/assistant/test_support/fake_service_context.cc b/chromeos/ash/services/assistant/test_support/fake_service_context.cc deleted file mode 100644 index f94338f2..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_service_context.cc +++ /dev/null
@@ -1,115 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <string> - -#include "base/task/sequenced_task_runner.h" -#include "base/task/single_thread_task_runner.h" -#include "chromeos/ash/services/assistant/public/cpp/device_actions.h" -#include "chromeos/ash/services/assistant/test_support/fake_service_context.h" - -namespace ash::assistant { - -/*static*/ -constexpr GaiaId::Literal FakeServiceContext::kGaiaId; - -FakeServiceContext::FakeServiceContext() = default; - -FakeServiceContext::~FakeServiceContext() = default; - -FakeServiceContext& FakeServiceContext::set_assistant_alarm_timer_controller( - AssistantAlarmTimerController* value) { - assistant_alarm_timer_controller_ = value; - return *this; -} - -FakeServiceContext& FakeServiceContext::set_main_task_runner( - scoped_refptr<base::SingleThreadTaskRunner> value) { - main_task_runner_ = value; - return *this; -} - -FakeServiceContext& FakeServiceContext::set_power_manager_client( - chromeos::PowerManagerClient* value) { - power_manager_client_ = value; - return *this; -} - -FakeServiceContext& FakeServiceContext::set_primary_account_gaia_id( - const GaiaId& value) { - gaia_id_ = value; - return *this; -} - -FakeServiceContext& FakeServiceContext::set_assistant_state( - AssistantStateBase* value) { - assistant_state_ = value; - return *this; -} - -FakeServiceContext& FakeServiceContext::set_assistant_notification_controller( - AssistantNotificationController* value) { - assistant_notification_controller_ = value; - return *this; -} - -FakeServiceContext& FakeServiceContext::set_cras_audio_handler( - CrasAudioHandler* value) { - cras_audio_handler_ = value; - return *this; -} - -AssistantAlarmTimerController* -FakeServiceContext::assistant_alarm_timer_controller() { - DCHECK(assistant_alarm_timer_controller_ != nullptr); - return assistant_alarm_timer_controller_; -} - -AssistantController* FakeServiceContext::assistant_controller() { - NOTIMPLEMENTED(); - return nullptr; -} - -AssistantNotificationController* -FakeServiceContext::assistant_notification_controller() { - DCHECK(assistant_notification_controller_ != nullptr); - return assistant_notification_controller_; -} - -AssistantScreenContextController* -FakeServiceContext::assistant_screen_context_controller() { - NOTIMPLEMENTED(); - return nullptr; -} - -AssistantStateBase* FakeServiceContext::assistant_state() { - DCHECK(assistant_state_ != nullptr); - return assistant_state_; -} - -CrasAudioHandler* FakeServiceContext::cras_audio_handler() { - DCHECK(cras_audio_handler_ != nullptr); - return cras_audio_handler_; -} - -DeviceActions* FakeServiceContext::device_actions() { - return DeviceActions::Get(); -} - -scoped_refptr<base::SequencedTaskRunner> -FakeServiceContext::main_task_runner() { - DCHECK(main_task_runner_ != nullptr); - return main_task_runner_; -} - -chromeos::PowerManagerClient* FakeServiceContext::power_manager_client() { - DCHECK(power_manager_client_ != nullptr); - return power_manager_client_; -} - -GaiaId FakeServiceContext::primary_account_gaia_id() { - return gaia_id_; -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/fake_service_context.h b/chromeos/ash/services/assistant/test_support/fake_service_context.h deleted file mode 100644 index b3363e2..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_service_context.h +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTEXT_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTEXT_H_ - -#include "base/memory/raw_ptr.h" -#include "base/task/sequenced_task_runner.h" -#include "base/task/single_thread_task_runner.h" -#include "chromeos/ash/services/assistant/service_context.h" -#include "google_apis/gaia/gaia_id.h" - -namespace ash::assistant { - -// Fake implementation of the |ServiceContext| used during the unittests. -// Every method will assert when called, -// unless you've provided the object using one of the setter methods. -class FakeServiceContext : public ServiceContext { - public: - // Gaia ID returned by primary_account_gaia_id() (unless overridden). - static constexpr GaiaId::Literal kGaiaId = GaiaId::Literal("<fake-gaia-id>"); - - FakeServiceContext(); - FakeServiceContext(const FakeServiceContext&) = delete; - FakeServiceContext& operator=(const FakeServiceContext&) = delete; - ~FakeServiceContext() override; - - FakeServiceContext& set_assistant_alarm_timer_controller( - AssistantAlarmTimerController*); - FakeServiceContext& set_main_task_runner( - scoped_refptr<base::SingleThreadTaskRunner>); - FakeServiceContext& set_power_manager_client(chromeos::PowerManagerClient*); - FakeServiceContext& set_primary_account_gaia_id(const GaiaId&); - FakeServiceContext& set_assistant_state(AssistantStateBase*); - FakeServiceContext& set_assistant_notification_controller( - AssistantNotificationController*); - FakeServiceContext& set_cras_audio_handler(CrasAudioHandler*); - - // ServiceContext implementation: - AssistantAlarmTimerController* assistant_alarm_timer_controller() override; - AssistantController* assistant_controller() override; - AssistantNotificationController* assistant_notification_controller() override; - AssistantScreenContextController* assistant_screen_context_controller() - override; - AssistantStateBase* assistant_state() override; - CrasAudioHandler* cras_audio_handler() override; - DeviceActions* device_actions() override; - scoped_refptr<base::SequencedTaskRunner> main_task_runner() override; - chromeos::PowerManagerClient* power_manager_client() override; - GaiaId primary_account_gaia_id() override; - - private: - scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_; - raw_ptr<AssistantStateBase> assistant_state_ = nullptr; - raw_ptr<chromeos::PowerManagerClient, DanglingUntriaged> - power_manager_client_ = nullptr; - GaiaId gaia_id_ = kGaiaId; - raw_ptr<AssistantAlarmTimerController> assistant_alarm_timer_controller_ = - nullptr; - raw_ptr<AssistantNotificationController> assistant_notification_controller_ = - nullptr; - raw_ptr<CrasAudioHandler> cras_audio_handler_ = nullptr; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTEXT_H_
diff --git a/chromeos/ash/services/assistant/test_support/fake_service_controller.cc b/chromeos/ash/services/assistant/test_support/fake_service_controller.cc deleted file mode 100644 index 8aa259f2c..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_service_controller.cc +++ /dev/null
@@ -1,143 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/fake_service_controller.h" - -#include "base/task/sequenced_task_runner.h" -#include "google_apis/gaia/gaia_id.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace ash::assistant { - -// A macro which ensures we are running on the mojom thread. -#define ENSURE_MOJOM_THREAD(method, ...) \ - if (!mojom_task_runner_->RunsTasksInCurrentSequence()) { \ - mojom_task_runner_->PostTask( \ - FROM_HERE, \ - base::BindOnce(method, weak_factory_.GetWeakPtr(), ##__VA_ARGS__)); \ - return; \ - } - -FakeServiceController::FakeServiceController() {} -FakeServiceController::~FakeServiceController() = default; - -void FakeServiceController::SetState(State new_state) { - // SetState() is called from our unittests, but the observers are registered - // on the mojom thread so we must switch threads. - ENSURE_MOJOM_THREAD(&FakeServiceController::SetState, new_state); - DCHECK_NE(state_, new_state); - - state_ = new_state; - - for (auto& observer : state_observers_) - observer->OnStateChanged(state_); -} - -void FakeServiceController::Bind( - mojo::PendingReceiver<libassistant::mojom::ServiceController> - service_receiver, - mojo::PendingReceiver<libassistant::mojom::SettingsController> - settings_receiver) { - service_receiver_.Bind(std::move(service_receiver)); - settings_receiver_.Bind(std::move(settings_receiver)); -} - -void FakeServiceController::Unbind() { - // All mojom objects must now be unbound, as that needs to happen on the - // same thread as they were bound (which is the background thread). - service_receiver_.reset(); - settings_receiver_.reset(); - state_observers_.Clear(); -} - -void FakeServiceController::BlockStartCalls() { - // This lock will be release in |UnblockStartCalls|. - start_mutex_.lock(); -} - -void FakeServiceController::UnblockStartCalls() { - start_mutex_.unlock(); -} - -std::string FakeServiceController::access_token() { - if (authentication_tokens_.size()) - return authentication_tokens_[0]->access_token; - else - return kNoValue; -} - -GaiaId FakeServiceController::gaia_id() { - if (authentication_tokens_.size()) { - return GaiaId(authentication_tokens_[0]->gaia_id); - } else { - return GaiaId(kNoValue); - } -} - -void FakeServiceController::Initialize( - libassistant::mojom::BootupConfigPtr config, - mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory) { - mojom_task_runner_ = base::SequencedTaskRunner::GetCurrentDefault(); - libassistant_config_ = std::move(config); - - authentication_tokens_ = - std::move(libassistant_config_->authentication_tokens); - dark_mode_enabled_ = libassistant_config_->dark_mode_enabled; -} - -void FakeServiceController::Start() { - // Will block if |BlockStartCalls| was invoked. - std::lock_guard<std::mutex> lock(start_mutex_); - - SetState(State::kStarted); -} - -void FakeServiceController::Stop() { - // Post a delayed task to make it possible to set other state between - // kStopping and kStopped. - base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&FakeServiceController::SetState, - weak_factory_.GetWeakPtr(), State::kStopped), - base::Milliseconds(1)); -} - -void FakeServiceController::ResetAllDataAndStop() { - SetState(State::kStopped); - has_data_been_reset_ = true; -} - -void FakeServiceController::AddAndFireStateObserver( - mojo::PendingRemote<libassistant::mojom::StateObserver> pending_observer) { - mojo::Remote<libassistant::mojom::StateObserver> observer( - std::move(pending_observer)); - - observer->OnStateChanged(state_); - - state_observers_.Add(std::move(observer)); -} - -void FakeServiceController::SetAuthenticationTokens( - std::vector<libassistant::mojom::AuthenticationTokenPtr> tokens) { - authentication_tokens_ = std::move(tokens); -} - -void FakeServiceController::SetDarkModeEnabled(bool value) { - dark_mode_enabled_ = value; -} - -void FakeServiceController::UpdateSettings(const std::string& settings, - UpdateSettingsCallback callback) { - // Callback must be called to satisfy the mojom contract. - std::move(callback).Run(std::string()); -} - -void FakeServiceController::GetSettings(const std::string& selector, - bool include_header, - GetSettingsCallback callback) { - // Callback must be called to satisfy the mojom contract. - std::move(callback).Run(std::string()); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/fake_service_controller.h b/chromeos/ash/services/assistant/test_support/fake_service_controller.h deleted file mode 100644 index dcab584..0000000 --- a/chromeos/ash/services/assistant/test_support/fake_service_controller.h +++ /dev/null
@@ -1,136 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTROLLER_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTROLLER_H_ - -#include <mutex> -#include <optional> -#include <string> - -#include "base/memory/weak_ptr.h" -#include "base/task/sequenced_task_runner.h" -#include "chromeos/ash/services/libassistant/public/mojom/service_controller.mojom.h" -#include "chromeos/ash/services/libassistant/public/mojom/settings_controller.mojom.h" -#include "google_apis/gaia/gaia_id.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote_set.h" - -namespace ash::assistant { - -// Fake implementation of the Mojom |ServiceController| and -// |SettingsController|. This implementation will inform the registered -// |StateObserver| instances of any state change, just like the real -// implementation. -class FakeServiceController : public libassistant::mojom::ServiceController, - public libassistant::mojom::SettingsController { - public: - // Value returned when optional fields |access_token| or |user_id| are - // missing. Note we use this instead of a |std::optional| because this - // results in a much nicer error message if the test fails. (otherwise you get - // a message like this: - // Expected equality of these values: - // "<new-user-id-wrong>" - // with 32-byte object <01-00 snip 00-00> - static constexpr const char* kNoValue = "<no-value>"; - - using State = libassistant::mojom::ServiceState; - - FakeServiceController(); - FakeServiceController(FakeServiceController&) = delete; - FakeServiceController& operator=(FakeServiceController&) = delete; - ~FakeServiceController() override; - - // Puts the service in the given state. Will inform all observers of the state - // change. - void SetState(State new_state); - State state() const { return state_; } - - // Returns the Libassistant config that was passed to Initialize(). - const libassistant::mojom::BootupConfig& libassistant_config() { - DCHECK(libassistant_config_); - return *libassistant_config_; - } - - void Bind(mojo::PendingReceiver<libassistant::mojom::ServiceController> - service_receiver, - mojo::PendingReceiver<libassistant::mojom::SettingsController> - settings_receiver); - void Unbind(); - - // Call this to block any call to |Start|. The observers will not be invoked - // as long as the start call is blocked. Unblock these calls using - // |UnblockStartCalls|. This is not enabled by default, so unless you call - // |BlockStartCalls| any |Start| call will simply finish immediately. - void BlockStartCalls(); - void UnblockStartCalls(); - - // Return the access-token that was passed to |SetAuthenticationTokens|, or - // |kNoValue| if an empty vector was passed in. - std::string access_token(); - // Return the user-id that was passed to |SetAuthenticationTokens|, or - // |kNoValue| if an empty vector was passed in. - GaiaId gaia_id(); - - // True if ResetAllDataAndStop() was called. - bool has_data_been_reset() const { return has_data_been_reset_; } - - std::optional<bool> dark_mode_enabled() const { return dark_mode_enabled_; } - - private: - // mojom::ServiceController implementation: - void Initialize(libassistant::mojom::BootupConfigPtr config, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - url_loader_factory) override; - void Start() override; - void Stop() override; - void ResetAllDataAndStop() override; - void AddAndFireStateObserver( - mojo::PendingRemote<libassistant::mojom::StateObserver> pending_observer) - override; - - // mojom::SettingsController implementation: - void SetAuthenticationTokens( - std::vector<libassistant::mojom::AuthenticationTokenPtr> tokens) override; - void SetListeningEnabled(bool value) override {} - void SetLocale(const std::string& value) override {} - void SetSpokenFeedbackEnabled(bool value) override {} - void SetDarkModeEnabled(bool value) override; - void UpdateSettings(const std::string& settings, - UpdateSettingsCallback callback) override; - void GetSettings(const std::string& selector, - bool include_header, - GetSettingsCallback callback) override; - void SetHotwordEnabled(bool value) override {} - - // Mutex taken in |Start| to allow the calls to block if |BlockStartCalls| was - // called. - std::mutex start_mutex_; - - // Config passed to LibAssistant when it was started. - libassistant::mojom::BootupConfigPtr libassistant_config_; - - // True if ResetAllDataAndStop() was called. - bool has_data_been_reset_ = false; - - // Authentication tokens passed to SetAuthenticationTokens(). - std::vector<libassistant::mojom::AuthenticationTokenPtr> - authentication_tokens_; - - std::optional<bool> dark_mode_enabled_; - - State state_ = State::kStopped; - mojo::Receiver<libassistant::mojom::ServiceController> service_receiver_{ - this}; - mojo::Receiver<libassistant::mojom::SettingsController> settings_receiver_{ - this}; - mojo::RemoteSet<libassistant::mojom::StateObserver> state_observers_; - scoped_refptr<base::SequencedTaskRunner> mojom_task_runner_; - - base::WeakPtrFactory<FakeServiceController> weak_factory_{this}; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FAKE_SERVICE_CONTROLLER_H_
diff --git a/chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.cc b/chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.cc deleted file mode 100644 index 1df9168..0000000 --- a/chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.cc +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.h" - -namespace ash::assistant { - -FullyInitializedAssistantState::FullyInitializedAssistantState() { - InitializeAllValues(); -} - -void FullyInitializedAssistantState::SetAssistantEnabled(bool enabled) { - settings_enabled_ = enabled; - - for (auto& observer : observers_) - observer.OnAssistantSettingsEnabled(settings_enabled_.value()); -} - -void FullyInitializedAssistantState::SetContextEnabled(bool enabled) { - context_enabled_ = enabled; -} - -void FullyInitializedAssistantState::InitializeAllValues() { - settings_enabled_ = true; - consent_status_ = prefs::ConsentStatus::kActivityControlAccepted; - context_enabled_ = true; - hotword_enabled_ = true; - hotword_always_on_ = true; - launch_with_mic_open_ = true; - notification_enabled_ = true; - allowed_state_ = AssistantAllowedState::ALLOWED; - locale_ = "en_US"; - arc_play_store_enabled_ = true; - locked_full_screen_enabled_ = true; -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.h b/chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.h deleted file mode 100644 index 079194e..0000000 --- a/chromeos/ash/services/assistant/test_support/fully_initialized_assistant_state.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FULLY_INITIALIZED_ASSISTANT_STATE_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FULLY_INITIALIZED_ASSISTANT_STATE_H_ - -#include "ash/public/cpp/assistant/assistant_state.h" - -namespace ash::assistant { - -// Instance of |AssistantState| where every std::optional value has a non-null -// value. All values will be set to their equivalent of enabled. -class FullyInitializedAssistantState : public AssistantState { - public: - FullyInitializedAssistantState(); - - FullyInitializedAssistantState(const FullyInitializedAssistantState&) = - delete; - FullyInitializedAssistantState& operator=( - const FullyInitializedAssistantState&) = delete; - - ~FullyInitializedAssistantState() override = default; - - void SetAssistantEnabled(bool enabled); - - void SetContextEnabled(bool enabled); - - private: - void InitializeAllValues(); -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_FULLY_INITIALIZED_ASSISTANT_STATE_H_
diff --git a/chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.cc b/chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.cc deleted file mode 100644 index ec904162..0000000 --- a/chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.cc +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.h" - -namespace ash::assistant { - -LibassistantMediaControllerMock::LibassistantMediaControllerMock() = default; -LibassistantMediaControllerMock::~LibassistantMediaControllerMock() = default; - -void LibassistantMediaControllerMock::Bind( - mojo::PendingReceiver<libassistant::mojom::MediaController> - pending_receiver) { - receiver_.Bind(std::move(pending_receiver)); -} - -void LibassistantMediaControllerMock::FlushForTesting() { - receiver_.FlushForTesting(); -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.h b/chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.h deleted file mode 100644 index f311b68..0000000 --- a/chromeos/ash/services/assistant/test_support/libassistant_media_controller_mock.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_LIBASSISTANT_MEDIA_CONTROLLER_MOCK_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_LIBASSISTANT_MEDIA_CONTROLLER_MOCK_H_ - -#include "chromeos/ash/services/libassistant/public/mojom/media_controller.mojom.h" - -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace ash::assistant { - -class LibassistantMediaControllerMock - : public libassistant::mojom::MediaController { - public: - LibassistantMediaControllerMock(); - LibassistantMediaControllerMock(const LibassistantMediaControllerMock&) = - delete; - LibassistantMediaControllerMock& operator=( - const LibassistantMediaControllerMock&) = delete; - ~LibassistantMediaControllerMock() override; - - void Bind(mojo::PendingReceiver<libassistant::mojom::MediaController>); - void FlushForTesting(); - - // libassistant::mojom::MediaController implementation: - MOCK_METHOD(void, ResumeInternalMediaPlayer, ()); - MOCK_METHOD(void, PauseInternalMediaPlayer, ()); - MOCK_METHOD(void, - SetExternalPlaybackState, - (libassistant::mojom::MediaStatePtr state)); - - private: - mojo::Receiver<libassistant::mojom::MediaController> receiver_{this}; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_LIBASSISTANT_MEDIA_CONTROLLER_MOCK_H_
diff --git a/chromeos/ash/services/assistant/test_support/mock_assistant.cc b/chromeos/ash/services/assistant/test_support/mock_assistant.cc deleted file mode 100644 index 81e7b6a..0000000 --- a/chromeos/ash/services/assistant/test_support/mock_assistant.cc +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/mock_assistant.h" -#include "chromeos/ash/services/libassistant/public/cpp/assistant_feedback.h" - -namespace ash::assistant { - -MockAssistant::MockAssistant() = default; - -MockAssistant::~MockAssistant() = default; - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/mock_assistant.h b/chromeos/ash/services/assistant/test_support/mock_assistant.h deleted file mode 100644 index 88b7ab3..0000000 --- a/chromeos/ash/services/assistant/test_support/mock_assistant.h +++ /dev/null
@@ -1,56 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_MOCK_ASSISTANT_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_MOCK_ASSISTANT_H_ - -#include <string> -#include <vector> - -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "ui/accessibility/mojom/ax_assistant_structure.mojom.h" - -namespace ash::assistant { - -class MockAssistant : public Assistant { - public: - MockAssistant(); - - MockAssistant(const MockAssistant&) = delete; - MockAssistant& operator=(const MockAssistant&) = delete; - - ~MockAssistant() override; - - MOCK_METHOD1(StartEditReminderInteraction, void(const std::string&)); - - MOCK_METHOD(void, - StartTextInteraction, - (const std::string&, AssistantQuerySource, bool)); - - MOCK_METHOD0(StartVoiceInteraction, void()); - - MOCK_METHOD1(StopActiveInteraction, void(bool)); - - MOCK_METHOD1(AddAssistantInteractionSubscriber, - void(AssistantInteractionSubscriber*)); - - MOCK_METHOD1(RemoveAssistantInteractionSubscriber, - void(AssistantInteractionSubscriber*)); - - MOCK_METHOD2(RetrieveNotification, void(const AssistantNotification&, int)); - - MOCK_METHOD1(DismissNotification, void(const AssistantNotification&)); - - MOCK_METHOD1(OnAccessibilityStatusChanged, void(bool)); - - MOCK_METHOD1(SendAssistantFeedback, void(const AssistantFeedback&)); - - MOCK_METHOD0(StopAlarmTimerRinging, void()); - MOCK_METHOD1(CreateTimer, void(base::TimeDelta)); -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_MOCK_ASSISTANT_H_
diff --git a/chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.cc b/chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.cc deleted file mode 100644 index 444680b1..0000000 --- a/chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.cc +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.h" - -namespace ash::assistant { - -MockAssistantInteractionSubscriber::MockAssistantInteractionSubscriber() = - default; -MockAssistantInteractionSubscriber::~MockAssistantInteractionSubscriber() = - default; - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.h b/chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.h deleted file mode 100644 index 0a4a4d8..0000000 --- a/chromeos/ash/services/assistant/test_support/mock_assistant_interaction_subscriber.h +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_MOCK_ASSISTANT_INTERACTION_SUBSCRIBER_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_MOCK_ASSISTANT_INTERACTION_SUBSCRIBER_H_ - -#include <string> -#include <vector> - -#include "chromeos/ash/services/assistant/public/cpp/assistant_service.h" -#include "testing/gmock/include/gmock/gmock.h" - -namespace ash::assistant { - -class MockAssistantInteractionSubscriber - : public AssistantInteractionSubscriber { - public: - MockAssistantInteractionSubscriber(); - MockAssistantInteractionSubscriber( - const MockAssistantInteractionSubscriber&) = delete; - MockAssistantInteractionSubscriber& operator=( - const MockAssistantInteractionSubscriber&) = delete; - ~MockAssistantInteractionSubscriber() override; - - // AssistantInteractionSubscriber: - MOCK_METHOD(void, - OnInteractionStarted, - (const AssistantInteractionMetadata&), - (override)); - MOCK_METHOD(void, - OnInteractionFinished, - (AssistantInteractionResolution), - (override)); - MOCK_METHOD(void, - OnHtmlResponse, - (const std::string&, const std::string&), - (override)); - MOCK_METHOD(void, - OnSuggestionsResponse, - (const std::vector<AssistantSuggestion>&), - (override)); - MOCK_METHOD(void, OnTextResponse, (const std::string&), (override)); - MOCK_METHOD(void, OnOpenUrlResponse, (const ::GURL&, bool), (override)); - MOCK_METHOD(void, OnOpenAppResponse, (const AndroidAppInfo&), (override)); - MOCK_METHOD(void, OnSpeechRecognitionStarted, (), (override)); - MOCK_METHOD(void, - OnSpeechRecognitionIntermediateResult, - (const std::string&, const std::string&), - (override)); - MOCK_METHOD(void, OnSpeechRecognitionEndOfUtterance, (), (override)); - MOCK_METHOD(void, - OnSpeechRecognitionFinalResult, - (const std::string&), - (override)); - MOCK_METHOD(void, OnSpeechLevelUpdated, (float), (override)); - MOCK_METHOD(void, OnTtsStarted, (bool), (override)); - MOCK_METHOD(void, OnWaitStarted, (), (override)); -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_MOCK_ASSISTANT_INTERACTION_SUBSCRIBER_H_
diff --git a/chromeos/ash/services/assistant/test_support/scoped_device_actions.cc b/chromeos/ash/services/assistant/test_support/scoped_device_actions.cc deleted file mode 100644 index ab8d953..0000000 --- a/chromeos/ash/services/assistant/test_support/scoped_device_actions.cc +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/test_support/scoped_device_actions.h" - -#include <utility> - -namespace ash::assistant { - -void ScopedDeviceActions::GetScreenBrightnessLevel( - GetScreenBrightnessLevelCallback callback) { - std::move(callback).Run(/*success=*/true, current_brightness_); -} - -bool ScopedDeviceActions::OpenAndroidApp(const AndroidAppInfo& app_info) { - return true; -} - -AppStatus ScopedDeviceActions::GetAndroidAppStatus( - const AndroidAppInfo& app_info) { - return AppStatus::kAvailable; -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/test_support/scoped_device_actions.h b/chromeos/ash/services/assistant/test_support/scoped_device_actions.h deleted file mode 100644 index da6a1a7..0000000 --- a/chromeos/ash/services/assistant/test_support/scoped_device_actions.h +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_SCOPED_DEVICE_ACTIONS_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_SCOPED_DEVICE_ACTIONS_H_ - -#include <string> -#include <vector> - -#include "chromeos/ash/services/assistant/public/cpp/device_actions.h" - -namespace ash::assistant { - -class ScopedDeviceActions : DeviceActions { - public: - ScopedDeviceActions() = default; - ~ScopedDeviceActions() override = default; - - // assistant::DeviceActions overrides: - void SetWifiEnabled(bool enabled) override {} - void SetBluetoothEnabled(bool enabled) override {} - void GetScreenBrightnessLevel( - GetScreenBrightnessLevelCallback callback) override; - void SetScreenBrightnessLevel(double level, bool gradual) override {} - void SetNightLightEnabled(bool enabled) override {} - void SetSwitchAccessEnabled(bool enabled) override {} - bool OpenAndroidApp(const AndroidAppInfo& app_info) override; - AppStatus GetAndroidAppStatus(const AndroidAppInfo& app_info) override; - void LaunchAndroidIntent(const std::string& intent) override {} - void AddAndFireAppListEventSubscriber( - AppListEventSubscriber* subscriber) override {} - void RemoveAppListEventSubscriber( - AppListEventSubscriber* subscriber) override {} - - // Set the brightness value that will be returned by - // GetScreenBrightnessLevel(); - void set_current_brightness(double value) { current_brightness_ = value; } - - private: - double current_brightness_ = 0.0; -}; - -} // namespace ash::assistant - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TEST_SUPPORT_SCOPED_DEVICE_ACTIONS_H_
diff --git a/chromeos/ash/services/assistant/timer_host.cc b/chromeos/ash/services/assistant/timer_host.cc deleted file mode 100644 index 4e2114b..0000000 --- a/chromeos/ash/services/assistant/timer_host.cc +++ /dev/null
@@ -1,96 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/ash/services/assistant/timer_host.h" - -#include "ash/public/cpp/assistant/controller/assistant_alarm_timer_controller.h" -#include "base/memory/raw_ref.h" -#include "chromeos/ash/services/assistant/public/cpp/features.h" -#include "chromeos/ash/services/assistant/service_context.h" -#include "chromeos/ash/services/libassistant/public/cpp/assistant_timer.h" -#include "chromeos/ash/services/libassistant/public/mojom/timer_controller.mojom.h" -#include "mojo/public/cpp/bindings/receiver.h" - -namespace ash::assistant { - -//////////////////////////////////////////////////////////////////////////////// -// TimerDelegateImpl -//////////////////////////////////////////////////////////////////////////////// - -class TimerHost::TimerDelegateImpl : public libassistant::mojom::TimerDelegate { - public: - explicit TimerDelegateImpl( - mojo::PendingReceiver<TimerDelegate> pending_receiver, - ServiceContext* context) - : receiver_(this, std::move(pending_receiver)), context_(*context) {} - TimerDelegateImpl(const TimerDelegateImpl&) = delete; - TimerDelegateImpl& operator=(const TimerDelegateImpl&) = delete; - ~TimerDelegateImpl() override = default; - - private: - // libassistant::mojom::TimerDelegate implementation: - void OnTimerStateChanged(const std::vector<AssistantTimer>& timers) override { - assistant_alarm_timer_controller().OnTimerStateChanged(timers); - } - - AssistantAlarmTimerController& assistant_alarm_timer_controller() { - auto* result = context_->assistant_alarm_timer_controller(); - DCHECK(result); - return *result; - } - - mojo::Receiver<TimerDelegate> receiver_; - - // Owned by the parent |Service|. - const raw_ref<ServiceContext> context_; -}; - -//////////////////////////////////////////////////////////////////////////////// -// TimerHost -//////////////////////////////////////////////////////////////////////////////// - -TimerHost::TimerHost(ServiceContext* context) : context_(*context) { - DCHECK(context); -} - -TimerHost::~TimerHost() = default; - -void TimerHost::Initialize( - libassistant::mojom::TimerController* libassistant_controller, - mojo::PendingReceiver<libassistant::mojom::TimerDelegate> delegate) { - DCHECK(!libassistant_controller_); - - timer_delegate_ = - std::make_unique<TimerDelegateImpl>(std::move(delegate), &*context_); - libassistant_controller_ = libassistant_controller; -} - -void TimerHost::Stop() { - timer_delegate_.reset(); - libassistant_controller_ = nullptr; -} - -void TimerHost::AddTimeToTimer(const std::string& id, - base::TimeDelta duration) { - libassistant_controller().AddTimeToTimer(id, duration); -} - -void TimerHost::PauseTimer(const std::string& id) { - libassistant_controller().PauseTimer(id); -} - -void TimerHost::RemoveTimer(const std::string& id) { - libassistant_controller().RemoveTimer(id); -} - -void TimerHost::ResumeTimer(const std::string& id) { - libassistant_controller().ResumeTimer(id); -} - -libassistant::mojom::TimerController& TimerHost::libassistant_controller() { - DCHECK(libassistant_controller_); - return *libassistant_controller_; -} - -} // namespace ash::assistant
diff --git a/chromeos/ash/services/assistant/timer_host.h b/chromeos/ash/services/assistant/timer_host.h deleted file mode 100644 index dcb7d12..0000000 --- a/chromeos/ash/services/assistant/timer_host.h +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_ASH_SERVICES_ASSISTANT_TIMER_HOST_H_ -#define CHROMEOS_ASH_SERVICES_ASSISTANT_TIMER_HOST_H_ - -#include <memory> -#include <string> - -#include "base/memory/raw_ptr.h" -#include "base/memory/raw_ref.h" -#include "base/time/time.h" -#include "chromeos/ash/services/libassistant/public/mojom/timer_controller.mojom-forward.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" - -namespace ash { - -class AssistantAlarmTimerController; - -namespace assistant { - -class ServiceContext; - -// Handles all timer related interactions with Libassistant, which can broadly -// be separated in 2 responsibilities: -// 1) Let Libassistant know about updates to the timers (pause/add time/...). -// 2) Let |AssistantAlarmTimerController| know when Libassistant adds or -// removes timers. -class TimerHost { - public: - explicit TimerHost(ServiceContext* context); - TimerHost(const TimerHost&) = delete; - TimerHost& operator=(const TimerHost&) = delete; - ~TimerHost(); - - void Initialize( - libassistant::mojom::TimerController* libassistant_controller, - mojo::PendingReceiver<libassistant::mojom::TimerDelegate> delegate); - void Stop(); - - void AddTimeToTimer(const std::string& id, base::TimeDelta duration); - void PauseTimer(const std::string& id); - void RemoveTimer(const std::string& id); - void ResumeTimer(const std::string& id); - - private: - class TimerDelegateImpl; - - AssistantAlarmTimerController* assistant_alarm_timer_controller(); - libassistant::mojom::TimerController& libassistant_controller(); - - bool IsStopped() const; - - // Owned by our parent |AssistantManagerServiceImpl|. - raw_ptr<libassistant::mojom::TimerController, DanglingUntriaged> - libassistant_controller_ = nullptr; - std::unique_ptr<TimerDelegateImpl> timer_delegate_; - - // Owned by the parent |Service| which will destroy |this| before - // |context_|. - const raw_ref<ServiceContext> context_; -}; - -} // namespace assistant -} // namespace ash - -#endif // CHROMEOS_ASH_SERVICES_ASSISTANT_TIMER_HOST_H_
diff --git a/chromeos/chromeos_export.h b/chromeos/chromeos_export.h index 1d61005..41d2f2a2 100644 --- a/chromeos/chromeos_export.h +++ b/chromeos/chromeos_export.h
@@ -15,11 +15,7 @@ #endif // defined(CHROMEOS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CHROMEOS_IMPLEMENTATION) || defined(IS_CHROMEOS_SYSTEM_IMPL) #define CHROMEOS_EXPORT __attribute__((visibility("default"))) -#else -#define CHROMEOS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index 3c4b506d..4ab69b6 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-137-7103.40-1745804339-benchmark-138.0.7155.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-138-7137.0-1746414666-benchmark-138.0.7164.0-r1-redacted.afdo.xz
diff --git a/clank b/clank index a85f502..11c3547 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit a85f502de34463769977268999f0dbce0321efa6 +Subproject commit 11c3547fd4f0706067ad840ff190038861085741
diff --git a/components/BUILD.gn b/components/BUILD.gn index 596e9b07..5c59002 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -809,6 +809,7 @@ "//components/safe_browsing/content/common:file_type_policies_unittest", "//components/safe_browsing/content/common:unit_tests", "//components/safe_browsing/core/browser:safe_browsing_url_checker_unittest", + "//components/safe_browsing/core/common/proto_to_value:unit_tests", ] }
diff --git a/components/affiliations/core/browser/affiliation_utils.cc b/components/affiliations/core/browser/affiliation_utils.cc index 1dd7d3a..efeffcf5 100644 --- a/components/affiliations/core/browser/affiliation_utils.cc +++ b/components/affiliations/core/browser/affiliation_utils.cc
@@ -449,25 +449,6 @@ return os << facet_uri.potentially_invalid_spec(); } -bool operator==(const FacetBrandingInfo& lhs, const FacetBrandingInfo& rhs) { - return std::tie(lhs.name, lhs.icon_url) == std::tie(rhs.name, rhs.icon_url); -} - -bool operator!=(const FacetBrandingInfo& lhs, const FacetBrandingInfo& rhs) { - return !(lhs == rhs); -} - -bool operator==(const Facet& lhs, const Facet& rhs) { - return std::tie(lhs.uri, lhs.branding_info, lhs.main_domain, - lhs.change_password_url) == - std::tie(rhs.uri, rhs.branding_info, rhs.main_domain, - rhs.change_password_url); -} - -bool operator!=(const Facet& lhs, const Facet& rhs) { - return !(lhs == rhs); -} - bool operator==(const GroupedFacets& lhs, const GroupedFacets& rhs) { if (!std::ranges::is_permutation(lhs.facets, rhs.facets)) { return false; @@ -475,10 +456,6 @@ return lhs.branding_info == rhs.branding_info; } -bool operator!=(const GroupedFacets& lhs, const GroupedFacets& rhs) { - return !(lhs == rhs); -} - bool AreEquivalenceClassesEqual(const AffiliatedFacets& a, const AffiliatedFacets& b) { return a.size() == b.size() &&
diff --git a/components/affiliations/core/browser/affiliation_utils.h b/components/affiliations/core/browser/affiliation_utils.h index b6c0354..38fabb2 100644 --- a/components/affiliations/core/browser/affiliation_utils.h +++ b/components/affiliations/core/browser/affiliation_utils.h
@@ -157,6 +157,9 @@ // The branding information for a given facet. Corresponds to the |BrandingInfo| // message in affiliation_api.proto. struct FacetBrandingInfo { + friend bool operator==(const FacetBrandingInfo&, + const FacetBrandingInfo&) = default; + // Human readable name of this facet, or empty if this information is not // available. // @@ -189,6 +192,8 @@ Facet& operator=(const Facet& other); Facet& operator=(Facet&& other); + friend bool operator==(const Facet&, const Facet&) = default; + FacetURI uri; FacetBrandingInfo branding_info; GURL change_password_url; @@ -272,12 +277,7 @@ std::ostream& operator<<(std::ostream& os, const FacetURI& facet_uri); // Needed for testing. -bool operator==(const FacetBrandingInfo& lhs, const FacetBrandingInfo& rhs); -bool operator!=(const FacetBrandingInfo& lhs, const FacetBrandingInfo& rhs); -bool operator==(const Facet& lhs, const Facet& rhs); -bool operator!=(const Facet& lhs, const Facet& rhs); bool operator==(const GroupedFacets& lhs, const GroupedFacets& rhs); -bool operator!=(const GroupedFacets& lhs, const GroupedFacets& rhs); struct FacetURIHash { size_t operator()(const FacetURI& facet_uri) const {
diff --git a/components/android_autofill/browser/android_autofill_features.cc b/components/android_autofill/browser/android_autofill_features.cc index fc33231..f1afcd1 100644 --- a/components/android_autofill/browser/android_autofill_features.cc +++ b/components/android_autofill/browser/android_autofill_features.cc
@@ -22,7 +22,8 @@ const base::Feature* const kFeaturesExposedToJava[] = { &kAndroidAutofillDeprecateAccessibilityApi, - &kAutofillVirtualViewStructureAndroidInCct}; + &kAutofillVirtualViewStructureAndroidInCct, + &kAndroidAutofillLazyFrameworkWrapper}; } // namespace @@ -47,6 +48,15 @@ "AutofillVirtualViewStructureAndroidPasskeyLongPress", base::FEATURE_DISABLED_BY_DEFAULT); +// If enabled, the AutofillManagerWrapper class will not be initialized when the +// AutofillProvider Java class is initialized. Some apps do not use Autofill at +// all, yet they incur the latency cost of initializing the wrapper. This +// experiment tests whether lazily initializing the wrapper will cause any +// issues. +BASE_FEATURE(kAndroidAutofillLazyFrameworkWrapper, + "AndroidAutofillLazyFrameworkWrapper", + base::FEATURE_DISABLED_BY_DEFAULT); + static jlong JNI_AndroidAutofillFeatures_GetFeature(JNIEnv* env, jint ordinal) { return reinterpret_cast<jlong>(kFeaturesExposedToJava[ordinal]); }
diff --git a/components/android_autofill/browser/android_autofill_features.h b/components/android_autofill/browser/android_autofill_features.h index fdd3bf5..223b38e 100644 --- a/components/android_autofill/browser/android_autofill_features.h +++ b/components/android_autofill/browser/android_autofill_features.h
@@ -15,6 +15,8 @@ BASE_DECLARE_FEATURE(kAutofillVirtualViewStructureAndroidPasskeyLongPress); +BASE_DECLARE_FEATURE(kAndroidAutofillLazyFrameworkWrapper); + } // namespace autofill::features #endif // COMPONENTS_ANDROID_AUTOFILL_BROWSER_ANDROID_AUTOFILL_FEATURES_H_
diff --git a/components/android_autofill/browser/java/src/org/chromium/components/autofill/AndroidAutofillFeatures.java b/components/android_autofill/browser/java/src/org/chromium/components/autofill/AndroidAutofillFeatures.java index ce6a5d3..179e3f4 100644 --- a/components/android_autofill/browser/java/src/org/chromium/components/autofill/AndroidAutofillFeatures.java +++ b/components/android_autofill/browser/java/src/org/chromium/components/autofill/AndroidAutofillFeatures.java
@@ -21,14 +21,19 @@ public class AndroidAutofillFeatures extends Features { public static final String ANDROID_AUTOFILL_DEPRECATE_ACCESSIBILITY_API_NAME = "AndroidAutofillDeprecateAccessibilityApi"; - public static final AndroidAutofillFeatures ANDROID_AUTOFILL_DEPRECATE_ACCESSIBILITY_API = - new AndroidAutofillFeatures(0, ANDROID_AUTOFILL_DEPRECATE_ACCESSIBILITY_API_NAME); + public static final String ANDROID_AUTOFILL_LAZY_FRAMEWORK_WRAPPER_NAME = + "AndroidAutofillLazyFrameworkWrapper"; + public static final String ANDROID_AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID_IN_CCT_NAME = "AutofillVirtualViewStructureAndroidInCct"; + public static final AndroidAutofillFeatures ANDROID_AUTOFILL_DEPRECATE_ACCESSIBILITY_API = + new AndroidAutofillFeatures(0, ANDROID_AUTOFILL_DEPRECATE_ACCESSIBILITY_API_NAME); public static final AndroidAutofillFeatures ANDROID_AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID_IN_CCT = new AndroidAutofillFeatures( 1, ANDROID_AUTOFILL_VIRTUAL_VIEW_STRUCTURE_ANDROID_IN_CCT_NAME); + public static final AndroidAutofillFeatures ANDROID_AUTOFILL_LAZY_FRAMEWORK_WRAPPER = + new AndroidAutofillFeatures(2, ANDROID_AUTOFILL_LAZY_FRAMEWORK_WRAPPER_NAME); private final int mOrdinal; private AndroidAutofillFeatures(int ordinal, String name) {
diff --git a/components/android_autofill/browser/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java b/components/android_autofill/browser/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java index 14e36fc..c71600f 100644 --- a/components/android_autofill/browser/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java +++ b/components/android_autofill/browser/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java
@@ -49,7 +49,7 @@ private WeakReference<AutofillManagerWrapper> mManager; public AutofillInputUiMonitor(AutofillManagerWrapper manager) { - mManager = new WeakReference<AutofillManagerWrapper>(manager); + mManager = new WeakReference<>(manager); } @Override
diff --git a/components/android_autofill/browser/java/src/org/chromium/components/autofill/AutofillProvider.java b/components/android_autofill/browser/java/src/org/chromium/components/autofill/AutofillProvider.java index a9708f5..2cc1a4e6 100644 --- a/components/android_autofill/browser/java/src/org/chromium/components/autofill/AutofillProvider.java +++ b/components/android_autofill/browser/java/src/org/chromium/components/autofill/AutofillProvider.java
@@ -66,7 +66,13 @@ private static AutofillManagerWrapperFactoryForTesting sAutofillManagerFactoryForTesting; private final String mProviderName; + + /** + * Do not use this object directly as it may not be initialized. Use the {@link + * #getAutofillManagerWrapper()} method instead. + */ private AutofillManagerWrapper mAutofillManager; + private ViewGroup mContainerView; private WebContents mWebContents; @@ -75,7 +81,7 @@ private AutofillProviderUMA mAutofillUMA; private AutofillManagerWrapper.InputUiObserver mInputUiObserver; private long mAutofillTriggeredTimeMillis; - private Context mContext; + private final Context mContext; private AutofillPopup mDatalistPopup; private AutofillSuggestion[] mDatalistSuggestions; private WebContentsAccessibility mWebContentsAccessibility; @@ -95,36 +101,52 @@ try (ScopedSysTraceEvent e = ScopedSysTraceEvent.scoped("AutofillProvider.constructor")) { if (sAutofillManagerFactoryForTesting != null) { mAutofillManager = sAutofillManagerFactoryForTesting.create(context); + maybeInitializeUmaRecorder(context); + maybeInitializeInputObserver(); } else { - mAutofillManager = new AutofillManagerWrapper(context); + if (!AndroidAutofillFeatures.ANDROID_AUTOFILL_LAZY_FRAMEWORK_WRAPPER.isEnabled()) { + initializeFrameworkWrapper(context); + } } mContainerView = containerView; - mAutofillUMA = - new AutofillProviderUMA( - context, - mAutofillManager.isAwGCurrentAutofillService(), - mAutofillManager.getPackageName()); - mInputUiObserver = - new AutofillManagerWrapper.InputUiObserver() { - @Override - public void onInputUiShown() { - // Not need to report suggestion window displayed if there is no live - // autofill session. - if (mRequest == null) return; - mAutofillUMA.onSuggestionDisplayed( - System.currentTimeMillis() - mAutofillTriggeredTimeMillis); - } - }; - mAutofillManager.addInputUiObserver(mInputUiObserver); mContext = context; } initializeNativeAutofillProvider(webContents); } + private void initializeFrameworkWrapper(Context context) { + mAutofillManager = new AutofillManagerWrapper(context); + maybeInitializeUmaRecorder(context); + maybeInitializeInputObserver(); + } + + private void maybeInitializeUmaRecorder(Context context) { + if (mAutofillUMA != null) return; + mAutofillUMA = + new AutofillProviderUMA( + context, + mAutofillManager.isAwGCurrentAutofillService(), + mAutofillManager.getPackageName()); + } + + private void maybeInitializeInputObserver() { + if (mInputUiObserver != null) return; + mInputUiObserver = + () -> { + // Not need to report suggestion window displayed if there is no live + // autofill session. + if (mRequest == null) return; + mAutofillUMA.onSuggestionDisplayed( + System.currentTimeMillis() - mAutofillTriggeredTimeMillis); + }; + + mAutofillManager.addInputUiObserver(mInputUiObserver); + } + public void destroy() { mAutofillUMA.recordSession(); detachFromJavaAutofillProvider(); - mAutofillManager.destroy(); + getAutofillManagerWrapper().destroy(); } /** @@ -199,16 +221,17 @@ public boolean shouldQueryAutofillSuggestion() { return mRequest != null && mRequest.getFocusField() != null - && !mAutofillManager.isAutofillInputUiShowing(); + && !getAutofillManagerWrapper().isAutofillInputUiShowing(); } public void queryAutofillSuggestion() { if (shouldQueryAutofillSuggestion()) { FocusField focusField = mRequest.getFocusField(); - mAutofillManager.requestAutofill( - mContainerView, - mRequest.getFieldVirtualId(focusField.fieldIndex), - focusField.absBound); + getAutofillManagerWrapper() + .requestAutofill( + mContainerView, + mRequest.getFieldVirtualId(focusField.fieldIndex), + focusField.absBound); } } @@ -239,7 +262,8 @@ mPrefillRequest = new PrefillRequest(form); mStructureProvidedForPrefillRequest = false; - mAutofillManager.notifyVirtualViewsReady(mContainerView, mPrefillRequest.getPrefillHints()); + getAutofillManagerWrapper() + .notifyVirtualViewsReady(mContainerView, mPrefillRequest.getPrefillHints()); } /** @@ -269,11 +293,11 @@ // Check focusField inside short value? Autofill Manager might have session that wasn't // started by AutofillProvider, we just always cancel existing session here. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { - mAutofillManager.cancel(); + getAutofillManagerWrapper().cancel(); } transformFormFieldToContainViewCoordinates(formData); - mAutofillUMA.onSessionStarted(mAutofillManager.isDisabled()); + mAutofillUMA.onSessionStarted(getAutofillManagerWrapper().isDisabled()); mRequest = new AutofillRequest( formData, new FocusField((short) focus, absBound), hasServerPrediction); @@ -287,7 +311,7 @@ } mAutofillTriggeredTimeMillis = System.currentTimeMillis(); - mAutofillManager.notifyNewSessionStarted(hasServerPrediction); + getAutofillManagerWrapper().notifyNewSessionStarted(hasServerPrediction); } /** @@ -426,14 +450,16 @@ if (!forceNotify && isDatalistField(index)) return; AutofillValue autofillValue = mRequest.getFieldNewValue(index); if (autofillValue == null) return; - mAutofillManager.notifyVirtualValueChanged( - mContainerView, mRequest.getFieldVirtualId((short) index), autofillValue); + getAutofillManagerWrapper() + .notifyVirtualValueChanged( + mContainerView, mRequest.getFieldVirtualId((short) index), autofillValue); } private void notifyVirtualViewVisibilityChanged(int index, boolean isVisible) { if (isDatalistField(index)) return; - mAutofillManager.notifyVirtualViewVisibilityChanged( - mContainerView, mRequest.getFieldVirtualId((short) index), isVisible); + getAutofillManagerWrapper() + .notifyVirtualViewVisibilityChanged( + mContainerView, mRequest.getFieldVirtualId((short) index), isVisible); } @RequiresApi(VERSION_CODES.TIRAMISU) @@ -441,21 +467,23 @@ // Refer to notifyVirtualValueChanged() for the reason of the datalist's special handling. if (isDatalistField(index)) return false; - return mAutofillManager.showAutofillDialog( - parent, mRequest.getFieldVirtualId((short) index)); + return getAutofillManagerWrapper() + .showAutofillDialog(parent, mRequest.getFieldVirtualId((short) index)); } private void notifyVirtualViewEntered(View parent, int index, Rect absBounds) { // Refer to notifyVirtualValueChanged() for the reason of the datalist's special handling. if (isDatalistField(index)) return; - mAutofillManager.notifyVirtualViewEntered( - parent, mRequest.getFieldVirtualId((short) index), absBounds); + getAutofillManagerWrapper() + .notifyVirtualViewEntered( + parent, mRequest.getFieldVirtualId((short) index), absBounds); } private void notifyVirtualViewExited(View parent, int index) { // Refer to notifyVirtualValueChanged() for the reason of the datalist's special handling. if (isDatalistField(index)) return; - mAutofillManager.notifyVirtualViewExited(parent, mRequest.getFieldVirtualId((short) index)); + getAutofillManagerWrapper() + .notifyVirtualViewExited(parent, mRequest.getFieldVirtualId((short) index)); } /** @@ -468,7 +496,7 @@ // The changes could be missing, like those made by Javascript, we'd better to notify // AutofillManager current values. also see crbug.com/353001 and crbug.com/732856. forceNotifyFormValues(); - mAutofillManager.commit(submissionSource); + getAutofillManagerWrapper().commit(submissionSource); mRequest = null; mAutofillUMA.onFormSubmitted(submissionSource); } @@ -565,9 +593,22 @@ } /** + * Returns the {@link AutofillManagerWrapper} object if initialized and creates it otherwise. Do + * not access the object directly as it may not be initialized. + * + * @return The wrapper object. It is guaranteed to be initialized. + */ + private AutofillManagerWrapper getAutofillManagerWrapper() { + if (mAutofillManager == null) { + initializeFrameworkWrapper(mContext); + } + return mAutofillManager; + } + + /** * Display the simplest popup for the datalist. This is same as WebView's datalist popup in - * Android pre-o. No suggestion from the autofill service will be presented, No advance - * features of AutofillPopup are used. + * Android pre-o. No suggestion from the autofill service will be presented, No advance features + * of AutofillPopup are used. */ private void showDatalistPopup( String[] datalistValues, String[] datalistLabels, RectF bounds, boolean isRtl) { @@ -693,7 +734,7 @@ private void onServerPredictionsAvailable() { if (mRequest == null) return; mRequest.onServerPredictionsAvailable(); - mAutofillManager.onServerPredictionsAvailable(); + getAutofillManagerWrapper().onServerPredictionsAvailable(); mAutofillUMA.onServerTypeAvailable(mRequest.getForm(), /* afterSessionStarted= */ true); } @@ -782,7 +823,7 @@ @CalledByNative public void cancelSession() { - mAutofillManager.cancel(); + getAutofillManagerWrapper().cancel(); mPrefillRequest = null; mRequest = null; }
diff --git a/components/app_restore/app_restore_data.cc b/components/app_restore/app_restore_data.cc index 4501f30..354e537 100644 --- a/components/app_restore/app_restore_data.cc +++ b/components/app_restore/app_restore_data.cc
@@ -522,7 +522,4 @@ status_bar_color == other.status_bar_color; } -bool AppRestoreData::operator!=(const AppRestoreData& other) const { - return !(*this == other); -} } // namespace app_restore
diff --git a/components/app_restore/app_restore_data.h b/components/app_restore/app_restore_data.h index 1423465..17e1514 100644 --- a/components/app_restore/app_restore_data.h +++ b/components/app_restore/app_restore_data.h
@@ -78,8 +78,6 @@ bool operator==(const AppRestoreData& other) const; - bool operator!=(const AppRestoreData& other) const; - // App launch parameters. // TODO: Replace this with a `AppLaunchInfo` object. std::optional<int32_t> event_flag;
diff --git a/components/autofill/android/BUILD.gn b/components/autofill/android/BUILD.gn index 95f1b1e..4f4271a 100644 --- a/components/autofill/android/BUILD.gn +++ b/components/autofill/android/BUILD.gn
@@ -254,6 +254,7 @@ "java/src/org/chromium/components/autofill/AutofillProfile.java", "java/src/org/chromium/components/autofill/AutofillSuggestion.java", "java/src/org/chromium/components/autofill/DropdownKeyValue.java", + "java/src/org/chromium/components/autofill/LoyaltyCard.java", "java/src/org/chromium/components/autofill/SubKeyRequester.java", ] srcjar_deps = [ @@ -270,6 +271,7 @@ "java/src/org/chromium/components/autofill/AutofillAddressUiComponent.java", "java/src/org/chromium/components/autofill/AutofillProfile.java", "java/src/org/chromium/components/autofill/DropdownKeyValue.java", + "java/src/org/chromium/components/autofill/LoyaltyCard.java", "java/src/org/chromium/components/autofill/SubKeyRequester.java", ] }
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/LoyaltyCard.java b/components/autofill/android/java/src/org/chromium/components/autofill/LoyaltyCard.java new file mode 100644 index 0000000..e6a0901b --- /dev/null +++ b/components/autofill/android/java/src/org/chromium/components/autofill/LoyaltyCard.java
@@ -0,0 +1,66 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.autofill; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; +import org.jni_zero.JniType; + +import org.chromium.build.annotations.NullMarked; +import org.chromium.url.GURL; + +import java.util.List; + +/** Represents a loyalty card coming from the the Google Wallet. */ +@JNINamespace("autofill") +@NullMarked +public class LoyaltyCard { + private String mLoyaltyCardId; + private String mMerchantName; + private String mProgramName; + private GURL mProgramLogo; + private String mLoyaltyCardNumber; + private List<GURL> mMerchantDomains; + + @CalledByNative + public LoyaltyCard( + @JniType("std::string") String loyaltyCardId, + @JniType("std::string") String merchantName, + @JniType("std::string") String programName, + @JniType("GURL") GURL programLogo, + @JniType("std::string") String loyaltyCardNumber, + @JniType("std::vector<GURL>") List<GURL> merchantDomains) { + mLoyaltyCardId = loyaltyCardId; + mMerchantName = merchantName; + mProgramName = programName; + mProgramLogo = programLogo; + mLoyaltyCardNumber = loyaltyCardNumber; + mMerchantDomains = merchantDomains; + } + + public String getLoyaltyCardId() { + return mLoyaltyCardId; + } + + public String getMerchantName() { + return mMerchantName; + } + + public String getProgramName() { + return mProgramName; + } + + public GURL getProgramLogo() { + return mProgramLogo; + } + + public String getLoyaltyCardNumber() { + return mLoyaltyCardNumber; + } + + public List<GURL> getMerchantDomains() { + return mMerchantDomains; + } +}
diff --git a/components/autofill/content/browser/content_identity_credential_delegate_unittest.cc b/components/autofill/content/browser/content_identity_credential_delegate_unittest.cc index 4f03864..ea692a04 100644 --- a/components/autofill/content/browser/content_identity_credential_delegate_unittest.cc +++ b/components/autofill/content/browser/content_identity_credential_delegate_unittest.cc
@@ -57,7 +57,7 @@ scoped_refptr<content::IdentityProviderData> identity_provider_data = base::MakeRefCounted<content::IdentityProviderData>( "idp.example", metadata, client, blink::mojom::RpContext::kSignIn, - disclosures, false); + blink::mojom::Format::kSdJwt, disclosures, false); account->identity_provider = identity_provider_data; @@ -243,7 +243,8 @@ base::MakeRefCounted<content::IdentityProviderData>( "idp.example", metadata, content::ClientMetadata((GURL()), (GURL()), (GURL()), (gfx::Image())), - blink::mojom::RpContext::kSignIn, disclosures, false); + blink::mojom::RpContext::kSignIn, blink::mojom::Format::kSdJwt, + disclosures, false); account->identity_provider = identity_provider; std::vector<IdentityRequestAccountPtr> accounts = {account};
diff --git a/components/autofill/core/browser/autofill_field.h b/components/autofill/core/browser/autofill_field.h index 1c2c403a..0990237 100644 --- a/components/autofill/core/browser/autofill_field.h +++ b/components/autofill/core/browser/autofill_field.h
@@ -212,16 +212,17 @@ bool ShouldSuppressSuggestionsAndFillingByDefault() const; // Returns the current value, formatted as desired for import: - // (1) If the user left a field unchanged, returns the empty string. - // (2) If the field has FormControlType::kSelect* and has a selected text, - // it is FormFieldData::selected_text(). + // (1) If the field value hasn't changed since it was seen and the field is a + // non-<select>, returns the empty string. + // (2) If the field has FormControlType::kSelect* and has a selected option, + // returns that option's human-readable text. + // (3) Otherwise returns value(). // // The motivation behind (1) is that unchanged values usually carry little - // value for importing. The exception are <select> fields, which often have - // a correct default value, so we consider them for import even if their value - // didn't change. - // TODO: crbug.com/40137859 - Consider making an exception for also for - // non-<select> ADDRESS_HOME_{STATE,COUNTRY} fields. + // value for importing. <select> fields are exempted because their default + // value is often correct (e.g., in ADDRESS_HOME_COUNTRY fields). + // TODO(crbug.com/40137859): Consider also exempting non-<select> + // ADDRESS_HOME_{STATE,COUNTRY} fields. // // The motivation behind (2) is that the human-readable text of an <option> is // usually better suited for import than the its value. See the documentation @@ -237,6 +238,8 @@ // - When the field has moved to another form. // - When the form has been extracted without the field. For example, this // could happen because the field was temporarily removed from the DOM. + // + // For the field's current value, see FormFieldData::value(). const std::u16string& initial_value() const { return initial_value_; } // Sets the field's current value. @@ -252,13 +255,6 @@ return credit_card_number_offset_; } - void set_vote_type(AutofillUploadContents::Field::VoteType type) { - vote_type_ = type; - } - AutofillUploadContents::Field::VoteType vote_type() const { - return vote_type_; - } - void SetPasswordRequirements(PasswordRequirementsSpec spec); const std::optional<PasswordRequirementsSpec>& password_requirements() const { return password_requirements_; @@ -464,12 +460,6 @@ // label when the label is divided between subsequent fields. std::u16string parseable_label_; - // The vote type, if the autofill type is USERNAME or any password vote. - // Otherwise, the field is ignored. |vote_type_| provides context as to what - // triggered the vote. - AutofillUploadContents::Field::VoteType vote_type_ = - AutofillUploadContents::Field::NO_INFORMATION; - // A list of field log events, which record when user interacts the field // during autofill or editing, such as user clicks on the field, the // suggestion list is shown for the field, user accepts one suggestion to
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc index 3e636fb8..9e2a736 100644 --- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.cc
@@ -386,8 +386,8 @@ added_field->add_autofill_type(field_type); } - if (field->vote_type()) { - added_field->set_vote_type(field->vote_type()); + if (field_options && field_options->vote_type) { + added_field->set_vote_type(field_options->vote_type); } if (field_options && field_options->initial_value_hash) {
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.h b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.h index 899f28e..16c2561 100644 --- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.h +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding.h
@@ -68,6 +68,12 @@ // before user-interactions or automatic fillings. This field is used to // detect static placeholders. On non-username fields, it is not set. std::optional<uint32_t> initial_value_hash; + + // The vote type, if the autofill type is USERNAME or any password vote. + // Otherwise, the field is ignored. `vote_type` provides context as to what + // triggered the vote. + AutofillUploadContents::Field::VoteType vote_type = + AutofillUploadContents::Field::NO_INFORMATION; }; EncodeUploadRequestOptions();
diff --git a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc index 0afbe53..4ba2258 100644 --- a/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc +++ b/components/autofill/core/browser/crowdsourcing/autofill_crowdsourcing_encoding_unittest.cc
@@ -524,8 +524,10 @@ field_options.generated_password_changed = true; } if (form_structure->field(i)->name() == u"username") { - form_structure->field(i)->set_vote_type( - AutofillUploadContents::Field::CREDENTIALS_REUSED); + auto& field_options = + options.fields[form_structure->field(i)->global_id()]; + field_options.vote_type = + AutofillUploadContents::Field::CREDENTIALS_REUSED; } }
diff --git a/components/autofill/core/browser/crowdsourcing/votes_uploader.h b/components/autofill/core/browser/crowdsourcing/votes_uploader.h index 8a1de4b..d238ac4 100644 --- a/components/autofill/core/browser/crowdsourcing/votes_uploader.h +++ b/components/autofill/core/browser/crowdsourcing/votes_uploader.h
@@ -61,8 +61,7 @@ // ▼ │ // Store PendingVote, which is uploaded when │ // - a submission happens in the frame; │ -// - the frame becomes inactive │ -// kAutofillVoteWhenInactive is enabled; │ +// - the frame becomes inactive; │ // - the frame is reset; │ // - the frame is deleted; │ // - the queue becomes too large. │
diff --git a/components/autofill/core/browser/data_manager/valuables/valuables_data_manager_test_api.h b/components/autofill/core/browser/data_manager/valuables/valuables_data_manager_test_api.h index cadbab38..3b2516d2 100644 --- a/components/autofill/core/browser/data_manager/valuables/valuables_data_manager_test_api.h +++ b/components/autofill/core/browser/data_manager/valuables/valuables_data_manager_test_api.h
@@ -29,6 +29,8 @@ valuables_data_manager_->loyalty_cards_ = loyalty_cards; } + void ClearLoyaltyCards() { valuables_data_manager_->loyalty_cards_.clear(); } + void NotifyObservers() { valuables_data_manager_->NotifyObservers(); } private:
diff --git a/components/autofill/core/browser/form_parsing/internal_resources b/components/autofill/core/browser/form_parsing/internal_resources index 8f3290e..ee4b7f29 160000 --- a/components/autofill/core/browser/form_parsing/internal_resources +++ b/components/autofill/core/browser/form_parsing/internal_resources
@@ -1 +1 @@ -Subproject commit 8f3290e53c07fe9527fc48952edde535c3cfa13a +Subproject commit ee4b7f29de55d7867a004208580a994e5da35ed0
diff --git a/components/autofill/core/browser/form_structure_test_api.cc b/components/autofill/core/browser/form_structure_test_api.cc index f838b27..812723f1 100644 --- a/components/autofill/core/browser/form_structure_test_api.cc +++ b/components/autofill/core/browser/form_structure_test_api.cc
@@ -60,17 +60,4 @@ SetFieldTypes(all_heuristic_types, server_types); } -AutofillUploadContents::Field::VoteType -FormStructureTestApi::get_username_vote_type() { - for (const auto& field : form_structure_->fields()) { - AutofillUploadContents::Field::VoteType vote_type = field->vote_type(); - if (vote_type == AutofillUploadContents::Field::USERNAME_OVERWRITTEN || - vote_type == AutofillUploadContents::Field::USERNAME_EDITED || - vote_type == AutofillUploadContents::Field::CREDENTIALS_REUSED) { - return vote_type; - } - } - return AutofillUploadContents::Field::NO_INFORMATION; -} - } // namespace autofill
diff --git a/components/autofill/core/browser/form_structure_test_api.h b/components/autofill/core/browser/form_structure_test_api.h index d931f5c6..8cead8a3 100644 --- a/components/autofill/core/browser/form_structure_test_api.h +++ b/components/autofill/core/browser/form_structure_test_api.h
@@ -66,11 +66,6 @@ /*server_types=*/overall_types); } - // Returns a vote type if a field contains a vote relating USERNAME correction - // (CREDENTIALS_REUSED, USERNAME_OVERWRITTEN, USERNAME_EDITED). If none, - // returns NO_INFORMATION. - AutofillUploadContents::Field::VoteType get_username_vote_type(); - void AssignSections() { autofill::AssignSections(form_structure_->fields_); } FieldCandidatesMap ParseFieldTypesWithPatterns(
diff --git a/components/autofill/core/browser/payments/payments_autofill_client.cc b/components/autofill/core/browser/payments/payments_autofill_client.cc index b875a8c9..80134d4d 100644 --- a/components/autofill/core/browser/payments/payments_autofill_client.cc +++ b/components/autofill/core/browser/payments/payments_autofill_client.cc
@@ -224,6 +224,12 @@ return false; } +bool PaymentsAutofillClient::ShowTouchToFillLoyaltyCard( + base::WeakPtr<TouchToFillDelegate> delegate, + base::span<const LoyaltyCard> loyalty_cards_to_suggest) { + return false; +} + void PaymentsAutofillClient::HideTouchToFillPaymentMethod() {} const PaymentsDataManager& PaymentsAutofillClient::GetPaymentsDataManager()
diff --git a/components/autofill/core/browser/payments/payments_autofill_client.h b/components/autofill/core/browser/payments/payments_autofill_client.h index 961b12ea..caf8d47 100644 --- a/components/autofill/core/browser/payments/payments_autofill_client.h +++ b/components/autofill/core/browser/payments/payments_autofill_client.h
@@ -536,6 +536,14 @@ virtual bool ShowTouchToFillIban(base::WeakPtr<TouchToFillDelegate> delegate, base::span<const Iban> ibans_to_suggest); + // Shows the Touch To Fill surface for filling Wallet loyalty card + // information, if possible, returning `true` on success. `delegate` will be + // notified of events. This function is not implemented on iOS and iOS + // WebView, and should not be used on those platforms. + virtual bool ShowTouchToFillLoyaltyCard( + base::WeakPtr<TouchToFillDelegate> delegate, + base::span<const LoyaltyCard> loyalty_cards_to_suggest); + // Hides the Touch To Fill surface for filling payment information if one is // currently shown. Should be called only if the feature is supported by the // platform.
diff --git a/components/autofill/core/common/autofill_test_utils.cc b/components/autofill/core/common/autofill_test_utils.cc index 3a5ac73..e4a04bd2 100644 --- a/components/autofill/core/common/autofill_test_utils.cc +++ b/components/autofill/core/common/autofill_test_utils.cc
@@ -314,6 +314,14 @@ return form; } +FormData CreateTestLoyaltyCardFormData() { + FormData form = ConstructFormWithNameRenderIdAndProtocol(/*is_https=*/true); + form.set_fields( + {CreateTestFormField("Your loyalty card:", "loyalty_card", /*value=*/"", + FormControlType::kInputText)}); + return form; +} + FormData CreateTestPasswordFormData() { std::vector<FormFieldData> fields; fields.push_back(
diff --git a/components/autofill/core/common/autofill_test_utils.h b/components/autofill/core/common/autofill_test_utils.h index f1a060b..6d3e796 100644 --- a/components/autofill/core/common/autofill_test_utils.h +++ b/components/autofill/core/common/autofill_test_utils.h
@@ -212,6 +212,10 @@ std::string_view value = kIbanValue, bool is_https = true); +// Populates `form_data` with data corresponding to a loyalty card form (a form +// with a single loyalty card field). +[[nodiscard]] FormData CreateTestLoyaltyCardFormData(); + // Creates a `FormData` with a username and a password field. [[nodiscard]] FormData CreateTestPasswordFormData();
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index 617f02c..6becf025 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -92,6 +92,9 @@ <message name="IDS_AUTOFILL_IBAN_GENERIC" desc="Generic IBAN name." formatter_data="android_java"> Iban </message> + <message name="IDS_AUTOFILL_LOYALTY_CARD_GENERIC" desc="Generic loyalty card name." formatter_data="android_java"> + Loyalty card + </message> <message name="IDS_AUTOFILL_ADDRESS_SUMMARY_SEPARATOR" desc="The separator character used in the summary of an address." formatter_data="android_java"> , ''' </message>
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_LOYALTY_CARD_GENERIC.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_LOYALTY_CARD_GENERIC.png.sha1 new file mode 100644 index 0000000..c1a924af --- /dev/null +++ b/components/autofill_strings_grdp/IDS_AUTOFILL_LOYALTY_CARD_GENERIC.png.sha1
@@ -0,0 +1 @@ +2171f8e701521399a583884eb34ad3c3e07e9d60 \ No newline at end of file
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd index fdb35cbe..07f6a97 100644 --- a/components/browser_ui/strings/android/browser_ui_strings.grd +++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -372,9 +372,6 @@ <message name="IDS_CONCAT_TWO_STRINGS_WITH_COMMA" desc="This string concatenates two other strings. In the English language, this particular concatenation is done via a comma and a whitespace in between the other strings. For example: '1 compromised password, 2 weak passwords'"> <ph name="TYPE_1">%1$s<ex>2 compromised passwords</ex></ph>, <ph name="TYPE_2">%2$s<ex>7 weak passwords</ex></ph> </message> - <message name="IDS_CONCAT_TWO_STRINGS_WITH_PERIODS" desc="This string concatenates two other strings. In the English language, this particular concatenation is done via a period and a whitespace after the first string, and a period after the second string. For example: '1 compromised password. 2 weak passwords.'"> - <ph name="TYPE_1">%1$s<ex>2 compromised passwords</ex></ph>. <ph name="TYPE_2">%2$s<ex>7 weak passwords</ex></ph>. - </message> <!-- Certificate viewer --> <message name="IDS_CERTTITLE" desc="Dialog box title for viewing security certificates. [CHAR_LIMIT=32]">
diff --git a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_CONCAT_TWO_STRINGS_WITH_PERIODS.png.sha1 b/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_CONCAT_TWO_STRINGS_WITH_PERIODS.png.sha1 deleted file mode 100644 index 88d45b3e..0000000 --- a/components/browser_ui/strings/android/browser_ui_strings_grd/IDS_CONCAT_TWO_STRINGS_WITH_PERIODS.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -7c4759e9ff383f9089f965694cc1964fe8145715 \ No newline at end of file
diff --git a/components/browsing_data/content/browsing_data_quota_helper_impl.cc b/components/browsing_data/content/browsing_data_quota_helper_impl.cc index 9a986491..97ab955 100644 --- a/components/browsing_data/content/browsing_data_quota_helper_impl.cc +++ b/components/browsing_data/content/browsing_data_quota_helper_impl.cc
@@ -21,7 +21,6 @@ #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/origin.h" -using blink::mojom::StorageType; using content::BrowserContext; using content::BrowserThread;
diff --git a/components/browsing_data/content/browsing_data_quota_helper_impl.h b/components/browsing_data/content/browsing_data_quota_helper_impl.h index 5bf3f2c..94ce616 100644 --- a/components/browsing_data/content/browsing_data_quota_helper_impl.h +++ b/components/browsing_data/content/browsing_data_quota_helper_impl.h
@@ -42,8 +42,6 @@ delete; private: - using PendingHosts = - std::set<std::pair<std::string, blink::mojom::StorageType>>; using QuotaInfoMap = std::map<blink::StorageKey, QuotaInfo>; ~BrowsingDataQuotaHelperImpl() override;
diff --git a/components/captive_portal/core/captive_portal_export.h b/components/captive_portal/core/captive_portal_export.h index 87c84845..0c5613e4 100644 --- a/components/captive_portal/core/captive_portal_export.h +++ b/components/captive_portal/core/captive_portal_export.h
@@ -15,11 +15,7 @@ #endif // defined(CAPTIVE_PORTAL_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CAPTIVE_PORTAL_IMPLEMENTATION) #define CAPTIVE_PORTAL_EXPORT __attribute__((visibility("default"))) -#else -#define CAPTIVE_PORTAL_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/capture_mode/capture_mode_export.h b/components/capture_mode/capture_mode_export.h index 7b689692..e13f918 100644 --- a/components/capture_mode/capture_mode_export.h +++ b/components/capture_mode/capture_mode_export.h
@@ -15,11 +15,7 @@ #endif // defined(CAPTURE_MODE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CAPTURE_MODE_IMPLEMENTATION) #define CAPTURE_MODE_EXPORT __attribute__((visibility("default"))) -#else -#define CAPTURE_MODE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/cast/cast_component_export.h b/components/cast/cast_component_export.h index 5c65030..decebae8 100644 --- a/components/cast/cast_component_export.h +++ b/components/cast/cast_component_export.h
@@ -5,10 +5,9 @@ #ifndef COMPONENTS_CAST_CAST_COMPONENT_EXPORT_H_ #define COMPONENTS_CAST_CAST_COMPONENT_EXPORT_H_ -#if defined(COMPONENT_BUILD) && defined(CAST_COMPONENT_IMPLEMENTATION) +#if defined(COMPONENT_BUILD) #define CAST_COMPONENT_EXPORT __attribute__((visibility("default"))) -#else // !defined(COMPONENT_BUILD) || - // !defined(CAST_COMPONENT_EXPORT) +#else // !defined(COMPONENT_BUILD) #define CAST_COMPONENT_EXPORT #endif
diff --git a/components/cbor/cbor_export.h b/components/cbor/cbor_export.h index a04d88c3..410d555 100644 --- a/components/cbor/cbor_export.h +++ b/components/cbor/cbor_export.h
@@ -15,11 +15,7 @@ #endif // defined(CBOR_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CBOR_IMPLEMENTATION) #define CBOR_EXPORT __attribute__((visibility("default"))) -#else -#define CBOR_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/collaboration/internal/android/collaboration_service_android.cc b/components/collaboration/internal/android/collaboration_service_android.cc index 600c984..2514ade1 100644 --- a/components/collaboration/internal/android/collaboration_service_android.cc +++ b/components/collaboration/internal/android/collaboration_service_android.cc
@@ -99,6 +99,21 @@ static_cast<CollaborationServiceShareOrManageEntryPoint>(entry)); } +void CollaborationServiceAndroid::StartLeaveOrDeleteFlow( + JNIEnv* env, + jlong delegateNativePtr, + const JavaParamRef<jstring>& j_sync_group_id, + jint entry) { + std::string sync_group_id_str = + base::android::ConvertJavaStringToUTF8(env, j_sync_group_id); + tab_groups::EitherGroupID either_id = + base::Uuid::ParseLowercase(sync_group_id_str); + + collaboration_service_->StartLeaveOrDeleteFlow( + conversion::GetDelegateUniquePtrFromJava(delegateNativePtr), either_id, + static_cast<CollaborationServiceLeaveOrDeleteEntryPoint>(entry)); +} + ScopedJavaLocalRef<jobject> CollaborationServiceAndroid::GetServiceStatus( JNIEnv* env) { ServiceStatus status = collaboration_service_->GetServiceStatus();
diff --git a/components/collaboration/internal/android/collaboration_service_android.h b/components/collaboration/internal/android/collaboration_service_android.h index 8338cbb..685131c4 100644 --- a/components/collaboration/internal/android/collaboration_service_android.h +++ b/components/collaboration/internal/android/collaboration_service_android.h
@@ -32,6 +32,11 @@ jlong delegate, const base::android::JavaParamRef<jstring>& j_sync_group_id, jint entry); + void StartLeaveOrDeleteFlow( + JNIEnv* env, + jlong delegate, + const base::android::JavaParamRef<jstring>& j_sync_group_id, + jint entry); base::android::ScopedJavaLocalRef<jobject> GetServiceStatus(JNIEnv* env); jint GetCurrentUserRoleForGroup( JNIEnv* env,
diff --git a/components/collaboration/internal/android/java/src/org/chromium/components/collaboration/CollaborationServiceImpl.java b/components/collaboration/internal/android/java/src/org/chromium/components/collaboration/CollaborationServiceImpl.java index 8fda275..ff97c4eb 100644 --- a/components/collaboration/internal/android/java/src/org/chromium/components/collaboration/CollaborationServiceImpl.java +++ b/components/collaboration/internal/android/java/src/org/chromium/components/collaboration/CollaborationServiceImpl.java
@@ -55,6 +55,15 @@ } @Override + public void startLeaveOrDeleteFlow( + CollaborationControllerDelegate delegate, + String syncId, + @CollaborationServiceLeaveOrDeleteEntryPoint int entry) { + CollaborationServiceImplJni.get() + .startLeaveOrDeleteFlow(mNativePtr, delegate.getNativePtr(), syncId, entry); + } + + @Override public ServiceStatus getServiceStatus() { return CollaborationServiceImplJni.get().getServiceStatus(mNativePtr); } @@ -116,6 +125,12 @@ String syncId, int entry); + void startLeaveOrDeleteFlow( + long nativeCollaborationServiceAndroid, + long delegateNativePtr, + String syncId, + int entry); + ServiceStatus getServiceStatus(long nativeCollaborationServiceAndroid); int getCurrentUserRoleForGroup(
diff --git a/components/collaboration/public/android/java/src/org/chromium/components/collaboration/CollaborationService.java b/components/collaboration/public/android/java/src/org/chromium/components/collaboration/CollaborationService.java index 8085f4c..6befab7 100644 --- a/components/collaboration/public/android/java/src/org/chromium/components/collaboration/CollaborationService.java +++ b/components/collaboration/public/android/java/src/org/chromium/components/collaboration/CollaborationService.java
@@ -53,12 +53,25 @@ * * @param delegate The delegate to perform action on the Android UI. * @param either_id The ID to identify a tab group. + * @param entry The entry point of the flow. */ void startShareOrManageFlow( CollaborationControllerDelegate delegate, String syncId, @CollaborationServiceShareOrManageEntryPoint int entry); + /** + * Starts a new collaboration leave or delete flow. + * + * @param delegate The delegate to perform action on the Android UI. + * @param either_id The ID to identify a tab group. + * @param entry The entry point of the flow. + */ + void startLeaveOrDeleteFlow( + CollaborationControllerDelegate delegate, + String syncId, + @CollaborationServiceLeaveOrDeleteEntryPoint int entry); + /** Returns the current {@link ServiceStatus} of the service. */ ServiceStatus getServiceStatus();
diff --git a/components/crash/core/common/crash_export.h b/components/crash/core/common/crash_export.h index 7496a5af..f13dc9c 100644 --- a/components/crash/core/common/crash_export.h +++ b/components/crash/core/common/crash_export.h
@@ -15,11 +15,7 @@ #endif // defined(CRASH_CORE_COMMON_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CRASH_CORE_COMMON_IMPLEMENTATION) #define CRASH_EXPORT __attribute__((visibility("default"))) -#else -#define CRASH_EXPORT -#endif // defined(CRASH_CORE_COMMON_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/credential_management/android/java/src/org/chromium/components/credential_management/ThirdPartyCredentialManagerBridge.java b/components/credential_management/android/java/src/org/chromium/components/credential_management/ThirdPartyCredentialManagerBridge.java index 8fa4d27..fb5b6157 100644 --- a/components/credential_management/android/java/src/org/chromium/components/credential_management/ThirdPartyCredentialManagerBridge.java +++ b/components/credential_management/android/java/src/org/chromium/components/credential_management/ThirdPartyCredentialManagerBridge.java
@@ -27,6 +27,8 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; +import java.util.Collections; + /** A bridge for interacting with Credential Manager. */ @JNINamespace("credential_management") @NullMarked @@ -42,13 +44,18 @@ } @CalledByNative - void get(String origin, Callback<PasswordCredentialResponse> callback) { + void get( + boolean isAutoSelectAllowed, + String origin, + Callback<PasswordCredentialResponse> callback) { Context context = ContextUtils.getApplicationContext(); CredentialManager credentialManager = sCredentialManagerForTesting == null ? CredentialManager.create(context) : sCredentialManagerForTesting; - GetPasswordOption passwordOption = new GetPasswordOption(); + GetPasswordOption passwordOption = + new GetPasswordOption( + Collections.emptySet(), isAutoSelectAllowed, Collections.emptySet()); GetCredentialRequest getPasswordRequest = new GetCredentialRequest.Builder() .addCredentialOption(passwordOption)
diff --git a/components/credential_management/android/java/src/org/chromium/components/credential_management/ThirdPartyCredentialManagerBridgeTest.java b/components/credential_management/android/java/src/org/chromium/components/credential_management/ThirdPartyCredentialManagerBridgeTest.java index 7bf2de1..8a985d1 100644 --- a/components/credential_management/android/java/src/org/chromium/components/credential_management/ThirdPartyCredentialManagerBridgeTest.java +++ b/components/credential_management/android/java/src/org/chromium/components/credential_management/ThirdPartyCredentialManagerBridgeTest.java
@@ -76,7 +76,7 @@ any(Executor.class), any(CredentialManagerCallback.class)); - mBridge.get(ORIGIN, mCredentialResponseCallback); + mBridge.get(true, ORIGIN, mCredentialResponseCallback); verify(mCredentialManager) .getCredentialAsync( @@ -103,7 +103,7 @@ any(Executor.class), any(CredentialManagerCallback.class)); - mBridge.get(ORIGIN, mCredentialResponseCallback); + mBridge.get(false, ORIGIN, mCredentialResponseCallback); verify(mCredentialManager) .getCredentialAsync(
diff --git a/components/credential_management/android/third_party_credential_manager_bridge.cc b/components/credential_management/android/third_party_credential_manager_bridge.cc index f9dc7db..0970b396 100644 --- a/components/credential_management/android/third_party_credential_manager_bridge.cc +++ b/components/credential_management/android/third_party_credential_manager_bridge.cc
@@ -66,12 +66,14 @@ jni_zero::AttachCurrentThread())); } - void Get(const std::string& origin, + void Get(bool is_auto_select_allowed, + const std::string& origin, base::OnceCallback<void(PasswordCredentialResponse)> completion_callback) override { JNIEnv* env = jni_zero::AttachCurrentThread(); Java_ThirdPartyCredentialManagerBridge_get( - env, java_bridge_, base::android::ConvertUTF8ToJavaString(env, origin), + env, java_bridge_, is_auto_select_allowed, + base::android::ConvertUTF8ToJavaString(env, origin), base::android::ToJniCallback(env, std::move(completion_callback))); } @@ -108,12 +110,13 @@ jni_delegate_->CreateBridge(); } -void ThirdPartyCredentialManagerBridge::Get(const std::string& origin, +void ThirdPartyCredentialManagerBridge::Get(bool is_auto_select_allowed, + const std::string& origin, GetCallback completion_callback) { base::OnceCallback<void(PasswordCredentialResponse)> on_complete = base::BindOnce(&OnPasswordCredentialReceived, origin, std::move(completion_callback)); - jni_delegate_->Get(origin, std::move(on_complete)); + jni_delegate_->Get(is_auto_select_allowed, origin, std::move(on_complete)); } void ThirdPartyCredentialManagerBridge::Store(
diff --git a/components/credential_management/android/third_party_credential_manager_bridge.h b/components/credential_management/android/third_party_credential_manager_bridge.h index 587a4a7..781b9660 100644 --- a/components/credential_management/android/third_party_credential_manager_bridge.h +++ b/components/credential_management/android/third_party_credential_manager_bridge.h
@@ -25,7 +25,8 @@ public: virtual ~CredentialManagerBridge() = default; - virtual void Get(const std::string& origin, + virtual void Get(bool is_auto_select_allowed, + const std::string& origin, GetCallback completion_callback) = 0; virtual void Store(const std::u16string& username, @@ -51,7 +52,8 @@ // Gets a credential from the Android Credential Manager. // The `completion_callback` should always be invoked on completion, passing // the PasswordCredentialResponse. - virtual void Get(const std::string& origin, + virtual void Get(bool is_auto_select_allowed, + const std::string& origin, base::OnceCallback<void(PasswordCredentialResponse)> completion_callback) = 0; @@ -78,7 +80,9 @@ void Create(); - void Get(const std::string& origin, GetCallback completion_callback) override; + void Get(bool is_auto_select_allowed, + const std::string& origin, + GetCallback completion_callback) override; void Store(const std::u16string& username, const std::u16string& password,
diff --git a/components/credential_management/android/third_party_credential_manager_bridge_unittest.cc b/components/credential_management/android/third_party_credential_manager_bridge_unittest.cc index c9e30dfa0..3cb8d7083 100644 --- a/components/credential_management/android/third_party_credential_manager_bridge_unittest.cc +++ b/components/credential_management/android/third_party_credential_manager_bridge_unittest.cc
@@ -42,7 +42,8 @@ void CreateBridge() override {} - void Get(const std::string& origin, + void Get(bool is_auto_select_allowed, + const std::string& origin, base::OnceCallback<void(PasswordCredentialResponse)> completion_callback) override { if (simulate_errors_) { @@ -113,7 +114,8 @@ mock_callback, Run(password_manager::CredentialManagerError::SUCCESS, testing::_)) .WillOnce(testing::Invoke([&]() { run_loop.Quit(); })); - bridge()->Get(kTestOrigin, mock_callback.Get()); + bridge()->Get(/*is_auto_select_allowed=*/false, kTestOrigin, + mock_callback.Get()); run_loop.Run(); } @@ -128,7 +130,8 @@ mock_callback, Run(password_manager::CredentialManagerError::UNKNOWN, testing::_)) .WillOnce(testing::Invoke([&]() { run_loop.Quit(); })); - bridge()->Get(kTestOrigin, mock_callback.Get()); + bridge()->Get(/*is_auto_select_allowed=*/true, kTestOrigin, + mock_callback.Get()); run_loop.Run(); } @@ -183,7 +186,8 @@ Run(password_manager::CredentialManagerError::SUCCESS, testing::_)) .WillOnce(testing::Invoke([&]() { run_loop_get.Quit(); })); - bridge()->Get(kTestOrigin, mock_get_callback.Get()); + bridge()->Get(/*is_auto_select_allowed=*/true, kTestOrigin, + mock_get_callback.Get()); run_loop_get.Run(); }
diff --git a/components/credential_management/android/third_party_credential_manager_impl.cc b/components/credential_management/android/third_party_credential_manager_impl.cc index ddd8915..d86dd8e2 100644 --- a/components/credential_management/android/third_party_credential_manager_impl.cc +++ b/components/credential_management/android/third_party_credential_manager_impl.cc
@@ -40,13 +40,59 @@ NOTIMPLEMENTED(); } +// This method decides if credential picker should be shown. + +// Credential mediation can be silent, optional, conditional or +// required. + +// Silent mediation should not show a credential picker even if there +// are multiple credentials available and return null. +// Silent mediation can't be implemented here, because the Android API +// doesn't support it. We'd have to know the amount of available credentials +// already before calling get. + +// By default, the GetCredentialRequest will have optional +// mediation: if there's more than one matching credential, the system +// will show the credential picker UI to the user. + +// Required mediation will show the credential picker, no matter the amount +// of choices. + +// Conditional mediation allows the user to pick a credential from the +// picker or avoid selecting a credential without any user-visible error +// condition. That type of mediotion is also not supported in the Android +// API. + +bool ShouldAllowAutoSelect( + password_manager::CredentialMediationRequirement mediation) { + switch (mediation) { + case password_manager::CredentialMediationRequirement::kOptional: + return true; + case password_manager::CredentialMediationRequirement::kRequired: + return false; + case password_manager::CredentialMediationRequirement::kSilent: + case password_manager::CredentialMediationRequirement::kConditional: + NOTIMPLEMENTED(); + } + return false; +} + void ThirdPartyCredentialManagerImpl::Get( password_manager::CredentialMediationRequirement mediation, bool include_passwords, const std::vector<GURL>& federations, GetCallback callback) { + if (mediation == password_manager::CredentialMediationRequirement::kSilent || + mediation == + password_manager::CredentialMediationRequirement::kConditional) { + std::move(callback).Run(password_manager::CredentialManagerError::UNKNOWN, + std::nullopt); + return; + } + // TODO(crbug.com/404199116): Pass all the parameters to the bridge. - bridge_->Get(render_frame_host().GetLastCommittedOrigin().Serialize(), + bridge_->Get(ShouldAllowAutoSelect(mediation), + render_frame_host().GetLastCommittedOrigin().Serialize(), std::move(callback)); }
diff --git a/components/credential_management/android/third_party_credential_manager_impl_unittest.cc b/components/credential_management/android/third_party_credential_manager_impl_unittest.cc index 06d198f..55eadbf 100644 --- a/components/credential_management/android/third_party_credential_manager_impl_unittest.cc +++ b/components/credential_management/android/third_party_credential_manager_impl_unittest.cc
@@ -32,7 +32,10 @@ MockThirdPartyCredentialManagerBridge() = default; ~MockThirdPartyCredentialManagerBridge() override = default; - MOCK_METHOD(void, Get, (const std::string&, GetCallback), (override)); + MOCK_METHOD(void, + Get, + (bool is_auto_select_allowed, const std::string&, GetCallback), + (override)); MOCK_METHOD(void, Store, (const std::u16string&, @@ -84,16 +87,58 @@ credential_manager()->Store(info, StoreCallback()); } -TEST_F(ThirdPartyCredentialManagerImplTest, TestGet) { +TEST_F(ThirdPartyCredentialManagerImplTest, TestGetWithOptionalMediation) { content::WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL(kTestOrigin)); - EXPECT_CALL(*mock_bridge(), Get(kTestOrigin, _)); + EXPECT_CALL(*mock_bridge(), Get(/*mediation=*/true, kTestOrigin, _)); credential_manager()->Get( - /*mediation=*/password_manager::CredentialMediationRequirement::kSilent, + /*mediation=*/password_manager::CredentialMediationRequirement::kOptional, /*include_passwords=*/true, /*federations=*/std::vector<GURL>(), GetCallback()); } +TEST_F(ThirdPartyCredentialManagerImplTest, TestGetWithRequiredMediation) { + content::WebContentsTester::For(web_contents()) + ->NavigateAndCommit(GURL(kTestOrigin)); + + EXPECT_CALL(*mock_bridge(), Get(/*mediation=*/false, kTestOrigin, _)); + + credential_manager()->Get( + /*mediation=*/password_manager::CredentialMediationRequirement::kRequired, + /*include_passwords=*/true, + /*federations=*/std::vector<GURL>(), GetCallback()); +} + +TEST_F(ThirdPartyCredentialManagerImplTest, TestGetWithSilentMediation) { + base::MockCallback<GetCallback> mock_get_callback; + content::WebContentsTester::For(web_contents()) + ->NavigateAndCommit(GURL(kTestOrigin)); + + EXPECT_CALL(mock_get_callback, + Run(password_manager::CredentialManagerError::UNKNOWN, + testing::Eq(std::nullopt))); + + credential_manager()->Get( + /*mediation=*/password_manager::CredentialMediationRequirement::kSilent, + /*include_passwords=*/true, + /*federations=*/std::vector<GURL>(), mock_get_callback.Get()); +} + +TEST_F(ThirdPartyCredentialManagerImplTest, TestGetWithConditionalMediation) { + base::MockCallback<GetCallback> mock_get_callback; + content::WebContentsTester::For(web_contents()) + ->NavigateAndCommit(GURL(kTestOrigin)); + + EXPECT_CALL(mock_get_callback, + Run(password_manager::CredentialManagerError::UNKNOWN, + testing::Eq(std::nullopt))); + + credential_manager()->Get( + /*mediation=*/password_manager::CredentialMediationRequirement:: + kConditional, + /*include_passwords=*/true, + /*federations=*/std::vector<GURL>(), mock_get_callback.Get()); +} } // namespace credential_management
diff --git a/components/cronet/gn2bp/gen_android_bp.py b/components/cronet/gn2bp/gen_android_bp.py index bb39bcdb..5265f93 100755 --- a/components/cronet/gn2bp/gen_android_bp.py +++ b/components/cronet/gn2bp/gen_android_bp.py
@@ -50,8 +50,6 @@ additional_args = None # Name of the java default module for non-test java modules defined in Android.extras.bp java_framework_defaults_module = 'MODIFIED_BY_MAIN_AFTER_PARSING_ARGS_IF_YOU_SEE_THIS_SOMETHING_BROKE_' -# Name of the java default module for test java modules defined in Android.extras.bp -java_framework_test_defaults_module = 'MODIFIED_BY_MAIN_AFTER_PARSING_ARGS_IF_YOU_SEE_THIS_SOMETHING_BROKE_' # Location of the project in the Android source tree. tree_path = 'MODIFIED_BY_MAIN_AFTER_PARSING_ARGS_IF_YOU_SEE_THIS_SOMETHING_BROKE_' @@ -74,9 +72,6 @@ global java_framework_defaults_module java_framework_defaults_module = f'{MODULE_PREFIX}java_framework_defaults' - global java_framework_test_defaults_module - java_framework_test_defaults_module = f'{MODULE_PREFIX}java_framework_test_defaults' - global tree_path tree_path = f'external/cronet/{IMPORT_CHANNEL}' @@ -2209,14 +2204,12 @@ return merged_module -def create_java_module(bp_module_name, target, is_test_target, blueprint): +def create_java_module(bp_module_name, target, blueprint): def add_java_library_properties(module): module.min_sdk_version = _MIN_SDK_VERSION module.apex_available = [tethering_apex] module.defaults.add(java_framework_defaults_module) - if is_test_target: - module.defaults.add(java_framework_test_defaults_module) module.build_file_path = target.build_file_path # As hinted in `parse_gn_desc()`, Java GN targets are... complicated. @@ -2651,8 +2644,7 @@ # leaf node. return () elif target.type == 'java_library': - modules = (create_java_module(bp_module_name, target, is_test_target, - blueprint), ) + modules = (create_java_module(bp_module_name, target, blueprint), ) else: # Note we don't have to handle `group` targets because parse_gn_desc() never # returns any; it just recurses through them and bubbles their dependencies
diff --git a/components/cronet/gn2bp/templates/Android.extras.bp.template b/components/cronet/gn2bp/templates/Android.extras.bp.template index 0cb202b..39a4e4d 100644 --- a/components/cronet/gn2bp/templates/Android.extras.bp.template +++ b/components/cronet/gn2bp/templates/Android.extras.bp.template
@@ -161,6 +161,7 @@ sdk_version: "module_current", libs: [ "framework-connectivity-pre-jarjar-without-cronet", + "framework-connectivity.stubs.module_lib", "framework-connectivity-t.stubs.module_lib", "framework-location.stubs.module_lib", "framework-mediaprovider.stubs.module_lib", @@ -173,18 +174,6 @@ ], } -java_defaults { - name: "${GN2BP_MODULE_PREFIX}java_framework_test_defaults", - sdk_version: "module_current", - libs: [ - // Some tests depend on http client api (e.g. cronet_all_java__testing) - "framework-connectivity-pre-jarjar", - ], - visibility: [ - "//external/cronet:__subpackages__", - ], -} - // rust_bindgen modules do not have an `include_dirs` attribute. Due to that, // C++ headers generated from rust_bindgen can't reference other headers // through paths relative to the repository root. This is what Chromium does
diff --git a/components/data_sharing/internal/group_data_model.cc b/components/data_sharing/internal/group_data_model.cc index 90e55842..c32746659 100644 --- a/components/data_sharing/internal/group_data_model.cc +++ b/components/data_sharing/internal/group_data_model.cc
@@ -384,13 +384,13 @@ void GroupDataModel::NotifyObserversAboutChangedMembers( const GroupData& old_group_data, const GroupData& new_group_data) { - std::vector<GaiaId> old_members_gaia_ids; + std::set<GaiaId> old_members_gaia_ids; for (const auto& member : old_group_data.members) { - old_members_gaia_ids.push_back(member.gaia_id); + old_members_gaia_ids.insert(member.gaia_id); } - std::vector<GaiaId> new_members_gaia_ids; + std::set<GaiaId> new_members_gaia_ids; for (const auto& member : new_group_data.members) { - new_members_gaia_ids.push_back(member.gaia_id); + new_members_gaia_ids.insert(member.gaia_id); } std::vector<GaiaId> added_members_gaia_ids;
diff --git a/components/data_sharing/internal/group_data_model_unittest.cc b/components/data_sharing/internal/group_data_model_unittest.cc index 4c9f6954..0ed1f18 100644 --- a/components/data_sharing/internal/group_data_model_unittest.cc +++ b/components/data_sharing/internal/group_data_model_unittest.cc
@@ -476,6 +476,35 @@ WaitForGroupUpdated(group_id); } +TEST_F(GroupDataModelTest, + ShouldNotifyAboutGroupChanges_MultipleMembersAddedRemoved) { + WaitForModelLoaded(); + + const GroupId group_id = MimicGroupAddedServerSide("group"); + WaitForGroupAdded(group_id); + + // Test that OnMemberAdded() is called when a member is added. + const GaiaId member_gaia_id1("gaia_id99"); + EXPECT_CALL(model_observer(), + OnMemberAdded(group_id, member_gaia_id1, NotNullTime())); + MimicMemberAddedServerSide(group_id, member_gaia_id1); + WaitForGroupUpdated(group_id); + testing::Mock::VerifyAndClearExpectations(&model_observer()); + + const GaiaId member_gaia_id2("gaia_id2"); + EXPECT_CALL(model_observer(), + OnMemberAdded(group_id, member_gaia_id2, NotNullTime())); + MimicMemberAddedServerSide(group_id, member_gaia_id2); + WaitForGroupUpdated(group_id); + testing::Mock::VerifyAndClearExpectations(&model_observer()); + + // Test that OnMemberRemoved() is called when a member is removed. + EXPECT_CALL(model_observer(), + OnMemberRemoved(group_id, member_gaia_id1, NotNullTime())); + MimicMemberRemovedServerSide(group_id, member_gaia_id1); + WaitForGroupUpdated(group_id); +} + TEST_F(GroupDataModelTest, ShouldNotifyOnSyncBridgeUpdateTypeChanged) { EXPECT_CALL(model_observer(), OnSyncBridgeUpdateTypeChanged( Eq(SyncBridgeUpdateType::kDisableSync)))
diff --git a/components/device_event_log/device_event_log_export.h b/components/device_event_log/device_event_log_export.h index 4c4cb52..6ca238a 100644 --- a/components/device_event_log/device_event_log_export.h +++ b/components/device_event_log/device_event_log_export.h
@@ -16,19 +16,11 @@ #endif // defined(DEVICE_EVENT_LOG_IMPLEMENTATION) #else // defined(WIN32) - -#if defined(DEVICE_EVENT_LOG_IMPLEMENTATION) #define DEVICE_EVENT_LOG_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_EVENT_LOG_EXPORT -#endif // defined(DEVICE_EVENT_LOG_IMPLEMENTATION) - #endif // defined(WIN32) #else // defined(COMPONENT_BUILD) - #define DEVICE_EVENT_LOG_EXPORT - #endif #endif // COMPONENTS_DEVICE_EVENT_LOG_DEVICE_EVENT_LOG_EXPORT_H_
diff --git a/components/discardable_memory/common/discardable_memory_export.h b/components/discardable_memory/common/discardable_memory_export.h index 857815c..6304070 100644 --- a/components/discardable_memory/common/discardable_memory_export.h +++ b/components/discardable_memory/common/discardable_memory_export.h
@@ -15,11 +15,7 @@ #endif // defined(DISCARDABLE_MEMORY_IMPLEMENTATION) #else // defined(WIN32) -#if defined(DISCARDABLE_MEMORY_IMPLEMENTATION) #define DISCARDABLE_MEMORY_EXPORT __attribute__((visibility("default"))) -#else -#define DISCARDABLE_MEMORY_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/domain_reliability/domain_reliability_export.h b/components/domain_reliability/domain_reliability_export.h index 169d9b66..87b98d6 100644 --- a/components/domain_reliability/domain_reliability_export.h +++ b/components/domain_reliability/domain_reliability_export.h
@@ -16,11 +16,7 @@ #else // defined(WIN32) -#if defined(DOMAIN_RELIABILITY_IMPLEMENTATION) #define DOMAIN_RELIABILITY_EXPORT __attribute__((visibility("default"))) -#else -#define DOMAIN_RELIABILITY_EXPORT -#endif #endif // defined(WIN32) #else // defined(COMPONENT_BUILD)
diff --git a/components/download/public/common/download_export.h b/components/download/public/common/download_export.h index abc049fc..4be8087 100644 --- a/components/download/public/common/download_export.h +++ b/components/download/public/common/download_export.h
@@ -15,11 +15,7 @@ #endif // defined(COMPONENTS_DOWNLOAD_IMPLEMENTATION) #else // defined(WIN32) -#if defined(COMPONENTS_DOWNLOAD_IMPLEMENTATION) #define COMPONENTS_DOWNLOAD_EXPORT __attribute__((visibility("default"))) -#else -#define COMPONENTS_DOWNLOAD_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/drive/drive_export.h b/components/drive/drive_export.h index 5c8d3c0..5d1fa02 100644 --- a/components/drive/drive_export.h +++ b/components/drive/drive_export.h
@@ -17,13 +17,8 @@ #endif // defined(COMPONENTS_DRIVE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(COMPONENTS_DRIVE_IMPLEMENTATION) #define COMPONENTS_DRIVE_EXPORT __attribute__((visibility("default"))) #define COMPONENTS_DRIVE_EXPORT_PRIVATE __attribute__((visibility("default"))) -#else -#define COMPONENTS_DRIVE_EXPORT -#define COMPONENTS_DRIVE_EXPORT_PRIVATE -#endif #endif #else /// defined(COMPONENT_BUILD)
diff --git a/components/enterprise/common/proto/BUILD.gn b/components/enterprise/common/proto/BUILD.gn index 98060e8a..d1144a66 100644 --- a/components/enterprise/common/proto/BUILD.gn +++ b/components/enterprise/common/proto/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( + "//components/safe_browsing/core/common/proto_to_value/proto_to_value.gni") import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni") import("//third_party/protobuf/proto_library.gni") @@ -19,6 +21,15 @@ deps = [ "//components/safe_browsing/core/common/proto:csd_proto" ] } +proto_to_value("connectors_proto_to_value") { + sources = [ "connectors.proto" ] + + deps = [ + "//components/safe_browsing/core/common/proto:csd_proto", + "//components/safe_browsing/core/common/proto:csd_proto_to_value", + ] +} + proto_library("dlp_policy_event_proto") { sources = [ "synced/dlp_policy_event.proto" ] }
diff --git a/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc b/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc index eec3b07..819a3b2 100644 --- a/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc +++ b/components/error_page/content/browser/net_error_auto_reloader_browsertest.cc
@@ -11,6 +11,7 @@ #include "base/memory/raw_ptr.h" #include "base/test/bind.h" #include "content/public/browser/navigation_controller.h" +#include "content/public/browser/navigation_throttle_registry.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/content_features.h" @@ -43,8 +44,9 @@ interceptor_(base::BindLambdaForTesting( [this, error](content::URLLoaderInterceptor::RequestParams* params) { - if (params->url_request.url != url_) + if (params->url_request.url != url_) { return false; + } network::URLLoaderCompletionStatus status; status.error_code = error; params->client->OnComplete(status); @@ -133,15 +135,17 @@ // content::WebContentsObserver: void DidFinishNavigation(content::NavigationHandle* handle) override { DCHECK(throttle_); - if (handle == throttle_->navigation_handle()) + if (handle == throttle_->navigation_handle()) { finish_wait_loop_.Quit(); + } } private: std::unique_ptr<content::NavigationThrottle> MaybeCreateThrottle( content::NavigationHandle* handle) { - if (throttle_) + if (throttle_) { return nullptr; + } auto throttle = std::make_unique<DeferringThrottle>( handle, defer_wait_loop_.QuitClosure()); @@ -170,15 +174,10 @@ content::ShellContentBrowserClient::Get() ->set_create_throttles_for_navigation_callback(base::BindRepeating( - [](content::NavigationHandle* handle) - -> std::vector<std::unique_ptr<content::NavigationThrottle>> { - std::vector<std::unique_ptr<content::NavigationThrottle>> - throttles; - auto throttle = - NetErrorAutoReloader::MaybeCreateThrottleFor(handle); - if (throttle) - throttles.push_back(std::move(throttle)); - return throttles; + [](content::NavigationThrottleRegistry& registry) -> void { + registry.MaybeAddThrottle( + NetErrorAutoReloader::MaybeCreateThrottleFor( + ®istry.GetNavigationHandle())); })); } @@ -193,8 +192,9 @@ std::optional<base::TimeDelta> GetCurrentAutoReloadDelay() { const std::optional<base::OneShotTimer>& timer = GetAutoReloader()->next_reload_timer_for_testing(); - if (!timer) + if (!timer) { return std::nullopt; + } return timer->GetCurrentDelay(); } @@ -239,8 +239,9 @@ error_page::NetErrorAutoReloader::FromWebContents(wc); std::optional<base::OneShotTimer>& timer = reloader->next_reload_timer_for_testing(); - if (timer && timer->IsRunning()) + if (timer && timer->IsRunning()) { timer->FireNow(); + } } static void SimulateNetworkGoingOnline(content::WebContents* wc) {
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index c2f8dae..80b05c4 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -239,7 +239,6 @@ "//base", "//base/test:test_support", "//chromeos/ui/base", - "//components/exo/wayland:test_controller_stub", "//components/exo/wayland:ui_controls_protocol_stub", "//components/viz/service", "//gpu",
diff --git a/components/exo/surface.h b/components/exo/surface.h index 284c2d81..76a2b2b 100644 --- a/components/exo/surface.h +++ b/components/exo/surface.h
@@ -514,7 +514,6 @@ ~State(); bool operator==(const State& other) const; - bool operator!=(const State& other) const { return !(*this == other); } cc::Region opaque_region; std::optional<cc::Region> input_region;
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index c95d9ffb..e7a7bdc 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -118,7 +118,6 @@ "zcr_stylus.h", "zcr_stylus_tools.cc", "zcr_stylus_tools.h", - "zcr_test_controller.h", "zcr_touchpad_haptics.cc", "zcr_touchpad_haptics.h", "zcr_ui_controls.h", @@ -229,26 +228,6 @@ } } -static_library("test_controller") { - testonly = true - sources = [ "zcr_test_controller.cc" ] - deps = [ - ":wayland", - "//base/test:test_support", - "//third_party/wayland:wayland_server", - "//third_party/wayland-protocols:test_controller_protocol", - "//ui/events", - ] -} - -static_library("test_controller_stub") { - testonly = false - sources = [ - "zcr_test_controller.h", - "zcr_test_controller_stub.cc", - ] -} - static_library("ui_controls_protocol") { testonly = true defines = [ "UI_CONTROLS_PROTOCOL_IMPLEMENTATION" ]
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index d682617d..cdeb838 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -81,7 +81,6 @@ #include "components/exo/wayland/zcr_remote_shell_v2.h" #include "components/exo/wayland/zcr_stylus.h" #include "components/exo/wayland/zcr_stylus_tools.h" -#include "components/exo/wayland/zcr_test_controller.h" #include "components/exo/wayland/zcr_touchpad_haptics.h" #include "components/exo/wayland/zcr_ui_controls.h" #include "components/exo/wayland/zcr_vsync_feedback.h" @@ -350,7 +349,6 @@ /*version=*/1, display_, bind_zwp_idle_inhibit_manager); ui_controls_holder_ = std::make_unique<UiControls>(this); - test_controller_ = std::make_unique<TestController>(this); zcr_keyboard_extension_data_ = std::make_unique<WaylandKeyboardExtension>(serial_tracker_.get());
diff --git a/components/exo/wayland/server.h b/components/exo/wayland/server.h index 89f9f50..e46e5f2 100644 --- a/components/exo/wayland/server.h +++ b/components/exo/wayland/server.h
@@ -28,7 +28,6 @@ class ClientTracker; class SerialTracker; -class TestController; class UiControls; struct WaylandDataDeviceManager; struct WaylandKeyboardExtension; @@ -140,7 +139,6 @@ std::unique_ptr<UiControls> ui_controls_holder_; std::unique_ptr<ClientTracker> client_tracker_; std::unique_ptr<WaylandProtocolLogger> wayland_protocol_logger_; - std::unique_ptr<TestController> test_controller_; }; } // namespace wayland
diff --git a/components/exo/wayland/zcr_test_controller.cc b/components/exo/wayland/zcr_test_controller.cc deleted file mode 100644 index 6276df76..0000000 --- a/components/exo/wayland/zcr_test_controller.cc +++ /dev/null
@@ -1,77 +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. - -#include "components/exo/wayland/zcr_test_controller.h" - -#include <stdint.h> -#include <test-controller-unstable-v1-server-protocol.h> -#include <wayland-server-core.h> - -#include <memory> - -#include "base/check.h" -#include "base/test/simple_test_tick_clock.h" -#include "base/time/time.h" -#include "components/exo/wayland/server.h" -#include "components/exo/wayland/server_util.h" -#include "ui/events/base_event_utils.h" - -namespace exo::wayland { - -struct TestController::State { - std::unique_ptr<base::SimpleTestTickClock> clock; -}; - -namespace { - -void test_controller_mock_event_tick_clock_start(struct wl_client* client, - struct wl_resource* resource) { - auto* state = GetUserDataAs<TestController::State>(resource); - CHECK(state); - state->clock = std::make_unique<base::SimpleTestTickClock>(); - state->clock->SetNowTicks(base::TimeTicks::Now()); - ui::SetEventTickClockForTesting(state->clock.get()); -} - -void test_controller_mock_event_tick_clock_advance(struct wl_client* client, - struct wl_resource* resource, - uint32_t milliseconds) { - auto* state = GetUserDataAs<TestController::State>(resource); - CHECK(state); - if (state->clock) { - state->clock->Advance(base::Milliseconds(milliseconds)); - } -} - -const struct zcr_test_controller_v1_interface test_controller_implementation = { - test_controller_mock_event_tick_clock_start, - test_controller_mock_event_tick_clock_advance}; - -void destroy_test_controller_resource(struct wl_resource* resource) { - ui::SetEventTickClockForTesting(nullptr); -} - -void bind_test_controller(wl_client* client, - void* data, - uint32_t version, - uint32_t id) { - wl_resource* resource = wl_resource_create( - client, &zcr_test_controller_v1_interface, version, id); - - wl_resource_set_implementation(resource, &test_controller_implementation, - data, destroy_test_controller_resource); -} - -} // namespace - -TestController::TestController(Server* server) - : state_(std::make_unique<TestController::State>()) { - wl_global_create(server->GetWaylandDisplay(), - &zcr_test_controller_v1_interface, - /*version=*/1, state_.get(), bind_test_controller); -} - -TestController::~TestController() = default; - -} // namespace exo::wayland
diff --git a/components/exo/wayland/zcr_test_controller.h b/components/exo/wayland/zcr_test_controller.h deleted file mode 100644 index 108291e..0000000 --- a/components/exo/wayland/zcr_test_controller.h +++ /dev/null
@@ -1,30 +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. - -#ifndef COMPONENTS_EXO_WAYLAND_ZCR_TEST_CONTROLLER_H_ -#define COMPONENTS_EXO_WAYLAND_ZCR_TEST_CONTROLLER_H_ - -#include <memory> - -namespace exo::wayland { - -class Server; - -class TestController { - public: - TestController(Server* server); - TestController(const TestController&) = delete; - TestController& operator=(const TestController&) = delete; - ~TestController(); - // State is declared here but not defined because its definition references - // symbols in test-only dependencies. - struct State; - - private: - std::unique_ptr<State> state_; -}; - -} // namespace exo::wayland - -#endif // COMPONENTS_EXO_WAYLAND_ZCR_TEST_CONTROLLER_H_
diff --git a/components/exo/wayland/zcr_test_controller_stub.cc b/components/exo/wayland/zcr_test_controller_stub.cc deleted file mode 100644 index ba84d84..0000000 --- a/components/exo/wayland/zcr_test_controller_stub.cc +++ /dev/null
@@ -1,17 +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. - -#include "components/exo/wayland/zcr_test_controller.h" - -namespace exo::wayland { - -class Server; - -TestController::TestController(Server* server) {} - -TestController::~TestController() = default; - -struct TestController::State {}; - -} // namespace exo::wayland
diff --git a/components/external_intents/android/external_intents_features.cc b/components/external_intents/android/external_intents_features.cc index 6c81905..0fd49eca 100644 --- a/components/external_intents/android/external_intents_features.cc +++ b/components/external_intents/android/external_intents_features.cc
@@ -26,7 +26,7 @@ // Array of features exposed through the Java ExternalIntentsFeatures API. const base::Feature* const kFeaturesExposedToJava[] = { &kExternalNavigationDebugLogs, &kBlockFrameRenavigations, - &kBlockIntentsToSelf}; + &kBlockIntentsToSelf, &kNavigationCaptureRefactorAndroid}; } // namespace @@ -44,6 +44,10 @@ "BlockIntentsToSelf", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kNavigationCaptureRefactorAndroid, + "NavigationCaptureRefactorAndroid", + base::FEATURE_DISABLED_BY_DEFAULT); + static jlong JNI_ExternalIntentsFeatures_GetFeature(JNIEnv* env, jint ordinal) { return reinterpret_cast<jlong>(kFeaturesExposedToJava[ordinal]); }
diff --git a/components/external_intents/android/external_intents_features.h b/components/external_intents/android/external_intents_features.h index 1c7535d..8eb1243 100644 --- a/components/external_intents/android/external_intents_features.h +++ b/components/external_intents/android/external_intents_features.h
@@ -12,6 +12,7 @@ BASE_DECLARE_FEATURE(kExternalNavigationDebugLogs); BASE_DECLARE_FEATURE(kBlockFrameRenavigations); BASE_DECLARE_FEATURE(kBlockIntentsToSelf); +BASE_DECLARE_FEATURE(kNavigationCaptureRefactorAndroid); } // namespace external_intents
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java index e2e4578..c3f5b39 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalIntentsFeatures.java
@@ -23,6 +23,8 @@ public static final String EXTERNAL_NAVIGATION_DEBUG_LOGS_NAME = "ExternalNavigationDebugLogs"; public static final String BLOCK_FRAME_RENAVIGATIONS_NAME = "BlockFrameRenavigations3"; public static final String BLOCK_INTENTS_TO_SELF_NAME = "BlockIntentsToSelf"; + public static final String NAVIGATION_CAPTURE_REFACTOR_ANDROID_NAME = + "NavigationCaptureRefactorAndroid"; public static final ExternalIntentsFeatures EXTERNAL_NAVIGATION_DEBUG_LOGS = new ExternalIntentsFeatures(0, EXTERNAL_NAVIGATION_DEBUG_LOGS_NAME); @@ -33,6 +35,9 @@ public static final ExternalIntentsFeatures BLOCK_INTENTS_TO_SELF = new ExternalIntentsFeatures(2, BLOCK_INTENTS_TO_SELF_NAME); + public static final ExternalIntentsFeatures NAVIGATION_CAPTURE_REFACTOR_ANDROID = + new ExternalIntentsFeatures(3, NAVIGATION_CAPTURE_REFACTOR_ANDROID_NAME); + private final int mOrdinal; private ExternalIntentsFeatures(int ordinal, String name) {
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java index 7567dd7a..2d78a72 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -1546,6 +1546,11 @@ Intent targetIntent, GURL browserFallbackUrl, MutableBoolean canLaunchExternalFallbackResult) { + + if (debug() && ExternalIntentsFeatures.NAVIGATION_CAPTURE_REFACTOR_ANDROID.isEnabled()) { + Log.i(TAG, "Navigation Capture refactor feature enabled"); + } + sanitizeQueryIntentActivitiesIntent(targetIntent); // Any subsequent navigations should cancel the existing dialog.
diff --git a/components/gcm_driver/common/gcm_driver_export.h b/components/gcm_driver/common/gcm_driver_export.h index aa47838..9c767a3 100644 --- a/components/gcm_driver/common/gcm_driver_export.h +++ b/components/gcm_driver/common/gcm_driver_export.h
@@ -15,11 +15,7 @@ #endif // defined(GCM_DRIVER_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GCM_DRIVER_IMPLEMENTATION) #define GCM_DRIVER_EXPORT __attribute__((visibility("default"))) -#else -#define GCM_DRIVER_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/gwp_asan/client/export.h b/components/gwp_asan/client/export.h index 99043e7..052dba5 100644 --- a/components/gwp_asan/client/export.h +++ b/components/gwp_asan/client/export.h
@@ -15,11 +15,7 @@ #endif // defined(GWP_ASAN_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GWP_ASAN_IMPLEMENTATION) #define GWP_ASAN_EXPORT __attribute__((visibility("default"))) -#else -#define GWP_ASAN_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/image_fetcher/core/request_metadata.cc b/components/image_fetcher/core/request_metadata.cc index 4fbfca2c..4ea9846 100644 --- a/components/image_fetcher/core/request_metadata.cc +++ b/components/image_fetcher/core/request_metadata.cc
@@ -9,14 +9,4 @@ RequestMetadata::RequestMetadata() : http_response_code(RESPONSE_CODE_INVALID) {} -bool operator==(const RequestMetadata& lhs, const RequestMetadata& rhs) { - return lhs.mime_type == rhs.mime_type && - lhs.http_response_code == rhs.http_response_code && - lhs.content_location_header == rhs.content_location_header; -} - -bool operator!=(const RequestMetadata& lhs, const RequestMetadata& rhs) { - return !(lhs == rhs); -} - } // namespace image_fetcher
diff --git a/components/image_fetcher/core/request_metadata.h b/components/image_fetcher/core/request_metadata.h index 7731941..4965461 100644 --- a/components/image_fetcher/core/request_metadata.h +++ b/components/image_fetcher/core/request_metadata.h
@@ -17,14 +17,14 @@ RequestMetadata(); + friend bool operator==(const RequestMetadata&, + const RequestMetadata&) = default; + std::string mime_type; int http_response_code; std::string content_location_header; }; -bool operator==(const RequestMetadata& lhs, const RequestMetadata& rhs); -bool operator!=(const RequestMetadata& lhs, const RequestMetadata& rhs); - } // namespace image_fetcher #endif // COMPONENTS_IMAGE_FETCHER_CORE_REQUEST_METADATA_H_
diff --git a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter.cc b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter.cc index 50dfa9a..0f28790 100644 --- a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter.cc +++ b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter.cc
@@ -12,6 +12,7 @@ #include "base/memory/ptr_util.h" #include "base/sequence_checker.h" +#include "base/types/expected.h" #include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/common/ip_protection_telemetry.h" #include "third_party/abseil-cpp/absl/status/statusor.h" @@ -33,55 +34,80 @@ // `group` should outlive returned encrypter. Used by static creator. // In anonymous namespace to prevent misuse. -absl::StatusOr<std::unique_ptr<ElGamalEncrypter>> CreateEncrypter( +base::expected<std::unique_ptr<ElGamalEncrypter>, absl::Status> CreateEncrypter( ECGroup const* group, const std::string& serialized_public_key) { - PJC_ASSIGN_OR_RETURN(ECPoint g, group->GetFixedGenerator()); - PJC_ASSIGN_OR_RETURN(ECPoint y, group->CreateECPoint(serialized_public_key)); + absl::StatusOr<ECPoint> maybe_g = group->GetFixedGenerator(); + if (!maybe_g.ok()) { + return base::unexpected(maybe_g.status()); + } + + absl::StatusOr<ECPoint> maybe_y = group->CreateECPoint(serialized_public_key); + if (!maybe_y.ok()) { + return base::unexpected(maybe_y.status()); + } return std::make_unique<ElGamalEncrypter>( - group, - std::make_unique<PublicKey>(PublicKey{std::move(g), std::move(y)})); + group, std::make_unique<PublicKey>(PublicKey{ + std::move(maybe_g).value(), std::move(maybe_y).value()})); } // `group` should outlive returned ciphertexts. Used by static creator. // In anonymous namespace to prevent misuse. -absl::StatusOr<std::vector<Ciphertext>> CreateCiphertext( +base::expected<std::vector<Ciphertext>, absl::Status> CreateCiphertext( ECGroup const* group, const std::vector<ProbabilisticRevealToken>& tokens) { std::vector<Ciphertext> ciphertext; ciphertext.reserve(tokens.size()); for (const auto& t : tokens) { - PJC_ASSIGN_OR_RETURN(ECPoint u, group->CreateECPoint(t.u)); - PJC_ASSIGN_OR_RETURN(ECPoint e, group->CreateECPoint(t.e)); - ciphertext.emplace_back(std::move(u), std::move(e)); + absl::StatusOr<ECPoint> maybe_u = group->CreateECPoint(t.u); + if (!maybe_u.ok()) { + return base::unexpected(maybe_u.status()); + } + absl::StatusOr<ECPoint> maybe_e = group->CreateECPoint(t.e); + if (!maybe_e.ok()) { + return base::unexpected(maybe_e.status()); + } + ciphertext.emplace_back(std::move(maybe_u).value(), + std::move(maybe_e).value()); } return ciphertext; } } // namespace -absl::StatusOr<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>> +base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> IpProtectionProbabilisticRevealTokenCrypter::Create( const std::string& serialized_public_key, const std::vector<ProbabilisticRevealToken>& tokens) { auto context = std::make_unique<Context>(); - std::unique_ptr<ECGroup> group; - { - PJC_ASSIGN_OR_RETURN(ECGroup local_group, - ECGroup::Create(NID_X9_62_prime256v1, context.get())); - group = std::make_unique<ECGroup>(std::move(local_group)); + absl::StatusOr<ECGroup> local_group = + ECGroup::Create(NID_X9_62_prime256v1, context.get()); + if (!local_group.ok()) { + return base::unexpected(local_group.status()); } - PJC_ASSIGN_OR_RETURN(std::unique_ptr<ElGamalEncrypter> encrypter, - CreateEncrypter(group.get(), serialized_public_key)); - PJC_ASSIGN_OR_RETURN(std::vector<Ciphertext> ciphertext, - CreateCiphertext(group.get(), tokens)); + std::unique_ptr<ECGroup> group = + std::make_unique<ECGroup>(std::move(local_group).value()); + base::expected<std::unique_ptr<ElGamalEncrypter>, absl::Status> + maybe_encrypter = CreateEncrypter(group.get(), serialized_public_key); + if (!maybe_encrypter.has_value()) { + return base::unexpected(maybe_encrypter.error()); + } + + base::expected<std::vector<Ciphertext>, absl::Status> maybe_ciphertext = + CreateCiphertext(group.get(), tokens); + if (!maybe_ciphertext.has_value()) { + return base::unexpected(maybe_ciphertext.error()); + } + // Can not use `make_unique` since constructor is private. // Can not use `return std::unique_ptr`, git cl upload // returns pre-submit error and recommends using base::WrapUnique. return base::WrapUnique<IpProtectionProbabilisticRevealTokenCrypter>( new IpProtectionProbabilisticRevealTokenCrypter( - std::move(context), std::move(group), std::move(encrypter), - std::move(ciphertext))); + std::move(context), std::move(group), + std::move(maybe_encrypter).value(), + std::move(maybe_ciphertext).value())); } IpProtectionProbabilisticRevealTokenCrypter:: @@ -105,13 +131,22 @@ const std::string& serialized_public_key, const std::vector<ProbabilisticRevealToken>& tokens) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - PJC_ASSIGN_OR_RETURN(std::unique_ptr<ElGamalEncrypter> encrypter, - CreateEncrypter(group_.get(), serialized_public_key)); - PJC_ASSIGN_OR_RETURN(std::vector<Ciphertext> ciphertext, - CreateCiphertext(group_.get(), tokens)); + base::expected<std::unique_ptr<ElGamalEncrypter>, absl::Status> + maybe_encrypter = CreateEncrypter(group_.get(), serialized_public_key); + if (!maybe_encrypter.has_value()) { + return maybe_encrypter.error(); + } + + base::expected<std::vector<Ciphertext>, absl::Status> maybe_ciphertext = + CreateCiphertext(group_.get(), tokens); + if (!maybe_ciphertext.has_value()) { + return maybe_ciphertext.error(); + } + // Creating encrypter and ciphertext succeeded, set members. - encrypter_.reset(encrypter.release()); - ciphertext_ = std::move(ciphertext); + encrypter_ = std::move(maybe_encrypter).value(); + + ciphertext_ = std::move(maybe_ciphertext).value(); return absl::OkStatus(); } @@ -123,21 +158,36 @@ ciphertext_.clear(); } -absl::StatusOr<ProbabilisticRevealToken> +base::expected<ProbabilisticRevealToken, absl::Status> IpProtectionProbabilisticRevealTokenCrypter::Randomize(size_t i) const { base::TimeTicks randomization_start_time = base::TimeTicks::Now(); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (i >= ciphertext_.size()) { - return absl::InvalidArgumentError("invalid index"); + return base::unexpected(absl::InvalidArgumentError("invalid index")); } - PJC_ASSIGN_OR_RETURN(Ciphertext randomized_ciphertext, - encrypter_->ReRandomize(ciphertext_[i])); + absl::StatusOr<Ciphertext> maybe_randomized_ciphertext = + encrypter_->ReRandomize(ciphertext_[i]); + if (!maybe_randomized_ciphertext.ok()) { + return base::unexpected(maybe_randomized_ciphertext.status()); + } + const auto& randomized_ciphertext = maybe_randomized_ciphertext.value(); + ProbabilisticRevealToken randomized_token; randomized_token.version = 1; - PJC_ASSIGN_OR_RETURN(randomized_token.u, - randomized_ciphertext.u.ToBytesCompressed()); - PJC_ASSIGN_OR_RETURN(randomized_token.e, - randomized_ciphertext.e.ToBytesCompressed()); + absl::StatusOr<std::string> maybe_serialized_u = + randomized_ciphertext.u.ToBytesCompressed(); + if (!maybe_serialized_u.ok()) { + return base::unexpected(maybe_serialized_u.status()); + } + randomized_token.u = std::move(maybe_serialized_u).value(); + + absl::StatusOr<std::string> maybe_serialized_e = + randomized_ciphertext.e.ToBytesCompressed(); + if (!maybe_serialized_e.ok()) { + return base::unexpected(maybe_serialized_e.status()); + } + randomized_token.e = std::move(maybe_serialized_e).value(); + Telemetry().ProbabilisticRevealTokenRandomizationTime( base::TimeTicks::Now() - randomization_start_time); return randomized_token;
diff --git a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter.h b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter.h index 7b8e467..ea8bcf4 100644 --- a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter.h +++ b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter.h
@@ -12,9 +12,9 @@ #include "base/sequence_checker.h" #include "base/thread_annotations.h" +#include "base/types/expected.h" #include "components/ip_protection/common/ip_protection_data_types.h" #include "third_party/abseil-cpp/absl/status/status.h" -#include "third_party/abseil-cpp/absl/status/statusor.h" #include "third_party/private-join-and-compute/src/crypto/context.h" #include "third_party/private-join-and-compute/src/crypto/ec_group.h" #include "third_party/private-join-and-compute/src/crypto/elgamal.h" @@ -31,8 +31,9 @@ class IpProtectionProbabilisticRevealTokenCrypter { public: // Returns a unique pointer to crypter if successful. - static absl::StatusOr< - std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>> + static base::expected< + std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> Create(const std::string& serialized_public_key, const std::vector<ProbabilisticRevealToken>& tokens); ~IpProtectionProbabilisticRevealTokenCrypter(); @@ -51,7 +52,8 @@ // ProbabilisticRevealToken by serializing it, if successful. This method // fails if there is no ciphertext for index `i` or `encrypter_.ReRandomize()` // fails. - absl::StatusOr<ProbabilisticRevealToken> Randomize(size_t i) const; + base::expected<ProbabilisticRevealToken, absl::Status> Randomize( + size_t i) const; private: // Private since it assumes all arguments are valid. Static `Create()`
diff --git a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter_fuzztests.cc b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter_fuzztests.cc index e3a0d4d3f..c042d1ad 100644 --- a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter_fuzztests.cc +++ b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter_fuzztests.cc
@@ -61,12 +61,14 @@ ASSERT_THAT(issuer->Tokens(), testing::SizeIs(1)); const ip_protection::ProbabilisticRevealToken& token = issuer->Tokens()[0]; - absl::StatusOr<std::unique_ptr< - ip_protection::IpProtectionProbabilisticRevealTokenCrypter>> + base::expected< + std::unique_ptr< + ip_protection::IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> maybe_crypter = ip_protection::IpProtectionProbabilisticRevealTokenCrypter::Create( issuer->GetSerializedPublicKey(), {token}); - ASSERT_TRUE(maybe_crypter.ok()); + ASSERT_TRUE(maybe_crypter.has_value()); auto& crypter = maybe_crypter.value(); ASSERT_TRUE(crypter->IsTokenAvailable()); ASSERT_EQ(crypter->NumTokens(), std::size_t(1));
diff --git a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter_unittest.cc b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter_unittest.cc index 1a511cd5..e36ad1a 100644 --- a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter_unittest.cc +++ b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_crypter_unittest.cc
@@ -64,9 +64,11 @@ }; CreateTokens(/*private_key=*/12345, plaintexts); - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - GetPublicKey(), GetTokens()); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), GetTokens()); + EXPECT_TRUE(maybe_crypter.has_value()); const auto& crypter = maybe_crypter.value(); EXPECT_TRUE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), plaintexts.size()); @@ -80,9 +82,11 @@ }; CreateTokens(/*private_key=*/12345, plaintexts); - auto maybe_crypter = - IpProtectionProbabilisticRevealTokenCrypter::Create(GetPublicKey(), {}); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), {}); + EXPECT_TRUE(maybe_crypter.has_value()); const auto& crypter = maybe_crypter.value(); EXPECT_FALSE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), std::size_t(0)); @@ -91,9 +95,11 @@ TEST_F(IpProtectionProbabilisticRevealTokenCrypterTest, CreateInvalidPublicKey) { const auto& serialized_public_key = "invalid-public-key"; - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - serialized_public_key, {}); - EXPECT_EQ(maybe_crypter.status().code(), absl::StatusCode::kInvalidArgument); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + serialized_public_key, {}); + EXPECT_EQ(maybe_crypter.error().code(), absl::StatusCode::kInvalidArgument); } TEST_F(IpProtectionProbabilisticRevealTokenCrypterTest, CreateInvalidTokenU) { @@ -106,9 +112,11 @@ std::vector<ProbabilisticRevealToken> tokens = GetTokens(); tokens.back().u = "invalid-u"; - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - GetPublicKey(), tokens); - EXPECT_EQ(maybe_crypter.status().code(), absl::StatusCode::kInvalidArgument); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), tokens); + EXPECT_EQ(maybe_crypter.error().code(), absl::StatusCode::kInvalidArgument); } TEST_F(IpProtectionProbabilisticRevealTokenCrypterTest, CreateInvalidTokenE) { @@ -121,9 +129,11 @@ std::vector<ProbabilisticRevealToken> tokens = GetTokens(); tokens.back().e = "invalid-e"; - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - GetPublicKey(), tokens); - EXPECT_EQ(maybe_crypter.status().code(), absl::StatusCode::kInvalidArgument); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), tokens); + EXPECT_EQ(maybe_crypter.error().code(), absl::StatusCode::kInvalidArgument); } TEST_F(IpProtectionProbabilisticRevealTokenCrypterTest, @@ -136,9 +146,11 @@ CreateTokens(/*private_key=*/11111, plaintexts); // Create a crypter with no tokens. - auto maybe_crypter = - IpProtectionProbabilisticRevealTokenCrypter::Create(GetPublicKey(), {}); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), {}); + EXPECT_TRUE(maybe_crypter.has_value()); auto& crypter = maybe_crypter.value(); EXPECT_FALSE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), std::size_t(0)); @@ -161,9 +173,11 @@ "------------Code never lies, ", "comments sometimes do.-------", }; CreateTokens(/*private_key=*/11111, plaintexts); - auto maybe_crypter = - IpProtectionProbabilisticRevealTokenCrypter::Create(GetPublicKey(), {}); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), {}); + EXPECT_TRUE(maybe_crypter.has_value()); auto& crypter = maybe_crypter.value(); EXPECT_FALSE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), std::size_t(0)); @@ -185,9 +199,11 @@ }; CreateTokens(/*private_key=*/42, plaintexts); - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - GetPublicKey(), GetTokens()); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), GetTokens()); + EXPECT_TRUE(maybe_crypter.has_value()); auto& crypter = maybe_crypter.value(); EXPECT_TRUE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), plaintexts.size()); @@ -208,9 +224,11 @@ }; CreateTokens(/*private_key=*/42, plaintexts); - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - GetPublicKey(), GetTokens()); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), GetTokens()); + EXPECT_TRUE(maybe_crypter.has_value()); auto& crypter = maybe_crypter.value(); EXPECT_TRUE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), plaintexts.size()); @@ -239,9 +257,11 @@ }; CreateTokens(/*private_key=*/42, plaintexts); - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - GetPublicKey(), GetTokens()); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), GetTokens()); + EXPECT_TRUE(maybe_crypter.has_value()); auto& crypter = maybe_crypter.value(); EXPECT_TRUE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), plaintexts.size()); @@ -268,9 +288,11 @@ "------------Code never lies, ", "comments sometimes do.-------", }; CreateTokens(/*private_key=*/7654, plaintexts); - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - GetPublicKey(), GetTokens()); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), GetTokens()); + EXPECT_TRUE(maybe_crypter.has_value()); auto& crypter = maybe_crypter.value(); EXPECT_TRUE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), plaintexts.size()); @@ -290,18 +312,20 @@ }; CreateTokens(/*private_key=*/2025, plaintexts); - const auto maybe_crypter = - IpProtectionProbabilisticRevealTokenCrypter::Create(GetPublicKey(), - GetTokens()); - EXPECT_TRUE(maybe_crypter.ok()); + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + GetPublicKey(), GetTokens()); + EXPECT_TRUE(maybe_crypter.has_value()); const auto& crypter = maybe_crypter.value(); EXPECT_TRUE(crypter->IsTokenAvailable()); EXPECT_EQ(crypter->NumTokens(), plaintexts.size()); // Decrypting randomized tokens should yield starting plaintexts. for (std::size_t i = 0; i < plaintexts.size(); ++i) { - const auto maybe_randomized_token = crypter->Randomize(i); - ASSERT_TRUE(maybe_randomized_token.ok()); + const base::expected<ProbabilisticRevealToken, absl::Status> + maybe_randomized_token = crypter->Randomize(i); + ASSERT_TRUE(maybe_randomized_token.has_value()); const auto& randomized_token = maybe_randomized_token.value(); EXPECT_EQ(randomized_token.version, 1); @@ -314,9 +338,10 @@ } // Try to randomize a token that does not exist. - const auto maybe_token = crypter->Randomize(plaintexts.size()); - ASSERT_FALSE(maybe_token.ok()); - EXPECT_EQ(maybe_token.status().code(), absl::StatusCode::kInvalidArgument); + const base::expected<ProbabilisticRevealToken, absl::Status> maybe_token = + crypter->Randomize(plaintexts.size()); + ASSERT_FALSE(maybe_token.has_value()); + EXPECT_EQ(maybe_token.error().code(), absl::StatusCode::kInvalidArgument); } } // namespace ip_protection
diff --git a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_direct_fetcher.cc b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_direct_fetcher.cc index 4ea23701..51fe17d 100644 --- a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_direct_fetcher.cc +++ b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_direct_fetcher.cc
@@ -328,9 +328,12 @@ response.num_tokens_with_signal() > response.tokens_size()) { return TryGetProbabilisticRevealTokensStatus::kInvalidNumTokensWithSignal; } - if (auto crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - response.public_key().y(), {}); - !crypter.ok()) { + if (base::expected< + std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> crypter = + IpProtectionProbabilisticRevealTokenCrypter::Create( + response.public_key().y(), {}); + !crypter.has_value()) { return TryGetProbabilisticRevealTokensStatus::kInvalidPublicKey; } if (response.epoch_id().size() != kEpochIdSize) {
diff --git a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_manager.cc b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_manager.cc index 82dcae38..0bbb808 100644 --- a/components/ip_protection/common/ip_protection_probabilistic_reveal_token_manager.cc +++ b/components/ip_protection/common/ip_protection_probabilistic_reveal_token_manager.cc
@@ -140,9 +140,11 @@ return; } DCHECK(outcome.has_value()); - auto maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( - outcome.value().public_key, outcome.value().tokens); - if (!maybe_crypter.ok()) { + base::expected<std::unique_ptr<IpProtectionProbabilisticRevealTokenCrypter>, + absl::Status> + maybe_crypter = IpProtectionProbabilisticRevealTokenCrypter::Create( + outcome.value().public_key, outcome.value().tokens); + if (!maybe_crypter.has_value()) { // Might happen if PRT issuer is misconfigured and public_key or tokens do // not belong to the group. Return without clearing existing tokens, which // might be still valid for current epoch. Retry in an hour. @@ -223,9 +225,9 @@ // Seeing this third party for the first time in this top level. // Randomize top level's token and return. - absl::StatusOr<ProbabilisticRevealToken> maybe_randomized_token = - crypter_->Randomize(token_index); - if (!maybe_randomized_token.ok()) { + base::expected<ProbabilisticRevealToken, absl::Status> + maybe_randomized_token = crypter_->Randomize(token_index); + if (!maybe_randomized_token.has_value()) { // Should not happen in theory, might happen with corrupted crypter. return std::nullopt; } @@ -234,9 +236,9 @@ } // Seeing first party for the first time. std::size_t token_selected = base::RandGenerator(crypter_->NumTokens()); - absl::StatusOr<ProbabilisticRevealToken> maybe_randomized_token = - crypter_->Randomize(token_selected); - if (!maybe_randomized_token.ok()) { + base::expected<ProbabilisticRevealToken, absl::Status> + maybe_randomized_token = crypter_->Randomize(token_selected); + if (!maybe_randomized_token.has_value()) { // Should not happen in theory, might happen with corrupted crypter. return std::nullopt; }
diff --git a/components/keyed_service/core/keyed_service_export.h b/components/keyed_service/core/keyed_service_export.h index 86482be..5edd1c7 100644 --- a/components/keyed_service/core/keyed_service_export.h +++ b/components/keyed_service/core/keyed_service_export.h
@@ -15,11 +15,7 @@ #endif // defined(KEYED_SERVICE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(KEYED_SERVICE_IMPLEMENTATION) #define KEYED_SERVICE_EXPORT __attribute__((visibility("default"))) -#else -#define KEYED_SERVICE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/login/login_export.h b/components/login/login_export.h index 35af257c..2203d3c 100644 --- a/components/login/login_export.h +++ b/components/login/login_export.h
@@ -16,19 +16,11 @@ #endif // defined(LOGIN_IMPLEMENTATION) #else // defined(WIN32) - -#if defined(LOGIN_IMPLEMENTATION) #define LOGIN_EXPORT __attribute__((visibility("default"))) -#else -#define LOGIN_EXPORT -#endif // defined(LOGIN_IMPLEMENTATION) - #endif // defined(WIN32) #else // defined(COMPONENT_BUILD) - #define LOGIN_EXPORT - #endif #endif // COMPONENTS_LOGIN_LOGIN_EXPORT_H_
diff --git a/components/metal_util/metal_util_export.h b/components/metal_util/metal_util_export.h index 2973ef0..e027220 100644 --- a/components/metal_util/metal_util_export.h +++ b/components/metal_util/metal_util_export.h
@@ -15,11 +15,7 @@ #endif // defined(METAL_UTIL_IMPLEMENTATION) #else // defined(WIN32) -#if defined(METAL_UTIL_IMPLEMENTATION) #define METAL_UTIL_EXPORT __attribute__((visibility("default"))) -#else -#define METAL_UTIL_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index 2c2c4594..8312adb 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -414,6 +414,7 @@ deps += [ ":jni_headers", "//components/browser_ui/util/android", + "//components/saved_tab_groups/public:conversion_utils", "//url", ] } else { @@ -620,6 +621,7 @@ "//components/cached_flags:java", "//components/embedder_support/android:util_java", "//components/omnibox/common:features_java", + "//components/saved_tab_groups/public:java", "//components/security_state/core:security_state_enums_java", "//third_party/android_deps:protobuf_lite_runtime_java", "//third_party/androidx:androidx_annotation_annotation_java",
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatch.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatch.java index 209faca..fa7dd21 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatch.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatch.java
@@ -91,6 +91,7 @@ private final boolean mAllowedToBeDefaultMatch; private final String mInlineAutocompletion; private final String mAdditionalText; + private @Nullable String mTabGroupUuid; public AutocompleteMatch( int nativeType, @@ -116,7 +117,8 @@ @Nullable List<OmniboxAction> actions, boolean allowedToBeDefaultMatch, String inlineAutocompletion, - String additionalText) { + String additionalText, + @Nullable String tabGroupUuid) { if (subtypes == null) { subtypes = Collections.emptySet(); } @@ -152,6 +154,7 @@ mAllowedToBeDefaultMatch = allowedToBeDefaultMatch; mInlineAutocompletion = inlineAutocompletion; mAdditionalText = additionalText; + mTabGroupUuid = tabGroupUuid; } @CalledByNative @@ -182,7 +185,8 @@ @JniType("std::vector") List<OmniboxAction> actions, boolean allowedToBeDefaultMatch, String inlineAutocompletion, - String additionalText) { + String additionalText, + String localTabGroupId) { assert contentClassificationOffsets.length == contentClassificationStyles.length; List<MatchClassification> contentClassifications = new ArrayList<>(); for (int i = 0; i < contentClassificationOffsets.length; i++) { @@ -221,7 +225,8 @@ actions, allowedToBeDefaultMatch, inlineAutocompletion, - additionalText); + additionalText, + TextUtils.isEmpty(localTabGroupId) ? null : localTabGroupId); match.updateNativeObjectRef(nativeObject); match.setDescription( description, descriptionClassificationOffsets, descriptionClassificationStyles); @@ -450,7 +455,8 @@ && Arrays.equals(mPostData, suggestion.mPostData) && mGroupId == suggestion.mGroupId && mAnswerType == suggestion.mAnswerType - && answer_template_is_equal; + && answer_template_is_equal + && ObjectsCompat.equals(mTabGroupUuid, suggestion.mTabGroupUuid); } /** @@ -462,6 +468,10 @@ return mGroupId; } + public @Nullable String getTabGroupUuid() { + return mTabGroupUuid; + } + /** * Retrieve the clipboard information and update this instance of AutocompleteMatch. Will * terminate immediately if the native counterpart of the AutocompleteMatch object does not @@ -567,7 +577,8 @@ /* actions= */ null, input.getAllowedToBeDefaultMatch(), input.getInlineAutocompletion(), - input.getAdditionalText()); + input.getAdditionalText(), + /* tabGroupUuid= */ null); } @Override
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatchBuilder.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatchBuilder.java index 4b8eae5..3b705c8 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatchBuilder.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/AutocompleteMatchBuilder.java
@@ -47,6 +47,7 @@ private boolean mAllowedToBeDefaultMatch; private String mInlineAutocompletion; private String mAdditionalText; + private String mTabGroupUuid; /** * Create a suggestion builder for a search suggestion. @@ -97,6 +98,7 @@ mAllowedToBeDefaultMatch = false; mInlineAutocompletion = null; mAdditionalText = null; + mTabGroupUuid = null; mDisplayTextClassifications.add( new AutocompleteMatch.MatchClassification(0, MatchClassificationStyle.NONE)); @@ -135,7 +137,8 @@ mActions, mAllowedToBeDefaultMatch, mInlineAutocompletion, - mAdditionalText); + mAdditionalText, + mTabGroupUuid); } /** @@ -328,4 +331,13 @@ mSerializedAnswerTemplate = serializedAnswerTemplate; return this; } + + /** + * @param tabGroupUuid Matching tab group's uuid. + * @return Omnibox suggestion builder. + */ + public AutocompleteMatchBuilder setTabGroupUuid(String tabGroupUuid) { + mTabGroupUuid = tabGroupUuid; + return this; + } }
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc index c1d6e8ea..7fe68a76a 100644 --- a/components/omnibox/browser/autocomplete_match.cc +++ b/components/omnibox/browser/autocomplete_match.cc
@@ -305,7 +305,8 @@ match.history_embeddings_answer_header_text), history_embeddings_answer_header_loading( match.history_embeddings_answer_header_loading), - feedback_type(match.feedback_type) {} + feedback_type(match.feedback_type), + matching_tab_group_uuid(match.matching_tab_group_uuid) {} AutocompleteMatch::AutocompleteMatch(AutocompleteMatch&& match) noexcept { *this = std::move(match); @@ -387,6 +388,7 @@ history_embeddings_answer_header_loading = std::move(match.history_embeddings_answer_header_loading); feedback_type = std::move(match.feedback_type); + matching_tab_group_uuid = std::move(match.matching_tab_group_uuid); #if BUILDFLAG(IS_ANDROID) DestroyJavaObject(); std::swap(java_match_, match.java_match_); @@ -482,6 +484,7 @@ history_embeddings_answer_header_loading = match.history_embeddings_answer_header_loading; feedback_type = match.feedback_type; + matching_tab_group_uuid = match.matching_tab_group_uuid; #if BUILDFLAG(IS_ANDROID) // In case the target element previously held a java object, release it.
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h index 2b7690b4b..b0925ae 100644 --- a/components/omnibox/browser/autocomplete_match.h +++ b/components/omnibox/browser/autocomplete_match.h
@@ -20,12 +20,14 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/strings/utf_offset_string_conversions.h" +#include "base/uuid.h" #include "build/build_config.h" #include "components/omnibox/browser/actions/omnibox_action_concepts.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match_type.h" #include "components/omnibox/browser/buildflags.h" #include "components/omnibox/browser/suggestion_answer.h" +#include "components/saved_tab_groups/public/types.h" #include "components/search_engines/template_url.h" #include "components/url_formatter/url_formatter.h" #include "third_party/metrics_proto/omnibox_event.pb.h" @@ -1020,6 +1022,9 @@ // The user feedback on the match. FeedbackType feedback_type = FeedbackType::kNone; + // Stores the matching tab group uuid for this suggestion. + std::optional<base::Uuid> matching_tab_group_uuid = std::nullopt; + // So users of AutocompleteMatch can use the same ellipsis that it uses. static const char16_t kEllipsis[];
diff --git a/components/omnibox/browser/autocomplete_match_android.cc b/components/omnibox/browser/autocomplete_match_android.cc index 8452c2f09..5b5db68 100644 --- a/components/omnibox/browser/autocomplete_match_android.cc +++ b/components/omnibox/browser/autocomplete_match_android.cc
@@ -11,11 +11,14 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/functional/bind.h" +#include "base/uuid.h" #include "components/omnibox/browser/actions/omnibox_action.h" #include "components/omnibox/browser/actions/omnibox_action_factory_android.h" #include "components/omnibox/browser/clipboard_provider.h" #include "components/omnibox/browser/search_suggestion_parser.h" #include "components/omnibox/common/omnibox_feature_configs.h" +#include "components/saved_tab_groups/public/android/tab_group_sync_conversions_bridge.h" +#include "components/saved_tab_groups/public/android/tab_group_sync_conversions_utils.h" #include "url/android/gurl_android.h" // Must come after all headers that specialize FromJniType() / ToJniType(). @@ -111,7 +114,9 @@ has_tab_match.value_or(false), actions_list, allowed_to_be_default_match, ConvertUTF16ToJavaString(env, inline_autocompletion), - ConvertUTF16ToJavaString(env, additional_text))); + ConvertUTF16ToJavaString(env, additional_text), + tab_groups::UuidToJavaString( + env, matching_tab_group_uuid.value_or(base::Uuid())))); return ScopedJavaLocalRef<jobject>(*java_match_); }
diff --git a/components/omnibox/browser/tab_group_provider.cc b/components/omnibox/browser/tab_group_provider.cc index 0543f91..9e3f0b8 100644 --- a/components/omnibox/browser/tab_group_provider.cc +++ b/components/omnibox/browser/tab_group_provider.cc
@@ -125,7 +125,7 @@ match.contents_class = ClassifyTermMatches( contents_terms, match.contents.size(), ACMatchClassification::MATCH, ACMatchClassification::NONE); - // TODO(crbug.com/410574178): Plumb tab group id through match. + match.matching_tab_group_uuid = group.saved_guid(); match.suggestion_group_id = omnibox::GROUP_MOBILE_OPEN_TABS; return match;
diff --git a/components/omnibox/browser/tab_group_provider_unittest.cc b/components/omnibox/browser/tab_group_provider_unittest.cc index 61a67fb5..3fd6845 100644 --- a/components/omnibox/browser/tab_group_provider_unittest.cc +++ b/components/omnibox/browser/tab_group_provider_unittest.cc
@@ -73,4 +73,7 @@ TestSchemeClassifier()); tab_group_provider().Start(input, /* minimal_changes= */ false); ASSERT_EQ(1UL, tab_group_provider().matches().size()); + ASSERT_EQ(u"test", tab_group_provider().matches()[0].contents); + ASSERT_TRUE( + tab_group_provider().matches()[0].matching_tab_group_uuid.has_value()); }
diff --git a/components/optimization_guide/core/model_execution/on_device_context.cc b/components/optimization_guide/core/model_execution/on_device_context.cc index f4e4fe8c..b350bb8 100644 --- a/components/optimization_guide/core/model_execution/on_device_context.cc +++ b/components/optimization_guide/core/model_execution/on_device_context.cc
@@ -211,7 +211,6 @@ // rather than max_tokens for this call. options->max_tokens = opts_.token_limits.max_context_tokens - tokens_processed_; - options->token_offset = 0; mojo::PendingRemote<on_device_model::mojom::ContextClient> pending; clients_.Add(this, pending.InitWithNewPipeAndPassReceiver()); session_->Append(std::move(options), std::move(pending));
diff --git a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc index 75d3d51..c4f8f14 100644 --- a/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc +++ b/components/optimization_guide/core/model_execution/on_device_model_service_controller_unittest.cc
@@ -332,7 +332,7 @@ session->ExecuteModel(PageUrlRequest("foo"), response_.GetStreamingCallback()); ASSERT_TRUE(response_.GetFinalStatus()); - const std::string expected_response = "Context: execute:foo off:0 max:1024\n"; + const std::string expected_response = "Context: execute:foo max:1024\n"; EXPECT_EQ(*response_.value(), expected_response); EXPECT_TRUE(*response_.provided_by_on_device()); EXPECT_THAT(response_.partials(), ElementsAre(expected_response)); @@ -447,7 +447,7 @@ response_.GetStreamingCallback()); ASSERT_TRUE(response_.GetFinalStatus()); EXPECT_EQ(*response_.value(), - "Adaptation model: 1015\nContext: execute:foo off:0 max:1024\n"); + "Adaptation model: 1015\nContext: execute:foo max:1024\n"); // If we destroy all sessions and wait long enough, everything should idle out // and the service should get terminated. @@ -500,11 +500,11 @@ ASSERT_TRUE(compose_response.GetFinalStatus()); EXPECT_EQ(*compose_response.value(), - "Adaptation model: 1015\nContext: execute:foo off:0 max:1024\n"); + "Adaptation model: 1015\nContext: execute:foo max:1024\n"); EXPECT_TRUE(*compose_response.provided_by_on_device()); ASSERT_TRUE(test_response.GetFinalStatus()); EXPECT_EQ(*test_response.value(), - "Adaptation model: 2024\nContext: execute:bar off:0 max:1024\n"); + "Adaptation model: 2024\nContext: execute:bar max:1024\n"); EXPECT_TRUE(*test_response.provided_by_on_device()); session_compose.reset(); @@ -559,10 +559,10 @@ ASSERT_TRUE(compose_response.GetFinalStatus()); EXPECT_EQ(*compose_response.value(), - "Adaptation model: 1015\nContext: execute:foo off:0 max:1024\n"); + "Adaptation model: 1015\nContext: execute:foo max:1024\n"); EXPECT_TRUE(*compose_response.provided_by_on_device()); ASSERT_TRUE(test_response.GetFinalStatus()); - EXPECT_EQ(*test_response.value(), "Context: execute:bar off:0 max:1024\n"); + EXPECT_EQ(*test_response.value(), "Context: execute:bar max:1024\n"); EXPECT_TRUE(*test_response.provided_by_on_device()); session_compose.reset(); @@ -687,7 +687,7 @@ response2.GetStreamingCallback()); ASSERT_TRUE(response2.GetFinalStatus()); EXPECT_EQ(*response2.value(), - "Base model: 2\nContext: execute:foo off:0 max:1024\n"); + "Base model: 2\nContext: execute:foo max:1024\n"); } TEST_F(OnDeviceModelServiceControllerTest, SessionFailsForInvalidFeature) { @@ -1603,7 +1603,7 @@ EXPECT_EQ( *resp1.error(), OptimizationGuideModelExecutionError::ModelExecutionError::kCancelled); - EXPECT_EQ(*resp2.value(), "Context: execute:bar off:0 max:1024\n"); + EXPECT_EQ(*resp2.value(), "Context: execute:bar max:1024\n"); } TEST_F(OnDeviceModelServiceControllerTest, WontStartSessionAfterGpuBlocked) { @@ -1789,8 +1789,8 @@ "OptimizationGuide.ModelExecution.OnDeviceExecuteModelResult.Compose", ExecuteModelResult::kUsedOnDevice, 1); std::string expected_response = - ("Context: ctx:foo off:0 max:8192\n" - "Context: execute:foobaz off:0 max:1024\n"); + ("Context: ctx:foo max:8192\n" + "Context: execute:foobaz max:1024\n"); EXPECT_EQ(*response_.value(), expected_response); } @@ -1828,16 +1828,16 @@ session2->ExecuteModel(PageUrlRequest("2"), response_.GetStreamingCallback()); ASSERT_TRUE(response_.GetFinalStatus()); std::string expected_response1 = - ("Context: ctx:bar off:0 max:8192\n" - "Context: execute:bar2 off:0 max:1024\n"); + ("Context: ctx:bar max:8192\n" + "Context: execute:bar2 max:1024\n"); EXPECT_EQ(*response_.value(), expected_response1); ResponseHolder response2; session1->ExecuteModel(PageUrlRequest("1"), response2.GetStreamingCallback()); ASSERT_TRUE(response2.GetFinalStatus()); std::string expected_response2 = - ("Context: ctx:foo off:0 max:8192\n" - "Context: execute:foo1 off:0 max:1024\n"); + ("Context: ctx:foo max:8192\n" + "Context: execute:foo1 max:1024\n"); EXPECT_EQ(*response2.value(), expected_response2); } @@ -2044,8 +2044,7 @@ session1->ExecuteModel(UserInputRequest("foo"), response_.GetStreamingCallback()); task_environment_.RunUntilIdle(); - const std::string expected_response1 = - "Context: execute:foo off:0 max:1024\n"; + const std::string expected_response1 = "Context: execute:foo max:1024\n"; EXPECT_EQ(*response_.value(), expected_response1); EXPECT_THAT(response_.partials(), IsEmpty()); @@ -2056,20 +2055,19 @@ session2->ExecuteModel(UserInputRequest("abarx"), response2.GetStreamingCallback()); task_environment_.RunUntilIdle(); - const std::string expected_response2 = - "Context: execute:abarx off:0 max:1024\n"; + const std::string expected_response2 = "Context: execute:abarx max:1024\n"; EXPECT_EQ(*response2.value(), expected_response2); EXPECT_THAT(response2.partials(), IsEmpty()); // Output contains redacted text (and input doesn't), so redact. - fake_settings_.set_execute_result({"Context: abarx off:0 max:1024\n"}); + fake_settings_.set_execute_result({"Context: abarx max:1024\n"}); auto session3 = CreateSession(); ASSERT_TRUE(session3); ResponseHolder response3; session3->ExecuteModel(UserInputRequest("foo"), response3.GetStreamingCallback()); task_environment_.RunUntilIdle(); - const std::string expected_response3 = "Context: a[###]x off:0 max:1024\n"; + const std::string expected_response3 = "Context: a[###]x max:1024\n"; EXPECT_EQ(*response3.value(), expected_response3); EXPECT_THAT(response3.partials(), IsEmpty()); } @@ -2130,7 +2128,7 @@ }); // Force 'bar' to be returned from model. - fake_settings_.set_execute_result({"Context: bar off:0 max:1024\n"}); + fake_settings_.set_execute_result({"Context: bar max:1024\n"}); auto session = CreateSession(); ASSERT_TRUE(session); @@ -2139,7 +2137,7 @@ response_.GetStreamingCallback()); task_environment_.RunUntilIdle(); // `bar` shouldn't be rewritten as it's in the input. - const std::string expected_response = "Context: bar off:0 max:1024\n"; + const std::string expected_response = "Context: bar max:1024\n"; EXPECT_EQ(*response_.value(), expected_response); EXPECT_THAT(response_.partials(), IsEmpty()); } @@ -2156,14 +2154,13 @@ }); // Output contains redacted text (and input doesn't), so redact. - fake_settings_.set_execute_result({"Context: abarx off:0 max:1024\n"}); + fake_settings_.set_execute_result({"Context: abarx max:1024\n"}); auto session = CreateSession(); ASSERT_TRUE(session); session->ExecuteModel(UserInputRequest("foo"), response_.GetStreamingCallback()); task_environment_.RunUntilIdle(); - const std::string expected_response = - "Context: a[redacted]x off:0 max:1024\n"; + const std::string expected_response = "Context: a[redacted]x max:1024\n"; EXPECT_EQ(*response_.value(), expected_response); EXPECT_THAT(response_.partials(), IsEmpty()); } @@ -2415,7 +2412,7 @@ task_environment_.RunUntilIdle(); EXPECT_TRUE(response_.value()); const std::vector<std::string> partial_responses = { - "Context: execute:foo off:0 max:1024\n", + "Context: execute:foo max:1024\n", }; EXPECT_EQ(*response_.value(), ConcatResponses(partial_responses)); EXPECT_THAT(response_.partials(), ElementsAreArray(partial_responses)); @@ -3220,7 +3217,7 @@ response_.GetStreamingCallback()); ASSERT_TRUE(response_.GetFinalStatus()); EXPECT_EQ(*response_.value(), - "Fastest inference\nContext: execute:foo off:0 max:1024\n"); + "Fastest inference\nContext: execute:foo max:1024\n"); } TEST_F(OnDeviceModelServiceControllerTest, ImageExecutionSuccess) { @@ -3277,9 +3274,8 @@ session->ExecuteModel(proto::ExampleForTestingRequest(), response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); - EXPECT_EQ( - *response.value(), - "Context: <image> off:0 max:22\nContext: <image> off:0 max:1024\n"); + EXPECT_EQ(*response.value(), + "Context: <image> max:22\nContext: <image> max:1024\n"); } // Session without capabilities should not allow images. @@ -3292,8 +3288,8 @@ response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); EXPECT_EQ(*response.value(), - "Context: <unsupported> off:0 max:22\nContext: <unsupported> " - "off:0 max:1024\n"); + "Context: <unsupported> max:22\nContext: <unsupported> " + "max:1024\n"); } } @@ -3386,7 +3382,7 @@ altered_response.GetStreamingCallback()); ASSERT_TRUE(altered_response.GetFinalStatus()); EXPECT_EQ(*altered_response.value(), - "Context: v1<image><audio>v2v3v4 off:0 max:22\n"); + "Context: v1<image><audio>v2v3v4 max:22\n"); // The clone that only extended should have sent input in separate chunks. ResponseHolder extended_response; @@ -3394,19 +3390,19 @@ extended_response.GetStreamingCallback()); ASSERT_TRUE(extended_response.GetFinalStatus()); EXPECT_EQ(*extended_response.value(), - "Context: v1<image><audio> off:0 max:22\n" - "Context: v2 off:0 max:22\n" - "Context: v3 off:0 max:4\n" - "Context: v4 off:0 max:4\n"); + "Context: v1<image><audio> max:22\n" + "Context: v2 max:22\n" + "Context: v3 max:4\n" + "Context: v4 max:4\n"); // The original should have input in separate chunks. session->ExecuteModel(proto::ExampleForTestingRequest(), response_.GetStreamingCallback()); ASSERT_TRUE(response_.GetFinalStatus()); EXPECT_EQ(*response_.value(), - "Context: v1<image><audio> off:0 max:22\n" - "Context: v2 off:0 max:22\n" - "Context: v3 off:0 max:4\n"); + "Context: v1<image><audio> max:22\n" + "Context: v2 max:22\n" + "Context: v3 max:4\n"); } TEST_F(OnDeviceModelServiceControllerTest, OmitEmptyInputs) { @@ -3477,7 +3473,7 @@ task_environment_.RunUntilIdle(); EXPECT_TRUE(response_.value()); const std::vector<std::string> partial_responses = { - "Context: execute:foo off:0 max:1024\n", + "Context: execute:foo max:1024\n", }; EXPECT_EQ(*response_.value(), ConcatResponses(partial_responses)); EXPECT_THAT(response_.partials(), ElementsAreArray(partial_responses)); @@ -3567,8 +3563,8 @@ clone->ExecuteModel(PageUrlRequest("bar"), response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); std::string expected_response = - ("Context: ctx:foo off:0 max:8192\n" - "Context: execute:foobar off:0 max:1024\n"); + ("Context: ctx:foo max:8192\n" + "Context: execute:foobar max:1024\n"); EXPECT_EQ(*response.value(), expected_response); } @@ -3579,8 +3575,8 @@ response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); std::string expected_response = - ("Context: ctx:foo off:0 max:8192\n" - "Context: execute:fooblah off:0 max:1024\n"); + ("Context: ctx:foo max:8192\n" + "Context: execute:fooblah max:1024\n"); EXPECT_EQ(*response.value(), expected_response); } } @@ -3599,7 +3595,7 @@ ResponseHolder response; clone->ExecuteModel(PageUrlRequest("bar"), response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); - EXPECT_EQ(*response.value(), "Context: execute:bar off:0 max:1024\n"); + EXPECT_EQ(*response.value(), "Context: execute:bar max:1024\n"); } // Original session should execute with context @@ -3609,8 +3605,8 @@ response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); std::string expected_response = - ("Context: ctx:foo off:0 max:8192\n" - "Context: execute:fooblah off:0 max:1024\n"); + ("Context: ctx:foo max:8192\n" + "Context: execute:fooblah max:1024\n"); EXPECT_EQ(*response.value(), expected_response); } } @@ -3628,7 +3624,7 @@ ResponseHolder response; clone->ExecuteModel(PageUrlRequest("bar"), response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); - EXPECT_EQ(*response.value(), "Context: execute:foobar off:0 max:1024\n"); + EXPECT_EQ(*response.value(), "Context: execute:foobar max:1024\n"); } TEST_F(OnDeviceModelServiceControllerTest, CloneAddContextDisconnectExecute) { @@ -3647,8 +3643,8 @@ clone->ExecuteModel(PageUrlRequest("bar"), response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); std::string expected_response = - ("Context: ctx:foo off:0 max:8192\n" - "Context: execute:foobar off:0 max:1024\n"); + ("Context: ctx:foo max:8192\n" + "Context: execute:foobar max:1024\n"); EXPECT_EQ(*response.value(), expected_response); } @@ -3673,7 +3669,7 @@ ResponseHolder response; session->ExecuteModel(PageUrlRequest("bar"), response.GetStreamingCallback()); ASSERT_TRUE(response.GetFinalStatus()); - EXPECT_EQ(*response.value(), "Context: execute:bar off:0 max:1024\n"); + EXPECT_EQ(*response.value(), "Context: execute:bar max:1024\n"); } TEST_F(OnDeviceModelServiceControllerTest, Priority) { @@ -3682,18 +3678,16 @@ auto session = CreateSession(); EXPECT_TRUE(session); - EXPECT_EQ(GetResponse(*session, "foo"), - "Context: execute:foo off:0 max:1024\n"); + EXPECT_EQ(GetResponse(*session, "foo"), "Context: execute:foo max:1024\n"); session->SetPriority(on_device_model::mojom::Priority::kBackground); EXPECT_EQ(GetResponse(*session, "foo"), - "Priority: background\nContext: execute:foo off:0 max:1024\n"); + "Priority: background\nContext: execute:foo max:1024\n"); EXPECT_EQ(GetResponse(*session, "foo"), - "Priority: background\nContext: execute:foo off:0 max:1024\n"); + "Priority: background\nContext: execute:foo max:1024\n"); session->SetPriority(on_device_model::mojom::Priority::kForeground); - EXPECT_EQ(GetResponse(*session, "foo"), - "Context: execute:foo off:0 max:1024\n"); + EXPECT_EQ(GetResponse(*session, "foo"), "Context: execute:foo max:1024\n"); } TEST_F(OnDeviceModelServiceControllerTest, PriorityClone) { @@ -3702,18 +3696,17 @@ auto session = CreateSession(); EXPECT_TRUE(session); - EXPECT_EQ(GetResponse(*session, "foo"), - "Context: execute:foo off:0 max:1024\n"); + EXPECT_EQ(GetResponse(*session, "foo"), "Context: execute:foo max:1024\n"); session->SetPriority(on_device_model::mojom::Priority::kBackground); EXPECT_EQ(GetResponse(*session, "foo"), - "Priority: background\nContext: execute:foo off:0 max:1024\n"); + "Priority: background\nContext: execute:foo max:1024\n"); auto clone = session->Clone(); EXPECT_EQ(GetResponse(*clone, "foo"), - "Priority: background\nContext: execute:foo off:0 max:1024\n"); + "Priority: background\nContext: execute:foo max:1024\n"); EXPECT_EQ(GetResponse(*clone, "foo"), - "Priority: background\nContext: execute:foo off:0 max:1024\n"); + "Priority: background\nContext: execute:foo max:1024\n"); } TEST_F(OnDeviceModelServiceControllerTest, SetInputCallback) { @@ -3733,7 +3726,7 @@ response_.GetStreamingCallback()); ASSERT_TRUE(response_.GetFinalStatus()); EXPECT_EQ(response_.value(), - "Context: ctx:foo off:0 max:8192\nContext: execute:foobar off:0 " + "Context: ctx:foo max:8192\nContext: execute:foobar " "max:1024\n"); } @@ -3763,7 +3756,7 @@ response_.GetStreamingCallback()); ASSERT_TRUE(response_.GetFinalStatus()); EXPECT_EQ(response_.value(), - "Context: ctx:foo off:0 max:8192\nContext: execute:foobar off:0 " + "Context: ctx:foo max:8192\nContext: execute:foobar " "max:1024\n"); } @@ -3792,10 +3785,9 @@ session->ExecuteModel(PageUrlRequest("foo"), response_.GetStreamingCallback()); ASSERT_TRUE(response_.GetFinalStatus()); - EXPECT_EQ(response_.value(), "Context: execute:foo off:0 max:1024\n"); + EXPECT_EQ(response_.value(), "Context: execute:foo max:1024\n"); EXPECT_EQ(response_.input_token_count(), strlen("execute:foo")); - EXPECT_EQ(response_.output_token_count(), - strlen("execute:foo off:0 max:1024")); + EXPECT_EQ(response_.output_token_count(), strlen("execute:foo max:1024")); } } // namespace optimization_guide
diff --git a/components/ownership/ownership_export.h b/components/ownership/ownership_export.h index 6932100..c259a1ce 100644 --- a/components/ownership/ownership_export.h +++ b/components/ownership/ownership_export.h
@@ -17,11 +17,7 @@ #else // defined(WIN32) -#if defined(OWNERSHIP_IMPLEMENTATION) #define OWNERSHIP_EXPORT __attribute__((visibility("default"))) -#else -#define OWNERSHIP_EXPORT -#endif // defined(OWNERSHIP_IMPLEMENTATION) #endif // defined(WIN32)
diff --git a/components/page_load_metrics/browser/observers/use_counter/webdx_feature_maps.cc b/components/page_load_metrics/browser/observers/use_counter/webdx_feature_maps.cc index 2627bae..80f8b6b6 100644 --- a/components/page_load_metrics/browser/observers/use_counter/webdx_feature_maps.cc +++ b/components/page_load_metrics/browser/observers/use_counter/webdx_feature_maps.cc
@@ -537,6 +537,7 @@ {CSSSampleId::kInteractivity, WebDXFeature::kInteractivity}, {CSSSampleId::kReadingFlow, WebDXFeature::kReadingFlow}, {CSSSampleId::kPrintColorAdjust, WebDXFeature::kPrintColorAdjust}, + {CSSSampleId::kLineBreak, WebDXFeature::kLineBreak}, // Add new features above this line. }};
diff --git a/components/page_load_metrics/browser/page_load_metrics_test_content_browser_client.cc b/components/page_load_metrics/browser/page_load_metrics_test_content_browser_client.cc index 2ec156b..3349573 100644 --- a/components/page_load_metrics/browser/page_load_metrics_test_content_browser_client.cc +++ b/components/page_load_metrics/browser/page_load_metrics_test_content_browser_client.cc
@@ -19,15 +19,13 @@ PageLoadMetricsTestContentBrowserClient:: ~PageLoadMetricsTestContentBrowserClient() = default; -std::vector<std::unique_ptr<content::NavigationThrottle>> -PageLoadMetricsTestContentBrowserClient::CreateThrottlesForNavigation( +void PageLoadMetricsTestContentBrowserClient::CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) { content::NavigationHandle& navigation_handle = registry.GetNavigationHandle(); if (navigation_handle.IsInMainFrame()) { registry.AddThrottle(page_load_metrics::MetricsNavigationThrottle::Create( &navigation_handle)); } - return {}; } } // namespace page_load_metrics
diff --git a/components/page_load_metrics/browser/page_load_metrics_test_content_browser_client.h b/components/page_load_metrics/browser/page_load_metrics_test_content_browser_client.h index c215994..7613343b 100644 --- a/components/page_load_metrics/browser/page_load_metrics_test_content_browser_client.h +++ b/components/page_load_metrics/browser/page_load_metrics_test_content_browser_client.h
@@ -24,8 +24,7 @@ ~PageLoadMetricsTestContentBrowserClient() override; // content::ContentBrowserClient: - std::vector<std::unique_ptr<content::NavigationThrottle>> - CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override; };
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 2fb34835..35ca418 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -73,6 +73,8 @@ "move_password_to_account_store_helper.h", "old_google_credentials_cleaner.cc", "old_google_credentials_cleaner.h", + "one_time_passwords/otp_form_manager.cc", + "one_time_passwords/otp_form_manager.h", "one_time_passwords/otp_manager.cc", "one_time_passwords/otp_manager.h", "origin_credential_store.cc", @@ -470,6 +472,7 @@ "leak_detection_delegate_unittest.cc", "leak_detection_dialog_utils_unittest.cc", "old_google_credentials_cleaner_unittest.cc", + "one_time_passwords/otp_manager_unittest.cc", "origin_credential_store_unittest.cc", "passkey_credential_unittest.cc", "password_autofill_manager_unittest.cc",
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/components/password_manager/core/browser/browser_save_password_progress_logger.cc index 755e147..036d5939 100644 --- a/components/password_manager/core/browser/browser_save_password_progress_logger.cc +++ b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -350,15 +350,16 @@ base::StrAppend(&field_info, {", VOTE: ", FieldTypeToStringView(type)}); } - if (field->vote_type()) { - field_info += ", vote_type=" + VoteTypeToString(field->vote_type()); - } - if (auto it = vote_metadata.fields.find(field->global_id()); it != vote_metadata.fields.end()) { const autofill::EncodeUploadRequestOptions::Field& field_metadata = it->second; + if (field_metadata.vote_type) { + field_info += + ", vote_type=" + VoteTypeToString(field_metadata.vote_type); + } + if (field_metadata.initial_value_hash.has_value()) { field_info += ", initial value hash="; field_info += NumberToString(field_metadata.initial_value_hash.value());
diff --git a/components/password_manager/core/browser/features/password_features.cc b/components/password_manager/core/browser/features/password_features.cc index 6c9db5fd..6aa1072 100644 --- a/components/password_manager/core/browser/features/password_features.cc +++ b/components/password_manager/core/browser/features/password_features.cc
@@ -10,6 +10,12 @@ namespace password_manager::features { +#if BUILDFLAG(IS_ANDROID) +BASE_FEATURE(kAndroidSmsOtpFilling, + "AndroidSmsOtpFilling", + base::FEATURE_DISABLED_BY_DEFAULT); +#endif // BUILDFLAG(IS_ANDROID) + BASE_FEATURE(kAutoApproveSharedPasswordUpdatesFromSameSender, "AutoApproveSharedPasswordUpdatesFromSameSender", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/password_manager/core/browser/features/password_features.h b/components/password_manager/core/browser/features/password_features.h index 3e3f21d..58a15bd 100644 --- a/components/password_manager/core/browser/features/password_features.h +++ b/components/password_manager/core/browser/features/password_features.h
@@ -16,6 +16,11 @@ // All features in alphabetical order. The features should be documented // alongside the definition of their values in the .cc file. +#if BUILDFLAG(IS_ANDROID) +// Enables filling of OTPs received via SMS on Android. +BASE_DECLARE_FEATURE(kAndroidSmsOtpFilling); +#endif // BUILDFLAG(IS_ANDROID) + // When enabled, updates to shared existing passwords from the same sender are // auto-approved. BASE_DECLARE_FEATURE(kAutoApproveSharedPasswordUpdatesFromSameSender);
diff --git a/components/password_manager/core/browser/leak_detection/leak_detection_api.proto b/components/password_manager/core/browser/leak_detection/leak_detection_api.proto index de653e1..066fa2b 100644 --- a/components/password_manager/core/browser/leak_detection/leak_detection_api.proto +++ b/components/password_manager/core/browser/leak_detection/leak_detection_api.proto
@@ -75,6 +75,10 @@ CHROME_IOS_SIGNED_IN_ON_DEVICE_PROACTIVE_PASSWORD_CHECKUP = 18; // Leak checks done by ios/web_view during sign in to a website. IOS_WEB_VIEW_SIGN_IN_CHECK = 19; + + // Edit server proto first and then update this file: + // http://google3/google/internal/identity/passwords/leak/check/v1/service.proto + reserved 22 to max; } ClientUseCase client_use_case = 4; }
diff --git a/components/password_manager/core/browser/one_time_passwords/otp_form_manager.cc b/components/password_manager/core/browser/one_time_passwords/otp_form_manager.cc new file mode 100644 index 0000000..cb71110 --- /dev/null +++ b/components/password_manager/core/browser/one_time_passwords/otp_form_manager.cc
@@ -0,0 +1,28 @@ +// 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/one_time_passwords/otp_form_manager.h" + +namespace password_manager { + +OtpFormManager::OtpFormManager( + autofill::FormGlobalId form_id, + const std::vector<autofill::FieldGlobalId>& otp_field_ids) + : form_id_(form_id), otp_field_ids_(std::move(otp_field_ids)) { + // TODO(crbug.com/415273770): Trigger OTP fetching if needed. +} + +OtpFormManager::OtpFormManager(OtpFormManager&&) = default; +OtpFormManager& OtpFormManager::operator=(OtpFormManager&&) = default; + +OtpFormManager::~OtpFormManager() = default; + +void OtpFormManager::ProcessUpdatedPredictions( + const std::vector<autofill::FieldGlobalId>& otp_field_ids) { + otp_field_ids_ = std::move(otp_field_ids); + + // TODO(crbug.com/415273770): Check if OTP source has changed. +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/one_time_passwords/otp_form_manager.h b/components/password_manager/core/browser/one_time_passwords/otp_form_manager.h new file mode 100644 index 0000000..c72cd80c --- /dev/null +++ b/components/password_manager/core/browser/one_time_passwords/otp_form_manager.h
@@ -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. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ONE_TIME_PASSWORDS_OTP_FORM_MANAGER_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ONE_TIME_PASSWORDS_OTP_FORM_MANAGER_H_ + +#include <vector> + +#include "base/containers/flat_map.h" +#include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/common/unique_ids.h" + +namespace password_manager { + +// A class in charge of handling individual OTP forms, one instance per form. +class OtpFormManager { + public: + OtpFormManager(autofill::FormGlobalId form_id, + const std::vector<autofill::FieldGlobalId>& otp_field_ids); + + OtpFormManager(const OtpFormManager&) = delete; + OtpFormManager& operator=(const OtpFormManager&) = delete; + OtpFormManager(OtpFormManager&&); + OtpFormManager& operator=(OtpFormManager&&); + + ~OtpFormManager(); + + // Forms can change dynamically during their lifetime. Ensure the most recent + // data is used for form filling. + void ProcessUpdatedPredictions( + const std::vector<autofill::FieldGlobalId>& otp_field_ids); + +#if defined(UNIT_TEST) + const std::vector<autofill::FieldGlobalId>& otp_field_ids() const { + return otp_field_ids_; + } +#endif // defined(UNIT_TEST) + + private: + autofill::FormGlobalId form_id_; + + std::vector<autofill::FieldGlobalId> otp_field_ids_; +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_ONE_TIME_PASSWORDS_OTP_FORM_MANAGER_H_
diff --git a/components/password_manager/core/browser/one_time_passwords/otp_manager.cc b/components/password_manager/core/browser/one_time_passwords/otp_manager.cc index 5d3dd83..98fc8cfe 100644 --- a/components/password_manager/core/browser/one_time_passwords/otp_manager.cc +++ b/components/password_manager/core/browser/one_time_passwords/otp_manager.cc
@@ -5,22 +5,61 @@ #include "components/password_manager/core/browser/one_time_passwords/otp_manager.h" #include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/form_field_data.h" +#include "components/password_manager/core/browser/one_time_passwords/otp_form_manager.h" #include "components/password_manager/core/browser/password_manager_client.h" namespace password_manager { -OtpManager::OtpManager(PasswordManagerClient* client) : client_(client) { - DCHECK(client_); +namespace { + +std::vector<autofill::FieldGlobalId> GetFillableOtpFieldIds( + const autofill::FormData& form, + const base::flat_map<autofill::FieldGlobalId, autofill::FieldType>& + field_predictions) { + std::vector<autofill::FieldGlobalId> fillable_otp_fields; + for (const auto& prediction : field_predictions) { + if (prediction.second != autofill::ONE_TIME_CODE) { + continue; + } + const autofill::FormFieldData* field = + form.FindFieldByGlobalId(prediction.first); + if (field->IsTextInputElement()) { + fillable_otp_fields.push_back(prediction.first); + } + } + return fillable_otp_fields; } +} // namespace + +OtpManager::OtpManager(PasswordManagerClient* client) : client_(client) { + CHECK(client_); +} + +OtpManager::~OtpManager() = default; + void OtpManager::ProcessClassificationModelPredictions( const autofill::FormData& form, const base::flat_map<autofill::FieldGlobalId, autofill::FieldType>& field_predictions) { - // TODO(415269545): Rationalize predictions and trigger OTP fetching if - // needed. + std::vector<autofill::FieldGlobalId> fillable_otp_fields( + GetFillableOtpFieldIds(form, field_predictions)); - client_->InformPasswordChangeServiceOfOtpPresent(); + autofill::FormGlobalId form_id(form.global_id()); + if (fillable_otp_fields.empty()) { + form_managers_.erase(form_id); + return; + } + + if (form_managers_.find(form_id) == form_managers_.end()) { + form_managers_.emplace(form_id, + OtpFormManager(form_id, fillable_otp_fields)); + client_->InformPasswordChangeServiceOfOtpPresent(); + + } else { + form_managers_.at(form_id).ProcessUpdatedPredictions(fillable_otp_fields); + } } } // namespace password_manager
diff --git a/components/password_manager/core/browser/one_time_passwords/otp_manager.h b/components/password_manager/core/browser/one_time_passwords/otp_manager.h index 003bbb6..f4da53f 100644 --- a/components/password_manager/core/browser/one_time_passwords/otp_manager.h +++ b/components/password_manager/core/browser/one_time_passwords/otp_manager.h
@@ -16,6 +16,7 @@ namespace password_manager { +class OtpFormManager; class PasswordManagerClient; // A class in charge of handling one time passwords, one per tab. @@ -23,15 +24,27 @@ public: explicit OtpManager(PasswordManagerClient* client); + ~OtpManager(); + // Processes the classification model predictions received via Autofill. void ProcessClassificationModelPredictions( const autofill::FormData& form, const base::flat_map<autofill::FieldGlobalId, autofill::FieldType>& field_predictions); +#if defined(UNIT_TEST) + const base::flat_map<autofill::FormGlobalId, OtpFormManager>& form_managers() + const { + return form_managers_; + } +#endif // defined(UNIT_TEST) + private: // The client that owns this class and is guaranteed to outlive it. const raw_ptr<PasswordManagerClient> client_; + + // Managers managing individual forms. + base::flat_map<autofill::FormGlobalId, OtpFormManager> form_managers_; }; } // namespace password_manager
diff --git a/components/password_manager/core/browser/one_time_passwords/otp_manager_unittest.cc b/components/password_manager/core/browser/one_time_passwords/otp_manager_unittest.cc new file mode 100644 index 0000000..af3dbfe --- /dev/null +++ b/components/password_manager/core/browser/one_time_passwords/otp_manager_unittest.cc
@@ -0,0 +1,116 @@ +// 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/one_time_passwords/otp_manager.h" + +#include "components/autofill/core/common/autofill_test_utils.h" +#include "components/autofill/core/common/form_data.h" +#include "components/password_manager/core/browser/one_time_passwords/otp_form_manager.h" +#include "components/password_manager/core/browser/stub_password_manager_client.h" + +namespace password_manager { + +namespace { + +using autofill::FormData; + +class MockPasswordManagerClient : public StubPasswordManagerClient { + public: + MockPasswordManagerClient() = default; + + MOCK_METHOD(void, InformPasswordChangeServiceOfOtpPresent, (), (override)); +}; +} // namespace + +class OtpManagerTest : public testing::Test { + public: + OtpManagerTest() : otp_manager_(&mock_client_) {} + + protected: + MockPasswordManagerClient mock_client_; + OtpManager otp_manager_; + + private: + autofill::test::AutofillUnitTestEnvironment autofill_environment_; +}; + +TEST_F(OtpManagerTest, FormManagerCreatedForOtpForm) { + FormData form; + form.set_fields({autofill::test::CreateTestFormField( + "some_label", "some_name", "some_value", + autofill::FormControlType::kInputText)}); + + EXPECT_CALL(mock_client_, InformPasswordChangeServiceOfOtpPresent); + otp_manager_.ProcessClassificationModelPredictions( + form, {{form.fields()[0].global_id(), autofill::ONE_TIME_CODE}}); + + EXPECT_TRUE(otp_manager_.form_managers().contains(form.global_id())); + std::vector<autofill::FieldGlobalId> expected_otp_field_ids = { + form.fields()[0].global_id()}; + EXPECT_EQ(expected_otp_field_ids, + otp_manager_.form_managers().at(form.global_id()).otp_field_ids()); +} + +TEST_F(OtpManagerTest, FormManagerNotCreatedForNotFillableForm) { + FormData form; + form.set_fields({autofill::test::CreateTestFormField( + "some_label", "some_name", "some_value", + // Radio element cannot be filled with a text value, this prediction + // should not be taken into account. + autofill::FormControlType::kInputRadio)}); + + EXPECT_CALL(mock_client_, InformPasswordChangeServiceOfOtpPresent).Times(0); + otp_manager_.ProcessClassificationModelPredictions( + form, {{form.fields()[0].global_id(), autofill::ONE_TIME_CODE}}); + + EXPECT_FALSE(otp_manager_.form_managers().contains(form.global_id())); +} + +TEST_F(OtpManagerTest, ManagersUpdatedWhenPredictionsChange) { + FormData form; + form.set_fields({autofill::test::CreateTestFormField( + "some_label1", "some_name1", "some_value1", + autofill::FormControlType::kInputText), + {autofill::test::CreateTestFormField( + "some_label2", "some_name2", "some_value2", + autofill::FormControlType::kInputPassword)}}); + + EXPECT_CALL(mock_client_, InformPasswordChangeServiceOfOtpPresent); + otp_manager_.ProcessClassificationModelPredictions( + form, {{form.fields()[0].global_id(), autofill::ONE_TIME_CODE}, + {form.fields()[1].global_id(), autofill::UNKNOWN_TYPE}}); + EXPECT_TRUE(otp_manager_.form_managers().contains(form.global_id())); + + // Simulate receiving new predictions. + // The client should not be notified the second time. + EXPECT_CALL(mock_client_, InformPasswordChangeServiceOfOtpPresent).Times(0); + otp_manager_.ProcessClassificationModelPredictions( + form, {{form.fields()[0].global_id(), autofill::UNKNOWN_TYPE}, + {form.fields()[1].global_id(), autofill::ONE_TIME_CODE}}); + + EXPECT_TRUE(otp_manager_.form_managers().contains(form.global_id())); + // Check that the manager reflects the latest predictions. + std::vector<autofill::FieldGlobalId> expected_otp_field_ids = { + form.fields()[1].global_id()}; + EXPECT_EQ(expected_otp_field_ids, + otp_manager_.form_managers().at(form.global_id()).otp_field_ids()); +} + +TEST_F(OtpManagerTest, FormManagerdDeletedWhenOtpFieldIsNoLongerParsedAsSuch) { + FormData form; + form.set_fields({autofill::test::CreateTestFormField( + "some_label", "some_name", "some_value", + autofill::FormControlType::kInputText)}); + + EXPECT_CALL(mock_client_, InformPasswordChangeServiceOfOtpPresent); + otp_manager_.ProcessClassificationModelPredictions( + form, {{form.fields()[0].global_id(), autofill::ONE_TIME_CODE}}); + EXPECT_TRUE(otp_manager_.form_managers().contains(form.global_id())); + + otp_manager_.ProcessClassificationModelPredictions( + form, {{form.fields()[0].global_id(), autofill::UNKNOWN_TYPE}}); + EXPECT_TRUE(otp_manager_.form_managers().empty()); +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index e75602a..f3bbab1 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -1463,7 +1463,9 @@ PasswordFormManager* submitted_manager = GetSubmittedManager(); if (!submitted_manager || !submitted_manager->GetSubmittedForm()) { - logger->LogMessage(Logger::STRING_NO_SUBMITTED_MANAGER_AVAILABLE); + if (logger) { + logger->LogMessage(Logger::STRING_NO_SUBMITTED_MANAGER_AVAILABLE); + } return; }
diff --git a/components/password_manager/core/browser/ui/credential_ui_entry.cc b/components/password_manager/core/browser/ui/credential_ui_entry.cc index 53a07f8..7f70a5b 100644 --- a/components/password_manager/core/browser/ui/credential_ui_entry.cc +++ b/components/password_manager/core/browser/ui/credential_ui_entry.cc
@@ -318,10 +318,6 @@ return CreateSortKey(lhs) == CreateSortKey(rhs); } -bool operator!=(const CredentialUIEntry& lhs, const CredentialUIEntry& rhs) { - return !(lhs == rhs); -} - bool operator<(const CredentialUIEntry& lhs, const CredentialUIEntry& rhs) { return CreateSortKey(lhs) < CreateSortKey(rhs); }
diff --git a/components/password_manager/core/browser/ui/credential_ui_entry.h b/components/password_manager/core/browser/ui/credential_ui_entry.h index 77fed51..0f9302b 100644 --- a/components/password_manager/core/browser/ui/credential_ui_entry.h +++ b/components/password_manager/core/browser/ui/credential_ui_entry.h
@@ -184,7 +184,6 @@ std::string CreateSortKey(const CredentialUIEntry& credential); bool operator==(const CredentialUIEntry& lhs, const CredentialUIEntry& rhs); -bool operator!=(const CredentialUIEntry& lhs, const CredentialUIEntry& rhs); bool operator<(const CredentialUIEntry& lhs, const CredentialUIEntry& rhs); // Returns true when the credential is either leaked or phished.
diff --git a/components/password_manager/core/browser/ui/passwords_grouper.cc b/components/password_manager/core/browser/ui/passwords_grouper.cc index c296076..17ca0479 100644 --- a/components/password_manager/core/browser/ui/passwords_grouper.cc +++ b/components/password_manager/core/browser/ui/passwords_grouper.cc
@@ -106,10 +106,10 @@ public: iterator(size_t i, const SortedPasskeysView* sorted) : i_(i), sorted_(sorted) {} + + friend bool operator==(const iterator&, const iterator&) = default; + void operator++() { i_++; } - bool operator!=(const iterator& other) const { - return i_ != other.i_ || sorted_ != other.sorted_; - } const PasskeyCredential& operator*() { return sorted_->passkeys_[sorted_->sorted_indexes_[i_]]; }
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc index fedbcfc..32c06772 100644 --- a/components/password_manager/core/browser/votes_uploader.cc +++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -134,26 +134,30 @@ void LabelFields(const FieldTypeMap& field_types, const bool field_name_collision, const VoteTypeMap& vote_types, - FormStructure* form_structure, - FieldTypeSet* available_field_types) { + FormStructure& form_structure, + autofill::EncodeUploadRequestOptions& options) { UMA_HISTOGRAM_BOOLEAN("PasswordManager.FieldNameCollisionInVotes", field_name_collision); - for (size_t i = 0; i < form_structure->field_count(); ++i) { - AutofillField* field = form_structure->field(i); + for (size_t i = 0; i < form_structure.field_count(); ++i) { + AutofillField* field = form_structure.field(i); FieldType type = autofill::UNKNOWN_TYPE; if (auto iter = field_types.find(field->renderer_id()); iter != field_types.end()) { type = iter->second; - available_field_types->insert(type); + options.available_field_types.insert(type); } if (auto vote_type_iter = vote_types.find(field->renderer_id()); vote_type_iter != vote_types.end()) { - field->set_vote_type(vote_type_iter->second); + AutofillUploadContents::Field::VoteType vote_type = + vote_type_iter->second; + options.fields[field->global_id()].vote_type = vote_type; + CHECK(type != autofill::USERNAME || + vote_type != AutofillUploadContents::Field::NO_INFORMATION); + } else { + CHECK(type != autofill::USERNAME); } - CHECK(type != autofill::USERNAME || - field->vote_type() != AutofillUploadContents::Field::NO_INFORMATION); FieldTypeSet types; types.insert(type); field->set_possible_types(types); @@ -535,7 +539,7 @@ LabelFields( field_types, field_name_collision, {{form_to_upload.username_element_renderer_id, username_vote_type}}, - &form_structure, &options.available_field_types); + form_structure, options); if (password_manager_util::IsLoggingActive(client_)) { BrowserSavePasswordProgressLogger logger(client_->GetCurrentLogManager()); @@ -583,8 +587,8 @@ AutofillUploadContents::Field::FIRST_USE; } - LabelFields(field_types, field_name_collision, vote_types, &form_structure, - &options.available_field_types); + LabelFields(field_types, field_name_collision, vote_types, form_structure, + options); SetKnownValueFlag(pending_credentials, best_matches, &form_structure); // Annotate the form with the source language of the page.
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn index e7c873ae..dba951de 100644 --- a/components/policy/core/common/BUILD.gn +++ b/components/policy/core/common/BUILD.gn
@@ -149,8 +149,6 @@ "config_dir_policy_loader.h", "configuration_policy_provider.cc", "configuration_policy_provider.h", - "device_local_account_type.cc", - "device_local_account_type.h", "external_data_fetcher.cc", "external_data_fetcher.h", "external_data_manager.h", @@ -338,7 +336,10 @@ deps += [ "//components/policy/android:jni_headers" ] } if (is_chromeos) { - deps += [ "//chromeos/ash/components/system" ] + deps += [ + "//chromeos/ash/components/policy/device_local_account", + "//chromeos/ash/components/system", + ] sources += [ "default_chrome_apps_migrator.cc", "default_chrome_apps_migrator.h",
diff --git a/components/policy/core/common/DEPS b/components/policy/core/common/DEPS index cc017e7..fb00f0d 100644 --- a/components/policy/core/common/DEPS +++ b/components/policy/core/common/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+absl/types/variant.h", + "+chromeos/ash/components/policy/device_local_account", "+chromeos/ash/components/system", "+chromeos/crosapi", "+chromeos/startup",
diff --git a/components/policy/core/common/cloud/affiliation.cc b/components/policy/core/common/cloud/affiliation.cc index 36cdb58..97edbcb3d 100644 --- a/components/policy/core/common/cloud/affiliation.cc +++ b/components/policy/core/common/cloud/affiliation.cc
@@ -7,9 +7,12 @@ #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/cloud_policy_core.h" #include "components/policy/core/common/cloud/cloud_policy_store.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/policy/proto/device_management_backend.pb.h" +#if BUILDFLAG(IS_CHROMEOS) +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" +#endif + namespace policy { bool IsAffiliated(const base::flat_set<std::string>& user_ids, @@ -31,9 +34,11 @@ return false; } +#if BUILDFLAG(IS_CHROMEOS) if (IsDeviceLocalAccountUser(email)) { return true; } +#endif return IsAffiliated(user_affiliation_ids, device_affiliation_ids); }
diff --git a/components/policy/core/common/features.cc b/components/policy/core/common/features.cc index bfb2659..3d22f424 100644 --- a/components/policy/core/common/features.cc +++ b/components/policy/core/common/features.cc
@@ -18,12 +18,4 @@ "EnhancedSecurityEventFields", base::FEATURE_DISABLED_BY_DEFAULT); -// Enables Kiosk session for the Helium android app. -BASE_FEATURE(kHeliumArcvmKiosk, - "HeliumArcvmKiosk", - base::FEATURE_DISABLED_BY_DEFAULT); -bool IsHeliumArcvmKioskEnabled() { - return base::FeatureList::IsEnabled(kHeliumArcvmKiosk); -} - } // namespace policy::features
diff --git a/components/policy/core/common/features.h b/components/policy/core/common/features.h index 94016d2..969677d2 100644 --- a/components/policy/core/common/features.h +++ b/components/policy/core/common/features.h
@@ -23,10 +23,6 @@ // Enables the addition of new security fields for SecOps. POLICY_EXPORT BASE_DECLARE_FEATURE(kEnhancedSecurityEventFields); -// Enables Kiosk session for the Helium android app. -POLICY_EXPORT BASE_DECLARE_FEATURE(kHeliumArcvmKiosk); -POLICY_EXPORT bool IsHeliumArcvmKioskEnabled(); - } // namespace policy::features #endif // COMPONENTS_POLICY_CORE_COMMON_FEATURES_H_
diff --git a/components/policy/policy_export.h b/components/policy/policy_export.h index a92647ff..1e52705 100644 --- a/components/policy/policy_export.h +++ b/components/policy/policy_export.h
@@ -16,19 +16,11 @@ #endif // defined(POLICY_COMPONENT_IMPLEMENTATION) #else // defined(WIN32) - -#if defined(POLICY_COMPONENT_IMPLEMENTATION) #define POLICY_EXPORT __attribute__((visibility("default"))) -#else -#define POLICY_EXPORT -#endif // defined(POLICY_COMPONENT_IMPLEMENTATION) - #endif // defined(WIN32) #else // defined(COMPONENT_BUILD) - #define POLICY_EXPORT - #endif // defined(COMPONENT_BUILD) #endif // COMPONENTS_POLICY_POLICY_EXPORT_H_
diff --git a/components/policy/proto/policy_proto_export.h b/components/policy/proto/policy_proto_export.h index 829356a..16dc5fe 100644 --- a/components/policy/proto/policy_proto_export.h +++ b/components/policy/proto/policy_proto_export.h
@@ -22,27 +22,14 @@ #endif // defined(POLICY_PROTO_COMPILATION) #else // defined(WIN32) - -#if defined(POLICY_PROTO_COMPILATION) #define POLICY_PROTO_EXPORT __attribute__((visibility("default"))) -#else -#define POLICY_PROTO_EXPORT -#endif // defined(POLICY_PROTO_COMPILATION) - -#if defined(POLICY_CHROME_SETTINGS_PROTO_COMPILATION) #define POLICY_CHROME_SETTINGS_PROTO_EXPORT \ __attribute__((visibility("default"))) -#else -#define POLICY_CHROME_SETTINGS_PROTO_EXPORT -#endif // defined(POLICY_PROTO_COMPILATION) - #endif // defined(WIN32) #else // defined(COMPONENT_BUILD) - #define POLICY_PROTO_EXPORT #define POLICY_CHROME_SETTINGS_PROTO_EXPORT - #endif // defined(COMPONENT_BUILD) #endif // COMPONENTS_POLICY_PROTO_POLICY_PROTO_EXPORT_H_
diff --git a/components/prefs/prefs_export.h b/components/prefs/prefs_export.h index 8e5ee4f0..2086ffc 100644 --- a/components/prefs/prefs_export.h +++ b/components/prefs/prefs_export.h
@@ -15,11 +15,7 @@ #endif // defined(COMPONENTS_PREFS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(COMPONENTS_PREFS_IMPLEMENTATION) #define COMPONENTS_PREFS_EXPORT __attribute__((visibility("default"))) -#else -#define COMPONENTS_PREFS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/proxy_config/proxy_config_export.h b/components/proxy_config/proxy_config_export.h index 375f6d08..0f82367e 100644 --- a/components/proxy_config/proxy_config_export.h +++ b/components/proxy_config/proxy_config_export.h
@@ -15,11 +15,7 @@ #endif // defined(PROXY_CONFIG_IMPLEMENTATION) #else // defined(WIN32) -#if defined(PROXY_CONFIG_IMPLEMENTATION) #define PROXY_CONFIG_EXPORT __attribute__((visibility("default"))) -#else -#define PROXY_CONFIG_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/quirks/quirks_export.h b/components/quirks/quirks_export.h index ff1a2e1..ba724142 100644 --- a/components/quirks/quirks_export.h +++ b/components/quirks/quirks_export.h
@@ -15,11 +15,7 @@ #endif // defined(QUIRKS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(QUIRKS_IMPLEMENTATION) #define QUIRKS_EXPORT __attribute__((visibility("default"))) -#else -#define QUIRKS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/reading_list/core/reading_list_local_data_batch_uploader.cc b/components/reading_list/core/reading_list_local_data_batch_uploader.cc index 7031c5e..fde1e3dd 100644 --- a/components/reading_list/core/reading_list_local_data_batch_uploader.cc +++ b/components/reading_list/core/reading_list_local_data_batch_uploader.cc
@@ -6,13 +6,18 @@ #include <memory> #include <utility> +#include <variant> #include <vector> #include "base/containers/flat_set.h" +#include "base/feature_list.h" #include "base/functional/callback.h" #include "components/reading_list/core/dual_reading_list_model.h" +#include "components/sync/base/data_type.h" +#include "components/sync/base/features.h" #include "components/sync/service/local_data_description.h" -#include "url/gurl.h" + +class GURL; namespace reading_list { @@ -29,8 +34,19 @@ base::flat_set<GURL> keys = dual_reading_list_model_->GetKeysThatNeedUploadToSyncServer(); - std::move(callback).Run( - syncer::LocalDataDescription(std::vector(keys.begin(), keys.end()))); + syncer::LocalDataDescription local_data_description = + syncer::LocalDataDescription(std::vector(keys.begin(), keys.end())); + + if (base::FeatureList::IsEnabled( + syncer::kSyncReadingListBatchUploadSelectedItems)) { + local_data_description.type = syncer::DataType::READING_LIST; + for (const GURL& key : keys) { + local_data_description.local_data_models.push_back( + DataItemModelFromURL(key)); + } + } + + std::move(callback).Run(local_data_description); } void ReadingListLocalDataBatchUploader::TriggerLocalDataMigration() { @@ -46,4 +62,13 @@ return dual_reading_list_model_ && dual_reading_list_model_->loaded(); } +syncer::LocalDataItemModel +ReadingListLocalDataBatchUploader::DataItemModelFromURL(const GURL& url) const { + syncer::LocalDataItemModel item; + item.id = url; + item.icon = syncer::LocalDataItemModel::PageUrlIcon(url); + item.title = dual_reading_list_model_->GetEntryByURL(url)->Title(); + return item; +} + } // namespace reading_list
diff --git a/components/reading_list/core/reading_list_local_data_batch_uploader.h b/components/reading_list/core/reading_list_local_data_batch_uploader.h index 15566b0f..14c04f4 100644 --- a/components/reading_list/core/reading_list_local_data_batch_uploader.h +++ b/components/reading_list/core/reading_list_local_data_batch_uploader.h
@@ -8,6 +8,8 @@ #include "base/memory/raw_ptr.h" #include "components/sync/service/data_type_local_data_batch_uploader.h" +class GURL; + namespace reading_list { class DualReadingListModel; @@ -34,6 +36,8 @@ private: bool CanUpload() const; + // Returns the `LocalDataItemModel` corresponding to the given `url`. + syncer::LocalDataItemModel DataItemModelFromURL(const GURL& url) const; const raw_ptr<DualReadingListModel> dual_reading_list_model_; };
diff --git a/components/reading_list/core/reading_list_local_data_batch_uploader_unittest.cc b/components/reading_list/core/reading_list_local_data_batch_uploader_unittest.cc index 85bb5f21..a3fec011 100644 --- a/components/reading_list/core/reading_list_local_data_batch_uploader_unittest.cc +++ b/components/reading_list/core/reading_list_local_data_batch_uploader_unittest.cc
@@ -9,11 +9,14 @@ #include "base/memory/ptr_util.h" #include "base/test/mock_callback.h" +#include "base/test/scoped_feature_list.h" #include "base/test/simple_test_clock.h" #include "base/test/test_future.h" #include "components/reading_list/core/dual_reading_list_model.h" #include "components/reading_list/core/fake_reading_list_model_storage.h" #include "components/reading_list/core/reading_list_model_impl.h" +#include "components/sync/base/data_type.h" +#include "components/sync/base/features.h" #include "components/sync/service/local_data_description.h" #include "components/sync/test/mock_data_type_local_change_processor.h" #include "testing/gmock/include/gmock/gmock.h" @@ -25,6 +28,7 @@ using ::testing::ElementsAre; using ::testing::IsEmpty; using ::testing::Return; +using ::testing::VariantWith; class ReadingListLocalDataBatchUploaderTest : public ::testing::Test { public: @@ -72,6 +76,8 @@ uploader.GetLocalDataDescription(description.GetCallback()); + EXPECT_EQ(description.Get().type, syncer::DataType::UNSPECIFIED); + EXPECT_THAT(description.Get().local_data_models, IsEmpty()); EXPECT_EQ(description.Get().item_count, 0u); EXPECT_EQ(description.Get().domain_count, 0u); EXPECT_THAT(description.Get().domains, IsEmpty()); @@ -84,6 +90,8 @@ uploader.GetLocalDataDescription(description.GetCallback()); + EXPECT_EQ(description.Get().type, syncer::DataType::UNSPECIFIED); + EXPECT_THAT(description.Get().local_data_models, IsEmpty()); EXPECT_EQ(description.Get().item_count, 0u); EXPECT_EQ(description.Get().domain_count, 0u); EXPECT_THAT(description.Get().domains, IsEmpty()); @@ -103,6 +111,42 @@ uploader.GetLocalDataDescription(description.GetCallback()); + EXPECT_EQ(description.Get().type, syncer::DataType::READING_LIST); + auto local_data_models = description.Get().local_data_models; + EXPECT_EQ(local_data_models.size(), 1u); + auto item = local_data_models.back(); + EXPECT_EQ(std::get<GURL>(item.id), GURL("https://local.com")); + EXPECT_EQ(item.title, "local"); + EXPECT_THAT(item.subtitle, IsEmpty()); + EXPECT_THAT(item.icon, VariantWith<syncer::LocalDataItemModel::PageUrlIcon>( + GURL("https://local.com/"))); + + EXPECT_EQ(description.Get().item_count, 1u); + EXPECT_EQ(description.Get().domain_count, 1u); + EXPECT_THAT(description.Get().domains, ElementsAre("local.com")); +} + +TEST_F(ReadingListLocalDataBatchUploaderTest, + LocalDescriptionEmptyItemsWhenFeatureDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature( + syncer::kSyncReadingListBatchUploadSelectedItems); + + LoadModel(); + dual_reading_list_model()->GetLocalOrSyncableModel()->AddOrReplaceEntry( + GURL("https://local.com"), "local", reading_list::ADDED_VIA_CURRENT_APP, + /*estimated_read_time=*/base::TimeDelta()); + dual_reading_list_model()->GetAccountModelIfSyncing()->AddOrReplaceEntry( + GURL("https://account.com"), "account", + reading_list::ADDED_VIA_CURRENT_APP, + /*estimated_read_time=*/base::TimeDelta()); + ReadingListLocalDataBatchUploader uploader(dual_reading_list_model()); + base::test::TestFuture<syncer::LocalDataDescription> description; + + uploader.GetLocalDataDescription(description.GetCallback()); + + EXPECT_EQ(description.Get().type, syncer::DataType::UNSPECIFIED); + EXPECT_THAT(description.Get().local_data_models, IsEmpty()); EXPECT_EQ(description.Get().item_count, 1u); EXPECT_EQ(description.Get().domain_count, 1u); EXPECT_THAT(description.Get().domains, ElementsAre("local.com"));
diff --git a/components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h b/components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h index bf4039af..6bbaa9b 100644 --- a/components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h +++ b/components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h
@@ -9,11 +9,7 @@ // RemoteCocoa app shim module can be exported to consumers. #if defined(COMPONENT_BUILD) -#if defined(REMOTE_COCOA_APP_SHIM_IMPLEMENTATION) #define REMOTE_COCOA_APP_SHIM_EXPORT __attribute__((visibility("default"))) -#else -#define REMOTE_COCOA_APP_SHIM_EXPORT -#endif #else // defined(COMPONENT_BUILD) #define REMOTE_COCOA_APP_SHIM_EXPORT
diff --git a/components/remote_cocoa/browser/remote_cocoa_browser_export.h b/components/remote_cocoa/browser/remote_cocoa_browser_export.h index 95efd0c7..3759f737 100644 --- a/components/remote_cocoa/browser/remote_cocoa_browser_export.h +++ b/components/remote_cocoa/browser/remote_cocoa_browser_export.h
@@ -9,11 +9,7 @@ // RemoteCocoa browser module can be exported to consumers. #if defined(COMPONENT_BUILD) -#if defined(REMOTE_COCOA_BROWSER_IMPLEMENTATION) #define REMOTE_COCOA_BROWSER_EXPORT __attribute__((visibility("default"))) -#else -#define REMOTE_COCOA_BROWSER_EXPORT -#endif #else // defined(COMPONENT_BUILD) #define REMOTE_COCOA_BROWSER_EXPORT
diff --git a/components/safe_browsing/content/browser/web_ui/BUILD.gn b/components/safe_browsing/content/browser/web_ui/BUILD.gn index ee290266..ddc4da5 100644 --- a/components/safe_browsing/content/browser/web_ui/BUILD.gn +++ b/components/safe_browsing/content/browser/web_ui/BUILD.gn
@@ -14,6 +14,7 @@ deps = [ "//base", + "//components/enterprise/common/proto:connectors_proto_to_value", "//components/enterprise/common/proto:connectors_proto", "//components/password_manager/core/browser:hash_password_manager", "//components/resources:components_resources_grit", @@ -31,6 +32,7 @@ "//components/safe_browsing/core/common/proto:csd_proto", "//components/safe_browsing/core/common/proto:csd_proto_to_value", "//components/safe_browsing/core/common/proto:realtimeapi_proto", + "//components/safe_browsing/core/common/proto:realtimeapi_proto_to_value", "//components/safe_browsing/core/common/proto:safebrowsingv5_proto", "//components/safe_browsing/core/common/proto:safebrowsingv5_proto_to_value", "//components/strings:components_strings_grit",
diff --git a/components/safe_browsing/content/browser/web_ui/DEPS b/components/safe_browsing/content/browser/web_ui/DEPS index 0e3849f..a2e080da 100644 --- a/components/safe_browsing/content/browser/web_ui/DEPS +++ b/components/safe_browsing/content/browser/web_ui/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+components/enterprise/common/proto/connectors.pb.h", + "+components/enterprise/common/proto/connectors.to_value.h", "+components/grit/safe_browsing_resources.h", "+components/grit/safe_browsing_resources_map.h", "+components/password_manager/core/browser/hash_password_manager.h",
diff --git a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc index 0f37736..4938581 100644 --- a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc +++ b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc
@@ -38,6 +38,7 @@ #include "components/safe_browsing/core/common/features.h" #include "components/safe_browsing/core/common/proto/csd.pb.h" #include "components/safe_browsing/core/common/proto/csd.to_value.h" +#include "components/safe_browsing/core/common/proto/realtimeapi.to_value.h" #include "components/safe_browsing/core/common/proto/safebrowsingv5.pb.h" #include "components/safe_browsing/core/common/proto/safebrowsingv5.to_value.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" @@ -58,6 +59,7 @@ #if BUILDFLAG(SAFE_BROWSING_DOWNLOAD_PROTECTION) && !BUILDFLAG(IS_ANDROID) #include "components/enterprise/common/proto/connectors.pb.h" +#include "components/enterprise/common/proto/connectors.to_value.h" #endif using base::Time; @@ -809,44 +811,6 @@ #endif -base::Value::Dict SerializeClientReportingMetadata( - const enterprise_connectors::ClientMetadata& client_metadata) { - base::Value::Dict client_metadata_dict; - if (client_metadata.has_browser()) { - base::Value::Dict browser_dict; - browser_dict.Set("browser_id", client_metadata.browser().browser_id()); - browser_dict.Set("user_agent", client_metadata.browser().user_agent()); - browser_dict.Set("chrome_version", - client_metadata.browser().chrome_version()); - browser_dict.Set("machine_user", client_metadata.browser().machine_user()); - client_metadata_dict.Set("browser", std::move(browser_dict)); - } - if (client_metadata.has_device()) { - base::Value::Dict device_dict; - device_dict.Set("dm_token", client_metadata.device().dm_token()); - device_dict.Set("client_id", client_metadata.device().client_id()); - device_dict.Set("os_version", client_metadata.device().os_version()); - device_dict.Set("os_platform", client_metadata.device().os_platform()); - device_dict.Set("name", client_metadata.device().name()); - device_dict.Set("device_fqdn", client_metadata.device().device_fqdn()); - device_dict.Set("network_name", client_metadata.device().network_name()); - client_metadata_dict.Set("device", std::move(device_dict)); - } - if (client_metadata.has_profile()) { - base::Value::Dict profile_dict; - profile_dict.Set("dm_token", client_metadata.profile().dm_token()); - profile_dict.Set("gaia_email", client_metadata.profile().gaia_email()); - profile_dict.Set("profile_path", client_metadata.profile().profile_path()); - profile_dict.Set("profile_name", client_metadata.profile().profile_name()); - profile_dict.Set("client_id", client_metadata.profile().client_id()); - client_metadata_dict.Set("profile", std::move(profile_dict)); - } - client_metadata_dict.Set( - "is_chrome_os_managed_guest_session", - client_metadata.is_chrome_os_managed_guest_session()); - return client_metadata_dict; -} - std::string SerializeClientDownloadRequest(const ClientDownloadRequest& cdr) { return SerializeJson(proto_to_value::Serialize(cdr)); } @@ -1022,61 +986,6 @@ return result; } -base::Value::Dict SerializeRTThreatInfo( - const RTLookupResponse::ThreatInfo& threat_info) { - base::Value::Dict threat_info_dict; - - threat_info_dict.Set( - "threat_type", - RTLookupResponse_ThreatInfo_ThreatType_Name(threat_info.threat_type())); - - threat_info_dict.Set("cache_duration_sec", - static_cast<double>(threat_info.cache_duration_sec())); - - threat_info_dict.Set( - "verdict_type", - RTLookupResponse_ThreatInfo_VerdictType_Name(threat_info.verdict_type())); - - threat_info_dict.Set( - "cache_expression_match_type", - RTLookupResponse_ThreatInfo_CacheExpressionMatchType_Name( - threat_info.cache_expression_match_type())); - threat_info_dict.Set("cache_expression_using_match_type", - threat_info.cache_expression_using_match_type()); - - if (threat_info.has_matched_url_navigation_rule()) { - base::Value::Dict matched_rule; - matched_rule.Set("rule_id", - threat_info.matched_url_navigation_rule().rule_id()); - matched_rule.Set("rule_name", - threat_info.matched_url_navigation_rule().rule_name()); - matched_rule.Set( - "matched_url_category", - threat_info.matched_url_navigation_rule().matched_url_category()); - - if (threat_info.matched_url_navigation_rule().has_custom_message()) { - base::Value::List message_segments; - for (const auto& segment : threat_info.matched_url_navigation_rule() - .custom_message() - .message_segments()) { - base::Value::Dict segment_value; - if (segment.has_text()) { - segment_value.Set("text", segment.text()); - } - if (segment.has_link()) { - segment_value.Set("link", segment.link()); - } - message_segments.Append(std::move(segment_value)); - } - matched_rule.Set("message_segments", std::move(message_segments)); - } - threat_info_dict.Set("matched_url_navigation_rule", - std::move(matched_rule)); - } - - return threat_info_dict; -} - #if BUILDFLAG(IS_ANDROID) // This serializes the internal::ReferringAppInfo struct (not to be confused // with the protobuf message ReferringAppInfo), which contains intermediate @@ -1108,72 +1017,13 @@ } std::string SerializeURTLookupPing(const URTLookupRequest& ping) { - base::Value::Dict request_dict; - const RTLookupRequest& request = ping.request; - - request_dict.Set("url", request.url()); - request_dict.Set("population", - proto_to_value::Serialize(request.population())); + base::Value::Dict request_dict = proto_to_value::Serialize(ping.request); request_dict.Set("scoped_oauth_token", ping.token); - request_dict.Set("dm_token", request.dm_token()); - request_dict.Set("profile_dm_token", request.profile_dm_token()); - request_dict.Set("browser_dm_token", request.browser_dm_token()); - request_dict.Set("email", request.email()); - if (request.has_client_reporting_metadata()) { - request_dict.Set( - "client_reporting_metadata", - SerializeClientReportingMetadata(request.client_reporting_metadata())); - } - - request_dict.Set("lookup_type", - RTLookupRequest_LookupType_Name(request.lookup_type())); - - request_dict.Set("version", request.version()); - - request_dict.Set("os", RTLookupRequest_OSType_Name(request.os_type())); - - base::Value::List local_ips; - for (const std::string& local_ip : request.local_ips()) { - local_ips.Append(local_ip); - } - request_dict.Set("local_ips", std::move(local_ips)); - - base::Value::List referrer_chain; - for (const auto& referrer_chain_entry : request.referrer_chain()) { - referrer_chain.Append(proto_to_value::Serialize(referrer_chain_entry)); - } - request_dict.Set("referrer_chain", std::move(referrer_chain)); -#if BUILDFLAG(IS_ANDROID) - if (request.has_referring_app_info()) { - request_dict.Set("referring_app_info", - proto_to_value::Serialize(request.referring_app_info())); - } -#endif - return SerializeJson(request_dict); } std::string SerializeURTLookupResponse(const RTLookupResponse& response) { - base::Value::Dict response_dict; - - base::Value::List threat_info_list; - for (const RTLookupResponse::ThreatInfo& threat_info : - response.threat_info()) { - threat_info_list.Append(SerializeRTThreatInfo(threat_info)); - } - response_dict.Set("threat_infos", std::move(threat_info_list)); - - response_dict.Set( - "client_side_detection_type", - ClientSideDetectionType_Name(response.client_side_detection_type())); - - base::Value::List url_categories_list; - for (const std::string& url_category : response.url_categories()) { - url_categories_list.Append(url_category); - } - response_dict.Set("url_categories", std::move(url_categories_list)); - - return SerializeJson(response_dict); + return SerializeJson(proto_to_value::Serialize(response)); } std::string SerializeHPRTLookupPing(const HPRTLookupRequest& ping) { @@ -1228,185 +1078,16 @@ const std::string& upload_info, const std::string& upload_url, const enterprise_connectors::ContentAnalysisRequest& request) { - base::Value::Dict request_dict; - - request_dict.Set(per_profile_request ? "profile_token" : "device_token", - request.device_token()); - request_dict.Set("blocking", request.blocking()); - request_dict.Set("analysis_connector", - enterprise_connectors::AnalysisConnector_Name( - request.analysis_connector())); - request_dict.Set("reason", - enterprise_connectors::ContentAnalysisRequest_Reason_Name( - request.reason())); - base::Value::List local_ips; - for (const std::string& local_ip : request.local_ips()) { - local_ips.Append(local_ip); - } - request_dict.Set("local_ips", std::move(local_ips)); - - if (request.has_request_data()) { - base::Value::Dict request_data; - request_data.Set("url", request.request_data().url()); - request_data.Set("filename", request.request_data().filename()); - request_data.Set("digest", request.request_data().digest()); - if (request.request_data().has_csd()) { - std::string csd_base64 = - base::Base64Encode(request.request_data().csd().SerializeAsString()); - request_data.Set("csd", std::move(csd_base64)); - } - if (request.request_data().referrer_chain_size() > 0) { - base::Value::List referrers; - for (const auto& referrer_chain_entry : - request.request_data().referrer_chain()) { - referrers.Append(proto_to_value::Serialize(referrer_chain_entry)); - } - request_data.Set("referrers", std::move(referrers)); - } - request_data.Set("content_type", request.request_data().content_type()); - request_data.Set("tab_url", request.request_data().tab_url()); - request_data.Set("source", request.request_data().source()); - request_data.Set("destination", request.request_data().destination()); - request_data.Set("email", request.request_data().email()); - request_data.Set("tab_title", request.request_data().tab_title()); - request_data.Set("content_area_account_email", - request.request_data().content_area_account_email()); - - if (request.request_data().has_print_metadata()) { - base::Value::Dict print_metadata; - print_metadata.Set( - "printer_name", - request.request_data().print_metadata().printer_name()); - print_metadata.Set( - "printer_type", - enterprise_connectors::ContentMetaData::PrintMetadata:: - PrinterType_Name( - request.request_data().print_metadata().printer_type())); - request_data.Set("print_metadata", std::move(print_metadata)); - } - - if (request.request_data().has_copied_text_source()) { - base::Value::Dict copied_text_source; - copied_text_source.Set("url", - request.request_data().copied_text_source().url()); - copied_text_source.Set( - "context", - enterprise_connectors::ContentMetaData::CopiedTextSource:: - CopiedTextSourceType_Name( - request.request_data().copied_text_source().context())); - request_data.Set("copied_text_source", std::move(copied_text_source)); - } - - request_dict.Set("request_data", std::move(request_data)); - } - - if (request.has_client_metadata()) { - base::Value::Dict metadata; - - if (request.client_metadata().has_browser()) { - const auto& browser = request.client_metadata().browser(); - base::Value::Dict browser_metadata; - browser_metadata.Set("browser_id", browser.browser_id()); - browser_metadata.Set("user_agent", browser.user_agent()); - browser_metadata.Set("chrome_version", browser.chrome_version()); - browser_metadata.Set("machine_user", browser.machine_user()); - metadata.Set("browser", std::move(browser_metadata)); - } - - if (request.client_metadata().has_device()) { - base::Value::Dict device_metadata; - const auto& device = request.client_metadata().device(); - device_metadata.Set("dm_token", device.dm_token()); - device_metadata.Set("client_id", device.client_id()); - device_metadata.Set("os_version", device.os_version()); - device_metadata.Set("os_platform", device.os_platform()); - device_metadata.Set("name", device.name()); - device_metadata.Set("device_fqdn", device.device_fqdn()); - device_metadata.Set("network_name", device.network_name()); - metadata.Set("device", std::move(device_metadata)); - } - - if (request.client_metadata().has_profile()) { - base::Value::Dict profile_metadata; - const auto& profile = request.client_metadata().profile(); - profile_metadata.Set("dm_token", profile.dm_token()); - profile_metadata.Set("gaia_email", profile.gaia_email()); - profile_metadata.Set("profile_path", profile.profile_path()); - profile_metadata.Set("profile_name", profile.profile_name()); - profile_metadata.Set("client_id", profile.client_id()); - metadata.Set("profile", std::move(profile_metadata)); - } - - request_dict.Set("client_metadata", std::move(metadata)); - } - - base::Value::List tags; - for (const std::string& tag : request.tags()) { - tags.Append(tag); - } - request_dict.Set("tags", std::move(tags)); - request_dict.Set("request_token", request.request_token()); + base::Value::Dict request_dict = proto_to_value::Serialize(request); request_dict.Set("access_token", access_token_truncated); request_dict.Set("upload_info", upload_info); - request_dict.Set( - "is_chrome_os_managed_guest_session", - request.client_metadata().is_chrome_os_managed_guest_session()); request_dict.Set("upload_url", upload_url); - return SerializeJson(request_dict); } std::string SerializeContentAnalysisResponse( const enterprise_connectors::ContentAnalysisResponse& response) { - base::Value::Dict response_dict; - - response_dict.Set("token", response.request_token()); - - base::Value::List result_values; - for (const auto& result : response.results()) { - base::Value::Dict result_value; - result_value.Set( - "status", - enterprise_connectors::ContentAnalysisResponse_Result_Status_Name( - result.status())); - result_value.Set("tag", result.tag()); - - base::Value::List triggered_rules; - for (const auto& rule : result.triggered_rules()) { - base::Value::Dict rule_value; - - rule_value.Set( - "action", - enterprise_connectors:: - ContentAnalysisResponse_Result_TriggeredRule_Action_Name( - rule.action())); - rule_value.Set("rule_name", rule.rule_name()); - rule_value.Set("rule_id", rule.rule_id()); - rule_value.Set("url_category", rule.url_category()); - - if (rule.has_custom_rule_message()) { - base::Value::List message_segments; - for (const auto& segment : - rule.custom_rule_message().message_segments()) { - base::Value::Dict segment_value; - if (segment.has_text()) { - segment_value.Set("text", segment.text()); - } - if (segment.has_link()) { - segment_value.Set("link", segment.link()); - } - message_segments.Append(std::move(segment_value)); - } - rule_value.Set("message_segments", std::move(message_segments)); - } - triggered_rules.Append(std::move(rule_value)); - } - result_value.Set("triggered_rules", std::move(triggered_rules)); - result_values.Append(std::move(result_value)); - } - response_dict.Set("results", std::move(result_values)); - - return SerializeJson(response_dict); + return SerializeJson(proto_to_value::Serialize(response)); } base::Value::Dict SerializeDeepScanDebugData(const std::string& token,
diff --git a/components/safe_browsing/core/common/proto/BUILD.gn b/components/safe_browsing/core/common/proto/BUILD.gn index e3af61bb6..f73e0ee8 100644 --- a/components/safe_browsing/core/common/proto/BUILD.gn +++ b/components/safe_browsing/core/common/proto/BUILD.gn
@@ -39,6 +39,16 @@ ] } +proto_to_value("realtimeapi_proto_to_value") { + sources = [ "realtimeapi.proto" ] + deps = [ + ":csd_proto", + ":csd_proto_to_value", + "//components/enterprise/common/proto:connectors_proto", + "//components/enterprise/common/proto:connectors_proto_to_value", + ] +} + fuzzable_proto_library("client_model_proto") { proto_in_dir = "//" sources = [ "client_model.proto" ]
diff --git a/components/safe_browsing/core/common/proto_to_value/BUILD.gn b/components/safe_browsing/core/common/proto_to_value/BUILD.gn index a80921e..8783f173 100644 --- a/components/safe_browsing/core/common/proto_to_value/BUILD.gn +++ b/components/safe_browsing/core/common/proto_to_value/BUILD.gn
@@ -11,3 +11,18 @@ ] } } + +source_set("unit_tests") { + testonly = true + sources = [ "to_value_plugin_unittest.cc" ] + + deps = [ + "//base", + "//base/test:test_support", + "//components/safe_browsing/core/common/proto_to_value/test_proto:test_proto", + "//components/safe_browsing/core/common/proto_to_value/test_proto:test_proto_to_value", + "//testing/gmock", + "//testing/gtest", + "//third_party/protobuf:protobuf_lite", + ] +}
diff --git a/components/safe_browsing/core/common/proto_to_value/proto_to_value.gni b/components/safe_browsing/core/common/proto_to_value/proto_to_value.gni index 8455976..47b6c44 100644 --- a/components/safe_browsing/core/common/proto_to_value/proto_to_value.gni +++ b/components/safe_browsing/core/common/proto_to_value/proto_to_value.gni
@@ -17,7 +17,13 @@ template("proto_to_value") { proto_library("${target_name}") { proto_in_dir = "//" + sources = invoker.sources + + if (defined(invoker.deps)) { + deps = invoker.deps + } + generator_plugin_label = "//components/safe_browsing/core/common/proto_to_value:to_value_plugin" generator_plugin_suffix = ".to_value"
diff --git a/components/safe_browsing/core/common/proto_to_value/test_proto/BUILD.gn b/components/safe_browsing/core/common/proto_to_value/test_proto/BUILD.gn new file mode 100644 index 0000000..359afaa74 --- /dev/null +++ b/components/safe_browsing/core/common/proto_to_value/test_proto/BUILD.gn
@@ -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. + +import( + "//components/safe_browsing/core/common/proto_to_value/proto_to_value.gni") +import("//third_party/protobuf/proto_library.gni") + +proto_library("test_proto") { + proto_in_dir = "//" + sources = [ + "test_proto.proto", + "test_proto_dependency.proto", + ] +} + +proto_to_value("test_proto_to_value") { + sources = [ + "test_proto.proto", + "test_proto_dependency.proto", + ] +}
diff --git a/components/safe_browsing/core/common/proto_to_value/test_proto/test_proto.proto b/components/safe_browsing/core/common/proto_to_value/test_proto/test_proto.proto new file mode 100644 index 0000000..0a36d46 --- /dev/null +++ b/components/safe_browsing/core/common/proto_to_value/test_proto/test_proto.proto
@@ -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. + +syntax = "proto3"; + +package proto_to_value; + +option optimize_for = LITE_RUNTIME; + +import "components/safe_browsing/core/common/proto_to_value/test_proto/test_proto_dependency.proto"; + +message TestMessage { + double double_field = 1; + + int32 int32_field = 2; + + message NestedMessage { + int32 int32_field = 1; + } + + NestedMessage nested_message_field = 3; + + enum TestEnum { + UNKNOWN = 0; + ENUM_A = 1; + ENUM_B = 2; + } + + TestEnum enum_field = 4; + + repeated int32 repeated_int32_field = 5; + + string string_field = 6; + + bytes bytes_field = 7; + + DependencyMessage dependency_message = 8; +}
diff --git a/components/safe_browsing/core/common/proto_to_value/test_proto/test_proto_dependency.proto b/components/safe_browsing/core/common/proto_to_value/test_proto/test_proto_dependency.proto new file mode 100644 index 0000000..c0de017 --- /dev/null +++ b/components/safe_browsing/core/common/proto_to_value/test_proto/test_proto_dependency.proto
@@ -0,0 +1,13 @@ +// 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 proto_to_value; + +message DependencyMessage { + int32 int32_field = 1; +}
diff --git a/components/safe_browsing/core/common/proto_to_value/to_value_plugin.cc b/components/safe_browsing/core/common/proto_to_value/to_value_plugin.cc index dccf977..dd5c4bbe 100644 --- a/components/safe_browsing/core/common/proto_to_value/to_value_plugin.cc +++ b/components/safe_browsing/core/common/proto_to_value/to_value_plugin.cc
@@ -31,13 +31,7 @@ const std::string& options, GeneratorContext* context, std::string* error) const override { -#if BUILDFLAG(IS_WIN) - base::FilePath base_file_path = - base::FilePath(base::ASCIIToWide(file->name())).RemoveExtension(); -#else - base::FilePath base_file_path = - base::FilePath(file->name()).RemoveExtension(); -#endif + base::FilePath base_file_path = ToValueFilePath(file->name()); base::FilePath h_file_path = base_file_path.AddExtension(FILE_PATH_LITERAL("to_value.h")); base::FilePath cc_file_path = @@ -79,6 +73,14 @@ cc_printer.Print("#include \"base/base64.h\"\n"); cc_printer.Print("#include \"$p$\"\n\n", "p", h_file_path.AsUTF8Unsafe()); + for (int i = 0; i < file->dependency_count(); i++) { + base::FilePath include_path = + ToValueFilePath(file->dependency(i)->name()) + .AddExtension(FILE_PATH_LITERAL("to_value.h")); + cc_printer.Print("#include \"$p$\"\n", "p", include_path.AsUTF8Unsafe()); + } + cc_printer.Print("\n"); + cc_printer.Print("namespace proto_to_value {\n\n"); for (int i = 0; i < file->message_type_count(); i++) { if (!PrintFunctionDefinition(*file->message_type(i), &cc_printer, @@ -93,6 +95,14 @@ } private: + base::FilePath ToValueFilePath(std::string_view file_name) const { +#if BUILDFLAG(IS_WIN) + return base::FilePath(base::ASCIIToWide(file_name)).RemoveExtension(); +#else + return base::FilePath(file_name).RemoveExtension(); +#endif + } + std::string CppFullName(std::string_view full_name) const { std::string ret; CHECK(base::ReplaceChars(full_name, ".", "::", &ret)); @@ -150,6 +160,15 @@ printer->Print("(message.$f$()));\n", "f", field_name); printer->Outdent(); printer->Print("}\n"); + } else if (field->type() == FieldDescriptor::Type::TYPE_STRING || + field->type() == FieldDescriptor::Type::TYPE_BYTES) { + printer->Print("if (!message.$f$().empty()) {\n", "f", field_name); + printer->Indent(); + printer->Print("dict.Set(\"$f$\", ", "f", field_name); + PrintFieldToValue(*field, printer); + printer->Print("(message.$f$()));\n", "f", field_name); + printer->Outdent(); + printer->Print("}\n"); } else { printer->Print("dict.Set(\"$f$\", ", "f", field_name); PrintFieldToValue(*field, printer);
diff --git a/components/safe_browsing/core/common/proto_to_value/to_value_plugin_unittest.cc b/components/safe_browsing/core/common/proto_to_value/to_value_plugin_unittest.cc new file mode 100644 index 0000000..23aaba8b --- /dev/null +++ b/components/safe_browsing/core/common/proto_to_value/to_value_plugin_unittest.cc
@@ -0,0 +1,71 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/test/values_test_util.h" +#include "components/safe_browsing/core/common/proto_to_value/test_proto/test_proto.pb.h" +#include "components/safe_browsing/core/common/proto_to_value/test_proto/test_proto.to_value.h" +#include "components/safe_browsing/core/common/proto_to_value/test_proto/test_proto_dependency.pb.h" +#include "components/safe_browsing/core/common/proto_to_value/test_proto/test_proto_dependency.to_value.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace proto_to_value { + +TEST(ProtoToValueTest, BasicField) { + TestMessage message; + message.set_double_field(1.0); + message.set_int32_field(2); + message.mutable_nested_message_field()->set_int32_field(3); + message.set_enum_field(TestMessage::ENUM_B); + message.set_string_field("abc"); + message.set_bytes_field("\x01\x02\x03"); + + EXPECT_EQ(Serialize(message), base::test::ParseJson(R"!({ + "double_field": 1.0, + "int32_field": 2, + "nested_message_field": { + "int32_field": 3 + }, + "enum_field": "ENUM_B", + "string_field": "abc", + "bytes_field": "AQID", +})!")); +} + +TEST(ProtoToValueTest, RepeatedField) { + TestMessage message; + + // Default fields only if empty + EXPECT_EQ(Serialize(message), base::test::ParseJson(R"!({ + "double_field": 0.0, + "int32_field": 0, + "enum_field": "UNKNOWN", +})!")); + + message.add_repeated_int32_field(1); + message.add_repeated_int32_field(2); + message.add_repeated_int32_field(3); + + EXPECT_EQ(Serialize(message), base::test::ParseJson(R"!({ + "double_field": 0.0, + "int32_field": 0, + "enum_field": "UNKNOWN", + "repeated_int32_field": [1, 2, 3], +})!")); +} + +TEST(ProtoToValueTest, DepedentFile) { + TestMessage message; + message.mutable_dependency_message()->set_int32_field(4); + + EXPECT_EQ(Serialize(message), base::test::ParseJson(R"!({ + "double_field": 0.0, + "int32_field": 0, + "enum_field": "UNKNOWN", + "dependency_message": { + "int32_field": 4, + }, +})!")); +} + +} // namespace proto_to_value
diff --git a/components/services/storage/dom_storage/async_dom_storage_database.cc b/components/services/storage/dom_storage/async_dom_storage_database.cc index b8b1cef3..c173270 100644 --- a/components/services/storage/dom_storage/async_dom_storage_database.cc +++ b/components/services/storage/dom_storage/async_dom_storage_database.cc
@@ -12,6 +12,7 @@ #include <string> #include <utility> +#include "base/debug/alias.h" #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" @@ -81,13 +82,19 @@ [](std::vector<BatchDatabaseTask> tasks, const DomStorageDatabase& db) { leveldb::WriteBatch batch; + // TODO(crbug.com/40245293): Remove this after debugging + // is complete. + size_t batch_task_count = tasks.size(); size_t iteration_count = 0; + size_t current_batch_size = 0; + base::debug::Alias(&batch_task_count); + base::debug::Alias(&iteration_count); + base::debug::Alias(¤t_batch_size); for (auto& task : tasks) { iteration_count++; - size_t current_batch_size = batch.ApproximateSize(); std::move(task).Run(&batch, db); - size_t new_batch_size = batch.ApproximateSize(); - size_t growth = new_batch_size - current_batch_size; + size_t growth = + batch.ApproximateSize() - current_batch_size; base::UmaHistogramCustomCounts( "Storage.DomStorage." "BatchTaskGrowthSizeBytes", @@ -97,7 +104,7 @@ size_t target_batch_size = batch_size_mb * 1024 * 1024; if (current_batch_size < target_batch_size && - new_batch_size >= target_batch_size) { + batch.ApproximateSize() >= target_batch_size) { base::UmaHistogramCounts10000( base::StringPrintf("Storage.DomStorage." "IterationsToReach%zuMB",
diff --git a/components/session_manager/session_manager_export.h b/components/session_manager/session_manager_export.h index ba11e2ae..406679a 100644 --- a/components/session_manager/session_manager_export.h +++ b/components/session_manager/session_manager_export.h
@@ -15,11 +15,7 @@ #endif // defined(SESSION_EXPORT) #else // defined(WIN32) -#if defined(SESSION_IMPLEMENTATION) #define SESSION_EXPORT __attribute__((visibility("default"))) -#else -#define SESSION_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/sessions/core/sessions_export.h b/components/sessions/core/sessions_export.h index 097301c0..4978bb5 100644 --- a/components/sessions/core/sessions_export.h +++ b/components/sessions/core/sessions_export.h
@@ -15,11 +15,7 @@ #endif // defined(SESSIONS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(SESSIONS_IMPLEMENTATION) #define SESSIONS_EXPORT __attribute__((visibility("default"))) -#else -#define SESSIONS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/sync/base/features.cc b/components/sync/base/features.cc index 133dbd5..e7a964b4 100644 --- a/components/sync/base/features.cc +++ b/components/sync/base/features.cc
@@ -112,6 +112,11 @@ base::FEATURE_DISABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID) +// Enabled by default, intended as a kill switch. +BASE_FEATURE(kSyncReadingListBatchUploadSelectedItems, + "SyncReadingListBatchUploadSelectedItems", + base::FEATURE_ENABLED_BY_DEFAULT); + BASE_FEATURE(kSeparateLocalAndAccountThemes, "SeparateLocalAndAccountThemes", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/sync/base/features.h b/components/sync/base/features.h index b659e83..e623c1b 100644 --- a/components/sync/base/features.h +++ b/components/sync/base/features.h
@@ -111,6 +111,19 @@ BASE_DECLARE_FEATURE(kMigrateAccountPrefs); #endif // BUILDFLAG(IS_IOS) || BUILDFLAG(IS_ANDROID) +// If enabled, support displaying and uploading individual Reading List items in +// the Batch Upload UI. +// +// Batch Upload of all items is supported regardless of this feature flag. +// +// On Windows/Mac/Linux: this flag only affects behavior if the +// `syncer::kReadingListEnableSyncTransportModeUponSignIn` feature is also +// enabled. +// +// On Android: this flag does not affect user-visiable behavior, but does enable +// new code paths. +BASE_DECLARE_FEATURE(kSyncReadingListBatchUploadSelectedItems); + // If enabled, distinguishes between local and account themes. BASE_DECLARE_FEATURE(kSeparateLocalAndAccountThemes);
diff --git a/components/sync/service/local_data_description.h b/components/sync/service/local_data_description.h index 3973f0a..878a037 100644 --- a/components/sync/service/local_data_description.h +++ b/components/sync/service/local_data_description.h
@@ -29,6 +29,8 @@ using DataId = std::variant< // BOOKMARKS. int64_t, // bookmarks::BookmarkNode::id() + // READING_LIST. + GURL, // CONTACT_INFO, THEMES. std::string, // PASSWORDS.
diff --git a/components/test/data/autofill/heuristics-json/internal b/components/test/data/autofill/heuristics-json/internal index dbd13cb..cdb4965 160000 --- a/components/test/data/autofill/heuristics-json/internal +++ b/components/test/data/autofill/heuristics-json/internal
@@ -1 +1 @@ -Subproject commit dbd13cb361518dac753112204eacd1ce9e1fab84 +Subproject commit cdb496540ac02f8d98cfc04097e3e10a197f18f4
diff --git a/components/tracing/tracing_export.h b/components/tracing/tracing_export.h index 357d8c09..51757111 100644 --- a/components/tracing/tracing_export.h +++ b/components/tracing/tracing_export.h
@@ -15,11 +15,7 @@ #endif // defined(TRACING_IMPLEMENTATION) #else // defined(WIN32) -#if defined(TRACING_IMPLEMENTATION) #define TRACING_EXPORT __attribute__((visibility("default"))) -#else -#define TRACING_EXPORT -#endif // defined(TRACING_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/ui_devtools/devtools_export.h b/components/ui_devtools/devtools_export.h index 46dfc805..ab39350 100644 --- a/components/ui_devtools/devtools_export.h +++ b/components/ui_devtools/devtools_export.h
@@ -15,11 +15,7 @@ #endif // defined(UI_DEVTOOLS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(UI_DEVTOOLS_IMPLEMENTATION) #define UI_DEVTOOLS_EXPORT __attribute__((visibility("default"))) -#else -#define UI_DEVTOOLS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/url_matcher/url_matcher_export.h b/components/url_matcher/url_matcher_export.h index 44504582..54ff967 100644 --- a/components/url_matcher/url_matcher_export.h +++ b/components/url_matcher/url_matcher_export.h
@@ -15,11 +15,7 @@ #endif // defined(URL_MATCHER_IMPLEMENTATION) #else // defined(WIN32) -#if defined(URL_MATCHER_IMPLEMENTATION) #define URL_MATCHER_EXPORT __attribute__((visibility("default"))) -#else -#define URL_MATCHER_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/user_manager/BUILD.gn b/components/user_manager/BUILD.gn index c6fadcd7a..9c7ddf9 100644 --- a/components/user_manager/BUILD.gn +++ b/components/user_manager/BUILD.gn
@@ -106,6 +106,7 @@ "//chromeos/ash/components/dbus/cryptohome", "//chromeos/ash/components/dbus/cryptohome:cryptohome_proto", "//chromeos/ash/components/dbus/userdataauth", + "//chromeos/ash/components/policy/device_local_account", "//chromeos/ash/components/settings", "//components/policy/core/common", "//components/prefs",
diff --git a/components/user_manager/DEPS b/components/user_manager/DEPS index 0bad503..553868c 100644 --- a/components/user_manager/DEPS +++ b/components/user_manager/DEPS
@@ -1,6 +1,7 @@ include_rules = [ "+ash/constants", "+chromeos/ash/components/install_attributes", + "+chromeos/ash/components/policy/device_local_account", "+chromeos/ash/components/settings", "+components/account_id/account_id.h", "+components/pref_registry",
diff --git a/components/user_manager/test_helper.cc b/components/user_manager/test_helper.cc index 1411c9744..f024d246 100644 --- a/components/user_manager/test_helper.cc +++ b/components/user_manager/test_helper.cc
@@ -7,8 +7,8 @@ #include "base/check_deref.h" #include "chromeos/ash/components/cryptohome/cryptohome_parameters.h" #include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h" +#include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h" #include "components/account_id/account_id.h" -#include "components/policy/core/common/device_local_account_type.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/user_manager/known_user.h" #include "components/user_manager/user_manager.h"
diff --git a/components/user_manager/user_manager_export.h b/components/user_manager/user_manager_export.h index f336d37f..51f149a 100644 --- a/components/user_manager/user_manager_export.h +++ b/components/user_manager/user_manager_export.h
@@ -15,11 +15,7 @@ #endif // defined(USER_MANAGER_EXPORT) #else // defined(WIN32) -#if defined(USER_MANAGER_IMPLEMENTATION) #define USER_MANAGER_EXPORT __attribute__((visibility("default"))) -#else -#define USER_MANAGER_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/user_prefs/user_prefs_export.h b/components/user_prefs/user_prefs_export.h index 736594374..a0be0f6b 100644 --- a/components/user_prefs/user_prefs_export.h +++ b/components/user_prefs/user_prefs_export.h
@@ -15,11 +15,7 @@ #endif // defined(USER_PREFS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(USER_PREFS_IMPLEMENTATION) #define USER_PREFS_EXPORT __attribute__((visibility("default"))) -#else -#define USER_PREFS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/variations/cros_evaluate_seed/early_boot_safe_seed.cc b/components/variations/cros_evaluate_seed/early_boot_safe_seed.cc index c2b664c..6eb23e3 100644 --- a/components/variations/cros_evaluate_seed/early_boot_safe_seed.cc +++ b/components/variations/cros_evaluate_seed/early_boot_safe_seed.cc
@@ -22,11 +22,9 @@ void EarlyBootSafeSeed::SetFetchTime(const base::Time& fetch_time) {} int EarlyBootSafeSeed::GetMilestone() const { - return safe_seed_details_.milestone(); + return GetCompressedSeed().milestone; } -void EarlyBootSafeSeed::SetMilestone(int milestone) {} - base::Time EarlyBootSafeSeed::GetTimeForStudyDateChecks() const { return base::Time::FromDeltaSinceWindowsEpoch( base::Milliseconds(safe_seed_details_.date())); @@ -39,13 +37,11 @@ return { .storage_format = StoredSeed::StorageFormat::kCompressedAndBase64Encoded, .data = safe_seed_details_.b64_compressed_data(), - .signature = safe_seed_details_.signature()}; + .signature = safe_seed_details_.signature(), + .milestone = safe_seed_details_.milestone()}; } -void EarlyBootSafeSeed::SetCompressedSeed( - const std::string& safe_compressed, - const std::string& base64_safe_compressed, - const std::string& signature) {} +void EarlyBootSafeSeed::SetCompressedSeed(ValidatedSeedInfo seed_info) {} std::string EarlyBootSafeSeed::GetLocale() const { return safe_seed_details_.locale();
diff --git a/components/variations/cros_evaluate_seed/early_boot_safe_seed.h b/components/variations/cros_evaluate_seed/early_boot_safe_seed.h index e86d554..a1def44 100644 --- a/components/variations/cros_evaluate_seed/early_boot_safe_seed.h +++ b/components/variations/cros_evaluate_seed/early_boot_safe_seed.h
@@ -39,15 +39,12 @@ void SetFetchTime(const base::Time& fetch_time) override; int GetMilestone() const override; - void SetMilestone(int milestone) override; base::Time GetTimeForStudyDateChecks() const override; void SetTimeForStudyDateChecks(const base::Time& safe_seed_time) override; StoredSeed GetCompressedSeed() const override; - void SetCompressedSeed(const std::string& safe_compressed, - const std::string& base64_safe_compressed, - const std::string& signature) override; + void SetCompressedSeed(ValidatedSeedInfo seed_info) override; std::string GetLocale() const override; void SetLocale(const std::string& locale) override;
diff --git a/components/variations/cros_evaluate_seed/early_boot_safe_seed_unittest.cc b/components/variations/cros_evaluate_seed/early_boot_safe_seed_unittest.cc index f2873ba..7045a25 100644 --- a/components/variations/cros_evaluate_seed/early_boot_safe_seed_unittest.cc +++ b/components/variations/cros_evaluate_seed/early_boot_safe_seed_unittest.cc
@@ -42,10 +42,6 @@ EXPECT_EQ(early_boot_safe_seed.GetMilestone(), 100); // Should not change. - early_boot_safe_seed.SetMilestone(101); - EXPECT_EQ(early_boot_safe_seed.GetMilestone(), 100); - - // Still should not change. early_boot_safe_seed.ClearState(); EXPECT_EQ(early_boot_safe_seed.GetMilestone(), 100); } @@ -86,7 +82,11 @@ EXPECT_EQ(early_boot_safe_seed.GetCompressedSeed().signature, "signature"); // Should not change. - early_boot_safe_seed.SetCompressedSeed("data", "base64_data", "asdf"); + early_boot_safe_seed.SetCompressedSeed( + ValidatedSeedInfo{.compressed_seed_data = "data", + .base64_seed_data = "base64_data", + .signature = "asdf", + .milestone = 100}); EXPECT_EQ(early_boot_safe_seed.GetCompressedSeed().signature, "signature"); } @@ -131,9 +131,12 @@ EarlyBootSafeSeed early_boot_safe_seed(details); early_boot_safe_seed.SetFetchTime(base::Time::Now()); - early_boot_safe_seed.SetMilestone(100); early_boot_safe_seed.SetTimeForStudyDateChecks(base::Time::Now()); - early_boot_safe_seed.SetCompressedSeed("data", "base64_data", "signature"); + early_boot_safe_seed.SetCompressedSeed( + ValidatedSeedInfo{.compressed_seed_data = "data", + .base64_seed_data = "base64_data", + .signature = "signature", + .milestone = 100}); early_boot_safe_seed.SetLocale("locale"); early_boot_safe_seed.SetPermanentConsistencyCountry("us"); early_boot_safe_seed.SetSessionConsistencyCountry("us");
diff --git a/components/variations/seed_reader_writer.cc b/components/variations/seed_reader_writer.cc index 2c2c6ce..39dcfa2 100644 --- a/components/variations/seed_reader_writer.cc +++ b/components/variations/seed_reader_writer.cc
@@ -87,11 +87,13 @@ const SeedFieldsPrefs kRegularSeedFieldsPrefs = { .seed = prefs::kVariationsCompressedSeed, - .signature = prefs::kVariationsSeedSignature}; + .signature = prefs::kVariationsSeedSignature, + .milestone = prefs::kVariationsSeedMilestone}; const SeedFieldsPrefs kSafeSeedFieldsPrefs = { .seed = prefs::kVariationsSafeCompressedSeed, - .signature = prefs::kVariationsSafeSeedSignature}; + .signature = prefs::kVariationsSafeSeedSignature, + .milestone = prefs::kVariationsSafeSeedMilestone}; SeedReaderWriter::SeedReaderWriter( PrefService* local_state, @@ -125,15 +127,12 @@ } } -void SeedReaderWriter::StoreValidatedSeedInfo( - std::string_view compressed_seed_data, - std::string_view base64_seed_data, - std::string_view signature) { +void SeedReaderWriter::StoreValidatedSeedInfo(ValidatedSeedInfo seed_info) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (ShouldUseSeedFile()) { - ScheduleSeedFileWrite(compressed_seed_data, signature); + ScheduleSeedFileWrite(seed_info); } else { - ScheduleLocalStateWrite(base64_seed_data, signature); + ScheduleLocalStateWrite(seed_info); } } @@ -141,10 +140,11 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // TODO(crbug.com/372009105): Remove if-statements when experiment has ended. if (ShouldUseSeedFile()) { - ScheduleSeedFileWrite(std::string_view(), std::string_view()); + ScheduleSeedFileClear(); } else { local_state_->ClearPref(fields_prefs_->seed); local_state_->ClearPref(fields_prefs_->signature); + local_state_->ClearPref(fields_prefs_->milestone); // Although only clients in the treatment group write seeds to dedicated // seed files, attempt to delete the seed file for clients with // Local-State-based seeds. If a client switches experiment groups or @@ -159,13 +159,15 @@ if (ShouldUseSeedFile()) { return StoredSeed{.storage_format = StoredSeed::StorageFormat::kCompressed, .data = seed_info_.data, - .signature = seed_info_.signature}; + .signature = seed_info_.signature, + .milestone = seed_info_.milestone}; } else { return StoredSeed{ .storage_format = StoredSeed::StorageFormat::kCompressedAndBase64Encoded, .data = local_state_->GetString(fields_prefs_->seed), - .signature = local_state_->GetString(fields_prefs_->signature)}; + .signature = local_state_->GetString(fields_prefs_->signature), + .milestone = local_state_->GetInteger(fields_prefs_->milestone)}; } } @@ -191,15 +193,15 @@ return base::BindOnce(&DoSerialize, seed_info_.data); } -void SeedReaderWriter::ScheduleSeedFileWrite(std::string_view seed_data, - std::string_view signature) { +void SeedReaderWriter::ScheduleSeedFileWrite(ValidatedSeedInfo seed_info) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Set `seed_info_.data`, this will be used later by the background // serialization and can be changed multiple times before a scheduled write // completes, in which case the background serializer will use the // `seed_info_.data` set at the last call of this function. - seed_info_.data = seed_data; - seed_info_.signature = signature; + seed_info_.data = seed_info.compressed_seed_data; + seed_info_.signature = seed_info.signature; + seed_info_.milestone = seed_info.milestone; // `seed_writer_` will eventually call // GetSerializedDataProducerForBackgroundSequence() on *this* object to get // a callback that will be run asynchronously. This callback will be used to @@ -212,11 +214,35 @@ // TODO(crbug.com/380465790): Seed-related info that has not yet been migrated // to seed files must continue to be maintained in local state. Once the // migration is complete, stop updating local state. - if (signature.empty()) { - local_state_->ClearPref(fields_prefs_->signature); - } else { - local_state_->SetString(fields_prefs_->signature, signature); - } + local_state_->SetString(fields_prefs_->signature, seed_info_.signature); + local_state_->SetInteger(fields_prefs_->milestone, seed_info_.milestone); +} + +void SeedReaderWriter::ScheduleSeedFileClear() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Set `seed_info_.data`, this will be used later by the background + // serialization and can be changed multiple times before a scheduled write + // completes, in which case the background serializer will use the + // `seed_info_.data` set at the last call of this function. + seed_info_ = { + .data = "", + .signature = "", + .milestone = 0, + }; + // `seed_writer_` will eventually call + // GetSerializedDataProducerForBackgroundSequence() on *this* object to get + // a callback that will be run asynchronously. This callback will be used to + // call the DoSerialize() function which will return the seed data to write + // to the file. This write will also be asynchronous and on a different + // thread. Note that it is okay to call this while a write is already + // occurring in a background thread and that this will result in a new write + // being scheduled. + seed_writer_->ScheduleWriteWithBackgroundDataSerializer(this); + // TODO(crbug.com/380465790): Seed-related info that has not yet been migrated + // to seed files must continue to be maintained in local state. Once the + // migration is complete, stop updating local state. + local_state_->ClearPref(fields_prefs_->signature); + local_state_->ClearPref(fields_prefs_->milestone); } void SeedReaderWriter::DeleteSeedFile() { @@ -237,9 +263,10 @@ if (success) { seed_info_.data = std::move(seed_file_data); - // TODO(crbug.com/380465790): Read signature from the seed file once it's - // stored there. + // TODO(crbug.com/380465790): Read other SeedInfo fields from the seed file + // once it's stored there. seed_info_.signature = local_state_->GetString(fields_prefs_->signature); + seed_info_.milestone = local_state_->GetInteger(fields_prefs_->milestone); } else { // Export seed data from Local State to a seed file in the following cases. // 1. Seed file does not exist because this is the first run. For Windows, @@ -251,8 +278,11 @@ std::string decoded_data; if (base::Base64Decode(local_state_->GetString(fields_prefs_->seed), &decoded_data)) { - ScheduleSeedFileWrite(decoded_data, - local_state_->GetString(fields_prefs_->signature)); + ScheduleSeedFileWrite(ValidatedSeedInfo{ + .compressed_seed_data = decoded_data, + .signature = local_state_->GetString(fields_prefs_->signature), + .milestone = local_state_->GetInteger(fields_prefs_->milestone), + }); // Record whether empty data is written to the seed file. This can happen // in the following cases. @@ -280,12 +310,11 @@ local_state_->ClearPref(fields_prefs_->seed); } -void SeedReaderWriter::ScheduleLocalStateWrite( - std::string_view base64_seed_data, - std::string_view signature) { +void SeedReaderWriter::ScheduleLocalStateWrite(ValidatedSeedInfo seed_info) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - local_state_->SetString(fields_prefs_->seed, base64_seed_data); - local_state_->SetString(fields_prefs_->signature, signature); + local_state_->SetString(fields_prefs_->seed, seed_info.base64_seed_data); + local_state_->SetString(fields_prefs_->signature, seed_info.signature); + local_state_->SetInteger(fields_prefs_->milestone, seed_info.milestone); } bool SeedReaderWriter::ShouldUseSeedFile() const {
diff --git a/components/variations/seed_reader_writer.h b/components/variations/seed_reader_writer.h index d89308a2..73d9ed3 100644 --- a/components/variations/seed_reader_writer.h +++ b/components/variations/seed_reader_writer.h
@@ -42,20 +42,23 @@ StorageFormat storage_format; std::string_view data; std::string_view signature; + int milestone = 0; }; -// TODO(crbug.com/380465790): Represents the seed and other related info. -// This info will be stored together in the SeedFile. Once all the seed-related -// info is stored in the struct, change it to a proto and use it to serialize -// and deserialize the data. -struct SeedInfo { - std::string data; - std::string signature; +// Groups the data from a seed and other seed-related info that is validated +// and ready to be stored in a seed file or local state. This struct is passed +// by value, so it must be copyable and lightweight. +struct ValidatedSeedInfo { + std::string_view compressed_seed_data; + std::string_view base64_seed_data; + std::string_view signature; + int milestone = 0; }; struct SeedFieldsPrefs { const char* seed; const char* signature; + const char* milestone; }; COMPONENT_EXPORT(VARIATIONS) @@ -99,9 +102,7 @@ // clients (see ShouldUseSeedFile()) and schedules a write of // `base64_seed_data` to local state for all other clients. Also stores other // seed-related info. - void StoreValidatedSeedInfo(std::string_view compressed_seed_data, - std::string_view base64_seed_data, - std::string_view signature); + void StoreValidatedSeedInfo(ValidatedSeedInfo seed_info); // Clears seed data and other seed-related info by overwriting it with an // empty string. @@ -115,14 +116,28 @@ void SetTimerForTesting(base::OneShotTimer* timer_override); private: + // TODO(crbug.com/380465790): Represents the seed and other related info. + // This info will be stored together in the SeedFile. Once all the + // seed-related info is stored in the struct, change it to a proto and use it + // to serialize and deserialize the data. + struct SeedInfo { + std::string data; + std::string signature; + int milestone = 0; + }; + // Returns the serialized data to be written to disk. This is done // asynchronously during the write process. base::ImportantFileWriter::BackgroundDataProducerCallback GetSerializedDataProducerForBackgroundSequence() override; - // Schedules `seed_info` to be written using `seed_writer_`. - void ScheduleSeedFileWrite(std::string_view seed_data, - std::string_view signature); + // Schedules `seed_info` to be written using `seed_writer_`. Fields with + // zero/empty values will be ignored. If you want to clear the seed file, use + // ScheduleSeedFileClear() instead. + void ScheduleSeedFileWrite(ValidatedSeedInfo seed_info); + + // Schedules `seed_info` to be cleared using `seed_writer_`. + void ScheduleSeedFileClear(); // Schedules the deletion of a seed file. void DeleteSeedFile(); @@ -134,9 +149,10 @@ // in `local state_`, additionally clears it. void ReadSeedFile(); - // Schedules a write of `base64_seed_data` to `local_state_`. - void ScheduleLocalStateWrite(std::string_view base64_seed_data, - std::string_view signature); + // Schedules a write of `base64_seed_data` to `local_state_`. Fields with + // zero/empty values will be ignored. If you want to clear the seed file, use + // ScheduleSeedFileClear() instead. + void ScheduleLocalStateWrite(ValidatedSeedInfo seed_info); // Returns true if a seed file should be used. bool ShouldUseSeedFile() const;
diff --git a/components/variations/seed_reader_writer_unittest.cc b/components/variations/seed_reader_writer_unittest.cc index 146f685..8d0aca3e 100644 --- a/components/variations/seed_reader_writer_unittest.cc +++ b/components/variations/seed_reader_writer_unittest.cc
@@ -234,7 +234,10 @@ const std::string base64_compressed_seed = base::Base64Encode(compressed_seed); seed_reader_writer.StoreValidatedSeedInfo( - compressed_seed, base64_compressed_seed, "signature"); + ValidatedSeedInfo{.compressed_seed_data = compressed_seed, + .base64_seed_data = base64_compressed_seed, + .signature = "signature", + .milestone = 2}); // Force write. timer_.Fire(); @@ -387,7 +390,10 @@ const std::string base64_compressed_seed = base::Base64Encode(compressed_seed); seed_reader_writer.StoreValidatedSeedInfo( - compressed_seed, base64_compressed_seed, "signature"); + ValidatedSeedInfo{.compressed_seed_data = compressed_seed, + .base64_seed_data = base64_compressed_seed, + .signature = "signature", + .milestone = 2}); // Ensure there's no pending write. EXPECT_FALSE(timer_.IsRunning()); @@ -475,7 +481,10 @@ const std::string base64_compressed_seed = base::Base64Encode(compressed_seed); seed_reader_writer.StoreValidatedSeedInfo( - compressed_seed, base64_compressed_seed, "signature"); + ValidatedSeedInfo{.compressed_seed_data = compressed_seed, + .base64_seed_data = base64_compressed_seed, + .signature = "signature", + .milestone = 2}); // Ensure there's no pending write. EXPECT_FALSE(timer_.IsRunning());
diff --git a/components/variations/variations_safe_seed_store.h b/components/variations/variations_safe_seed_store.h index 2dd4ae8c..f503a762 100644 --- a/components/variations/variations_safe_seed_store.h +++ b/components/variations/variations_safe_seed_store.h
@@ -29,9 +29,8 @@ virtual base::Time GetFetchTime() const = 0; virtual void SetFetchTime(const base::Time& fetch_time) = 0; - // Getter and setter for the milestone that was used for the safe seed. + // Getter for the milestone that was used for the safe seed. virtual int GetMilestone() const = 0; - virtual void SetMilestone(int milestone) = 0; // Getter and setter for the last server-provided safe seed date of when the // seed to be used was fetched. (See GetTimeForStudyDateChecks.) @@ -40,9 +39,7 @@ // Getter and setter for the compressed and base64-encoded safe seed. virtual StoredSeed GetCompressedSeed() const = 0; - virtual void SetCompressedSeed(const std::string& safe_compressed, - const std::string& base64_safe_compressed, - const std::string& signature) = 0; + virtual void SetCompressedSeed(ValidatedSeedInfo seed_info) = 0; // Getter and setter for the locale associated with the safe seed in the // underlying storage.
diff --git a/components/variations/variations_safe_seed_store_local_state.cc b/components/variations/variations_safe_seed_store_local_state.cc index 7e2dcfb..4265e64a 100644 --- a/components/variations/variations_safe_seed_store_local_state.cc +++ b/components/variations/variations_safe_seed_store_local_state.cc
@@ -46,11 +46,7 @@ } int VariationsSafeSeedStoreLocalState::GetMilestone() const { - return local_state_->GetInteger(prefs::kVariationsSafeSeedMilestone); -} - -void VariationsSafeSeedStoreLocalState::SetMilestone(int milestone) { - local_state_->SetInteger(prefs::kVariationsSafeSeedMilestone, milestone); + return seed_reader_writer_->GetSeedData().milestone; } base::Time VariationsSafeSeedStoreLocalState::GetTimeForStudyDateChecks() @@ -68,11 +64,8 @@ } void VariationsSafeSeedStoreLocalState::SetCompressedSeed( - const std::string& safe_compressed, - const std::string& base64_safe_compressed, - const std::string& signature) { - seed_reader_writer_->StoreValidatedSeedInfo(safe_compressed, - base64_safe_compressed, signature); + ValidatedSeedInfo seed_info) { + seed_reader_writer_->StoreValidatedSeedInfo(seed_info); } std::string VariationsSafeSeedStoreLocalState::GetLocale() const { @@ -123,7 +116,6 @@ local_state_->ClearPref(prefs::kVariationsSafeSeedDate); local_state_->ClearPref(prefs::kVariationsSafeSeedFetchTime); local_state_->ClearPref(prefs::kVariationsSafeSeedLocale); - local_state_->ClearPref(prefs::kVariationsSafeSeedMilestone); local_state_->ClearPref( prefs::kVariationsSafeSeedPermanentConsistencyCountry); local_state_->ClearPref(prefs::kVariationsSafeSeedSessionConsistencyCountry);
diff --git a/components/variations/variations_safe_seed_store_local_state.h b/components/variations/variations_safe_seed_store_local_state.h index 18eb3baa..55fc94ae 100644 --- a/components/variations/variations_safe_seed_store_local_state.h +++ b/components/variations/variations_safe_seed_store_local_state.h
@@ -50,15 +50,12 @@ void SetFetchTime(const base::Time& fetch_time) override; int GetMilestone() const override; - void SetMilestone(int milestone) override; base::Time GetTimeForStudyDateChecks() const override; void SetTimeForStudyDateChecks(const base::Time& safe_seed_time) override; StoredSeed GetCompressedSeed() const override; - void SetCompressedSeed(const std::string& safe_compressed, - const std::string& base64_safe_compressed, - const std::string& signature) override; + void SetCompressedSeed(ValidatedSeedInfo seed_info) override; std::string GetLocale() const override; void SetLocale(const std::string& locale) override;
diff --git a/components/variations/variations_seed_store.cc b/components/variations/variations_seed_store.cc index 3ae9f91..c283c8e 100644 --- a/components/variations/variations_seed_store.cc +++ b/components/variations/variations_seed_store.cc
@@ -324,7 +324,7 @@ } int VariationsSeedStore::GetLatestMilestone() const { - return local_state_->GetInteger(prefs::kVariationsSeedMilestone); + return seed_reader_writer_->GetSeedData().milestone; } int VariationsSeedStore::GetSafeSeedMilestone() const { @@ -727,20 +727,24 @@ if (!country_code.empty()) local_state_->SetString(prefs::kVariationsCountry, country_code); - int milestone; - if (base::StringToInt(version_info::GetMajorVersionNumber(), &milestone)) - local_state_->SetInteger(prefs::kVariationsSeedMilestone, milestone); + int milestone = version_info::GetMajorVersionNumberAsInt(); // As a space optimization, store an alias to the safe seed if the contents // are identical. if (seed.MatchesStoredSeed(safe_seed_store_->GetCompressedSeed())) { - seed_reader_writer_->StoreValidatedSeedInfo(kIdenticalToSafeSeedSentinel, - kIdenticalToSafeSeedSentinel, - seed.base64_seed_signature); + seed_reader_writer_->StoreValidatedSeedInfo(ValidatedSeedInfo{ + .compressed_seed_data = kIdenticalToSafeSeedSentinel, + .base64_seed_data = kIdenticalToSafeSeedSentinel, + .signature = seed.base64_seed_signature, + .milestone = milestone, + }); } else { - seed_reader_writer_->StoreValidatedSeedInfo(seed.compressed_seed_data, - seed.base64_seed_data, - seed.base64_seed_signature); + seed_reader_writer_->StoreValidatedSeedInfo(ValidatedSeedInfo{ + .compressed_seed_data = seed.compressed_seed_data, + .base64_seed_data = seed.base64_seed_data, + .signature = seed.base64_seed_signature, + .milestone = milestone, + }); } UpdateSeedDateAndLogDayChange(date_fetched); latest_serial_number_ = seed.parsed.serial_number(); @@ -752,52 +756,45 @@ const ClientFilterableState& client_state, base::Time seed_fetch_time) { const StoredSeed previous_safe_seed = safe_seed_store_->GetCompressedSeed(); - // Avoid overwriting the previous safe seed with an identical copy, which - // would be an expensive no-op. This can happen as follows: + // Before updating the safe seed, update the latest seed if the latest + // seed's value is |kIdenticalToSafeSeedSentinel|. // - // 1. The client has safe seed A and latest seed B and is applying B. - // 2. The client attempts to fetch a seed, receives a 304 Not Modified - // response from the variations server, and promotes B to safe seed. Note - // that B is both the safe seed and the latest seed. - // 3. The client attempts to fetch another seed and receives another 304 - // response. In this case, the below condition is false and an unnecessary - // write is avoided. - if (!seed.MatchesStoredSeed(previous_safe_seed)) { - // Before updating the safe seed, update the latest seed if the latest - // seed's value is |kIdenticalToSafeSeedSentinel|. + // It's theoretically possible for the client to be in the following state: + // 1. The client has safe seed A. + // 2. The client is applying seed B. In other words, seed B was the latest + // seed when Chrome was started. + // 3. The client has just successfully fetched a new latest seed that + // happens to be seed A—perhaps due to a rollback. In this case, + // |kIdenticalToSafeSeedSentinel| is stored as the latest seed value to + // avoid duplicating seed A in storage. + // 4. The client is promoting seed B to safe seed. + auto latest_seed = seed_reader_writer_->GetSeedData(); + if (!seed.MatchesStoredSeed(previous_safe_seed) && + latest_seed.data == kIdenticalToSafeSeedSentinel) { + // For the below call to StoreValidatedSeed(), there are two possibilities + // to consider: // - // It's theoretically possible for the client to be in the following state: - // 1. The client has safe seed A. - // 2. The client is applying seed B. In other words, seed B was the latest - // seed when Chrome was started. - // 3. The client has just successfully fetched a new latest seed that - // happens to be seed A—perhaps due to a rollback. In this case, - // |kIdenticalToSafeSeedSentinel| is stored as the latest seed value to - // avoid duplicating seed A in storage. - // 4. The client is promoting seed B to safe seed. - if (seed_reader_writer_->GetSeedData().data == - kIdenticalToSafeSeedSentinel) { - // For the below call to StoreValidatedSeed(), there are two possibilities - // to consider: - // - // 1. The client is in the SeedFile experiment's treatment group. In this - // case, StoreValidatedSeedInfo() updates the seed file and ignores the - // local state seed. - // 2. The client is either not in the experiment or is in its control or - // default group. In this case, |previous_safe_seed.data| is ignored. - seed_reader_writer_->StoreValidatedSeedInfo( - previous_safe_seed.data, - local_state_->GetString(prefs::kVariationsSafeCompressedSeed), - previous_safe_seed.signature); - } - safe_seed_store_->SetCompressedSeed(seed.compressed_seed_data, - seed.base64_seed_data, - seed.base64_seed_signature); + // 1. The client is in the SeedFile experiment's treatment group. In this + // case, StoreValidatedSeedInfo() updates the seed file and ignores the + // local state seed. + // 2. The client is either not in the experiment or is in its control or + // default group. In this case, |previous_safe_seed.data| is ignored. + seed_reader_writer_->StoreValidatedSeedInfo(ValidatedSeedInfo{ + .compressed_seed_data = previous_safe_seed.data, + .base64_seed_data = + local_state_->GetString(prefs::kVariationsSafeCompressedSeed), + .signature = latest_seed.signature, + .milestone = latest_seed.milestone}); } + safe_seed_store_->SetCompressedSeed( + ValidatedSeedInfo{.compressed_seed_data = seed.compressed_seed_data, + .base64_seed_data = seed.base64_seed_data, + .signature = seed.base64_seed_signature, + .milestone = seed_milestone}); + safe_seed_store_->SetTimeForStudyDateChecks(client_state.reference_date); safe_seed_store_->SetLocale(client_state.locale); - safe_seed_store_->SetMilestone(seed_milestone); safe_seed_store_->SetPermanentConsistencyCountry( client_state.permanent_consistency_country); safe_seed_store_->SetSessionConsistencyCountry( @@ -806,9 +803,11 @@ // As a space optimization, overwrite the stored latest seed data with an // alias to the safe seed, if they are identical. if (seed.MatchesStoredSeed(seed_reader_writer_->GetSeedData())) { - seed_reader_writer_->StoreValidatedSeedInfo(kIdenticalToSafeSeedSentinel, - kIdenticalToSafeSeedSentinel, - seed.base64_seed_signature); + seed_reader_writer_->StoreValidatedSeedInfo( + ValidatedSeedInfo{.compressed_seed_data = kIdenticalToSafeSeedSentinel, + .base64_seed_data = kIdenticalToSafeSeedSentinel, + .signature = latest_seed.signature, + .milestone = latest_seed.milestone}); // Moreover, in this case, the last fetch time for the safe seed should // match the latest seed's.
diff --git a/components/variations/variations_seed_store_unittest.cc b/components/variations/variations_seed_store_unittest.cc index 1e3aca91..79e5e4a 100644 --- a/components/variations/variations_seed_store_unittest.cc +++ b/components/variations/variations_seed_store_unittest.cc
@@ -237,8 +237,12 @@ // seed OR the seed-file-based seed depending on the seed file trial group to // which the client belongs. seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - /*compressed_seed_data=*/"coffee", - /*base64_seed_data=*/"coffee", /*signature=*/"tea"); + ValidatedSeedInfo{ + .compressed_seed_data = "coffee", + .base64_seed_data = "coffee", + .signature = "tea", + .milestone = 1, + }); prefs->SetTime(prefs::kVariationsLastFetchTime, now); prefs->SetTime(prefs::kVariationsSeedDate, now - delta * 1); @@ -246,12 +250,15 @@ // seed OR the seed-file-based seed depending on the seed file trial group to // which the client belongs. seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - /*compressed_seed_data=*/"ketchup", - /*base64_seed_data=*/"ketchup", /*signature=*/"mustard"); + ValidatedSeedInfo{ + .compressed_seed_data = "ketchup", + .base64_seed_data = "ketchup", + .signature = "mustard", + .milestone = 90, + }); prefs->SetTime(prefs::kVariationsSafeSeedDate, now - delta * 2); prefs->SetTime(prefs::kVariationsSafeSeedFetchTime, now - delta * 3); prefs->SetString(prefs::kVariationsSafeSeedLocale, "en-MX"); - prefs->SetInteger(prefs::kVariationsSafeSeedMilestone, 90); prefs->SetString(prefs::kVariationsSafeSeedPermanentConsistencyCountry, "mx"); prefs->SetString(prefs::kVariationsSafeSeedSessionConsistencyCountry, "gt"); } @@ -264,15 +271,16 @@ void CheckRegularSeedAndSeedPrefsAreSet(const TestingPrefServiceSimple& prefs, TestVariationsSeedStore& seed_store) { - EXPECT_THAT(seed_store.GetSeedReaderWriterForTesting()->GetSeedData().data, - Not(IsEmpty())); - EXPECT_THAT( - seed_store.GetSeedReaderWriterForTesting()->GetSeedData().signature, - Not(IsEmpty())); + StoredSeed stored_seed = + seed_store.GetSeedReaderWriterForTesting()->GetSeedData(); + EXPECT_THAT(stored_seed.data, Not(IsEmpty())); + EXPECT_THAT(stored_seed.signature, Not(IsEmpty())); + EXPECT_NE(stored_seed.milestone, 0); if (ShouldUseLocalStateSeed()) { EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed)); - EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature)); } + EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature)); + EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedMilestone)); EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsLastFetchTime)); EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate)); } @@ -280,37 +288,37 @@ void CheckRegularSeedAndSeedPrefsAreCleared( const TestingPrefServiceSimple& prefs, TestVariationsSeedStore& seed_store) { - EXPECT_THAT(seed_store.GetSeedReaderWriterForTesting()->GetSeedData().data, - IsEmpty()); - EXPECT_THAT( - seed_store.GetSeedReaderWriterForTesting()->GetSeedData().signature, - IsEmpty()); + StoredSeed stored_seed = + seed_store.GetSeedReaderWriterForTesting()->GetSeedData(); + EXPECT_THAT(stored_seed.data, IsEmpty()); + EXPECT_THAT(stored_seed.signature, IsEmpty()); + EXPECT_EQ(stored_seed.milestone, 0); if (ShouldUseLocalStateSeed()) { EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsCompressedSeed)); - EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature)); } + EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedSignature)); + EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedMilestone)); EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsLastFetchTime)); EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSeedDate)); } void CheckSafeSeedAndSeedPrefsAreSet(const TestingPrefServiceSimple& prefs, TestVariationsSeedStore& seed_store) { - EXPECT_THAT( - seed_store.GetSafeSeedReaderWriterForTesting()->GetSeedData().data, - Not(IsEmpty())); - EXPECT_THAT( - seed_store.GetSafeSeedReaderWriterForTesting()->GetSeedData().signature, - Not(IsEmpty())); + StoredSeed stored_seed = + seed_store.GetSafeSeedReaderWriterForTesting()->GetSeedData(); + EXPECT_THAT(stored_seed.data, Not(IsEmpty())); + EXPECT_THAT(stored_seed.signature, Not(IsEmpty())); + EXPECT_NE(stored_seed.milestone, 0); if (ShouldUseLocalStateSeed()) { EXPECT_FALSE( PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed)); - EXPECT_FALSE( - PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature)); } + EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature)); + EXPECT_FALSE( + PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedMilestone)); EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate)); EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedFetchTime)); EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale)); - EXPECT_FALSE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedMilestone)); EXPECT_FALSE(PrefHasDefaultValue( prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry)); EXPECT_FALSE(PrefHasDefaultValue( @@ -319,22 +327,21 @@ void CheckSafeSeedAndSeedPrefsAreCleared(const TestingPrefServiceSimple& prefs, TestVariationsSeedStore& seed_store) { - EXPECT_THAT( - seed_store.GetSafeSeedReaderWriterForTesting()->GetSeedData().data, - IsEmpty()); - EXPECT_THAT( - seed_store.GetSafeSeedReaderWriterForTesting()->GetSeedData().signature, - IsEmpty()); + StoredSeed stored_seed = + seed_store.GetSafeSeedReaderWriterForTesting()->GetSeedData(); + EXPECT_THAT(stored_seed.data, IsEmpty()); + EXPECT_THAT(stored_seed.signature, IsEmpty()); + EXPECT_EQ(stored_seed.milestone, 0); if (ShouldUseLocalStateSeed()) { EXPECT_TRUE( PrefHasDefaultValue(prefs, prefs::kVariationsSafeCompressedSeed)); - EXPECT_TRUE( - PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature)); } + EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedSignature)); + EXPECT_TRUE( + PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedMilestone)); EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedDate)); EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedFetchTime)); EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedLocale)); - EXPECT_TRUE(PrefHasDefaultValue(prefs, prefs::kVariationsSafeSeedMilestone)); EXPECT_TRUE(PrefHasDefaultValue( prefs, prefs::kVariationsSafeSeedPermanentConsistencyCountry)); EXPECT_TRUE(PrefHasDefaultValue( @@ -416,7 +423,12 @@ std::string compressed_seed_data = Gzip(SerializeSeed(seed)); std::string base64_seed_data = SerializeSeedBase64(seed); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_seed_data, base64_seed_data, test_signature); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_seed_data, + .base64_seed_data = base64_seed_data, + .signature = test_signature, + .milestone = 1, + }); } std::string seed_data_; @@ -438,7 +450,12 @@ TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath()); ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_seed, base64_seed, base64_seed_signature); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_seed, + .base64_seed_data = base64_seed, + .signature = base64_seed_signature, + .milestone = 1, + }); const std::string expected_seed = GetParam() == kSeedFilesGroup ? compressed_seed : base64_seed; @@ -476,8 +493,10 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); SetAllSeedsAndSeedPrefsToNonDefaultValues(&prefs_, seed_store); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(seed_data), GzipAndBase64Encode(seed_data), - "a deeply compromised signature."); + ValidatedSeedInfo{.compressed_seed_data = Gzip(seed_data), + .base64_seed_data = GzipAndBase64Encode(seed_data), + .signature = "a deeply compromised signature.", + .milestone = 1}); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -500,9 +519,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); SetAllSeedsAndSeedPrefsToNonDefaultValues(&prefs_, seed_store); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip("Not a proto"), GzipAndBase64Encode("Not a proto"), - "ignored signature"); - + ValidatedSeedInfo{ + .compressed_seed_data = Gzip("Not a proto"), + .base64_seed_data = GzipAndBase64Encode("Not a proto"), + .signature = "ignored signature", + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; std::string loaded_seed_data; @@ -527,7 +549,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); SetAllSeedsAndSeedPrefsToNonDefaultValues(&prefs_, seed_store); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(seed_data), GzipAndBase64Encode(seed_data), /*signature=*/""); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(seed_data), + .base64_seed_data = GzipAndBase64Encode(seed_data), + .signature = "", + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -557,7 +584,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); SetAllSeedsAndSeedPrefsToNonDefaultValues(&prefs_, seed_store); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(seed_data), GzipAndBase64Encode(seed_data), /*signature=*/""); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(seed_data), + .base64_seed_data = GzipAndBase64Encode(seed_data), + .signature = "", + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -574,9 +606,12 @@ EXPECT_THAT( seed_store.GetSeedReaderWriterForTesting()->GetSeedData().signature, IsEmpty()); + EXPECT_NE(seed_store.GetSeedReaderWriterForTesting()->GetSeedData().milestone, + 0); if (ShouldUseLocalStateSeed()) { EXPECT_FALSE(PrefHasDefaultValue(prefs_, prefs::kVariationsCompressedSeed)); EXPECT_FALSE(PrefHasDefaultValue(prefs_, prefs::kVariationsSeedSignature)); + EXPECT_FALSE(PrefHasDefaultValue(prefs_, prefs::kVariationsSeedMilestone)); } EXPECT_FALSE(PrefHasDefaultValue(prefs_, prefs::kVariationsLastFetchTime)); EXPECT_FALSE(PrefHasDefaultValue(prefs_, prefs::kVariationsSeedDate)); @@ -611,10 +646,19 @@ TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath()); ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - kIdenticalToSafeSeedSentinel, kIdenticalToSafeSeedSentinel, - base64_seed_signature); + ValidatedSeedInfo{ + .compressed_seed_data = kIdenticalToSafeSeedSentinel, + .base64_seed_data = kIdenticalToSafeSeedSentinel, + .signature = base64_seed_signature, + .milestone = 2, + }); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(seed_data), GzipAndBase64Encode(seed_data), base64_seed_signature); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(seed_data), + .base64_seed_data = GzipAndBase64Encode(seed_data), + .signature = base64_seed_signature, + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -644,8 +688,12 @@ compressed_seed[5] ^= 0xFF; compressed_seed[10] ^= 0xFF; seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_seed, base::Base64Encode(compressed_seed), - "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_seed, + .base64_seed_data = base::Base64Encode(compressed_seed), + .signature = "ignored signature", + .milestone = 1, + }); base::HistogramTester histogram_tester; ASSERT_FALSE(MakeSeedStoreLoadStoredSeed(seed_store)); @@ -665,8 +713,12 @@ // 51MiB of uncompressed data to exceed 50MiB limit. const std::string compressed_seed = Gzip(std::string(51 * 1024 * 1024, 'A')); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_seed, base::Base64Encode(compressed_seed), - "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_seed, + .base64_seed_data = base::Base64Encode(compressed_seed), + .signature = "ignored signature", + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -698,7 +750,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); SetAllSeedsAndSeedPrefsToNonDefaultValues(&prefs_, seed_store); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - "invalid seed data", "invalid seed data", "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = "invalid seed data", + .base64_seed_data = "invalid seed data", + .signature = "ignored signature", + .milestone = 1, + }); base::HistogramTester histogram_tester; ASSERT_FALSE(MakeSeedStoreLoadStoredSeed(seed_store)); @@ -926,8 +983,13 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam().field_trial_group); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(kSeedDeltaTestData.GetInitialSeedData()), - kSeedDeltaTestData.GetInitialSeedDataAsPrefValue(), "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(kSeedDeltaTestData.GetInitialSeedData()), + .base64_seed_data = + kSeedDeltaTestData.GetInitialSeedDataAsPrefValue(), + .signature = "ignored signature", + .milestone = 1, + }); ASSERT_TRUE(StoreSeedData(seed_store, kSeedDeltaTestData.GetDeltaData(), {.is_delta_compressed = true})); @@ -939,8 +1001,13 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam().field_trial_group); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(kSeedDeltaTestData.GetInitialSeedData()), - kSeedDeltaTestData.GetInitialSeedDataAsPrefValue(), "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(kSeedDeltaTestData.GetInitialSeedData()), + .base64_seed_data = + kSeedDeltaTestData.GetInitialSeedDataAsPrefValue(), + .signature = "ignored signature", + .milestone = 1, + }); ASSERT_TRUE(StoreSeedData(seed_store, Gzip(kSeedDeltaTestData.GetDeltaData()), { @@ -969,8 +1036,13 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam().field_trial_group); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(kSeedDeltaTestData.GetInitialSeedData()), - kSeedDeltaTestData.GetInitialSeedDataAsPrefValue(), "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(kSeedDeltaTestData.GetInitialSeedData()), + .base64_seed_data = + kSeedDeltaTestData.GetInitialSeedDataAsPrefValue(), + .signature = "ignored signature", + .milestone = 1, + }); store_success_ = true; // Provide a gzipped delta, when gzip is not expected. @@ -986,8 +1058,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam().field_trial_group); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(serialized_seed), GzipAndBase64Encode(serialized_seed), - "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(serialized_seed), + .base64_seed_data = GzipAndBase64Encode(serialized_seed), + .signature = "ignored signature", + .milestone = 1, + }); ASSERT_TRUE(StoreSeedData(seed_store, serialized_seed)); // Verify that the pref has a sentinel value, rather than the full string. @@ -1021,8 +1097,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam().field_trial_group); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(seed_data), GzipAndBase64Encode(seed_data), - "a completely ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(seed_data), + .base64_seed_data = GzipAndBase64Encode(seed_data), + .signature = "a completely ignored signature", + .milestone = 1, + }); EXPECT_EQ("123", seed_store.GetLatestSerialNumber()); VariationsSeed new_seed = CreateTestSeed(); @@ -1063,7 +1143,12 @@ TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath()); ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_seed, base64_seed, "a test signature, ignored."); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_seed, + .base64_seed_data = base64_seed, + .signature = "a test signature, ignored.", + .milestone = 1, + }); prefs_.SetTime(prefs::kVariationsSafeSeedDate, reference_date); prefs_.SetTime(prefs::kVariationsSafeSeedFetchTime, reference_date - base::Days(3)); @@ -1123,8 +1208,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); SetAllSeedsAndSeedPrefsToNonDefaultValues(&prefs_, seed_store); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(seed_data), GzipAndBase64Encode((seed_data)), - "a deeply compromised signature."); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(seed_data), + .base64_seed_data = GzipAndBase64Encode(seed_data), + .signature = "a deeply compromised signature.", + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -1180,8 +1269,12 @@ compressed_seed[5] ^= 0xFF; compressed_seed[10] ^= 0xFF; seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_seed, base::Base64Encode(compressed_seed), - "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_seed, + .base64_seed_data = base::Base64Encode(compressed_seed), + .signature = "ignored signature", + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -1216,8 +1309,12 @@ // 51MiB of uncompressed data to exceed 50MiB limit. const std::string compressed_seed = Gzip(std::string(51 * 1024 * 1024, 'A')); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_seed, base::Base64Encode(compressed_seed), - "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_seed, + .base64_seed_data = base::Base64Encode(compressed_seed), + .signature = "ignored signature", + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -1259,7 +1356,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); SetAllSeedsAndSeedPrefsToNonDefaultValues(&prefs_, seed_store); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - "invalid seed data", "invalid seed data", "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = "invalid seed data", + .base64_seed_data = "invalid seed data", + .signature = "ignored signature", + .milestone = 1, + }); base::HistogramTester histogram_tester; VariationsSeed loaded_seed; @@ -1552,10 +1654,19 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam().field_trial_group); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_old_seed, base64_old_seed, "a completely ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_old_seed, + .base64_seed_data = base64_old_seed, + .signature = "a completely ignored signature", + .milestone = 1, + }); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - kIdenticalToSafeSeedSentinel, kIdenticalToSafeSeedSentinel, - "a completely ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = kIdenticalToSafeSeedSentinel, + .base64_seed_data = kIdenticalToSafeSeedSentinel, + .signature = "a completely ignored signature", + .milestone = 2, + }); base::HistogramTester histogram_tester; ASSERT_TRUE(seed_store.StoreSafeSeed( new_seed_data, "a completely ignored signature", @@ -1688,10 +1799,19 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam().field_trial_group); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_old_seed, base64_old_seed, "a completely ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_old_seed, + .base64_seed_data = base64_old_seed, + .signature = "a completely ignored signature", + .milestone = 1, + }); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - kIdenticalToSafeSeedSentinel, kIdenticalToSafeSeedSentinel, - "a completely ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = kIdenticalToSafeSeedSentinel, + .base64_seed_data = kIdenticalToSafeSeedSentinel, + .signature = "a completely ignored signature", + .milestone = 2, + }); base::HistogramTester histogram_tester; ASSERT_TRUE(seed_store.StoreSafeSeed( new_seed_data, "a completely ignored signature", @@ -1753,7 +1873,12 @@ ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam().field_trial_group); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - compressed_seed, base64_seed, "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = compressed_seed, + .base64_seed_data = base64_seed, + .signature = "ignored signature", + .milestone = 92, + }); prefs_.SetTime(prefs::kVariationsLastFetchTime, last_fetch_time); const std::string expected_seed = GetParam().field_trial_group == kSeedFilesGroup ? compressed_seed @@ -1902,9 +2027,19 @@ TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath()); ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - "one", "one", "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = "one", + .base64_seed_data = "one", + .signature = "ignored signature", + .milestone = 1, + }); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - "not one", "not one", "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = "not one", + .base64_seed_data = "not one", + .signature = "ignored signature", + .milestone = 2, + }); prefs_.SetTime(prefs::kVariationsLastFetchTime, WrapTime(1)); prefs_.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(0)); seed_store.RecordLastFetchTime(WrapTime(11)); @@ -1924,10 +2059,19 @@ TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath()); ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - kIdenticalToSafeSeedSentinel, kIdenticalToSafeSeedSentinel, - "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = kIdenticalToSafeSeedSentinel, + .base64_seed_data = kIdenticalToSafeSeedSentinel, + .signature = "ignored signature", + .milestone = 1, + }); seed_store.GetSafeSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - "some seed", "some seed", "ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = "some seed", + .base64_seed_data = "some seed", + .signature = "ignored signature", + .milestone = 1, + }); prefs_.SetTime(prefs::kVariationsLastFetchTime, WrapTime(1)); prefs_.SetTime(prefs::kVariationsSafeSeedFetchTime, WrapTime(0)); seed_store.RecordLastFetchTime(WrapTime(11)); @@ -1951,8 +2095,12 @@ TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath()); ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - Gzip(seed_data), GzipAndBase64Encode(seed_data), - "a completely ignored signature"); + ValidatedSeedInfo{ + .compressed_seed_data = Gzip(seed_data), + .base64_seed_data = GzipAndBase64Encode(seed_data), + .signature = "a completely ignored signature", + .milestone = 1, + }); EXPECT_EQ("123", seed_store.GetLatestSerialNumber()); } @@ -1964,7 +2112,12 @@ TestVariationsSeedStore seed_store(&prefs_, temp_dir_.GetPath()); ASSERT_EQ(base::FieldTrialList::FindFullName(kSeedFileTrial), GetParam()); seed_store.GetSeedReaderWriterForTesting()->StoreValidatedSeedInfo( - "invalid seed data", "invalid seed data", "an unused signature"); + ValidatedSeedInfo{ + .compressed_seed_data = "invalid seed data", + .base64_seed_data = "invalid seed data", + .signature = "an unused signature", + .milestone = 1, + }); EXPECT_EQ(std::string(), seed_store.GetLatestSerialNumber()); EXPECT_TRUE(PrefHasDefaultValue(prefs_, prefs::kVariationsCompressedSeed)); EXPECT_THAT(seed_store.GetSeedReaderWriterForTesting()->GetSeedData().data,
diff --git a/components/visited_url_ranking/internal/url_grouping/group_suggestions_manager.cc b/components/visited_url_ranking/internal/url_grouping/group_suggestions_manager.cc index 1c4c065..1fe8743d 100644 --- a/components/visited_url_ranking/internal/url_grouping/group_suggestions_manager.cc +++ b/components/visited_url_ranking/internal/url_grouping/group_suggestions_manager.cc
@@ -298,6 +298,7 @@ const std::vector<scoped_refptr<segmentation_platform::InputContext>>& inputs, GroupSuggestionsDelegate::UserResponseMetadata user_response) { + RecordSuggestionUKM(shown_suggestion, inputs, user_response); if (user_response.user_response == GroupSuggestionsDelegate::UserResponse::kNotShown || user_response.user_response == @@ -308,7 +309,6 @@ DCHECK_EQ(user_response.suggestion_id, shown_suggestion.suggestion_id); suggestion_tracker_->AddSuggestion(shown_suggestion, user_response.user_response); - RecordSuggestionUKM(shown_suggestion, inputs, user_response); } } // namespace visited_url_ranking
diff --git a/components/viz/client/viz_client_export.h b/components/viz/client/viz_client_export.h index 6aed35de..006adf5 100644 --- a/components/viz/client/viz_client_export.h +++ b/components/viz/client/viz_client_export.h
@@ -15,11 +15,7 @@ #endif // defined(VIZ_CLIENT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VIZ_CLIENT_IMPLEMENTATION) #define VIZ_CLIENT_EXPORT __attribute__((visibility("default"))) -#else -#define VIZ_CLIENT_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/viz/common/quads/render_pass_io_unittest.cc b/components/viz/common/quads/render_pass_io_unittest.cc index 65f4a47..e099485 100644 --- a/components/viz/common/quads/render_pass_io_unittest.cc +++ b/components/viz/common/quads/render_pass_io_unittest.cc
@@ -234,7 +234,7 @@ render_pass0->CreateAndAppendDrawQuad<TextureDrawQuad>(); quad->SetAll(render_pass0->shared_quad_state_list.ElementAt(sqs_index), gfx::Rect(10, 10, 300, 400), gfx::Rect(10, 10, 200, 400), - false, ResourceId(100), false, gfx::PointF(0.f, 0.f), + false, ResourceId(100), true, gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f), SkColors::kTransparent, false, false, gfx::ProtectedVideoType::kHardwareProtected); quad->is_stream_video = true; @@ -256,7 +256,7 @@ render_pass0->CreateAndAppendDrawQuad<TextureDrawQuad>(); quad->SetAll(render_pass0->shared_quad_state_list.ElementAt(sqs_index), gfx::Rect(0, 0, 100, 50), gfx::Rect(0, 0, 100, 50), false, - ResourceId(9u), false, gfx::PointF(0.f, 0.f), + ResourceId(9u), true, gfx::PointF(0.f, 0.f), gfx::PointF(1.f, 1.f), SkColors::kBlue, true, false, gfx::ProtectedVideoType::kHardwareProtected);
diff --git a/components/viz/common/viz_common_export.h b/components/viz/common/viz_common_export.h index a383ced..f4355209 100644 --- a/components/viz/common/viz_common_export.h +++ b/components/viz/common/viz_common_export.h
@@ -15,11 +15,7 @@ #endif // defined(VIZ_COMMON_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VIZ_COMMON_IMPLEMENTATION) #define VIZ_COMMON_EXPORT __attribute__((visibility("default"))) -#else -#define VIZ_COMMON_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/viz/common/viz_metal_context_provider_export.h b/components/viz/common/viz_metal_context_provider_export.h index edf4d63..d405ecc 100644 --- a/components/viz/common/viz_metal_context_provider_export.h +++ b/components/viz/common/viz_metal_context_provider_export.h
@@ -15,11 +15,7 @@ #endif // defined(VIZ_METAL_CONTEXT_PROVIDER_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VIZ_METAL_CONTEXT_PROVIDER_IMPLEMENTATION) #define VIZ_METAL_CONTEXT_PROVIDER_EXPORT __attribute__((visibility("default"))) -#else -#define VIZ_METAL_CONTEXT_PROVIDER_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/viz/host/viz_host_export.h b/components/viz/host/viz_host_export.h index 2cc7dc7..9913f109 100644 --- a/components/viz/host/viz_host_export.h +++ b/components/viz/host/viz_host_export.h
@@ -15,11 +15,7 @@ #endif // defined(VIZ_HOST_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VIZ_HOST_IMPLEMENTATION) #define VIZ_HOST_EXPORT __attribute__((visibility("default"))) -#else -#define VIZ_HOST_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/viz/service/display/occlusion_culler_unittest.cc b/components/viz/service/display/occlusion_culler_unittest.cc index 28f3f3c..55f1bd4 100644 --- a/components/viz/service/display/occlusion_culler_unittest.cc +++ b/components/viz/service/display/occlusion_culler_unittest.cc
@@ -91,7 +91,7 @@ bool is_overlay_candidate) { bool nearest_neighbor = false; bool needs_blending = false; - bool premultiplied_alpha = false; + bool premultiplied_alpha = true; gfx::Size resource_size_in_pixels = rect.size(); TestResourceFactory::TestResourceContext resource_context;
diff --git a/components/viz/service/display/overlay_candidate_factory_unittest.cc b/components/viz/service/display/overlay_candidate_factory_unittest.cc index 188171b..23a6b08 100644 --- a/components/viz/service/display/overlay_candidate_factory_unittest.cc +++ b/components/viz/service/display/overlay_candidate_factory_unittest.cc
@@ -360,7 +360,7 @@ sqs->quad_to_target_transform = quad_to_target_transform; TextureDrawQuad quad; quad.SetNew(sqs, quad_rect, quad_rect, false, - CreateResource(/*is_overlay_candidate=*/true, origin), false, + CreateResource(/*is_overlay_candidate=*/true, origin), true, gfx::PointF(), gfx::PointF(1, 1), SkColors::kTransparent, false, false, gfx::ProtectedVideoType::kClear); return quad; @@ -771,7 +771,7 @@ quad.SetNew( sqs, quad_rect, quad_rect, false, CreateResource(/*is_overlay_candidate=*/true, kTopLeft_GrSurfaceOrigin), - false, quad_uv_rect.origin(), quad_uv_rect.bottom_right(), + true, quad_uv_rect.origin(), quad_uv_rect.bottom_right(), SkColors::kTransparent, false, false, gfx::ProtectedVideoType::kClear); return quad;
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc index 720a171..48be71b 100644 --- a/components/viz/service/display/overlay_unittest.cc +++ b/components/viz/service/display/overlay_unittest.cc
@@ -772,7 +772,7 @@ const gfx::Size& resource_size_in_pixels, SurfaceId test_surface_id = SurfaceId()) { bool needs_blending = false; - bool premultiplied_alpha = false; + bool premultiplied_alpha = true; bool low_latency_rendering = false; return CreateCandidateQuadAt( shared_quad_state, render_pass, rect, needs_blending, @@ -788,7 +788,7 @@ SharedImageFormat format, SurfaceId test_surface_id = SurfaceId()) { bool needs_blending = false; - bool premultiplied_alpha = false; + bool premultiplied_alpha = true; bool low_latency_rendering = false; gfx::Size resource_size_in_pixels = rect.size(); return CreateCandidateQuadAt( @@ -813,7 +813,7 @@ const gfx::Rect& rect, SurfaceId test_surface_id = SurfaceId()) { bool needs_blending = false; - bool premultiplied_alpha = false; + bool premultiplied_alpha = true; bool low_latency_rendering = true; gfx::Size resource_size_in_pixels = rect.size(); gfx::ProtectedVideoType protected_video_type = @@ -831,7 +831,7 @@ AggregatedRenderPass* render_pass, const gfx::Rect& rect) { bool needs_blending = true; - bool premultiplied_alpha = false; + bool premultiplied_alpha = true; bool low_latency_rendering = false; gfx::Size resource_size_in_pixels = rect.size(); @@ -1839,9 +1839,9 @@ pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); quad_small->SetNew(shared_quad_state_a, kCandidateRectA, kCandidateRectA, false /*needs_blending*/, resource_id_a, - false /*premultiplied_alpha*/, kUVTopLeft, - kUVBottomRight, SkColors::kTransparent, - false /*nearest_neighbor*/, false /*secure_output_only*/, + true /*premultiplied_alpha*/, kUVTopLeft, kUVBottomRight, + SkColors::kTransparent, false /*nearest_neighbor*/, + false /*secure_output_only*/, gfx::ProtectedVideoType::kClear); AddExpectedRectToOverlayProcessor(gfx::RectF(kCandidateRectA)); @@ -1853,7 +1853,7 @@ quad_big->SetNew(shared_quad_state_b, kCandidateRectB, kCandidateRectB, false /*needs_blending*/, resource_id_b, - false /*premultiplied_alpha*/, kUVTopLeft, kUVBottomRight, + true /*premultiplied_alpha*/, kUVTopLeft, kUVBottomRight, SkColors::kTransparent, false /*nearest_neighbor*/, false /*secure_output_only*/, gfx::ProtectedVideoType::kClear); @@ -3116,7 +3116,7 @@ original_quad->SetNew( pass->shared_quad_state_list.back(), pass->output_rect, pass->output_rect, false /*needs_blending*/, resource_id, - false /*premultiplied_alpha*/, kUVTopLeft, kUVBottomRight, + true /*premultiplied_alpha*/, kUVTopLeft, kUVBottomRight, SkColors::kTransparent, false /*nearest_neighbor*/, false /*secure_output_only*/, gfx::ProtectedVideoType::kClear); @@ -3316,7 +3316,7 @@ quad_candidate_no_occlusion->SetNew( sqs, kOverlayTopLeftRect, kOverlayTopLeftRect, /*needs_blending=*/false, no_occlusion_quad_resource_id, - /*premultiplied=*/false, kUVTopLeft, kUVBottomRight, + /*premultiplied=*/true, kUVTopLeft, kUVBottomRight, SkColors::kTransparent, /*nearest=*/false, /*secure_output=*/false, gfx::ProtectedVideoType::kClear); TrackingIdData track_data_top_left{
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index a33be0d5..2cbd748 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -4948,7 +4948,7 @@ auto* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); quad->SetNew(shared_state, viewport, viewport, needs_blending, - mapped_resource, false, gfx::PointF(0, 0), gfx::PointF(1, 1), + mapped_resource, true, gfx::PointF(0, 0), gfx::PointF(1, 1), SkColors::kBlack, nearest_neighbor, /*secure_output_only=*/false, gfx::ProtectedVideoType::kClear);
diff --git a/components/viz/service/viz_service_export.h b/components/viz/service/viz_service_export.h index e89b1fd..2a56680f 100644 --- a/components/viz/service/viz_service_export.h +++ b/components/viz/service/viz_service_export.h
@@ -15,11 +15,7 @@ #endif // defined(VIZ_SERVICE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VIZ_SERVICE_IMPLEMENTATION) #define VIZ_SERVICE_EXPORT __attribute__((visibility("default"))) -#else -#define VIZ_SERVICE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/web_modal/web_modal_export.h b/components/web_modal/web_modal_export.h index 158e79e..0a4f3306 100644 --- a/components/web_modal/web_modal_export.h +++ b/components/web_modal/web_modal_export.h
@@ -15,11 +15,7 @@ #endif // defined(WEB_MODAL_IMPLEMENTATION) #else // defined(WIN32) -#if defined(WEB_MODAL_IMPLEMENTATION) #define WEB_MODAL_EXPORT __attribute__((visibility("default"))) -#else -#define WEB_MODAL_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/webauthn/core/browser/immediate_request_rate_limiter.h b/components/webauthn/core/browser/immediate_request_rate_limiter.h index 5ecdfb4..fc28a82d 100644 --- a/components/webauthn/core/browser/immediate_request_rate_limiter.h +++ b/components/webauthn/core/browser/immediate_request_rate_limiter.h
@@ -6,17 +6,16 @@ #define COMPONENTS_WEBAUTHN_CORE_BROWSER_IMMEDIATE_REQUEST_RATE_LIMITER_H_ #include "base/containers/flat_map.h" +#include "components/keyed_service/core/keyed_service.h" #include "components/webauthn/core/browser/rate_limiter_slide_window.h" #include "url/origin.h" namespace webauthn { -class ImmediateRequestRateLimiter { +class ImmediateRequestRateLimiter : public KeyedService { public: ImmediateRequestRateLimiter(); - ~ImmediateRequestRateLimiter(); - - static ImmediateRequestRateLimiter& GetInstance(); + ~ImmediateRequestRateLimiter() override; bool IsRequestAllowed(const url::Origin& origin);
diff --git a/components/webdata/common/webdata_export.h b/components/webdata/common/webdata_export.h index fbeffc0..1a4b2eed 100644 --- a/components/webdata/common/webdata_export.h +++ b/components/webdata/common/webdata_export.h
@@ -15,11 +15,7 @@ #endif // defined(WEBDATA_IMPLEMENTATION) #else // defined(WIN32) -#if defined(WEBDATA_IMPLEMENTATION) #define WEBDATA_EXPORT __attribute__((visibility("default"))) -#else -#define WEBDATA_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/components/wifi/wifi_export.h b/components/wifi/wifi_export.h index 0070df1..9dc2ce354 100644 --- a/components/wifi/wifi_export.h +++ b/components/wifi/wifi_export.h
@@ -15,11 +15,7 @@ #endif // defined(WIFI_IMPLEMENTATION) #else // defined(WIN32) -#if defined(WIFI_IMPLEMENTATION) #define WIFI_EXPORT __attribute__((visibility("default"))) -#else -#define WIFI_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 586f1a6..4008b7bd 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -239,6 +239,28 @@ base::test::ScopedFeatureList feature_list_; }; +class SelectReparentInputDumpAccessibilityTreeTest + : public DumpAccessibilityTreeTest { + protected: + SelectReparentInputDumpAccessibilityTreeTest() { + feature_list_.InitWithFeatures( + {{blink::features::kCustomizableSelect, + blink::features::kSelectParserRelaxation, + blink::features::kSelectAccessibilityReparentInput}}, + {/* disabled_features */}); + } + + ~SelectReparentInputDumpAccessibilityTreeTest() override { + // Ensure that the feature lists are destroyed in the same order they + // were created in. + scoped_feature_list_.Reset(); + feature_list_.Reset(); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + class OnScreenModeDumpAccessibilityTreeTest : public DumpAccessibilityTreeTest { }; @@ -282,6 +304,12 @@ INSTANTIATE_TEST_SUITE_P( All, + SelectReparentInputDumpAccessibilityTreeTest, + ::testing::ValuesIn(DumpAccessibilityTestBase::TreeTestPasses()), + DumpAccessibilityTreeTestPassToString()); + +INSTANTIATE_TEST_SUITE_P( + All, OnScreenModeDumpAccessibilityTreeTest, ::testing::ValuesIn(DumpAccessibilityTestBase::TreeTestPasses()), DumpAccessibilityTreeTestPassToString()); @@ -2283,6 +2311,11 @@ RunHtmlTest(FILE_PATH_LITERAL("select-slowly-build.html")); } +IN_PROC_BROWSER_TEST_P(SelectReparentInputDumpAccessibilityTreeTest, + AccessibilityCustomSelectWithInput) { + RunHtmlTest(FILE_PATH_LITERAL("select-with-input.html")); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityDd) { RunHtmlTest(FILE_PATH_LITERAL("dd.html")); }
diff --git a/content/browser/android/content_feature_map.cc b/content/browser/android/content_feature_map.cc index 208670c..17520c84 100644 --- a/content/browser/android/content_feature_map.cc +++ b/content/browser/android/content_feature_map.cc
@@ -36,6 +36,7 @@ &features::kAndroidFallbackToNextSlot, &features::kAndroidOpenPdfInline, &features::kFedCm, + &features::kGroupRebindingForGroupImportance, &features::kHidePastePopupOnGSB, &features::kReduceGpuPriorityOnBackground, &features::kContinueGestureOnLosingFocus,
diff --git a/content/browser/back_forward_cache_internal_browsertest.cc b/content/browser/back_forward_cache_internal_browsertest.cc index 87ec411..85a599d 100644 --- a/content/browser/back_forward_cache_internal_browsertest.cc +++ b/content/browser/back_forward_cache_internal_browsertest.cc
@@ -3516,10 +3516,9 @@ // NavigationThrottles. content::ShellContentBrowserClient::Get() ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting( - [&did_register_throttles](content::NavigationHandle* handle) - -> std::vector<std::unique_ptr<content::NavigationThrottle>> { + [&did_register_throttles]( + content::NavigationThrottleRegistry& registry) -> void { did_register_throttles = true; - return std::vector<std::unique_ptr<content::NavigationThrottle>>(); })); // 2) Navigate to B.
diff --git a/content/browser/cache_storage/cache_storage.cc b/content/browser/cache_storage/cache_storage.cc index ad6cf28..7263aff1 100644 --- a/content/browser/cache_storage/cache_storage.cc +++ b/content/browser/cache_storage/cache_storage.cc
@@ -56,7 +56,6 @@ #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" using blink::mojom::CacheStorageError; -using blink::mojom::StorageType; namespace content {
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc index aff91cd..058e79e 100644 --- a/content/browser/cache_storage/cache_storage_manager_unittest.cc +++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -99,7 +99,6 @@ kThirdPartyNamed, }; -using blink::mojom::StorageType; using ResponseHeaderMap = base::flat_map<std::string, std::string>; constexpr char16_t kReplacementCharacter = 0xFFFD;
diff --git a/content/browser/child_process_launcher_helper_android.cc b/content/browser/child_process_launcher_helper_android.cc index 4f91da1..3459186a 100644 --- a/content/browser/child_process_launcher_helper_android.cc +++ b/content/browser/child_process_launcher_helper_android.cc
@@ -153,29 +153,31 @@ size_t file_count = files_to_register->GetMappingSize(); DCHECK(file_count > 0); - ScopedJavaLocalRef<jclass> j_file_info_class = base::android::GetClass( - env, "org/chromium/base/process_launcher/FileDescriptorInfo"); - ScopedJavaLocalRef<jobjectArray> j_file_infos( - env, env->NewObjectArray(file_count, j_file_info_class.obj(), NULL)); - base::android::CheckException(env); - + std::vector<int32_t> ids(file_count); + std::vector<int32_t> fds(file_count); + std::vector<bool> auto_closes(file_count); + std::vector<int64_t> offsets(file_count); + std::vector<int64_t> sizes(file_count); for (size_t i = 0; i < file_count; ++i) { int fd = files_to_register->GetFDAt(i); CHECK(0 <= fd); - int id = files_to_register->GetIDAt(i); + fds[i] = fd; + ids[i] = files_to_register->GetIDAt(i); const auto& region = files_to_register->GetRegionAt(i); + offsets[i] = region.offset; + sizes[i] = region.size; bool auto_close = files_to_register->OwnsFD(fd); if (auto_close) { std::ignore = files_to_register->ReleaseFD(fd).release(); } - - ScopedJavaLocalRef<jobject> j_file_info = - Java_ChildProcessLauncherHelperImpl_makeFdInfo( - env, id, fd, auto_close, region.offset, region.size); - CHECK(j_file_info.obj()); - env->SetObjectArrayElement(j_file_infos.obj(), i, j_file_info.obj()); + auto_closes[i] = auto_close; } + ScopedJavaLocalRef<jobjectArray> j_file_infos = + Java_ChildProcessLauncherHelperImpl_makeFdInfos( + env, ids, fds, auto_closes, offsets, sizes); + CHECK(j_file_infos.obj()); + AddRef(); // Balanced by OnChildProcessStarted. java_peer_.Reset(Java_ChildProcessLauncherHelperImpl_createAndStart( env, reinterpret_cast<intptr_t>(this), j_argv, j_file_infos,
diff --git a/content/browser/device_posture/foldable_apis_origin_trial_browsertest.cc b/content/browser/device_posture/foldable_apis_origin_trial_browsertest.cc deleted file mode 100644 index 9077af31..0000000 --- a/content/browser/device_posture/foldable_apis_origin_trial_browsertest.cc +++ /dev/null
@@ -1,174 +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. - -#include <memory> - -#include "base/test/scoped_feature_list.h" -#include "content/browser/web_contents/web_contents_impl.h" -#include "content/public/browser/render_widget_host_observer.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/url_loader_interceptor.h" -#include "content/shell/browser/shell.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -namespace content { - -namespace { - -constexpr char kBaseDataDir[] = "content/test/data/device_posture"; - -class TestRenderWidgetHostObserver : public RenderWidgetHostObserver { - public: - explicit TestRenderWidgetHostObserver(RenderWidgetHost* widget_host) - : widget_host_(widget_host) { - widget_host_->AddObserver(this); - } - - ~TestRenderWidgetHostObserver() override { - widget_host_->RemoveObserver(this); - } - - // RenderWidgetHostObserver: - void RenderWidgetHostDidUpdateVisualProperties( - RenderWidgetHost* widget_host) override { - run_loop_.Quit(); - } - - void WaitForVisualPropertiesUpdate() { run_loop_.Run(); } - - private: - raw_ptr<RenderWidgetHost> widget_host_ = nullptr; - base::RunLoop run_loop_; -}; - -class FoldableAPIsOriginTrialBrowserTest : public ContentBrowserTest { - public: - ~FoldableAPIsOriginTrialBrowserTest() override = default; - - void SetUpOnMainThread() override { - ContentBrowserTest::SetUpOnMainThread(); - - // We need to use URLLoaderInterceptor (rather than a EmbeddedTestServer), - // because origin trial token is associated with a fixed origin, whereas - // EmbeddedTestServer serves content on a random port. - interceptor_ = URLLoaderInterceptor::ServeFilesFromDirectoryAtOrigin( - kBaseDataDir, GURL("https://example.test/")); - } - - RenderWidgetHostViewBase* view() { - return static_cast<RenderWidgetHostViewBase*>( - shell()->web_contents()->GetRenderWidgetHostView()); - } - - WebContentsImpl* web_contents_impl() { - return static_cast<WebContentsImpl*>(shell()->web_contents()); - } - - void SetUpFoldableState() { - const int kDisplayFeatureLength = 10; - DisplayFeature emulated_display_feature{ - DisplayFeature::Orientation::kVertical, - /* offset */ view()->GetVisibleViewportSize().width() / 2 - - kDisplayFeatureLength / 2, - /* mask_length */ kDisplayFeatureLength}; - view()->OverrideDisplayFeatureForEmulation(&emulated_display_feature); - FrameTreeNode* root = web_contents_impl()->GetPrimaryFrameTree().root(); - RenderWidgetHostImpl* root_widget = - root->current_frame_host()->GetRenderWidgetHost(); - // We need to wait that visual properties are updated before we test the - // CSS APIs of Viewport Segments. - while (root_widget->visual_properties_ack_pending_for_testing()) { - TestRenderWidgetHostObserver(root_widget).WaitForVisualPropertiesUpdate(); - } - } - - void TearDownOnMainThread() override { - interceptor_.reset(); - ContentBrowserTest::TearDownOnMainThread(); - view()->DisableDisplayFeatureOverrideForEmulation(); - } - - bool HasViewportSegmentsApi() { - return EvalJs( - shell(), - "window.viewport != undefined && 'segments' in window.viewport") - .ExtractBool(); - } - - bool HasViewportSegmentsCSSApi() { - return EvalJs( - shell(), - "window.matchMedia('(horizontal-viewport-segments: 2)').matches") - .ExtractBool(); - } - - bool HasViewportSegmentsEnvVariablesCSSApi() { - return EvalJs(shell(), - "getComputedStyle(document.getElementById('content')).width " - "!= '0px'") - .ExtractBool(); - } - - protected: - const GURL kValidTokenUrl{"https://example.test/valid_token.html"}; - const GURL kNoTokenUrl{"https://example.test/no_token.html"}; - - std::unique_ptr<content::URLLoaderInterceptor> interceptor_; -}; - -IN_PROC_BROWSER_TEST_F(FoldableAPIsOriginTrialBrowserTest, - ValidOriginTrialToken) { - ASSERT_TRUE(NavigateToURL(shell(), kValidTokenUrl)); - SetUpFoldableState(); - EXPECT_TRUE(HasViewportSegmentsApi()); - EXPECT_TRUE(HasViewportSegmentsCSSApi()); - EXPECT_TRUE(HasViewportSegmentsEnvVariablesCSSApi()); -} - -IN_PROC_BROWSER_TEST_F(FoldableAPIsOriginTrialBrowserTest, NoOriginTrialToken) { - ASSERT_TRUE(NavigateToURL(shell(), kNoTokenUrl)); - SetUpFoldableState(); - EXPECT_FALSE(HasViewportSegmentsApi()); - EXPECT_FALSE(HasViewportSegmentsCSSApi()); - EXPECT_FALSE(HasViewportSegmentsEnvVariablesCSSApi()); -} - -class FoldableAPIsOriginTrialKillSwitchBrowserTest - : public FoldableAPIsOriginTrialBrowserTest { - public: - FoldableAPIsOriginTrialKillSwitchBrowserTest() { - scoped_feature_list_.Reset(); - scoped_feature_list_.InitWithFeatures({}, - {blink::features::kViewportSegments}); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_F(FoldableAPIsOriginTrialKillSwitchBrowserTest, - ValidOriginTrialToken) { - ASSERT_TRUE(NavigateToURL(shell(), kValidTokenUrl)); - SetUpFoldableState(); - EXPECT_FALSE(HasViewportSegmentsApi()); - EXPECT_FALSE(HasViewportSegmentsCSSApi()); - EXPECT_FALSE(HasViewportSegmentsEnvVariablesCSSApi()); -} - -IN_PROC_BROWSER_TEST_F(FoldableAPIsOriginTrialKillSwitchBrowserTest, - NoOriginTrialToken) { - ASSERT_TRUE(NavigateToURL(shell(), kNoTokenUrl)); - SetUpFoldableState(); - EXPECT_FALSE(HasViewportSegmentsApi()); - EXPECT_FALSE(HasViewportSegmentsCSSApi()); - EXPECT_FALSE(HasViewportSegmentsEnvVariablesCSSApi()); -} - -} // namespace - -} // namespace content
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index 4a222bd..d3ce52f 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc
@@ -770,9 +770,28 @@ info->save_info->total_bytes = info->total_bytes; } content::devtools_instrumentation::WillBeginDownload(info.get(), download); + // Check if the download is a duplicate. Only GET download URL that has + // existed are considered duplicate. + bool is_duplicate = duplicate_file_exists && (info->method == "GET"); + if (is_duplicate) { + bool found_same_url = false; + // If there is another download with the same path, the download is + // not a duplicate. + for (auto it = downloads_.begin(); it != downloads_.end(); ++it) { + if (it->second->GetTargetFilePath() == duplicate_download_file_path) { + if (it->second->GetURL() != info->url()) { + is_duplicate = false; + break; + } else { + found_same_url = true; + } + } + } + is_duplicate = is_duplicate && found_same_url; + } std::move(callback).Run( std::move(info), download, - duplicate_file_exists ? duplicate_download_file_path : base::FilePath(), + is_duplicate ? duplicate_download_file_path : base::FilePath(), should_persist_new_download_); if (download) { // For new downloads, we notify here, rather than earlier, so that
diff --git a/content/browser/indexed_db/BUILD.gn b/content/browser/indexed_db/BUILD.gn index 6bed2df..aa96ae0 100644 --- a/content/browser/indexed_db/BUILD.gn +++ b/content/browser/indexed_db/BUILD.gn
@@ -72,6 +72,12 @@ "instance/lock_request_data.h", "instance/pending_connection.cc", "instance/pending_connection.h", + "instance/sqlite/backing_store_database_impl.cc", + "instance/sqlite/backing_store_database_impl.h", + "instance/sqlite/backing_store_impl.cc", + "instance/sqlite/backing_store_impl.h", + "instance/sqlite/backing_store_transaction_impl.cc", + "instance/sqlite/backing_store_transaction_impl.h", "instance/transaction.cc", "instance/transaction.h", "list_set.h",
diff --git a/content/browser/indexed_db/instance/backing_store.h b/content/browser/indexed_db/instance/backing_store.h index f6c58fb..77384e0 100644 --- a/content/browser/indexed_db/instance/backing_store.h +++ b/content/browser/indexed_db/instance/backing_store.h
@@ -158,9 +158,6 @@ const blink::IndexedDBKey& key, IndexedDBValue* value, RecordIdentifier* record) = 0; - [[nodiscard]] virtual Status DeleteRecord( - int64_t object_store_id, - const RecordIdentifier& record) = 0; [[nodiscard]] virtual Status DeleteRange( int64_t object_store_id, const blink::IndexedDBKeyRange&) = 0;
diff --git a/content/browser/indexed_db/instance/fake_transaction.cc b/content/browser/indexed_db/instance/fake_transaction.cc index a070598..468c84a 100644 --- a/content/browser/indexed_db/instance/fake_transaction.cc +++ b/content/browser/indexed_db/instance/fake_transaction.cc
@@ -102,12 +102,6 @@ return wrapped_transaction_->PutRecord(object_store_id, key, value, record); } -Status FakeTransaction::DeleteRecord( - int64_t object_store_id, - const BackingStore::RecordIdentifier& record) { - return wrapped_transaction_->DeleteRecord(object_store_id, record); -} - Status FakeTransaction::DeleteRange(int64_t object_store_id, const blink::IndexedDBKeyRange& key_range) { return wrapped_transaction_->DeleteRange(object_store_id, key_range);
diff --git a/content/browser/indexed_db/instance/fake_transaction.h b/content/browser/indexed_db/instance/fake_transaction.h index 7c705315..31d5590 100644 --- a/content/browser/indexed_db/instance/fake_transaction.h +++ b/content/browser/indexed_db/instance/fake_transaction.h
@@ -53,8 +53,6 @@ const blink::IndexedDBKey& key, IndexedDBValue* value, BackingStore::RecordIdentifier* record) override; - Status DeleteRecord(int64_t object_store_id, - const BackingStore::RecordIdentifier& record) override; Status DeleteRange(int64_t object_store_id, const blink::IndexedDBKeyRange&) override; Status GetKeyGeneratorCurrentNumber(int64_t object_store_id,
diff --git a/content/browser/indexed_db/instance/leveldb/backing_store.cc b/content/browser/indexed_db/instance/leveldb/backing_store.cc index c1a0a9c9..bfbed18a 100644 --- a/content/browser/indexed_db/instance/leveldb/backing_store.cc +++ b/content/browser/indexed_db/instance/leveldb/backing_store.cc
@@ -1611,7 +1611,7 @@ } // static -std::tuple<std::unique_ptr<BackingStore>, +std::tuple<std::unique_ptr<indexed_db::BackingStore>, Status, IndexedDBDataLossInfo, bool /* is_disk_full */> @@ -2354,31 +2354,6 @@ LevelDBScopeDeletionMode::kImmediateWithRangeEndExclusive)); } -Status BackingStore::Transaction::DeleteRecord( - int64_t object_store_id, - const RecordIdentifier& record_identifier) { - TRACE_EVENT0("IndexedDB", "BackingStore::DeleteRecord"); - if (!KeyPrefix::ValidIds(database_id(), object_store_id)) { - return InvalidDBKeyStatus(); - } - TransactionalLevelDBTransaction* leveldb_transaction = transaction(); - - const std::string object_store_data_key = ObjectStoreDataKey::Encode( - database_id(), object_store_id, record_identifier.primary_key()); - Status s(leveldb_transaction->Remove(object_store_data_key)); - if (!s.ok()) { - return s; - } - s = PutExternalObjectsIfNeeded(object_store_data_key, nullptr); - if (!s.ok()) { - return s; - } - - const std::string exists_entry_key = ExistsEntryKey::Encode( - database_id(), object_store_id, record_identifier.primary_key()); - return Status(leveldb_transaction->Remove(exists_entry_key)); -} - Status BackingStore::Transaction::DeleteRange( int64_t object_store_id, const IndexedDBKeyRange& key_range) {
diff --git a/content/browser/indexed_db/instance/leveldb/backing_store.h b/content/browser/indexed_db/instance/leveldb/backing_store.h index cf627e5..5659f52 100644 --- a/content/browser/indexed_db/instance/leveldb/backing_store.h +++ b/content/browser/indexed_db/instance/leveldb/backing_store.h
@@ -182,8 +182,6 @@ IndexedDBValue* value, RecordIdentifier* record) override; Status ClearObjectStore(int64_t object_store_id) override; - Status DeleteRecord(int64_t object_store_id, - const RecordIdentifier& record) override; Status DeleteRange(int64_t object_store_id, const blink::IndexedDBKeyRange&) override; Status GetKeyGeneratorCurrentNumber(int64_t object_store_id, @@ -527,7 +525,7 @@ blink::mojom::IDBTransactionDurability durability); // Create and initialize a BackingStore; verify and report its status. - static std::tuple<std::unique_ptr<BackingStore>, + static std::tuple<std::unique_ptr<indexed_db::BackingStore>, Status, IndexedDBDataLossInfo, bool /* is_disk_full */>
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_database_impl.cc b/content/browser/indexed_db/instance/sqlite/backing_store_database_impl.cc new file mode 100644 index 0000000..20e0526 --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/backing_store_database_impl.cc
@@ -0,0 +1,116 @@ +// 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 "content/browser/indexed_db/instance/sqlite/backing_store_database_impl.h" + +#include "base/check.h" +#include "base/notimplemented.h" +#include "content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.h" +#include "content/browser/indexed_db/status.h" +#include "sql/database.h" +#include "sql/meta_table.h" +#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h" + +namespace content::indexed_db::sqlite { + +struct MetadataConstants { + public: + // These are schema versions of our implementation of `sql::Database`; not the + // version supplied by the application for the IndexedDB database. + static constexpr int kCurrentSchemaVersion = 1; + static constexpr int kCompatibleSchemaVersion = 1; + + // Keys of properties stored in the meta table. + struct Keys { + // Metadata relevant to the IndexedDB database. Though these are strictly + // "data" and not "metadata", they are stored in the meta table for + // convenience. + struct Idb { + // The application-supplied version of the IndexedDB database. + static constexpr char kVersion[] = "idb.version"; + static constexpr char kMaxObjectStoreId[] = "idb.max_object_store_id"; + }; + }; +}; + +BackingStoreDatabaseImpl::BackingStoreDatabaseImpl( + const std::u16string& name, + base::WeakPtr<DatabaseConnection> open_db) + : connection_(open_db), metadata_(name) { + CHECK(connection_->db()->is_open()); + bool new_db = !sql::MetaTable::DoesTableExist(connection_->db()); + sql::MetaTable* meta_table = connection_->meta_table(); + CHECK(meta_table->Init(connection_->db(), + MetadataConstants::kCurrentSchemaVersion, + MetadataConstants::kCompatibleSchemaVersion)); + if (new_db) { + metadata_.version = blink::IndexedDBDatabaseMetadata::NO_VERSION; + metadata_.max_object_store_id = 0; + meta_table->SetValue(MetadataConstants::Keys::Idb::kVersion, + metadata_.version); + meta_table->SetValue(MetadataConstants::Keys::Idb::kMaxObjectStoreId, + metadata_.max_object_store_id); + } else { + meta_table->GetValue(MetadataConstants::Keys::Idb::kVersion, + &metadata_.version); + meta_table->GetValue(MetadataConstants::Keys::Idb::kMaxObjectStoreId, + &metadata_.max_object_store_id); + } +} + +BackingStoreDatabaseImpl::~BackingStoreDatabaseImpl() { + if (connection_) { + // The underlying `DatabaseConnection` can be reused by a new instance. + connection_->meta_table()->Reset(); + } +} + +void BackingStoreDatabaseImpl::RollbackUpgrade(UpgradePassKey& pass_key) { + metadata_ = std::move(pass_key.metadata_snapshot_); +} + +Status BackingStoreDatabaseImpl::SetDatabaseVersion(UpgradePassKey&, + int64_t version) { + connection_->meta_table()->SetValue(MetadataConstants::Keys::Idb::kVersion, + version); + metadata_.version = version; + return Status::OK(); +} + +const blink::IndexedDBDatabaseMetadata& +BackingStoreDatabaseImpl::GetMetadata() { + return metadata_; +} + +PartitionedLockId BackingStoreDatabaseImpl::GetLockId( + int64_t object_store_id) const { + NOTIMPLEMENTED(); + return PartitionedLockId(); +} + +std::unique_ptr<BackingStore::Transaction> +BackingStoreDatabaseImpl::CreateTransaction( + blink::mojom::IDBTransactionDurability durability, + blink::mojom::IDBTransactionMode mode) { + // TODO(crbug.com/40253999): Handle `durability` and assert preconditions for + // `mode`. + if (mode == blink::mojom::IDBTransactionMode::VersionChange) { + return std::make_unique<BackingStoreVersionChangeTransaction>( + GetWeakPtr(), UpgradePassKey(metadata_)); + } + return std::make_unique<BackingStoreTransactionImpl>(GetWeakPtr()); +} + +Status BackingStoreDatabaseImpl::DeleteDatabase( + std::vector<PartitionedLock> locks, + base::OnceClosure on_complete) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +base::WeakPtr<BackingStoreDatabaseImpl> BackingStoreDatabaseImpl::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + +} // namespace content::indexed_db::sqlite
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_database_impl.h b/content/browser/indexed_db/instance/sqlite/backing_store_database_impl.h new file mode 100644 index 0000000..72c4b465 --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/backing_store_database_impl.h
@@ -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. + +#ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_DATABASE_IMPL_H_ +#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_DATABASE_IMPL_H_ + +#include "base/memory/weak_ptr.h" +#include "content/browser/indexed_db/instance/backing_store.h" +#include "content/browser/indexed_db/instance/sqlite/backing_store_impl.h" +#include "third_party/blink/public/common/indexeddb/indexeddb_metadata.h" + +namespace sql { +class Database; +} // namespace sql + +namespace content::indexed_db::sqlite { + +class DatabaseConnection; + +// Owns metadata maintenance. There is at most one instance per +// `DatabaseConnection`. +class BackingStoreDatabaseImpl : public BackingStore::Database { + public: + // Enables calling methods that upgrade the IndexedDB database. + // This is modeled after `base::PassKey` which cannot be used directly since + // we want to store some data inside the key too. + class UpgradePassKey { + public: + UpgradePassKey(const UpgradePassKey&) = delete; + UpgradePassKey& operator=(const UpgradePassKey&) = delete; + UpgradePassKey(UpgradePassKey&&) = default; + UpgradePassKey& operator=(UpgradePassKey&&) = default; + + private: + friend class BackingStoreDatabaseImpl; + explicit UpgradePassKey(blink::IndexedDBDatabaseMetadata metadata_snapshot) + : metadata_snapshot_(std::move(metadata_snapshot)) {} + + // The metadata before the upgrade. + blink::IndexedDBDatabaseMetadata metadata_snapshot_; + }; + + BackingStoreDatabaseImpl(const std::u16string& name, + base::WeakPtr<DatabaseConnection> open_db); + BackingStoreDatabaseImpl(const BackingStoreDatabaseImpl&) = delete; + BackingStoreDatabaseImpl& operator=(const BackingStoreDatabaseImpl&) = delete; + ~BackingStoreDatabaseImpl() override; + + sql::Database* db() const { return connection_->db(); } + + // Rolls back all changes made through this pass key. + void RollbackUpgrade(UpgradePassKey&); + + // Methods to upgrade the IndexedDB database. Require a valid pass key. + Status SetDatabaseVersion(UpgradePassKey&, int64_t version); + + // BackingStore::Database: + const blink::IndexedDBDatabaseMetadata& GetMetadata() override; + PartitionedLockId GetLockId(int64_t object_store_id) const override; + std::unique_ptr<BackingStore::Transaction> CreateTransaction( + blink::mojom::IDBTransactionDurability durability, + blink::mojom::IDBTransactionMode mode) override; + Status DeleteDatabase(std::vector<PartitionedLock> locks, + base::OnceClosure on_complete) override; + + private: + base::WeakPtr<BackingStoreDatabaseImpl> GetWeakPtr(); + + base::WeakPtr<DatabaseConnection> connection_; + blink::IndexedDBDatabaseMetadata metadata_; + base::WeakPtrFactory<BackingStoreDatabaseImpl> weak_factory_{this}; +}; + +} // namespace content::indexed_db::sqlite + +#endif // CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_DATABASE_IMPL_H_
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_impl.cc b/content/browser/indexed_db/instance/sqlite/backing_store_impl.cc new file mode 100644 index 0000000..7673ad98 --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/backing_store_impl.cc
@@ -0,0 +1,104 @@ +// 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 "content/browser/indexed_db/instance/sqlite/backing_store_impl.h" + +#include "base/check.h" +#include "base/files/file_path.h" +#include "base/notimplemented.h" +#include "content/browser/indexed_db/indexed_db_data_loss_info.h" +#include "content/browser/indexed_db/instance/sqlite/backing_store_database_impl.h" +#include "content/browser/indexed_db/status.h" +#include "sql/database.h" +#include "sql/meta_table.h" + +namespace content::indexed_db::sqlite { + +DatabaseConnection::DatabaseConnection(std::unique_ptr<sql::Database> db) + : db_(std::move(db)), meta_table_(std::make_unique<sql::MetaTable>()) {} + +DatabaseConnection::~DatabaseConnection() = default; + +base::WeakPtr<DatabaseConnection> DatabaseConnection::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + +std::tuple<std::unique_ptr<BackingStore>, Status, IndexedDBDataLossInfo, bool> +BackingStoreImpl::OpenAndVerify(base::FilePath data_path) { + return { + std::make_unique<BackingStoreImpl>(std::move(data_path)), + Status::OK(), + IndexedDBDataLossInfo(), + false, + }; +} + +BackingStoreImpl::BackingStoreImpl(base::FilePath data_path) + : data_path_(std::move(data_path)) {} + +BackingStoreImpl::~BackingStoreImpl() = default; + +void BackingStoreImpl::TearDown(base::WaitableEvent* signal_on_destruction) { + NOTIMPLEMENTED(); + signal_on_destruction->Signal(); +} + +void BackingStoreImpl::InvalidateBlobReferences() { + NOTIMPLEMENTED(); +} + +void BackingStoreImpl::StartPreCloseTasks(base::OnceClosure on_done) { + NOTIMPLEMENTED(); + std::move(on_done).Run(); +} + +void BackingStoreImpl::StopPreCloseTasks() { + NOTIMPLEMENTED(); +} + +int64_t BackingStoreImpl::GetInMemorySize() const { + NOTIMPLEMENTED(); + return 0; +} + +Status BackingStoreImpl::GetDatabaseNames(std::vector<std::u16string>* names) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreImpl::GetDatabaseNamesAndVersions( + std::vector<blink::mojom::IDBNameAndVersionPtr>* names_and_versions) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +base::expected<std::unique_ptr<BackingStore::Database>, Status> +BackingStoreImpl::CreateOrOpenDatabase(const std::u16string& name) { + auto it = open_connections_.find(name); + if (it == open_connections_.end()) { + // TODO(crbug.com/40253999): Create new tag(s) for metrics. + constexpr sql::Database::Tag kSqlTag = "Test"; + auto db = std::make_unique<sql::Database>( + sql::DatabaseOptions().set_exclusive_locking(true).set_wal_mode(true), + kSqlTag); + // TODO(crbug.com/40253999): Support on-disk databases. + CHECK(db->OpenInMemory()); + auto result = open_connections_.try_emplace(name, std::move(db)); + CHECK(result.second); + it = result.first; + } + return std::make_unique<BackingStoreDatabaseImpl>(name, + it->second.GetWeakPtr()); +} + +uintptr_t BackingStoreImpl::GetIdentifierForMemoryDump() { + NOTIMPLEMENTED(); + return 0; +} + +void BackingStoreImpl::FlushForTesting() { + NOTIMPLEMENTED(); +} + +} // namespace content::indexed_db::sqlite
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_impl.h b/content/browser/indexed_db/instance/sqlite/backing_store_impl.h new file mode 100644 index 0000000..c07b41a --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/backing_store_impl.h
@@ -0,0 +1,83 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_IMPL_H_ +#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_IMPL_H_ + +#include <memory> +#include <string> +#include <unordered_map> + +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "content/browser/indexed_db/instance/backing_store.h" + +namespace sql { +class Database; +class MetaTable; +} // namespace sql + +namespace content::indexed_db { + +struct IndexedDBDataLossInfo; + +namespace sqlite { + +// Owns an open connection to a SQLite database and supports weak pointer +// semantics. +class DatabaseConnection { + public: + explicit DatabaseConnection(std::unique_ptr<sql::Database> db); + DatabaseConnection(const DatabaseConnection&) = delete; + DatabaseConnection& operator=(const DatabaseConnection&) = delete; + ~DatabaseConnection(); + + sql::Database* db() const { return db_.get(); } + sql::MetaTable* meta_table() const { return meta_table_.get(); } + + base::WeakPtr<DatabaseConnection> GetWeakPtr(); + + private: + std::unique_ptr<sql::Database> db_; + std::unique_ptr<sql::MetaTable> meta_table_; + base::WeakPtrFactory<DatabaseConnection> weak_factory_{this}; +}; + +class BackingStoreImpl : public BackingStore { + public: + static std::tuple<std::unique_ptr<BackingStore>, + Status, + IndexedDBDataLossInfo, + bool /* is_disk_full */> + OpenAndVerify(base::FilePath data_path); + + BackingStoreImpl(base::FilePath data_path); + BackingStoreImpl(const BackingStoreImpl&) = delete; + BackingStoreImpl& operator=(const BackingStoreImpl&) = delete; + ~BackingStoreImpl() override; + + // BackingStore: + void TearDown(base::WaitableEvent* signal_on_destruction) override; + void InvalidateBlobReferences() override; + void StartPreCloseTasks(base::OnceClosure on_done) override; + void StopPreCloseTasks() override; + int64_t GetInMemorySize() const override; + Status GetDatabaseNames(std::vector<std::u16string>* names) override; + Status GetDatabaseNamesAndVersions( + std::vector<blink::mojom::IDBNameAndVersionPtr>* names_and_versions) + override; + base::expected<std::unique_ptr<BackingStore::Database>, Status> + CreateOrOpenDatabase(const std::u16string& name) override; + uintptr_t GetIdentifierForMemoryDump() override; + void FlushForTesting() override; + + private: + const base::FilePath data_path_; + std::unordered_map<std::u16string, DatabaseConnection> open_connections_; +}; + +} // namespace sqlite +} // namespace content::indexed_db + +#endif // CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_IMPL_H_
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.cc b/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.cc new file mode 100644 index 0000000..3cdd7a4 --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.cc
@@ -0,0 +1,224 @@ +// 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 "content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.h" + +#include "base/check.h" +#include "base/notimplemented.h" +#include "base/notreached.h" +#include "content/browser/indexed_db/instance/sqlite/backing_store_database_impl.h" +#include "content/browser/indexed_db/status.h" +#include "sql/transaction.h" + +namespace content::indexed_db::sqlite { + +BackingStoreTransactionImpl::BackingStoreTransactionImpl( + base::WeakPtr<BackingStoreDatabaseImpl> db) + : db_(db), transaction_(db_->db()) {} + +BackingStoreTransactionImpl::~BackingStoreTransactionImpl() = default; + +void BackingStoreTransactionImpl::Begin(std::vector<PartitionedLock> locks) { + CHECK(transaction_.Begin()); +} + +Status BackingStoreTransactionImpl::CommitPhaseOne(BlobWriteCallback callback) { + return std::move(callback).Run( + BlobWriteResult::kRunPhaseTwoAndReturnResult, + storage::mojom::WriteBlobToFileResult::kSuccess); +} + +Status BackingStoreTransactionImpl::CommitPhaseTwo() { + transaction_.Commit(); + return Status::OK(); +} + +void BackingStoreTransactionImpl::Rollback() { + transaction_.Rollback(); +} + +Status BackingStoreTransactionImpl::SetDatabaseVersion(int64_t version) { + NOTREACHED() << "Implemented by BackingStoreVersionChangeTransaction"; +} + +Status BackingStoreTransactionImpl::CreateObjectStore( + int64_t object_store_id, + const std::u16string& name, + blink::IndexedDBKeyPath key_path, + bool auto_increment) { + NOTREACHED() << "Implemented by BackingStoreVersionChangeTransaction"; +} + +Status BackingStoreTransactionImpl::DeleteObjectStore(int64_t object_store_id) { + NOTREACHED() << "Implemented by BackingStoreVersionChangeTransaction"; +} + +Status BackingStoreTransactionImpl::RenameObjectStore( + int64_t object_store_id, + const std::u16string& new_name) { + NOTREACHED() << "Implemented by BackingStoreVersionChangeTransaction"; +} + +Status BackingStoreTransactionImpl::ClearObjectStore(int64_t object_store_id) { + NOTREACHED() << "Implemented by BackingStoreVersionChangeTransaction"; +} + +Status BackingStoreTransactionImpl::CreateIndex( + int64_t object_store_id, + int64_t index_id, + const std::u16string& name, + blink::IndexedDBKeyPath key_path, + bool is_unique, + bool is_multi_entry) { + NOTREACHED() << "Implemented by BackingStoreVersionChangeTransaction"; +} + +Status BackingStoreTransactionImpl::DeleteIndex(int64_t object_store_id, + int64_t index_id) { + NOTREACHED() << "Implemented by BackingStoreVersionChangeTransaction"; +} + +Status BackingStoreTransactionImpl::RenameIndex( + int64_t object_store_id, + int64_t index_id, + const std::u16string& new_name) { + NOTREACHED() << "Implemented by BackingStoreVersionChangeTransaction"; +} + +Status BackingStoreTransactionImpl::GetRecord(int64_t object_store_id, + const blink::IndexedDBKey& key, + IndexedDBValue* record) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreTransactionImpl::PutRecord( + int64_t object_store_id, + const blink::IndexedDBKey& key, + IndexedDBValue* value, + BackingStore::RecordIdentifier* record) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreTransactionImpl::DeleteRange( + int64_t object_store_id, + const blink::IndexedDBKeyRange&) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreTransactionImpl::GetKeyGeneratorCurrentNumber( + int64_t object_store_id, + int64_t* current_number) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreTransactionImpl::MaybeUpdateKeyGeneratorCurrentNumber( + int64_t object_store_id, + int64_t new_state, + bool check_current) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreTransactionImpl::KeyExistsInObjectStore( + int64_t object_store_id, + const blink::IndexedDBKey& key, + BackingStore::RecordIdentifier* found_record_identifier, + bool* found) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreTransactionImpl::PutIndexDataForRecord( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKey& key, + const BackingStore::RecordIdentifier& record) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreTransactionImpl::GetPrimaryKeyViaIndex( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKey& key, + std::unique_ptr<blink::IndexedDBKey>* primary_key) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +Status BackingStoreTransactionImpl::KeyExistsInIndex( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKey& key, + std::unique_ptr<blink::IndexedDBKey>* found_primary_key, + bool* exists) { + NOTIMPLEMENTED(); + return Status::OK(); +} + +std::unique_ptr<BackingStore::Cursor> +BackingStoreTransactionImpl::OpenObjectStoreKeyCursor( + int64_t object_store_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection, + Status*) { + NOTIMPLEMENTED(); + return nullptr; +} + +std::unique_ptr<BackingStore::Cursor> +BackingStoreTransactionImpl::OpenObjectStoreCursor( + int64_t object_store_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection, + Status*) { + NOTIMPLEMENTED(); + return nullptr; +} + +std::unique_ptr<BackingStore::Cursor> +BackingStoreTransactionImpl::OpenIndexKeyCursor( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection, + Status*) { + NOTIMPLEMENTED(); + return nullptr; +} + +std::unique_ptr<BackingStore::Cursor> +BackingStoreTransactionImpl::OpenIndexCursor( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection, + Status*) { + NOTIMPLEMENTED(); + return nullptr; +} + +BackingStoreVersionChangeTransaction::BackingStoreVersionChangeTransaction( + base::WeakPtr<BackingStoreDatabaseImpl> db, + BackingStoreDatabaseImpl::UpgradePassKey pass_key) + : BackingStoreTransactionImpl(db), pass_key_(std::move(pass_key)) {} + +BackingStoreVersionChangeTransaction::~BackingStoreVersionChangeTransaction() = + default; + +void BackingStoreVersionChangeTransaction::Rollback() { + BackingStoreTransactionImpl::Rollback(); + db_->RollbackUpgrade(pass_key_); +} + +Status BackingStoreVersionChangeTransaction::SetDatabaseVersion( + int64_t version) { + return db_->SetDatabaseVersion(pass_key_, version); +} + +} // namespace content::indexed_db::sqlite
diff --git a/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.h b/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.h new file mode 100644 index 0000000..5d97093e --- /dev/null +++ b/content/browser/indexed_db/instance/sqlite/backing_store_transaction_impl.h
@@ -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. + +#ifndef CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_TRANSACTION_IMPL_H_ +#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_TRANSACTION_IMPL_H_ + +#include "base/memory/weak_ptr.h" +#include "content/browser/indexed_db/instance/backing_store.h" +#include "content/browser/indexed_db/instance/sqlite/backing_store_database_impl.h" +#include "sql/transaction.h" + +namespace content::indexed_db::sqlite { + +class BackingStoreTransactionImpl : public BackingStore::Transaction { + public: + explicit BackingStoreTransactionImpl( + base::WeakPtr<BackingStoreDatabaseImpl> db); + BackingStoreTransactionImpl(const BackingStoreTransactionImpl&) = delete; + BackingStoreTransactionImpl& operator=(const BackingStoreTransactionImpl&) = + delete; + ~BackingStoreTransactionImpl() override; + + // BackingStore::Transaction: + void Begin(std::vector<PartitionedLock> locks) override; + Status CommitPhaseOne(BlobWriteCallback callback) override; + Status CommitPhaseTwo() override; + void Rollback() override; + void Reset() override {} + Status SetDatabaseVersion(int64_t version) override; + Status CreateObjectStore(int64_t object_store_id, + const std::u16string& name, + blink::IndexedDBKeyPath key_path, + bool auto_increment) override; + Status DeleteObjectStore(int64_t object_store_id) override; + Status RenameObjectStore(int64_t object_store_id, + const std::u16string& new_name) override; + Status ClearObjectStore(int64_t object_store_id) override; + Status CreateIndex(int64_t object_store_id, + int64_t index_id, + const std::u16string& name, + blink::IndexedDBKeyPath key_path, + bool is_unique, + bool is_multi_entry) override; + Status DeleteIndex(int64_t object_store_id, int64_t index_id) override; + Status RenameIndex(int64_t object_store_id, + int64_t index_id, + const std::u16string& new_name) override; + Status GetRecord(int64_t object_store_id, + const blink::IndexedDBKey& key, + IndexedDBValue* record) override; + Status PutRecord(int64_t object_store_id, + const blink::IndexedDBKey& key, + IndexedDBValue* value, + BackingStore::RecordIdentifier* record) override; + Status DeleteRange(int64_t object_store_id, + const blink::IndexedDBKeyRange&) override; + Status GetKeyGeneratorCurrentNumber(int64_t object_store_id, + int64_t* current_number) override; + Status MaybeUpdateKeyGeneratorCurrentNumber(int64_t object_store_id, + int64_t new_state, + bool check_current) override; + Status KeyExistsInObjectStore( + int64_t object_store_id, + const blink::IndexedDBKey& key, + BackingStore::RecordIdentifier* found_record_identifier, + bool* found) override; + Status PutIndexDataForRecord( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKey& key, + const BackingStore::RecordIdentifier& record) override; + Status GetPrimaryKeyViaIndex( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKey& key, + std::unique_ptr<blink::IndexedDBKey>* primary_key) override; + Status KeyExistsInIndex( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKey& key, + std::unique_ptr<blink::IndexedDBKey>* found_primary_key, + bool* exists) override; + std::unique_ptr<BackingStore::Cursor> OpenObjectStoreKeyCursor( + int64_t object_store_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection, + Status*) override; + std::unique_ptr<BackingStore::Cursor> OpenObjectStoreCursor( + int64_t object_store_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection, + Status*) override; + std::unique_ptr<BackingStore::Cursor> OpenIndexKeyCursor( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection, + Status*) override; + std::unique_ptr<BackingStore::Cursor> OpenIndexCursor( + int64_t object_store_id, + int64_t index_id, + const blink::IndexedDBKeyRange& key_range, + blink::mojom::IDBCursorDirection, + Status*) override; + + protected: + base::WeakPtr<BackingStoreDatabaseImpl> db_; + sql::Transaction transaction_; +}; + +class BackingStoreVersionChangeTransaction + : public BackingStoreTransactionImpl { + public: + BackingStoreVersionChangeTransaction( + base::WeakPtr<BackingStoreDatabaseImpl> db, + BackingStoreDatabaseImpl::UpgradePassKey pass_key); + BackingStoreVersionChangeTransaction( + const BackingStoreVersionChangeTransaction&) = delete; + BackingStoreVersionChangeTransaction& operator=( + const BackingStoreVersionChangeTransaction&) = delete; + ~BackingStoreVersionChangeTransaction() override; + + // BackingStore::Transaction: + void Rollback() override; + Status SetDatabaseVersion(int64_t version) override; + // TODO(crbug.com/40253999): Implement the other relevant methods. + + private: + BackingStoreDatabaseImpl::UpgradePassKey pass_key_; +}; + +} // namespace content::indexed_db::sqlite + +#endif // CONTENT_BROWSER_INDEXED_DB_INSTANCE_SQLITE_BACKING_STORE_TRANSACTION_IMPL_H_
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc index 03c7429..a6a63ac 100644 --- a/content/browser/media/capture/desktop_capture_device.cc +++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -57,6 +57,10 @@ #include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h" #include "ui/gfx/icc_profile.h" +#if BUILDFLAG(IS_WIN) +#include "base/win/windows_version.h" +#endif + namespace content { namespace { @@ -151,6 +155,43 @@ } } +#if BUILDFLAG(IS_WIN) +bool IsWgcEnabledForScreenCapture() { + bool enabled = + base::FeatureList::IsEnabled(features::kWebRtcAllowWgcScreenCapturer); + if (enabled) { + return true; + } + + if (base::FeatureList::GetInstance() && + base::FeatureList::GetInstance()->IsFeatureOverridden( + features::kWebRtcAllowWgcScreenCapturer.name)) { + return enabled; + } + + // Starting from WIN11 24H2 (build 26100), the Capture API returns empty + // frame when the captured content is unchanged, helping to maintain + // performance for 0Hz capture scenarios. + enabled = (base::win::GetVersion() >= base::win::Version::WIN11_24H2); + return enabled; +} + +bool IsWgcZeroHzEnabledForScreenCapture() { + bool enabled = + base::FeatureList::IsEnabled(features::kWebRtcAllowWgcScreenZeroHz); + if (enabled) { + return true; + } + + if (base::FeatureList::GetInstance() && + base::FeatureList::GetInstance()->IsFeatureOverridden( + features::kWebRtcAllowWgcScreenZeroHz.name)) { + return enabled; + } + return IsWgcEnabledForScreenCapture(); +} +#endif // BUILDFLAG(IS_WIN) + // Helper class which request that the system-global Windows timer interrupt // frequency be raised at construction. The corresponding deactivation is done // at destruction. How high the frequency is raised depends on the system's @@ -871,7 +912,7 @@ // set to true. GDI does not use this option. options.set_prefer_cursor_embedded(true); - if (base::FeatureList::IsEnabled(features::kWebRtcAllowWgcScreenCapturer)) { + if (IsWgcEnabledForScreenCapture()) { options.set_allow_wgc_screen_capturer(true); // 0Hz support is by default disabled for WGC but it can be enabled using @@ -882,8 +923,7 @@ // has changed and contain one (damage) region corresponding to the complete // screen or window being captured if any change is detected. if (source.type == DesktopMediaID::TYPE_SCREEN) { - options.set_allow_wgc_zero_hertz( - base::FeatureList::IsEnabled(features::kWebRtcAllowWgcScreenZeroHz)); + options.set_allow_wgc_zero_hertz(IsWgcZeroHzEnabledForScreenCapture()); } } if (base::FeatureList::IsEnabled(features::kWebRtcAllowWgcWindowCapturer)) { @@ -1009,12 +1049,10 @@ #endif bool zero_hertz_is_supported = true; #if BUILDFLAG(IS_WIN) - const bool wgc_screen_zero_hertz = - base::FeatureList::IsEnabled(features::kWebRtcAllowWgcScreenZeroHz); + const bool wgc_screen_zero_hertz = IsWgcZeroHzEnabledForScreenCapture(); const bool wgc_window_zero_hertz = base::FeatureList::IsEnabled(features::kWebRtcAllowWgcWindowZeroHz); - const bool wgc_screen_capturer = - base::FeatureList::IsEnabled(features::kWebRtcAllowWgcScreenCapturer); + const bool wgc_screen_capturer = IsWgcEnabledForScreenCapture(); const bool wgc_window_capturer = base::FeatureList::IsEnabled(features::kWebRtcAllowWgcWindowCapturer); if (!wgc_window_capturer && !wgc_screen_capturer) {
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc index e8d7389..1fd69fc 100644 --- a/content/browser/preloading/prerender/prerender_browsertest.cc +++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -4101,8 +4101,9 @@ private: void DidFinishNavigation(NavigationHandle* handle) override { - if (handle->GetURL() != url_) + if (handle->GetURL() != url_) { return; + } redirect_chain_ = handle->GetRedirectChain(); } @@ -5409,8 +5410,9 @@ private: void DidStartNavigation(NavigationHandle* handle) override { - if (handle->GetURL() != url_) + if (handle->GetURL() != url_) { return; + } did_navigate_ = true; was_activation_ = handle->IsPrerenderedPageActivation(); } @@ -5470,20 +5472,16 @@ // WillStartRequest into all new navigations. ShellContentBrowserClient::Get() ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting( - [&throttle](NavigationHandle* handle) - -> std::vector<std::unique_ptr<NavigationThrottle>> { - std::vector<std::unique_ptr<NavigationThrottle>> throttles; - - auto throttle_ptr = - std::make_unique<TestNavigationThrottle>(handle); + [&throttle](NavigationThrottleRegistry& registry) -> void { + auto throttle_ptr = std::make_unique<TestNavigationThrottle>( + ®istry.GetNavigationHandle()); CHECK(!throttle); throttle = throttle_ptr.get(); throttle_ptr->SetResponse( TestNavigationThrottle::WILL_START_REQUEST, TestNavigationThrottle::SYNCHRONOUS, NavigationThrottle::DEFER); - throttles.push_back(std::move(throttle_ptr)); - return throttles; + registry.AddThrottle(std::move(throttle_ptr)); })); // Start a prerender and ensure that a NavigationThrottle can defer the @@ -5768,13 +5766,11 @@ // before PrerenderSubframeNavigationThrottle. ShellContentBrowserClient::Get() ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting( - [](NavigationHandle* handle) - -> std::vector<std::unique_ptr<NavigationThrottle>> { - std::vector<std::unique_ptr<NavigationThrottle>> throttles; - throttles.push_back( + [](NavigationThrottleRegistry& registry) -> void { + registry.AddThrottle( std::make_unique< - TestPrerenderCancellerSubframeNavigationThrottle>(handle)); - return throttles; + TestPrerenderCancellerSubframeNavigationThrottle>( + ®istry.GetNavigationHandle())); })); // Use ExecuteScriptAsync instead of EvalJs as inserted cross-origin iframe @@ -6654,8 +6650,9 @@ // Skip the test when the block type is kCertError. With the type, this test // times out due to https://crbug.com/1311887. // TODO(crbug.com/40220378): Enable the test with kCertError. - if (GetParam() == SSLPrerenderTestErrorBlockType::kCertError) + if (GetParam() == SSLPrerenderTestErrorBlockType::kCertError) { return; + } // Load an initial page and register a service worker that intercepts // resources requests. @@ -8061,8 +8058,9 @@ // Confirm that all the other prerender hosts are successfully cancelled. for (auto& url : prerender_urls) { - if (url == prerender_urls[0]) + if (url == prerender_urls[0]) { continue; + } EXPECT_TRUE(GetHostForUrl(url).is_null()); } @@ -11999,10 +11997,11 @@ void FrameDisplayStateChanged(RenderFrameHost* host, bool is_display_none) override { if (host == target_host_) { - if (callback_) + if (callback_) { std::move(callback_).Run(); - else + } else { changed_count_++; + } } } @@ -12509,8 +12508,9 @@ // Note: Checking the origin of `request.GetURL()` doesn't work here because // the host part of the URL is translated (e.g., "a.test" to "127.0.0.1") // based on the host resolver rule before this point. - if (request.relative_url.find("cors") == std::string::npos) + if (request.relative_url.find("cors") == std::string::npos) { return nullptr; + } // Serves a fake response with the ACAO header. auto response = std::make_unique<net::test_server::BasicHttpResponse>(); @@ -13257,8 +13257,9 @@ // child frames. size_t child_frame_count = 0; prerendered_rfh->ForEachRenderFrameHostImpl([&](RenderFrameHostImpl* rfh) { - if (rfh != prerendered_rfh) + if (rfh != prerendered_rfh) { child_frame_count++; + } }); EXPECT_EQ(0lu, child_frame_count); @@ -13444,8 +13445,9 @@ static std::unique_ptr<net::test_server::HttpResponse> HandleRequest( const net::test_server::HttpRequest& request) { - if (request.relative_url.find("acceptch") == std::string::npos) + if (request.relative_url.find("acceptch") == std::string::npos) { return nullptr; + } // Serve a response indicating clients to provide full version of UA. auto response = std::make_unique<net::test_server::BasicHttpResponse>();
diff --git a/content/browser/renderer_host/navigation_request_browsertest.cc b/content/browser/renderer_host/navigation_request_browsertest.cc index 552a481..f16f62c 100644 --- a/content/browser/renderer_host/navigation_request_browsertest.cc +++ b/content/browser/renderer_host/navigation_request_browsertest.cc
@@ -272,32 +272,36 @@ TestNavigationThrottle* navigation_throttle() { return navigation_throttle_; } void WaitForThrottleWillStart() { - if (will_start_called_) + if (will_start_called_) { return; + } will_start_loop_runner_ = new MessageLoopRunner(); will_start_loop_runner_->Run(); will_start_loop_runner_ = nullptr; } void WaitForThrottleWillRedirect() { - if (will_redirect_called_) + if (will_redirect_called_) { return; + } will_redirect_loop_runner_ = new MessageLoopRunner(); will_redirect_loop_runner_->Run(); will_redirect_loop_runner_ = nullptr; } void WaitForThrottleWillFail() { - if (will_fail_called_) + if (will_fail_called_) { return; + } will_fail_loop_runner_ = new MessageLoopRunner(); will_fail_loop_runner_->Run(); will_fail_loop_runner_ = nullptr; } void WaitForThrottleWillProcess() { - if (will_process_called_) + if (will_process_called_) { return; + } will_process_loop_runner_ = new MessageLoopRunner(); will_process_loop_runner_->Run(); will_process_loop_runner_ = nullptr; @@ -314,10 +318,11 @@ void Continue(NavigationThrottle::ThrottleCheckResult result) { ASSERT_NE(NavigationThrottle::DEFER, result.action()); - if (result.action() == NavigationThrottle::PROCEED) + if (result.action() == NavigationThrottle::PROCEED) { navigation_throttle()->ResumeNavigation(); - else + } else { navigation_throttle()->CancelNavigation(result); + } } int will_start_called() { return will_start_called_; } @@ -333,26 +338,30 @@ protected: virtual void DidCallWillStartRequest() { will_start_called_++; - if (will_start_loop_runner_) + if (will_start_loop_runner_) { will_start_loop_runner_->Quit(); + } } virtual void DidCallWillRedirectRequest() { will_redirect_called_++; - if (will_redirect_loop_runner_) + if (will_redirect_loop_runner_) { will_redirect_loop_runner_->Quit(); + } } virtual void DidCallWillFailRequest() { will_fail_called_++; - if (will_fail_loop_runner_) + if (will_fail_loop_runner_) { will_fail_loop_runner_->Quit(); + } } virtual void DidCallWillProcessResponse() { will_process_called_++; - if (will_process_loop_runner_) + if (will_process_loop_runner_) { will_process_loop_runner_->Quit(); + } } virtual void DidCallWillCommitWithoutUrlLoader() { @@ -365,8 +374,9 @@ private: void DidStartNavigation(NavigationHandle* handle) override { if (!expected_start_url_.is_empty() && - handle->GetURL() != expected_start_url_) + handle->GetURL() != expected_start_url_) { return; + } std::unique_ptr<NavigationThrottle> throttle(new TestNavigationThrottle( handle, will_start_result_, will_redirect_result_, will_fail_result_, @@ -391,11 +401,13 @@ } void DidFinishNavigation(NavigationHandle* handle) override { - if (!navigation_throttle_) + if (!navigation_throttle_) { return; + } - if (handle == navigation_throttle_->navigation_handle()) + if (handle == navigation_throttle_->navigation_handle()) { navigation_throttle_ = nullptr; + } } NavigationThrottle::ThrottleCheckResult will_start_result_; @@ -2663,19 +2675,17 @@ // |client_throttle| when its registered. content::ShellContentBrowserClient::Get() ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting( - [&client_throttle](content::NavigationHandle* handle) - -> std::vector<std::unique_ptr<content::NavigationThrottle>> { - std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; + [&client_throttle]( + content::NavigationThrottleRegistry& registry) -> void { std::unique_ptr<TestNavigationThrottle> throttle( new TestNavigationThrottle( - handle, NavigationThrottle::DEFER, + ®istry.GetNavigationHandle(), NavigationThrottle::DEFER, NavigationThrottle::PROCEED, NavigationThrottle::PROCEED, NavigationThrottle::PROCEED, NavigationThrottle::PROCEED, base::DoNothing(), base::DoNothing(), base::DoNothing(), base::DoNothing(), base::DoNothing())); client_throttle = throttle.get(); - throttles.push_back(std::move(throttle)); - return throttles; + registry.AddThrottle(std::move(throttle)); })); // Add another similar throttle using the installer which will use @@ -2938,8 +2948,9 @@ auto add_suffix = [&names](std::vector<std::string> suffixes) { size_t original_size = names.size(); for (size_t i = 0; i < original_size; i++) { - for (const std::string& suffix : suffixes) + for (const std::string& suffix : suffixes) { names.push_back(names[i] + suffix); + } } }; add_suffix({kProcessSuffixes.at(process_type)}); @@ -4493,9 +4504,9 @@ DCHECK_EQ(navigation_handle->GetNavigatingFrameType(), GetParam() == TestMPArchType::kPrerender ? FrameType::kPrerenderMainFrame - : GetParam() == TestMPArchType::kFencedFrame - ? FrameType::kFencedFrameRoot - : FrameType::kPrimaryMainFrame); + : GetParam() == TestMPArchType::kFencedFrame + ? FrameType::kFencedFrameRoot + : FrameType::kPrimaryMainFrame); EXPECT_FALSE(navigation_handle->ShouldUpdateHistory()); })); }; @@ -4689,14 +4700,12 @@ // to this throttle in `client_throttle` on registration. content::ShellContentBrowserClient::Get() ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting( - [&client_throttle](content::NavigationHandle* handle) - -> std::vector<std::unique_ptr<content::NavigationThrottle>> { - std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; - auto throttle = - std::make_unique<ResponseBodyNavigationThrottle>(handle); + [&client_throttle]( + content::NavigationThrottleRegistry& registry) -> void { + auto throttle = std::make_unique<ResponseBodyNavigationThrottle>( + ®istry.GetNavigationHandle()); client_throttle = throttle.get(); - throttles.push_back(std::move(throttle)); - return throttles; + registry.AddThrottle(std::move(throttle)); })); // Start navigating. @@ -4732,14 +4741,12 @@ // to this throttle in `client_throttle` on registration. content::ShellContentBrowserClient::Get() ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting( - [&client_throttle](content::NavigationHandle* handle) - -> std::vector<std::unique_ptr<content::NavigationThrottle>> { - std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; - auto throttle = - std::make_unique<ResponseBodyNavigationThrottle>(handle); + [&client_throttle]( + content::NavigationThrottleRegistry& registry) -> void { + auto throttle = std::make_unique<ResponseBodyNavigationThrottle>( + ®istry.GetNavigationHandle()); client_throttle = throttle.get(); - throttles.push_back(std::move(throttle)); - return throttles; + registry.AddThrottle(std::move(throttle)); })); // Start navigating. @@ -4775,14 +4782,12 @@ // to this throttle in `client_throttle` on registration. content::ShellContentBrowserClient::Get() ->set_create_throttles_for_navigation_callback(base::BindLambdaForTesting( - [&client_throttle](content::NavigationHandle* handle) - -> std::vector<std::unique_ptr<content::NavigationThrottle>> { - std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; - auto throttle = - std::make_unique<ResponseBodyNavigationThrottle>(handle); + [&client_throttle]( + content::NavigationThrottleRegistry& registry) -> void { + auto throttle = std::make_unique<ResponseBodyNavigationThrottle>( + ®istry.GetNavigationHandle()); client_throttle = throttle.get(); - throttles.push_back(std::move(throttle)); - return throttles; + registry.AddThrottle(std::move(throttle)); })); // Start navigating to a page with a large body (>5 million characters).
diff --git a/content/browser/renderer_host/navigation_request_unittest.cc b/content/browser/renderer_host/navigation_request_unittest.cc index 10505c2e..d4a96ab 100644 --- a/content/browser/renderer_host/navigation_request_unittest.cc +++ b/content/browser/renderer_host/navigation_request_unittest.cc
@@ -592,13 +592,11 @@ }; class ThrottleTestContentBrowserClient : public ContentBrowserClient { - std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( NavigationThrottleRegistry& registry) override { - std::vector<std::unique_ptr<NavigationThrottle>> throttle; registry.AddThrottle( std::make_unique<GetRenderFrameHostOnFailureNavigationThrottle>( ®istry.GetNavigationHandle())); - return throttle; } };
diff --git a/content/browser/renderer_host/navigation_throttle_runner.cc b/content/browser/renderer_host/navigation_throttle_runner.cc index 455a6c9a..b4f7e218 100644 --- a/content/browser/renderer_host/navigation_throttle_runner.cc +++ b/content/browser/renderer_host/navigation_throttle_runner.cc
@@ -218,16 +218,7 @@ // NavigationRequest. NavigationRequest* request = static_cast<NavigationRequest*>(delegate_); - std::vector<std::unique_ptr<NavigationThrottle>> throttles_under_migration = - request->GetDelegate()->CreateThrottlesForNavigation(*this); - // TODO(https://crbug.com/412524375): Remove `throttles_under_migration` and - // following code to move them to the member variable. When the call returns - // above, migrated throttles are already registered in `throttles_` via the - // new NavigationThrottleRegistry interface. So, we cannot assign the returned - // vector directly to `throttles_`. - throttles_.insert(throttles_.end(), - std::make_move_iterator(throttles_under_migration.begin()), - std::make_move_iterator(throttles_under_migration.end())); + request->GetDelegate()->CreateThrottlesForNavigation(*this); // Check for renderer-inititated main frame navigations to blocked URL schemes // (data, filesystem). This is done early as it may block the main frame
diff --git a/content/browser/renderer_host/navigator_delegate.h b/content/browser/renderer_host/navigator_delegate.h index dd41492b..645edb8 100644 --- a/content/browser/renderer_host/navigator_delegate.h +++ b/content/browser/renderer_host/navigator_delegate.h
@@ -120,12 +120,8 @@ // Returns the NavigationThrottles to add to this navigation. Normally these // are defined by the content/ embedder, except in the case of interstitials // where no NavigationThrottles are added to the navigation. - // TODO(https://crbug.com/412524375): New code should add a NavigationThrottle - // via the given `registry` instead of returning a NavigationThrottle from - // this method. Once all existing NavigationThrottles are migrated, the - // returned type will be changed to `void`. - virtual std::vector<std::unique_ptr<NavigationThrottle>> - CreateThrottlesForNavigation(NavigationThrottleRegistry& registry) = 0; + virtual void CreateThrottlesForNavigation( + NavigationThrottleRegistry& registry) = 0; // Returns commit deferring conditions to add to this navigation. virtual std::vector<std::unique_ptr<CommitDeferringCondition>>
diff --git a/content/browser/service_worker/service_worker_quota_client.cc b/content/browser/service_worker/service_worker_quota_client.cc index d3842b9..afd55e7 100644 --- a/content/browser/service_worker/service_worker_quota_client.cc +++ b/content/browser/service_worker/service_worker_quota_client.cc
@@ -18,7 +18,6 @@ #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/origin.h" -using ::blink::mojom::StorageType; using ::storage::mojom::QuotaClient; namespace content {
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index b64480c..0698239c 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -2018,15 +2018,16 @@ // routing_id are invalid. It can't be added yet because somehow routing_id // is valid here. if (service_worker_context_->context()) { - auto* container_host = service_worker_context_->context() - ->service_worker_client_owner() - .GetServiceWorkerClientByWindowId(*window_id); - if (container_host) { - if (container_host->GetRenderFrameHostId()) { - // Use ServiceWorkerContainerHost's GlobalRenderFrameHostId when - // the navigation commit has already started. + auto* service_worker_client = + service_worker_context_->context() + ->service_worker_client_owner() + .GetServiceWorkerClientByWindowId(*window_id); + if (service_worker_client) { + if (service_worker_client->GetRenderFrameHostId()) { + // Use ServiceWorkerClient's GlobalRenderFrameHostId when the + // navigation commit has already started. GlobalRenderFrameHostId render_frame_host_id = - container_host->GetRenderFrameHostId(); + service_worker_client->GetRenderFrameHostId(); context = URLLoaderNetworkContext::CreateForRenderFrameHost( render_frame_host_id); @@ -2035,8 +2036,9 @@ is_primary_main_frame_navigation = false; is_navigation_request = false; } else if (NavigationRequest* ongoing_navigation = - container_host->GetOngoingNavigationRequestBeforeCommit( - base::PassKey<StoragePartitionImpl>())) { + service_worker_client + ->GetOngoingNavigationRequestBeforeCommit( + base::PassKey<StoragePartitionImpl>())) { // This auth request is for an ongoing navigation controlled // by service worker. The navigation request can be nullptr if user // has closed the WebContents. @@ -2303,20 +2305,22 @@ // routing_id are invalid. It can't be added yet because somehow routing_id // is valid here. if (service_worker_context_->context()) { - auto* container_host = service_worker_context_->context() - ->service_worker_client_owner() - .GetServiceWorkerClientByWindowId(*window_id); - if (container_host) { - if (container_host->GetRenderFrameHostId()) { - // Use ServiceWorkerContainerHost's GlobalRenderFrameHostId when - // the navigation commit has already started. + auto* service_worker_client = + service_worker_context_->context() + ->service_worker_client_owner() + .GetServiceWorkerClientByWindowId(*window_id); + if (service_worker_client) { + if (service_worker_client->GetRenderFrameHostId()) { + // Use ServiceWorkerClient's GlobalRenderFrameHostId when the + // navigation commit has already started. GlobalRenderFrameHostId render_frame_host_id = - container_host->GetRenderFrameHostId(); + service_worker_client->GetRenderFrameHostId(); context = URLLoaderNetworkContext::CreateForRenderFrameHost( render_frame_host_id); } else if (NavigationRequest* ongoing_navigation = - container_host->GetOngoingNavigationRequestBeforeCommit( - base::PassKey<StoragePartitionImpl>())) { + service_worker_client + ->GetOngoingNavigationRequestBeforeCommit( + base::PassKey<StoragePartitionImpl>())) { // This certification request is for an ongoing navigation. // Overwrite the context; set `type` to kNavigationRequestContext. // TODO(crbug.com/40784852): Optimize locating logic.
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 45b84cb..6d39dcc1 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -9534,13 +9534,12 @@ return GetPageVisibilityState() == PageVisibilityState::kHidden; } -std::vector<std::unique_ptr<NavigationThrottle>> -WebContentsImpl::CreateThrottlesForNavigation( +void WebContentsImpl::CreateThrottlesForNavigation( NavigationThrottleRegistry& registry) { OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::CreateThrottlesForNavigation", "navigation", registry.GetNavigationHandle()); - return GetContentClient()->browser()->CreateThrottlesForNavigation(registry); + GetContentClient()->browser()->CreateThrottlesForNavigation(registry); } std::vector<std::unique_ptr<CommitDeferringCondition>>
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index eabf30ff..98fdc7f7 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -1067,7 +1067,7 @@ bool is_outermost_main_frame_navigation) override; const blink::UserAgentOverride& GetUserAgentOverride( FrameTree& frame_tree) override; - std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( NavigationThrottleRegistry& registry) override; std::vector<std::unique_ptr<CommitDeferringCondition>> CreateDeferringConditionsForNavigationCommit(
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index e5b951c..1bd76e3 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -469,8 +469,12 @@ FederatedAuthRequestImpl::IdentityProviderGetInfo::IdentityProviderGetInfo( blink::mojom::IdentityProviderRequestOptionsPtr provider, blink::mojom::RpContext rp_context, - blink::mojom::RpMode rp_mode) - : provider(std::move(provider)), rp_context(rp_context), rp_mode(rp_mode) {} + blink::mojom::RpMode rp_mode, + std::optional<blink::mojom::Format> format) + : provider(std::move(provider)), + rp_context(rp_context), + rp_mode(rp_mode), + format(format) {} FederatedAuthRequestImpl::IdentityProviderGetInfo::~IdentityProviderGetInfo() = default; @@ -485,6 +489,7 @@ provider = other.provider->Clone(); rp_context = other.rp_context; rp_mode = other.rp_mode; + format = other.format; return *this; } @@ -493,12 +498,14 @@ IdpNetworkRequestManager::Endpoints endpoints, IdentityProviderMetadata metadata, blink::mojom::RpContext rp_context, - blink::mojom::RpMode rp_mode) + blink::mojom::RpMode rp_mode, + std::optional<blink::mojom::Format> format) : provider(provider->Clone()), endpoints(std::move(endpoints)), metadata(std::move(metadata)), rp_context(rp_context), - rp_mode(rp_mode) {} + rp_mode(rp_mode), + format(format) {} FederatedAuthRequestImpl::IdentityProviderInfo::~IdentityProviderInfo() = default; @@ -511,6 +518,7 @@ rp_context = other.rp_context; rp_mode = other.rp_mode; data = other.data; + format = other.format; } FederatedAuthRequestImpl::FederatedAuthRequestImpl( @@ -1018,9 +1026,11 @@ blink::mojom::RpContext rp_context = idp_get_params_ptr->context; blink::mojom::RpMode rp_mode = idp_get_params_ptr->mode; const GURL& idp_config_url = idp_ptr->config->config_url; + std::optional<blink::mojom::Format> format = + IsFedCmDelegationEnabled() ? idp_ptr->format : std::nullopt; token_request_get_infos_.emplace( - idp_config_url, - IdentityProviderGetInfo(std::move(idp_ptr), rp_context, rp_mode)); + idp_config_url, IdentityProviderGetInfo(std::move(idp_ptr), + rp_context, rp_mode, format)); } } if (any_idp_has_parameters || any_idp_has_custom_scopes) { @@ -1296,7 +1306,8 @@ get_info_it->second.provider, std::move(fetch_result.endpoints), fetch_result.metadata ? std::move(*fetch_result.metadata) : IdentityProviderMetadata(), - get_info_it->second.rp_context, get_info_it->second.rp_mode); + get_info_it->second.rp_context, get_info_it->second.rp_mode, + get_info_it->second.format); if (fetch_result.error) { const FederatedProviderFetcher::FetchError& fetch_error = @@ -1535,7 +1546,7 @@ ClientMetadata{client_metadata.terms_of_service_url, client_metadata.privacy_policy_url, client_metadata.brand_icon_url, rp_brand_icon}, - idp_info->rp_context, disclosure_fields, + idp_info->rp_context, idp_info->format, disclosure_fields, /*has_login_status_mismatch=*/false); for (auto& account : accounts) { account->identity_provider = idp_info->data; @@ -2016,7 +2027,8 @@ idp_info->data = base::MakeRefCounted<IdentityProviderData>( idp_for_display, idp_info->metadata, ClientMetadata{GURL(), GURL(), GURL(), gfx::Image()}, - idp_info->rp_context, GetDisclosureFields(*idp_info->provider), + idp_info->rp_context, idp_info->format, + GetDisclosureFields(*idp_info->provider), /*has_login_status_mismatch=*/true); idp_infos_[idp_config_url] = std::move(idp_info);
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h index 6b90f6c..688067a 100644 --- a/content/browser/webid/federated_auth_request_impl.h +++ b/content/browser/webid/federated_auth_request_impl.h
@@ -159,7 +159,8 @@ struct IdentityProviderGetInfo { IdentityProviderGetInfo(blink::mojom::IdentityProviderRequestOptionsPtr, blink::mojom::RpContext rp_context, - blink::mojom::RpMode rp_mode); + blink::mojom::RpMode rp_mode, + std::optional<blink::mojom::Format> format); ~IdentityProviderGetInfo(); IdentityProviderGetInfo(const IdentityProviderGetInfo&); IdentityProviderGetInfo& operator=(const IdentityProviderGetInfo& other); @@ -167,6 +168,7 @@ blink::mojom::IdentityProviderRequestOptionsPtr provider; blink::mojom::RpContext rp_context{blink::mojom::RpContext::kSignIn}; blink::mojom::RpMode rp_mode{blink::mojom::RpMode::kPassive}; + std::optional<blink::mojom::Format> format; }; struct IdentityProviderInfo { @@ -174,7 +176,8 @@ IdpNetworkRequestManager::Endpoints, IdentityProviderMetadata, blink::mojom::RpContext rp_context, - blink::mojom::RpMode rp_mode); + blink::mojom::RpMode rp_mode, + std::optional<blink::mojom::Format> format); ~IdentityProviderInfo(); IdentityProviderInfo(const IdentityProviderInfo&); @@ -184,6 +187,7 @@ bool has_failing_idp_signin_status{false}; blink::mojom::RpContext rp_context{blink::mojom::RpContext::kSignIn}; blink::mojom::RpMode rp_mode{blink::mojom::RpMode::kPassive}; + std::optional<blink::mojom::Format> format; IdentityProviderDataPtr data; gfx::Image decoded_idp_brand_icon; };
diff --git a/content/browser/webid/webid_browsertest.cc b/content/browser/webid/webid_browsertest.cc index 2987d53..58685f59 100644 --- a/content/browser/webid/webid_browsertest.cc +++ b/content/browser/webid/webid_browsertest.cc
@@ -29,6 +29,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/values_test_util.h" #include "base/values.h" +#include "build/build_config.h" #include "components/network_session_configurator/common/network_switches.h" #include "content/browser/in_memory_federated_permission_context.h" #include "content/browser/webid/fake_identity_request_dialog_controller.h" @@ -2115,6 +2116,9 @@ EXPECT_EQ(suggestions->size(), 1ul); auto account = (*suggestions)[0]; + + EXPECT_EQ(account->identity_provider->format, blink::mojom::Format::kSdJwt); + source->NotifyAutofillSuggestionAccepted( account->identity_provider->idp_metadata.config_url, account->id, /*show_modal=*/true, base::NullCallback()); @@ -2139,6 +2143,87 @@ testing::UnorderedElementsAre("Sam")); } +// Flaky on mac, https://crbug.com/415953689 +#if BUILDFLAG(IS_MAC) +#define MAYBE_ConditionalMediationForMediatedRequest \ + DISABLED_ConditionalMediationForMediatedRequest +#else +#define MAYBE_ConditionalMediationForMediatedRequest \ + ConditionalMediationForMediatedRequest +#endif +IN_PROC_BROWSER_TEST_F(WebIdDelegationBrowserTest, + MAYBE_ConditionalMediationForMediatedRequest) { + idp_server()->SetConfigResponseDetails(BuildValidConfigDetails()); + + auto mock = std::make_unique< + ::testing::NiceMock<MockIdentityRequestDialogController>>(); + // Keep a copy of the pointer before the std::move. + MockIdentityRequestDialogController* controller = mock.get(); + test_browser_client_->SetIdentityRequestDialogController(std::move(mock)); + + auto configURL = BaseIdpUrl(); + + base::RunLoop run_loop; + + EXPECT_TRUE(NavigateToURL(shell(), GURL(configURL))); + + std::string script = R"( + var token = navigator.credentials.get({ + mediation: 'conditional', + identity: { + providers: [{ + fields: ['name'], + configURL: ')" + + configURL + R"(', + clientId: 'client_id_1', + nonce: '12345', + }], + }, + }).then(({token}) => token) + )"; + + // Await until the accounts are available for autofill. + EXPECT_CALL(*controller, NotifyAutofillSourceReadyForTesting) + .WillOnce([&run_loop]() { run_loop.Quit(); }); + + auto promise = EvalJs(shell(), script, EXECUTE_SCRIPT_NO_RESOLVE_PROMISES); + + run_loop.Run(); + + // Gets the pending conditional request. + auto* source = FederatedAuthAutofillSource::FromPage( + shell()->web_contents()->GetPrimaryPage()); + + EXPECT_TRUE(source != nullptr); + + // Gets all the autofill suggestion and selects the first one. + auto suggestions = source->GetAutofillSuggestions(); + EXPECT_TRUE(suggestions); + EXPECT_EQ(suggestions->size(), 1ul); + + auto account = (*suggestions)[0]; + + // Mediated FedCM has an empty format. + EXPECT_EQ(account->identity_provider->format, std::nullopt); + + base::RunLoop callback; + + source->NotifyAutofillSuggestionAccepted( + account->identity_provider->idp_metadata.config_url, account->id, + /*show_modal=*/false, + base::BindLambdaForTesting([&callback](bool accepted) { + EXPECT_TRUE(accepted); + callback.Quit(); + })); + + // Wait for the identity provider to return a token. + callback.Run(); + + // Assert that the conditional mediation request resolved and that + // the right token was provided. + EXPECT_EQ(std::string(kToken), EvalJs(shell(), "token")); +} + class WebIdMetricsBrowserTest : public WebIdBrowserTest { public: void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/content/common/content_export.h b/content/common/content_export.h index 92ad6c7..c4245cfe 100644 --- a/content/common/content_export.h +++ b/content/common/content_export.h
@@ -15,11 +15,7 @@ #endif // defined(CONTENT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CONTENT_IMPLEMENTATION) #define CONTENT_EXPORT __attribute__((visibility("default"))) -#else -#define CONTENT_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn index 7743c3f..d96d069 100644 --- a/content/public/android/BUILD.gn +++ b/content/public/android/BUILD.gn
@@ -129,7 +129,6 @@ "java/src/org/chromium/content/app/SandboxedProcessService.java", "java/src/org/chromium/content/browser/BrowserStartupControllerImpl.java", "java/src/org/chromium/content/browser/ChildProcessCreationParamsImpl.java", - "java/src/org/chromium/content/browser/ContentChildProcessConstants.java", "java/src/org/chromium/content/browser/DeviceUtilsImpl.java", "java/src/org/chromium/content/browser/ServicificationStartupUma.java", "java/src/org/chromium/content/browser/TracingControllerAndroidImpl.java",
diff --git a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java index d4d1f86..c34d342 100644 --- a/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java +++ b/content/public/android/java/src/org/chromium/content/app/ContentChildProcessServiceDelegate.java
@@ -29,10 +29,10 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.memory.MemoryPressureUma; import org.chromium.base.process_launcher.ChildProcessServiceDelegate; +import org.chromium.base.process_launcher.IChildProcessArgs; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.content.browser.ChildProcessCreationParamsImpl; -import org.chromium.content.browser.ContentChildProcessConstants; import org.chromium.content.common.IGpuProcessCallback; import org.chromium.content.common.InputTransferTokenWrapper; import org.chromium.content.common.SurfaceWrapper; @@ -79,18 +79,18 @@ @Override public void onConnectionSetup( - Bundle connectionBundle, List<IBinder> clientInterfaces, IBinder binderBox) { + IChildProcessArgs args, List<IBinder> clientInterfaces, IBinder binderBox) { mBinderBox = binderBox; mGpuCallback = clientInterfaces != null && !clientInterfaces.isEmpty() ? IGpuProcessCallback.Stub.asInterface(clientInterfaces.get(0)) : null; - mCpuCount = connectionBundle.getInt(ContentChildProcessConstants.EXTRA_CPU_COUNT); - mCpuFeatures = connectionBundle.getLong(ContentChildProcessConstants.EXTRA_CPU_FEATURES); + mCpuCount = args.cpuCount; + mCpuFeatures = args.cpuFeatures; assert mCpuCount > 0; - LibraryLoader.getInstance().getMediator().takeSharedRelrosFromBundle(connectionBundle); + LibraryLoader.getInstance().getMediator().takeSharedRelrosFromBundle(args.relroBundle); } @Override
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java index 8e53629..a7ecf74 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java
@@ -17,6 +17,7 @@ import org.jni_zero.CalledByNative; import org.jni_zero.JNINamespace; +import org.jni_zero.JniType; import org.jni_zero.NativeMethods; import org.chromium.base.ApplicationState; @@ -36,7 +37,8 @@ import org.chromium.base.process_launcher.ChildProcessConnection; import org.chromium.base.process_launcher.ChildProcessConstants; import org.chromium.base.process_launcher.ChildProcessLauncher; -import org.chromium.base.process_launcher.FileDescriptorInfo; +import org.chromium.base.process_launcher.IChildProcessArgs; +import org.chromium.base.process_launcher.IFileDescriptorInfo; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; import org.chromium.build.annotations.NullMarked; @@ -174,20 +176,16 @@ } @Override - public void onBeforeConnectionSetup(Bundle connectionBundle) { + public void onBeforeConnectionSetup(IChildProcessArgs childProcessArgs) { // Populate the bundle passed to the service setup call with content specific // parameters. - connectionBundle.putInt( - ContentChildProcessConstants.EXTRA_CPU_COUNT, CpuFeatures.getCount()); - connectionBundle.putLong( - ContentChildProcessConstants.EXTRA_CPU_FEATURES, CpuFeatures.getMask()); - if (sZygoteBundle != null) { - connectionBundle.putAll(sZygoteBundle); - } else { - LibraryLoader.getInstance() - .getMediator() - .putSharedRelrosToBundle(connectionBundle); + childProcessArgs.cpuCount = CpuFeatures.getCount(); + childProcessArgs.cpuFeatures = CpuFeatures.getMask(); + Bundle relros = sZygoteBundle; + if (relros == null) { + relros = LibraryLoader.getInstance().getMediator().getSharedRelrosBundle(); } + childProcessArgs.relroBundle = relros; } @Override @@ -353,29 +351,47 @@ private boolean mIsSpareRenderer; @CalledByNative - private static @Nullable FileDescriptorInfo makeFdInfo( - int id, int fd, boolean autoClose, long offset, long size) { + private static IFileDescriptorInfo @Nullable [] makeFdInfos( + @JniType("std::vector<int32_t>") int[] ids, + @JniType("std::vector<int32_t>") int[] fds, + @JniType("std::vector<bool>") boolean[] autoCloses, + @JniType("std::vector<int64_t>") long[] offsets, + @JniType("std::vector<int64_t>") long[] sizes) { assert LauncherThread.runningOnLauncherThread(); - ParcelFileDescriptor pFd; - if (autoClose) { - // Adopt the FD, it will be closed when we close the ParcelFileDescriptor. - pFd = ParcelFileDescriptor.adoptFd(fd); - } else { - try { - pFd = ParcelFileDescriptor.fromFd(fd); - } catch (IOException e) { - Log.e(TAG, "Invalid FD provided for process connection, aborting connection.", e); - return null; + IFileDescriptorInfo[] fileDescriptorInfos = new IFileDescriptorInfo[ids.length]; + for (int i = 0; i < ids.length; i++) { + ParcelFileDescriptor pFd; + if (autoCloses[i]) { + // Adopt the FD, it will be closed when we close the ParcelFileDescriptor. + pFd = ParcelFileDescriptor.adoptFd(fds[i]); + } else { + try { + pFd = ParcelFileDescriptor.fromFd(fds[i]); + } catch (IOException e) { + Log.e( + TAG, + "Invalid FD provided for process connection, id: " + + ids[i] + + " fd: " + + fds[i]); + return null; + } } + IFileDescriptorInfo fileDescriptorInfo = new IFileDescriptorInfo(); + fileDescriptorInfo.id = ids[i]; + fileDescriptorInfo.fd = pFd; + fileDescriptorInfo.size = sizes[i]; + fileDescriptorInfo.offset = offsets[i]; + fileDescriptorInfos[i] = fileDescriptorInfo; } - return new FileDescriptorInfo(id, pFd, offset, size); + return fileDescriptorInfos; } @CalledByNative private static ChildProcessLauncherHelperImpl createAndStart( long nativePointer, String[] commandLine, - FileDescriptorInfo[] filesToBeMapped, + IFileDescriptorInfo[] filesToBeMapped, boolean canUseWarmUpConnection, @Nullable IBinder binderBox) { assert LauncherThread.runningOnLauncherThread(); @@ -670,7 +686,7 @@ private ChildProcessLauncherHelperImpl( long nativePointer, String[] commandLine, - FileDescriptorInfo[] filesToBeMapped, + IFileDescriptorInfo[] filesToBeMapped, boolean sandboxed, boolean reducePriorityOnBackground, boolean canUseWarmUpConnection, @@ -1031,7 +1047,7 @@ public static ChildProcessLauncherHelperImpl createAndStartForTesting( String[] commandLine, - FileDescriptorInfo[] filesToBeMapped, + IFileDescriptorInfo[] filesToBeMapped, boolean sandboxed, boolean reducePriorityOnBackground, boolean canUseWarmUpConnection,
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessRanking.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessRanking.java index 16236c1..5706cff 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessRanking.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessRanking.java
@@ -317,8 +317,10 @@ if (!mEnableServiceGroupImportance) return; if (!connection.shouldBeInLowRankGroup()) { - if (connection.connection.getGroup() != NO_GROUP) { - connection.connection.updateGroupImportance(NO_GROUP, 0); + if (connection.connection.getGroup() != NO_GROUP + && connection.connection.updateGroupImportance(NO_GROUP, 0)) { + // Rebind a service binding to apply the group importance change. + connection.connection.rebind(); } return; } @@ -349,9 +351,15 @@ // If gap is small, use average. // If there is no room left, reshuffle everything. if (gap > 2 * FROM_RIGHT) { - connection.connection.updateGroupImportance(LOW_RANK_GROUP, right - FROM_RIGHT); + if (connection.connection.updateGroupImportance(LOW_RANK_GROUP, right - FROM_RIGHT)) { + // Rebind a service binding to apply the group importance change. + connection.connection.rebind(); + } } else if (gap > 2) { - connection.connection.updateGroupImportance(LOW_RANK_GROUP, left + gap / 2); + if (connection.connection.updateGroupImportance(LOW_RANK_GROUP, left + gap / 2)) { + // Rebind a service binding to apply the group importance change. + connection.connection.rebind(); + } } else { reshuffleGroupImportance(); } @@ -362,12 +370,24 @@ private void reshuffleGroupImportance() { int importance = Integer.MAX_VALUE - FROM_RIGHT; + ConnectionWithRank lastUpdatedConnection = null; for (int i = mRankings.size() - 1; i >= 0; --i) { ConnectionWithRank connection = mRankings.get(i); if (!connection.shouldBeInLowRankGroup()) break; - connection.connection.updateGroupImportance(LOW_RANK_GROUP, importance); + if (connection.connection.updateGroupImportance(LOW_RANK_GROUP, importance)) { + if (ContentFeatureList.sGroupRebindingForGroupImportance.isEnabled()) { + lastUpdatedConnection = connection; + } else { + // Rebind a service binding to apply the group importance change. + connection.connection.rebind(); + } + } importance -= FROM_RIGHT; } + if (lastUpdatedConnection != null) { + // Rebind a service connection in the group to apply the group importance changes. + lastUpdatedConnection.connection.rebind(); + } } private void postRebindHighRankConnectionsIfNeeded() {
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentChildProcessConstants.java b/content/public/android/java/src/org/chromium/content/browser/ContentChildProcessConstants.java deleted file mode 100644 index 05cdf99..0000000 --- a/content/public/android/java/src/org/chromium/content/browser/ContentChildProcessConstants.java +++ /dev/null
@@ -1,25 +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. - -package org.chromium.content.browser; - -import org.chromium.build.annotations.NullMarked; - -/** Constants to be used by child processes. */ -@NullMarked -public interface ContentChildProcessConstants { - // Below are the names for the items placed in the bind or start command intent. - // Note that because that intent maybe reused if a service is restarted, none should be process - // specific. - - // Below are the names for the items placed in the Bundle passed in the - // IChildProcessService.setupConnection call, once the connection has been established. - - // Key for the number of CPU cores. - public static final String EXTRA_CPU_COUNT = "com.google.android.apps.chrome.extra.cpu_count"; - - // Key for the CPU features mask. - public static final String EXTRA_CPU_FEATURES = - "com.google.android.apps.chrome.extra.cpu_features"; -}
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java b/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java index 3f3d0b4..d0948fb0 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java
@@ -55,6 +55,12 @@ public static final String DIPS_TTL = "DIPSTtl"; + public static final MutableFlagWithSafeDefault sGroupRebindingForGroupImportance = + new MutableFlagWithSafeDefault( + ContentFeatureMap.getInstance(), + ContentFeatures.GROUP_REBINDING_FOR_GROUP_IMPORTANCE, + false); + public static final MutableFlagWithSafeDefault sSpareRendererProcessPriority = new MutableFlagWithSafeDefault( ContentFeatureMap.getInstance(),
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java index 88782c45..fbdc104 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherHelperTest.java
@@ -34,7 +34,7 @@ import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.process_launcher.ChildConnectionAllocator; import org.chromium.base.process_launcher.ChildProcessConnection; -import org.chromium.base.process_launcher.FileDescriptorInfo; +import org.chromium.base.process_launcher.IFileDescriptorInfo; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; @@ -498,7 +498,7 @@ public ChildProcessLauncherHelperImpl call() { return ChildProcessLauncherHelperImpl.createAndStartForTesting( sProcessWaitArguments, - new FileDescriptorInfo[0], + new IFileDescriptorInfo[0], sandboxed, reducePriorityOnBackground, canUseWarmUpConnection,
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherIntegrationTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherIntegrationTest.java index 62e52f4..946acd08 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherIntegrationTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherIntegrationTest.java
@@ -18,6 +18,7 @@ import org.chromium.base.process_launcher.ChildConnectionAllocator; import org.chromium.base.process_launcher.ChildProcessConnection; +import org.chromium.base.process_launcher.IChildProcessArgs; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; @@ -241,7 +242,7 @@ private boolean mCrashServiceCalled; private final CountDownLatch mDisconnectedLatch = new CountDownLatch(1); // Arguments to setupConnection - private Bundle mConnectionBundle; + private IChildProcessArgs mChildProcessArgs; private List<IBinder> mClientInterfaces; private IBinder mBinderBox; private ConnectionCallback mConnectionCallback; @@ -269,14 +270,14 @@ super.onServiceConnectedOnLauncherThread(service); crashServiceForTesting(); mCrashServiceCalled = true; - if (mConnectionBundle != null) { + if (mChildProcessArgs != null) { super.setupConnection( - mConnectionBundle, + mChildProcessArgs, mClientInterfaces, mBinderBox, mConnectionCallback, null); - mConnectionBundle = null; + mChildProcessArgs = null; mClientInterfaces = null; mBinderBox = null; mConnectionCallback = null; @@ -291,7 +292,7 @@ @Override public void setupConnection( - Bundle connectionBundle, + IChildProcessArgs childProcessArgs, List<IBinder> clientInterfaces, IBinder binderBox, ConnectionCallback connectionCallback, @@ -300,10 +301,10 @@ // setupConnection is guaranteed to fail. if (mCrashServiceCalled) { super.setupConnection( - connectionBundle, clientInterfaces, binderBox, connectionCallback, null); + childProcessArgs, clientInterfaces, binderBox, connectionCallback, null); return; } - mConnectionBundle = connectionBundle; + mChildProcessArgs = childProcessArgs; mClientInterfaces = clientInterfaces; mBinderBox = binderBox; mConnectionCallback = connectionCallback;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java index 3659bd7e..490293a 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java
@@ -20,7 +20,8 @@ import org.chromium.base.process_launcher.ChildConnectionAllocator; import org.chromium.base.process_launcher.ChildProcessConnection; import org.chromium.base.process_launcher.ChildProcessLauncher; -import org.chromium.base.process_launcher.FileDescriptorInfo; +import org.chromium.base.process_launcher.IChildProcessArgs; +import org.chromium.base.process_launcher.IFileDescriptorInfo; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; @@ -47,10 +48,6 @@ private static final String EXTRA_SERVICE_PARAM = "org.chromium.content.browser.SERVICE_EXTRA"; private static final String EXTRA_SERVICE_PARAM_VALUE = "SERVICE_EXTRA"; - private static final String EXTRA_CONNECTION_PARAM = - "org.chromium.content.browser.CONNECTION_EXTRA"; - private static final String EXTRA_CONNECTION_PARAM_VALUE = "CONNECTION_EXTRA"; - private static final int CONNECTION_BLOCK_UNTIL_CONNECTED = 1; private static final int CONNECTION_BLOCK_UNTIL_SETUP = 2; @@ -133,7 +130,6 @@ // Can be accessed after mOnConnectionSetupCalled is signaled. private boolean mServiceCreated; private Bundle mServiceBundle; - private Bundle mConnectionBundle; // Can be accessed after mOnLoadNativeCalled is signaled. private boolean mNativeLibraryLoaded; @@ -142,11 +138,9 @@ private String[] mCommandLine; @Override - public void onConnectionSetup( - boolean serviceCreatedCalled, Bundle serviceBundle, Bundle connectionBundle) { + public void onConnectionSetup(boolean serviceCreatedCalled, Bundle serviceBundle) { mServiceCreated = serviceCreatedCalled; mServiceBundle = serviceBundle; - mConnectionBundle = connectionBundle; Assert.assertEquals(0, mOnConnectionSetupHelper.getCallCount()); mOnConnectionSetupHelper.notifyCalled(); } @@ -228,9 +222,7 @@ } @Override - public void onBeforeConnectionSetup(Bundle connectionBundle) { - connectionBundle.putString( - EXTRA_CONNECTION_PARAM, EXTRA_CONNECTION_PARAM_VALUE); + public void onBeforeConnectionSetup(IChildProcessArgs childProcessArgs) { Assert.assertEquals(0, onBeforeConnectionSetupHelper.getCallCount()); onBeforeConnectionSetupHelper.notifyCalled(); } @@ -249,7 +241,7 @@ }; final String[] commandLine = new String[] {"--test-param1", "--test-param2"}; - final FileDescriptorInfo[] filesToBeMapped = new FileDescriptorInfo[0]; + final IFileDescriptorInfo[] filesToBeMapped = new IFileDescriptorInfo[0]; final IChildProcessBinder childProcessBinder = new IChildProcessBinder(); @@ -287,15 +279,11 @@ childProcessBinder.waitForOnConnectionSetupCalled(); Assert.assertTrue(childProcessBinder.mServiceCreated); Assert.assertNotNull(childProcessBinder.mServiceBundle); - Assert.assertNotNull(childProcessBinder.mConnectionBundle); if (allocatedConnection) { Assert.assertEquals( EXTRA_SERVICE_PARAM_VALUE, childProcessBinder.mServiceBundle.getString(EXTRA_SERVICE_PARAM)); } - Assert.assertEquals( - EXTRA_CONNECTION_PARAM_VALUE, - childProcessBinder.mConnectionBundle.getString(EXTRA_CONNECTION_PARAM)); // Wait for the client onConnectionEstablished call. onConnectionEstablishedHelper.waitForCallback(/* currentCallCount= */ 0); @@ -519,7 +507,7 @@ LauncherThread.getHandler(), new ChildProcessLauncher.Delegate() {}, new String[0], - new FileDescriptorInfo[0], + new IFileDescriptorInfo[0], connectionAllocator, /* clientInterfaces= */ null, /* binderBox= */ null);
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 1f5468c6f..3c8b332 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -997,11 +997,8 @@ std::move(callback).Run(nullptr); } -std::vector<std::unique_ptr<NavigationThrottle>> -content::ContentBrowserClient::CreateThrottlesForNavigation( - NavigationThrottleRegistry& registry) { - return std::vector<std::unique_ptr<NavigationThrottle>>(); -} +void ContentBrowserClient::CreateThrottlesForNavigation( + NavigationThrottleRegistry& registry) {} std::vector<std::unique_ptr<CommitDeferringCondition>> ContentBrowserClient::CreateCommitDeferringConditionsForNavigation(
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index a0f6c7e..afc93525 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -1705,12 +1705,8 @@ // navigations; they are specifically not run for page activating navigations // such as prerender activation and back-forward cache restores or for // navigations that don't use a URLLoader like same-document navigations. - // TODO(https://crbug.com/412524375): New code should add a NavigationThrottle - // via the given `registry` instead of returning a NavigationThrottle from - // this method. Once all existing NavigationThrottles are migrated, the - // returned type will be changed to `void`. - virtual std::vector<std::unique_ptr<NavigationThrottle>> - CreateThrottlesForNavigation(NavigationThrottleRegistry& registry); + virtual void CreateThrottlesForNavigation( + NavigationThrottleRegistry& registry); // Allows the embedder to register one or more CommitDeferringConditions for // the navigation indicated by |navigation_handle|. A
diff --git a/content/public/browser/identity_request_dialog_controller.cc b/content/public/browser/identity_request_dialog_controller.cc index d10efd7..f68ebb575 100644 --- a/content/public/browser/identity_request_dialog_controller.cc +++ b/content/public/browser/identity_request_dialog_controller.cc
@@ -32,12 +32,14 @@ const IdentityProviderMetadata& idp_metadata, const ClientMetadata& client_metadata, blink::mojom::RpContext rp_context, + std::optional<blink::mojom::Format> format, const std::vector<IdentityRequestDialogDisclosureField>& disclosure_fields, bool has_login_status_mismatch) : idp_for_display{idp_for_display}, idp_metadata{idp_metadata}, client_metadata{client_metadata}, rp_context(rp_context), + format(format), disclosure_fields(disclosure_fields), has_login_status_mismatch(has_login_status_mismatch) {}
diff --git a/content/public/browser/identity_request_dialog_controller.h b/content/public/browser/identity_request_dialog_controller.h index ed2068e..99bc325 100644 --- a/content/public/browser/identity_request_dialog_controller.h +++ b/content/public/browser/identity_request_dialog_controller.h
@@ -102,6 +102,7 @@ const IdentityProviderMetadata& idp_metadata, const ClientMetadata& client_metadata, blink::mojom::RpContext rp_context, + std::optional<blink::mojom::Format> format, const std::vector<IdentityRequestDialogDisclosureField>& disclosure_fields, bool has_login_status_mismatch); @@ -110,6 +111,7 @@ IdentityProviderMetadata idp_metadata; ClientMetadata client_metadata; blink::mojom::RpContext rp_context; + std::optional<blink::mojom::Format> format; // For which fields should the dialog request permission for (assuming // this is for signup). std::vector<IdentityRequestDialogDisclosureField> disclosure_fields;
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 761ea53..2ce80c8 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -1375,6 +1375,13 @@ "GinJavaBridgeMojoSkipClearObjectsOnMainDocumentReady", base::FEATURE_ENABLED_BY_DEFAULT); +// Rebind service binding when consecutive Context.updateServiceGroup() call is +// done. If this is disabled, it rebinds the service binding on each +// Context.updateServiceGroup() call. +BASE_FEATURE(kGroupRebindingForGroupImportance, + "GroupRebindingForGroupImportance", + base::FEATURE_DISABLED_BY_DEFAULT); + // Reduce the priority of GPU process when in background so it is more likely // to be killed first if the OS needs more memory. BASE_FEATURE(kReduceGpuPriorityOnBackground,
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index b11246a..415dae84 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -305,6 +305,7 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kAndroidWebAppLaunchHandler); CONTENT_EXPORT BASE_DECLARE_FEATURE( kGinJavaBridgeMojoSkipClearObjectsOnMainDocumentReady); +CONTENT_EXPORT BASE_DECLARE_FEATURE(kGroupRebindingForGroupImportance); CONTENT_EXPORT BASE_DECLARE_FEATURE(kReduceGpuPriorityOnBackground); CONTENT_EXPORT BASE_DECLARE_FEATURE(kSmartZoom); CONTENT_EXPORT BASE_DECLARE_FEATURE(kUserMediaScreenCapturing);
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestHelperService.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestHelperService.java index 724f9ff..031c559 100644 --- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestHelperService.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestHelperService.java
@@ -18,7 +18,7 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.process_launcher.ChildProcessConnection; -import org.chromium.base.process_launcher.FileDescriptorInfo; +import org.chromium.base.process_launcher.IFileDescriptorInfo; import org.chromium.content.browser.ChildProcessLauncherHelperImpl; import org.chromium.content_public.browser.ChildProcessCreationParams; @@ -87,7 +87,7 @@ ChildProcessLauncherTestUtils.startForTesting( /* sandboxed= */ true, commandLine, - new FileDescriptorInfo[0], + new IFileDescriptorInfo[0], /* doSetupConnection= */ true); // Poll the launcher until the connection is set up. The main test in
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestUtils.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestUtils.java index 29deab7..ef3e6e2 100644 --- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestUtils.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ChildProcessLauncherTestUtils.java
@@ -5,8 +5,8 @@ package org.chromium.content_shell_apk; import org.chromium.base.process_launcher.ChildProcessConnection; -import org.chromium.base.process_launcher.FileDescriptorInfo; import org.chromium.base.process_launcher.IChildProcessService; +import org.chromium.base.process_launcher.IFileDescriptorInfo; import org.chromium.content.browser.ChildProcessLauncherHelperImpl; import org.chromium.content.browser.LauncherThread; @@ -56,7 +56,7 @@ public static ChildProcessLauncherHelperImpl startForTesting( final boolean sandboxed, final String[] commandLine, - final FileDescriptorInfo[] filesToBeMapped, + final IFileDescriptorInfo[] filesToBeMapped, final boolean doSetupConnection) { return runOnLauncherAndGetResult( new Callable<ChildProcessLauncherHelperImpl>() {
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/IChildProcessTest.aidl b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/IChildProcessTest.aidl index b715d3a..0766e0d 100644 --- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/IChildProcessTest.aidl +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/IChildProcessTest.aidl
@@ -13,7 +13,7 @@ interface IChildProcessTest { // Called by the service when onConnectionSetup is received. Echos back the parameters received // so far. - oneway void onConnectionSetup(boolean serviceCreatedCalled, in Bundle serviceBundle, in Bundle connectionBundle); + oneway void onConnectionSetup(boolean serviceCreatedCalled, in Bundle serviceBundle); oneway void onLoadNativeLibrary(boolean loadedSuccessfully);
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/TestChildProcessService.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/TestChildProcessService.java index 709d1fb3..e06273e 100644 --- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/TestChildProcessService.java +++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/TestChildProcessService.java
@@ -19,6 +19,7 @@ import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.base.process_launcher.ChildProcessService; import org.chromium.base.process_launcher.ChildProcessServiceDelegate; +import org.chromium.base.process_launcher.IChildProcessArgs; import java.util.List; @@ -54,14 +55,13 @@ @Override public void onConnectionSetup( - Bundle connectionBundle, List<IBinder> clientInterfaces, IBinder binderBox) { + IChildProcessArgs args, List<IBinder> clientInterfaces, IBinder binderBox) { if (clientInterfaces != null && !clientInterfaces.isEmpty()) { mIChildProcessTest = IChildProcessTest.Stub.asInterface(clientInterfaces.get(0)); } if (mIChildProcessTest != null) { try { - mIChildProcessTest.onConnectionSetup( - mServiceCreated, mServiceBundle, connectionBundle); + mIChildProcessTest.onConnectionSetup(mServiceCreated, mServiceBundle); } catch (RemoteException re) { Log.e(TAG, "Failed to call IChildProcessTest.onConnectionSetup.", re); }
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index e9a17824..cdf869046 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -693,16 +693,11 @@ ->web_contents()); } -std::vector<std::unique_ptr<NavigationThrottle>> -ShellContentBrowserClient::CreateThrottlesForNavigation( +void ShellContentBrowserClient::CreateThrottlesForNavigation( NavigationThrottleRegistry& registry) { - std::vector<std::unique_ptr<NavigationThrottle>> empty_throttles; if (create_throttles_for_navigation_callback_) { - // TODO(https://crbug.com/412524375): NavigationThrottleRegistry migration. - return create_throttles_for_navigation_callback_.Run( - ®istry.GetNavigationHandle()); + create_throttles_for_navigation_callback_.Run(registry); } - return empty_throttles; } std::unique_ptr<LoginDelegate> ShellContentBrowserClient::CreateLoginDelegate(
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h index 2730cbc..e608835c 100644 --- a/content/shell/browser/shell_content_browser_client.h +++ b/content/shell/browser/shell_content_browser_client.h
@@ -125,7 +125,7 @@ void OpenURL(SiteInstance* site_instance, const OpenURLParams& params, base::OnceCallback<void(WebContents*)> callback) override; - std::vector<std::unique_ptr<NavigationThrottle>> CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( NavigationThrottleRegistry& registry) override; std::unique_ptr<LoginDelegate> CreateLoginDelegate( const net::AuthChallengeInfo& auth_info, @@ -218,8 +218,8 @@ std::move(url_loader_factory_params_callback); } void set_create_throttles_for_navigation_callback( - base::RepeatingCallback<std::vector<std::unique_ptr<NavigationThrottle>>( - NavigationHandle*)> create_throttles_for_navigation_callback) { + base::RepeatingCallback<void(NavigationThrottleRegistry&)> + create_throttles_for_navigation_callback) { create_throttles_for_navigation_callback_ = create_throttles_for_navigation_callback; } @@ -271,8 +271,7 @@ bool is_for_isolated_world, bool is_for_service_worker)> url_loader_factory_params_callback_; - base::RepeatingCallback<std::vector<std::unique_ptr<NavigationThrottle>>( - NavigationHandle*)> + base::RepeatingCallback<void(NavigationThrottleRegistry&)> create_throttles_for_navigation_callback_; base::RepeatingCallback<void(blink::web_pref::WebPreferences*)> override_web_preferences_callback_;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index cc799cd5..30ab9e2 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1461,7 +1461,6 @@ "../browser/cookie_deprecation_label/cookie_deprecation_label_browsertest.cc", "../browser/cross_site_transfer_browsertest.cc", "../browser/data_decoder_browsertest.cc", - "../browser/device_posture/foldable_apis_origin_trial_browsertest.cc", "../browser/device_sensors/device_sensor_browsertest.cc", "../browser/devtools/devtools_issue_storage_browsertest.cc", "../browser/devtools/devtools_trust_token_browsertest.cc",
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist index 3b2cf19..f4530f5 100644 --- a/content/test/content_test_bundle_data.filelist +++ b/content/test/content_test_bundle_data.filelist
@@ -5234,6 +5234,9 @@ data/accessibility/html/select-slowly-build-expected-auralinux.txt data/accessibility/html/select-slowly-build-expected-blink.txt data/accessibility/html/select-slowly-build.html +data/accessibility/html/select-with-input-expected-auralinux.txt +data/accessibility/html/select-with-input-expected-blink.txt +data/accessibility/html/select-with-input.html data/accessibility/html/select.html data/accessibility/html/selection-container-expected-android-assist-data.txt data/accessibility/html/selection-container-expected-android-external.txt @@ -6764,8 +6767,6 @@ data/dark_color_scheme_meta_slow.html data/data_url_navigations.html data/detach_frame_in_copy.html -data/device_posture/no_token.html -data/device_posture/valid_token.html data/device_sensors/cross_origin_iframe.html data/device_sensors/device_inertial_sensor_diagnostics.html data/device_sensors/device_motion_null_test.html
diff --git a/content/test/data/accessibility/html/select-with-input-expected-auralinux.txt b/content/test/data/accessibility/html/select-with-input-expected-auralinux.txt new file mode 100644 index 0000000..f1f30144 --- /dev/null +++ b/content/test/data/accessibility/html/select-with-input-expected-auralinux.txt
@@ -0,0 +1,32 @@ +[document web] +++[section] +++++[combo box] +++++++[entry] selectable-text controller-for=[menu] +++++++[menu] controlled-by=[entry] +++++++++[section] +++++++++++[section] +++++++++++[menu item] name='one' selectable selected +++++++++++[menu item] name='two' selectable +++++[combo box] +++++++[entry] selectable-text controller-for=[menu] +++++++[menu] controlled-by=[entry] +++++++++[section] +++++++++++[menu item] name='one' selectable selected +++++++++++[section] +++++++++++[menu item] name='two' selectable +++++[combo box] +++++++[dialog] +++++++++[section] +++++++++++[section] +++++++++++++[radio button] checkable checkable:true +++++++++++[menu item] name='one' selectable selected +++++++++++[menu item] name='two' selectable +++++[combo box] +++++++[entry] selectable-text controller-for=[dialog] +++++++[dialog] controlled-by=[entry,entry] +++++++++[section] +++++++++++[section] +++++++++++[section] +++++++++++++[entry] selectable-text controller-for=[dialog] +++++++++++[menu item] name='one' selectable selected +++++++++++[menu item] name='two' selectable
diff --git a/content/test/data/accessibility/html/select-with-input-expected-blink.txt b/content/test/data/accessibility/html/select-with-input-expected-blink.txt new file mode 100644 index 0000000..be7a21d8 --- /dev/null +++ b/content/test/data/accessibility/html/select-with-input-expected-blink.txt
@@ -0,0 +1,37 @@ +rootWebArea +++genericContainer ignored +++++genericContainer +++++++comboBoxSelect collapsed value='one' +++++++++textField invisible controlsIds=menuListPopup +++++++++++genericContainer invisible +++++++++menuListPopup invisible ispopup=auto +++++++++++genericContainer invisible +++++++++++++genericContainer invisible +++++++++++++menuListOption name='one' selected=true +++++++++++++menuListOption invisible name='two' selected=false +++++++comboBoxSelect collapsed value='one' +++++++++textField invisible controlsIds=menuListPopup +++++++++++genericContainer invisible +++++++++menuListPopup invisible ispopup=auto +++++++++++genericContainer invisible +++++++++++++menuListOption name='one' selected=true +++++++++++++genericContainer invisible +++++++++++++menuListOption invisible name='two' selected=false +++++++comboBoxSelect collapsed value='one' +++++++++dialog invisible ispopup=auto +++++++++++genericContainer invisible +++++++++++++genericContainer invisible +++++++++++++++radioButton invisible checkedState=false +++++++++++++menuListOption name='one' selected=true +++++++++++++menuListOption invisible name='two' selected=false +++++++comboBoxSelect collapsed value='one' +++++++++textField invisible controlsIds=dialog +++++++++++genericContainer invisible +++++++++dialog invisible ispopup=auto +++++++++++genericContainer invisible +++++++++++++genericContainer invisible +++++++++++++genericContainer invisible +++++++++++++++textField invisible controlsIds=dialog +++++++++++++++++genericContainer invisible +++++++++++++menuListOption name='one' selected=true +++++++++++++menuListOption invisible name='two' selected=false
diff --git a/content/test/data/accessibility/html/select-with-input.html b/content/test/data/accessibility/html/select-with-input.html new file mode 100644 index 0000000..4f6b8d1 --- /dev/null +++ b/content/test/data/accessibility/html/select-with-input.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<style> +select, ::picker(select) { + appearance: base-select; +} +</style> + +<select id=s1> + <span class=input></span> + <option>one</option> + <option>two</option> +</select> + +<select id=s2> + <option>one</option> + <span class=input></span> + <option>two</option> +</select> + +<select id=s3> + <span class=input data-type=radio></span> + <option>one</option> + <option>two</option> +</select> + +<select id=s4> + <span class=input></span> + <span class=input></span> + <option>one</option> + <option>two</option> +</select> + +<script> + document.querySelectorAll('.input').forEach(container => { + const input = document.createElement('input'); + input.type = container.getAttribute('data-type'); + container.appendChild(input); + }); +</script>
diff --git a/content/test/data/device_posture/no_token.html b/content/test/data/device_posture/no_token.html deleted file mode 100644 index 702faa52..0000000 --- a/content/test/data/device_posture/no_token.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>Device Posture API No Origin Trial Test</title> -<head> - <style> - #content { - width: 0; - } - @media (horizontal-viewport-segments: 2) { - #content { - width: env(viewport-segment-width 0 0); - } - } - </style> -</head> -<body> - <div id="content"></div> -</body>
diff --git a/content/test/data/device_posture/valid_token.html b/content/test/data/device_posture/valid_token.html deleted file mode 100644 index f9b40cd..0000000 --- a/content/test/data/device_posture/valid_token.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<!-- The OT token below expires in 2033. - Regenerate this token with the command: - generate_token.py https://example.test FoldableAPIs --expire-timestamp=2000000000 --> -<meta http-equiv="origin-trial" content="A7lNZO0Koy9FElYOLjQGgwGDgSdFxS93UMw7Am6gPnaHa+nsKHPYZjj3Z3dllkkmSQCgb+wlKWkLGMXoqEFcBwgAAABXeyJvcmlnaW4iOiAiaHR0cHM6Ly9leGFtcGxlLnRlc3Q6NDQzIiwgImZlYXR1cmUiOiAiRm9sZGFibGVBUElzIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9"> -<title>Device Posture API Origin Trial Test</title> -<head> - <style> - #content { - width: 0; - } - @media (horizontal-viewport-segments: 2) { - #content { - width: env(viewport-segment-width 0 0); - } - } - </style> -</head> -<body> - <div id="content"></div> -</body>
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 8193dcd..71b92177 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -551,8 +551,6 @@ ## Win / Intel ## -crbug.com/384257970 [ angle-d3d11 intel-0x9bc5 win ] conformance/textures/canvas_sub_rectangle/* [ RetryOnFailure ] -crbug.com/384257970 [ angle-d3d11 intel-0x9bc5 win ] conformance2/textures/canvas_sub_rectangle/* [ RetryOnFailure ] crbug.com/401515599 [ win11 amd-0x7480 ] deqp/functional/gles3/transformfeedback/interpolation_centroid.html [ Failure ] crbug.com/401515599 [ win11 amd-0x7480 ] deqp/functional/gles3/transformfeedback/interpolation_smooth.html [ Failure ] @@ -846,8 +844,6 @@ crbug.com/1000354 [ android android-pixel-2 passthrough ] conformance2/reading/read-pixels-from-fbo-test.html [ Failure ] crbug.com/1276186 [ android android-pixel-2 ] conformance2/glsl3/array-equality.html [ Failure ] crbug.com/angleproject/7421 [ android android-pixel-2 angle-disabled no-passthrough ] conformance2/renderbuffers/invalidate-framebuffer.html [ Failure ] -# Slow test that sometimes hits the 300s global timeout -crbug.com/402726806 [ android android-pixel-2 angle-disabled no-passthrough ] deqp/functional/gles3/vertexarrays/multiple_attributes.stride.html [ RetryOnFailure ] ## Pixel 4 ##
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 32b90d6..01f66e3 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
@@ -524,7 +524,6 @@ crbug.com/642822 [ mac amd ] conformance/rendering/clipping-wide-points.html [ Failure ] crbug.com/1230781 [ mac amd angle-opengl ] conformance/canvas/to-data-url-test.html [ Failure ] crbug.com/328100306 [ amd angle-metal sonoma ] conformance/glsl/bugs/sampler-array-using-loop-index.html [ Failure ] -crbug.com/328102507 [ amd-0x7340 angle-opengl asan graphite-disabled mac-x86_64 release sonoma ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ Failure ] crbug.com/354627705 [ mac amd-0x7340 angle-opengl ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ] crbug.com/354627705 [ mac amd-0x7340 angle-metal ] conformance/extensions/webgl-polygon-mode.html [ Failure ] crbug.com/354627705 [ mac amd-0x7340 angle-opengl ] conformance/rendering/color-mask-preserved-during-implicit-clears.html [ Failure ] @@ -636,23 +635,8 @@ crbug.com/1372149 [ android android-sm-a236b no-passthrough ] conformance/rendering/blending.html [ Failure ] crbug.com/40241618 [ android android-sm-s911u1 no-passthrough ] conformance/rendering/blending.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/extensions/oes-texture-float-with-video.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/extensions/oes-texture-half-float-with-video.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/image_bitmap_from_video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/image_bitmap_from_video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ] crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_byte.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/image_bitmap_from_video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_byte.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/image_bitmap_from_video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ] crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/misc/video-rotation.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_byte.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_4_4_4_4.html [ Failure ] -crbug.com/1499000 [ android android-sm-a236b no-passthrough ] conformance/textures/video/tex-2d-rgba-rgba-unsigned_short_5_5_5_1.html [ Failure ] crbug.com/331489774 [ android android-sm-s911u1 no-passthrough ] conformance/context/context-attributes-alpha-depth-stencil-antialias.html [ Failure ]
diff --git a/content/web_test/browser/web_test_content_browser_client.cc b/content/web_test/browser/web_test_content_browser_client.cc index e5f7596..7f265db6 100644 --- a/content/web_test/browser/web_test_content_browser_client.cc +++ b/content/web_test/browser/web_test_content_browser_client.cc
@@ -420,21 +420,14 @@ WebTestControlHost::Get()->OverrideWebPreferences(prefs); } -std::vector<std::unique_ptr<content::NavigationThrottle>> -WebTestContentBrowserClient::CreateThrottlesForNavigation( +void WebTestContentBrowserClient::CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) { - content::NavigationHandle* navigation_handle = - ®istry.GetNavigationHandle(); - std::vector<std::unique_ptr<content::NavigationThrottle>> throttles = - ShellContentBrowserClient::CreateThrottlesForNavigation(registry); - - throttles.push_back(std::make_unique<WebTestOriginTrialThrottle>( - navigation_handle, navigation_handle->GetWebContents() - ->GetBrowserContext() - ->GetOriginTrialsControllerDelegate())); - - // TODO(https://crbug.com/412524375): NavigationThrottleRegistry migration. - return throttles; + ShellContentBrowserClient::CreateThrottlesForNavigation(registry); + content::NavigationHandle& navigation_handle = registry.GetNavigationHandle(); + registry.AddThrottle(std::make_unique<WebTestOriginTrialThrottle>( + &navigation_handle, navigation_handle.GetWebContents() + ->GetBrowserContext() + ->GetOriginTrialsControllerDelegate())); } void WebTestContentBrowserClient::AppendExtraCommandLineSwitches(
diff --git a/content/web_test/browser/web_test_content_browser_client.h b/content/web_test/browser/web_test_content_browser_client.h index e4eaba6..b50d562 100644 --- a/content/web_test/browser/web_test_content_browser_client.h +++ b/content/web_test/browser/web_test_content_browser_client.h
@@ -75,8 +75,7 @@ void OverrideWebPreferences(WebContents* web_contents, SiteInstance& main_frame_site, blink::web_pref::WebPreferences* prefs) override; - std::vector<std::unique_ptr<content::NavigationThrottle>> - CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override; void AppendExtraCommandLineSwitches(base::CommandLine* command_line, int child_process_id) override;
diff --git a/crypto/crypto_export.h b/crypto/crypto_export.h index 66bd53c..186d294be 100644 --- a/crypto/crypto_export.h +++ b/crypto/crypto_export.h
@@ -18,11 +18,7 @@ #endif // defined(CRYPTO_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CRYPTO_IMPLEMENTATION) #define CRYPTO_EXPORT __attribute__((visibility("default"))) -#else -#define CRYPTO_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/dbus/dbus_export.h b/dbus/dbus_export.h index 1874aa9c..029b7ec 100644 --- a/dbus/dbus_export.h +++ b/dbus/dbus_export.h
@@ -15,17 +15,9 @@ #endif // defined(WIN32) #if defined(COMPONENT_BUILD) - -#if defined(DBUS_IMPLEMENTATION) #define CHROME_DBUS_EXPORT __attribute__((visibility("default"))) -#else -#define CHROME_DBUS_EXPORT -#endif - #else // !defined(COMPONENT_BUILD) - #define CHROME_DBUS_EXPORT - #endif // defined(COMPONENT_BUILD) #endif // DBUS_DBUS_EXPORT_H_
diff --git a/device/base/device_base_export.h b/device/base/device_base_export.h index 8672b65..f7d74539 100644 --- a/device/base/device_base_export.h +++ b/device/base/device_base_export.h
@@ -15,11 +15,7 @@ #elif defined(COMPONENT_BUILD) && !defined(WIN32) -#if defined(DEVICE_BASE_IMPLEMENTATION) #define DEVICE_BASE_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_BASE_EXPORT -#endif #else #define DEVICE_BASE_EXPORT
diff --git a/device/base/features.cc b/device/base/features.cc index 2565670..2af045b 100644 --- a/device/base/features.cc +++ b/device/base/features.cc
@@ -41,7 +41,7 @@ // Serial. BASE_FEATURE(kBluetoothRfcommAndroid, "BluetoothRfcommAndroid", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID)
diff --git a/device/bluetooth/bluetooth_export.h b/device/bluetooth/bluetooth_export.h index 7b82a39..69af504b 100644 --- a/device/bluetooth/bluetooth_export.h +++ b/device/bluetooth/bluetooth_export.h
@@ -15,11 +15,7 @@ #elif defined(COMPONENT_BUILD) && !defined(WIN32) -#if defined(DEVICE_BLUETOOTH_IMPLEMENTATION) #define DEVICE_BLUETOOTH_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_BLUETOOTH_EXPORT -#endif #else #define DEVICE_BLUETOOTH_EXPORT
diff --git a/device/gamepad/gamepad_export.h b/device/gamepad/gamepad_export.h index 3479e78..1d6cf2d 100644 --- a/device/gamepad/gamepad_export.h +++ b/device/gamepad/gamepad_export.h
@@ -15,11 +15,7 @@ #elif defined(COMPONENT_BUILD) && !defined(WIN32) -#if defined(DEVICE_GAMEPAD_IMPLEMENTATION) #define DEVICE_GAMEPAD_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_GAMEPAD_EXPORT -#endif #else #define DEVICE_GAMEPAD_EXPORT
diff --git a/device/gamepad/public/cpp/gamepad_features_export.h b/device/gamepad/public/cpp/gamepad_features_export.h index 0b3a46e..a769952 100644 --- a/device/gamepad/public/cpp/gamepad_features_export.h +++ b/device/gamepad/public/cpp/gamepad_features_export.h
@@ -17,11 +17,7 @@ #else // !defined(WIN32) -#if defined(GAMEPAD_FEATURES_IMPLEMENTATION) #define GAMEPAD_FEATURES_EXPORT __attribute__((visibility("default"))) -#else -#define GAMEPAD_FEATURES_EXPORT -#endif #endif
diff --git a/device/vr/android/arcore/arcore_impl.cc b/device/vr/android/arcore/arcore_impl.cc index f22fe58..1239e05f 100644 --- a/device/vr/android/arcore/arcore_impl.cc +++ b/device/vr/android/arcore/arcore_impl.cc
@@ -156,48 +156,41 @@ out_pixels.copy_from(src_span); } -// Helper, copies ARCore image to the passed in vector, discovering the buffer -// size and resizing the vector first. -template <typename T> -void CopyArCoreImage(const ArSession* session, - const ArImage* image, - int32_t plane_index, - std::vector<T>* out_pixels, - uint32_t* out_width, - uint32_t* out_height) { - // Get source image information - int32_t width = 0, height = 0; - ArImage_getWidth(session, image, &width); - ArImage_getHeight(session, image, &height); - - *out_width = width; - *out_height = height; - - // Allocate memory for the output. - out_pixels->resize(width * height); - - CopyArCoreImage(session, image, plane_index, - base::as_writable_byte_span(*out_pixels), sizeof(T), width, - height); -} - device::mojom::XRLightProbePtr GetLightProbe( ArSession* arcore_session, ArLightEstimate* arcore_light_estimate) { // ArCore hands out 9 sets of RGB spherical harmonics coefficients // https://developers.google.com/ar/reference/c/group/light#arlightestimate_getenvironmentalhdrambientsphericalharmonics constexpr size_t kNumShCoefficients = 9; + constexpr size_t kNumChannels = 3; + constexpr size_t kRedChannel = 0; + constexpr size_t kGreenChannel = 1; + constexpr size_t kBlueChannel = 2; auto light_probe = device::mojom::XRLightProbe::New(); light_probe->spherical_harmonics = device::mojom::XRSphericalHarmonics::New(); - light_probe->spherical_harmonics->coefficients = - std::vector<device::RgbTupleF32>(kNumShCoefficients, - device::RgbTupleF32{}); + // Create a temporary array to hold the values from ARCore. We'll need to + // transform them into an `RgbTupleF32` to send across mojom. + std::array<float, kNumShCoefficients * kNumChannels> coefficient_list; ArLightEstimate_getEnvironmentalHdrAmbientSphericalHarmonics( - arcore_session, arcore_light_estimate, - light_probe->spherical_harmonics->coefficients.data()->components.data()); + arcore_session, arcore_light_estimate, coefficient_list.data()); + + // The returned data is 27 floats (kNumShCoefficients * kNumChannels), in + // the repeating order of RGB. We can thus iterate over chunks of 3 to + // create our RgbTupleF32s. + base::span<const float> coefficients(coefficient_list); + light_probe->spherical_harmonics->coefficients.reserve(coefficients.size()); + while (!coefficients.empty()) { + auto [coefficient, rem] = coefficients.split_at<kNumChannels>(); + // Copy the first set of data. + light_probe->spherical_harmonics->coefficients.emplace_back( + coefficient[kRedChannel], coefficient[kGreenChannel], + coefficient[kBlueChannel]); + // Advance the array. + coefficients = rem; + } float main_light_direction[3] = {}; ArLightEstimate_getEnvironmentalHdrMainLightDirection( @@ -206,6 +199,10 @@ light_probe->main_light_direction.set_y(main_light_direction[1]); light_probe->main_light_direction.set_z(main_light_direction[2]); + // Intensity is returned as three floats, r, g, then b: + // https://developers.google.com/ar/reference/c/group/ar-light-estimate#arlightestimate_getenvironmentalhdrmainlightintensity. + // Since this is just a single value, it's okay to have this read directly + // into the backing array of the RgbTupleF32. ArLightEstimate_getEnvironmentalHdrMainLightIntensity( arcore_session, arcore_light_estimate, light_probe->main_light_intensity.components.data()); @@ -221,7 +218,7 @@ arcore_session, arcore_light_estimate, arcore_cube_map); auto cube_map = device::mojom::XRCubeMap::New(); - std::array<std::vector<device::RgbaTupleF16>*, 6> const cube_map_faces = { + std::array<std::vector<uint16_t>*, 6> const cube_map_faces = { &cube_map->positive_x, &cube_map->negative_x, &cube_map->positive_y, &cube_map->negative_y, &cube_map->positive_z, &cube_map->negative_z}; @@ -244,8 +241,6 @@ return nullptr; } - auto* cube_map_face = cube_map_faces[i]; - // Make sure we only have a single image plane int32_t num_planes = 0; ArImage_getNumberOfPlanes(arcore_session, arcore_cube_map_face, @@ -268,9 +263,9 @@ } // Copy the cubemap - uint32_t face_width = 0, face_height = 0; - CopyArCoreImage(arcore_session, arcore_cube_map_face, 0, cube_map_face, - &face_width, &face_height); + int32_t face_width = 0, face_height = 0; + ArImage_getWidth(arcore_session, arcore_cube_map_face, &face_width); + ArImage_getHeight(arcore_session, arcore_cube_map_face, &face_height); // Make sure the cube map is square if (face_width != face_height) { @@ -279,15 +274,29 @@ return nullptr; } + const int32_t signed_width_and_height = + base::checked_cast<int32_t>(cube_map->width_and_height); // Make sure all faces have the same dimensions if (i == 0) { cube_map->width_and_height = face_width; - } else if (face_width != cube_map->width_and_height || - face_height != cube_map->width_and_height) { + } else if (face_width != signed_width_and_height || + face_height != signed_width_and_height) { DVLOG(1) << "ArCore cube map faces not all of the same dimensions."; ReleaseArCoreCubemap(&arcore_cube_map); return nullptr; } + + // ARCore returns (and mojom expects) to receive the data as r, g, b, a, ... + // There are width*height "pixels" of 4 components each, with each component + // being a uint16_t. + auto* cube_map_face = cube_map_faces[i]; + cube_map_face->resize(face_width * face_height * + device::mojom::XRCubeMap::kNumComponentsPerPixel); + size_t pixel_size = + device::mojom::XRCubeMap::kNumComponentsPerPixel * sizeof(uint16_t); + CopyArCoreImage(arcore_session, arcore_cube_map_face, 0, + base::as_writable_byte_span(*cube_map_face), pixel_size, + face_width, face_height); } ReleaseArCoreCubemap(&arcore_cube_map);
diff --git a/device/vr/public/mojom/BUILD.gn b/device/vr/public/mojom/BUILD.gn index b6b8bdd..a969521e 100644 --- a/device/vr/public/mojom/BUILD.gn +++ b/device/vr/public/mojom/BUILD.gn
@@ -28,10 +28,6 @@ shared_cpp_typemap = { types = [ { - mojom = "device.mojom.RgbaTupleF16" - cpp = "::device::RgbaTupleF16" - }, - { mojom = "device.mojom.RgbTupleF32" cpp = "::device::RgbTupleF32" },
diff --git a/device/vr/public/mojom/rgba_tuple_f16.h b/device/vr/public/mojom/rgba_tuple_f16.h deleted file mode 100644 index e321f2af..0000000 --- a/device/vr/public/mojom/rgba_tuple_f16.h +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef DEVICE_VR_PUBLIC_MOJOM_RGBA_TUPLE_F16_H_ -#define DEVICE_VR_PUBLIC_MOJOM_RGBA_TUPLE_F16_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <array> - -namespace device { - -struct RgbaTupleF16 { - // Because C++ does not have a native 16-bit floating point type, - // the components are stored as |uint16_t|s. - using Component = uint16_t; - static constexpr size_t kNumComponents = 4; - - RgbaTupleF16() : RgbaTupleF16(0, 0, 0, 0) {} - RgbaTupleF16(uint16_t red, uint16_t green, uint16_t blue, uint16_t alpha) - : components{red, green, blue, alpha} {} - - uint16_t red() const { return components[0]; } - void set_red(uint16_t red) { components[0] = red; } - uint16_t green() const { return components[1]; } - void set_green(uint16_t green) { components[1] = green; } - uint16_t blue() const { return components[2]; } - void set_blue(uint16_t blue) { components[2] = blue; } - uint16_t alpha() const { return components[3]; } - void set_alpha(uint16_t alpha) { components[3] = alpha; } - - std::array<Component, kNumComponents> components; -}; - -static_assert(sizeof(RgbaTupleF16) == sizeof(RgbaTupleF16::Component) * - RgbaTupleF16::kNumComponents, - "RgbaTupleF16 must be contiguous"); - -} // namespace device - -#endif // DEVICE_VR_PUBLIC_MOJOM_RGBA_TUPLE_F16_H_
diff --git a/device/vr/public/mojom/vr_service.mojom b/device/vr/public/mojom/vr_service.mojom index b1bd3e7..47e5a1b 100644 --- a/device/vr/public/mojom/vr_service.mojom +++ b/device/vr/public/mojom/vr_service.mojom
@@ -551,24 +551,12 @@ // Contains the coefficient data for L2 spherical harmonics generated by ArCore. struct XRSphericalHarmonics { // L2 (3rd order) spherical harmonics coefficients. - // This array has 9 RGB vector elements, representing the 27 coefficients - // given by ArCore. + // This array has 9 RGB vector elements, representing the 27 required + // coefficients for 3rd order spherical harmonics. // Units are expressed in nits: // https://github.com/immersive-web/lighting-estimation/blob/master/lighting-estimation-explainer.md#physically-based-units array<RgbTupleF32, 9> coefficients; }; - -// Tuple of half-precision floating point RGBA data. -// Since there isn't a native way to represent half-precision floats, they are -// stored a uint16s. -// This is the pixel format used by ArCore for cubemap textures. -struct RgbaTupleF16 { - uint16 red; - uint16 green; - uint16 blue; - uint16 alpha; -}; - // Contains the pixel data for all six faces of an HDR cubemap generated by // ArCore. Pixel data is stored in RGBA16F format. struct XRCubeMap { @@ -578,19 +566,23 @@ // The width and height (in pixels) of each cube map face. // Since each face is equal and square, this is only given as a single value. // Additionally, the dimensions of each face will be a power of two. - // Note that each pixel is a contiguous RGBA16F vector, so the length of each - // array will be this times |kNumComponentsPerPixel|. uint32 width_and_height; - // Each cube map face, stored in RGBA row-major order. Units are in nits. - // Each array will be |width_and_height ** 2| in length. + // Each cube map face, stored in RGBA row-major order. + // Each array will be |kNumComponentsPerPixel| * |width_and_height ** 2| in + // length, since each RGBA component is represented separately, but in a + // repeating order. + // Since there isn't a native way to represent half-precision floats, they are + // stored as uint16s. + // This matches the pixel format used by ArCore for cubemap textures. + // Units are expressed in nits: // https://github.com/immersive-web/lighting-estimation/blob/master/lighting-estimation-explainer.md#physically-based-units - array<RgbaTupleF16> positive_x; - array<RgbaTupleF16> negative_x; - array<RgbaTupleF16> positive_y; - array<RgbaTupleF16> negative_y; - array<RgbaTupleF16> positive_z; - array<RgbaTupleF16> negative_z; + array<uint16> positive_x; + array<uint16> negative_x; + array<uint16> positive_y; + array<uint16> negative_y; + array<uint16> positive_z; + array<uint16> negative_z; }; // Contains lighting information generated from ArCore for use in diffuse
diff --git a/device/vr/public/mojom/vr_service_mojom_traits.h b/device/vr/public/mojom/vr_service_mojom_traits.h index dcd7ebc..b2ffddc 100644 --- a/device/vr/public/mojom/vr_service_mojom_traits.h +++ b/device/vr/public/mojom/vr_service_mojom_traits.h
@@ -7,7 +7,6 @@ #include "device/vr/public/mojom/pose.h" #include "device/vr/public/mojom/rgb_tuple_f32.h" -#include "device/vr/public/mojom/rgba_tuple_f16.h" #include "device/vr/public/mojom/vr_service.mojom-shared.h" #include "mojo/public/cpp/bindings/struct_traits.h" #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h" @@ -17,26 +16,6 @@ namespace mojo { template <> -struct StructTraits<device::mojom::RgbaTupleF16DataView, device::RgbaTupleF16> { - static uint16_t red(const device::RgbaTupleF16& rgba) { return rgba.red(); } - static uint16_t green(const device::RgbaTupleF16& rgba) { - return rgba.green(); - } - static uint16_t blue(const device::RgbaTupleF16& rgba) { return rgba.blue(); } - static uint16_t alpha(const device::RgbaTupleF16& rgba) { - return rgba.alpha(); - } - static bool Read(device::mojom::RgbaTupleF16DataView data, - device::RgbaTupleF16* out) { - out->set_red(data.red()); - out->set_green(data.green()); - out->set_blue(data.blue()); - out->set_alpha(data.alpha()); - return true; - } -}; - -template <> struct StructTraits<device::mojom::RgbTupleF32DataView, device::RgbTupleF32> { static float red(const device::RgbTupleF32& rgba) { return rgba.red(); } static float green(const device::RgbTupleF32& rgba) { return rgba.green(); }
diff --git a/device/vr/vr_export.h b/device/vr/vr_export.h index 43390e1..adc9426 100644 --- a/device/vr/vr_export.h +++ b/device/vr/vr_export.h
@@ -15,11 +15,7 @@ #elif defined(COMPONENT_BUILD) && !defined(WIN32) -#if defined(DEVICE_VR_IMPLEMENTATION) #define DEVICE_VR_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_VR_EXPORT -#endif #else #define DEVICE_VR_EXPORT
diff --git a/docs/mac/debugging.md b/docs/mac/debugging.md index 95fc9e5..d56867b 100644 --- a/docs/mac/debugging.md +++ b/docs/mac/debugging.md
@@ -220,11 +220,11 @@ ### (2) Use *gn* 1. Tell `gn` to generate an Xcode project for your out directory: - `gn gen --ide=xcode out/debug` + `gn gen --ide=xcode out/debug --ninja-executable=autoninja` 2. Open *out/debug/all.xcodeproj* 3. Have it automatically generate schemes for you 4. You can now build targets from within Xcode, which will simply call out to - `ninja` via an Xcode script. But the resulting binaries are available as + `autoninja` via an Xcode script. But the resulting binaries are available as debuggable targets in Xcode. Note that any changes to the .xcodeproj will be overwritten; all changes to the
diff --git a/docs/website b/docs/website index e157e12..b2558d3 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit e157e12d99cfc729a970b474344673c44e2d2c9c +Subproject commit b2558d301fc88f8e4671024c47960ff1ee82cf34
diff --git a/extensions/browser/api/serial/BUILD.gn b/extensions/browser/api/serial/BUILD.gn index adf7c5b..ba6d5a0 100644 --- a/extensions/browser/api/serial/BUILD.gn +++ b/extensions/browser/api/serial/BUILD.gn
@@ -19,17 +19,15 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ - "//content/public/common", + public_deps = [ + "//base", + "//content/public/browser", + "//extensions/browser:browser_sources", "//extensions/common", "//extensions/common/api", "//mojo/public/cpp/bindings", + "//mojo/public/cpp/system", + "//net", "//services/device/public/mojom", - "//services/service_manager/public/cpp", - ] - - public_deps = [ - "//content/public/browser", - "//extensions/browser:browser_sources", ] }
diff --git a/extensions/browser/api/socket/BUILD.gn b/extensions/browser/api/socket/BUILD.gn index c4be578..75d3b54 100644 --- a/extensions/browser/api/socket/BUILD.gn +++ b/extensions/browser/api/socket/BUILD.gn
@@ -28,25 +28,33 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + public_deps = [ + "//base", "//build:chromeos_buildflags", "//content/public/browser", "//content/public/common", + "//extensions/browser:browser_sources", "//extensions/common", "//extensions/common/api", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/system", + "//net", + "//net/traffic_annotation", + "//services/network/public/cpp", + "//services/network/public/mojom", + "//services/network/public/mojom:mojom_host_resolver", ] + deps = [ "//url" ] + if (is_chromeos) { sources += [ "app_firewall_hole_manager.cc", "app_firewall_hole_manager.h", ] - deps += [ - "//chromeos/components/firewall_hole", - "//components/keyed_service/content", - ] - } + public_deps += [ "//chromeos/components/firewall_hole" ] - public_deps = [ "//extensions/browser:browser_sources" ] + deps += [ "//components/keyed_service/content" ] + } }
diff --git a/extensions/browser/api/sockets_udp/BUILD.gn b/extensions/browser/api/sockets_udp/BUILD.gn index 9678c8c..1df2633 100644 --- a/extensions/browser/api/sockets_udp/BUILD.gn +++ b/extensions/browser/api/sockets_udp/BUILD.gn
@@ -17,14 +17,19 @@ configs += [ "//build/config/compiler:wexit_time_destructors" ] - deps = [ + public_deps = [ + "//base", + "//content/public/browser", + "//extensions/browser:browser_sources", "//extensions/browser/api/socket", "//extensions/common", "//extensions/common/api", + "//mojo/public/cpp/bindings", ] - public_deps = [ - "//content/public/browser", - "//extensions/browser:browser_sources", + deps = [ + "//content/public/common", + "//net", + "//services/network/public/mojom", ] }
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h b/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h index a1fe26d8..8e2e25dc 100644 --- a/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h +++ b/extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h
@@ -98,6 +98,8 @@ virtual bool ForwardEmbeddedMediaPermissionChecksAsEmbedder( const url::Origin& embedder_origin); + // Allows the delegate to override the results of permission requests; useful + // when custom handling is needed for specific webviews. virtual std::optional<content::PermissionResult> OverridePermissionResult( ContentSettingsType type);
diff --git a/extensions/common/extensions_export.h b/extensions/common/extensions_export.h index 5f05f358..1f2cb671e 100644 --- a/extensions/common/extensions_export.h +++ b/extensions/common/extensions_export.h
@@ -16,11 +16,7 @@ #endif // defined(EXTENSIONS_COMPONENT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(EXTENSIONS_COMPONENT_IMPLEMENTATION) #define EXTENSIONS_EXPORT __attribute__((visibility("default"))) -#else -#define EXTENSIONS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/extensions/shell/browser/shell_content_browser_client.cc b/extensions/shell/browser/shell_content_browser_client.cc index 28e12bf5..fab3a40 100644 --- a/extensions/shell/browser/shell_content_browser_client.cc +++ b/extensions/shell/browser/shell_content_browser_client.cc
@@ -252,8 +252,7 @@ render_frame_host.GetGlobalId())); } -std::vector<std::unique_ptr<content::NavigationThrottle>> -ShellContentBrowserClient::CreateThrottlesForNavigation( +void ShellContentBrowserClient::CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) { content::NavigationHandle& navigation_handle = registry.GetNavigationHandle(); @@ -265,7 +264,6 @@ } registry.MaybeAddThrottle( WebViewGuest::MaybeCreateNavigationThrottle(&navigation_handle)); - return {}; } std::unique_ptr<content::NavigationUIData>
diff --git a/extensions/shell/browser/shell_content_browser_client.h b/extensions/shell/browser/shell_content_browser_client.h index 8da3baa..368f9a48 100644 --- a/extensions/shell/browser/shell_content_browser_client.h +++ b/extensions/shell/browser/shell_content_browser_client.h
@@ -89,8 +89,7 @@ void RegisterAssociatedInterfaceBindersForRenderFrameHost( content::RenderFrameHost& render_frame_host, blink::AssociatedInterfaceRegistry& associated_registry) override; - std::vector<std::unique_ptr<content::NavigationThrottle>> - CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override; std::unique_ptr<content::NavigationUIData> GetNavigationUIData( content::NavigationHandle* navigation_handle) override;
diff --git a/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc b/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc index 80729d4..c0bfdc62 100644 --- a/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc +++ b/fuchsia_web/webengine/browser/web_engine_content_browser_client.cc
@@ -310,8 +310,7 @@ return base::OnceClosure(); } -std::vector<std::unique_ptr<content::NavigationThrottle>> -WebEngineContentBrowserClient::CreateThrottlesForNavigation( +void WebEngineContentBrowserClient::CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) { auto& navigation_handle = registry.GetNavigationHandle(); auto* frame_impl = @@ -334,8 +333,6 @@ navigation_handle.GetWebContents()->GetBrowserContext(), *explicit_sites_filter_error_page)); } - - return {}; } std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
diff --git a/fuchsia_web/webengine/browser/web_engine_content_browser_client.h b/fuchsia_web/webengine/browser/web_engine_content_browser_client.h index e887887..057785c 100644 --- a/fuchsia_web/webengine/browser/web_engine_content_browser_client.h +++ b/fuchsia_web/webengine/browser/web_engine_content_browser_client.h
@@ -62,8 +62,7 @@ net::SSLCertRequestInfo* cert_request_info, net::ClientCertIdentityList client_certs, std::unique_ptr<content::ClientCertificateDelegate> delegate) override; - std::vector<std::unique_ptr<content::NavigationThrottle>> - CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override; std::vector<std::unique_ptr<blink::URLLoaderThrottle>> CreateURLLoaderThrottles(
diff --git a/fuchsia_web/webengine/web_engine_export.h b/fuchsia_web/webengine/web_engine_export.h index f96cb77..e219ead 100644 --- a/fuchsia_web/webengine/web_engine_export.h +++ b/fuchsia_web/webengine/web_engine_export.h
@@ -7,11 +7,7 @@ #if defined(COMPONENT_BUILD) -#if defined(WEB_ENGINE_IMPLEMENTATION) #define WEB_ENGINE_EXPORT __attribute__((visibility("default"))) -#else -#define WEB_ENGINE_EXPORT -#endif #else // defined(COMPONENT_BUILD) #define WEB_ENGINE_EXPORT
diff --git a/gin/gin_export.h b/gin/gin_export.h index 83986e6..9aa36fe 100644 --- a/gin/gin_export.h +++ b/gin/gin_export.h
@@ -15,11 +15,7 @@ #endif // defined(GIN_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GIN_IMPLEMENTATION) #define GIN_EXPORT __attribute__((visibility("default"))) -#else -#define GIN_EXPORT -#endif // defined(GIN_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/google_apis/gcm/base/gcm_export.h b/google_apis/gcm/base/gcm_export.h index 7e29ee7..82e0f33 100644 --- a/google_apis/gcm/base/gcm_export.h +++ b/google_apis/gcm/base/gcm_export.h
@@ -15,11 +15,7 @@ #endif // defined(GCM_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GCM_IMPLEMENTATION) #define GCM_EXPORT __attribute__((visibility("default"))) -#else -#define GCM_EXPORT -#endif // defined(GCM_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/command_buffer/client/gles2_c_lib_export.h b/gpu/command_buffer/client/gles2_c_lib_export.h index b9d3fb1..3d6449a 100644 --- a/gpu/command_buffer/client/gles2_c_lib_export.h +++ b/gpu/command_buffer/client/gles2_c_lib_export.h
@@ -15,11 +15,7 @@ #endif // defined(GLES2_C_LIB_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GLES2_C_LIB_IMPLEMENTATION) #define GLES2_C_LIB_EXPORT __attribute__((visibility("default"))) -#else -#define GLES2_C_LIB_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/command_buffer/client/gles2_impl_export.h b/gpu/command_buffer/client/gles2_impl_export.h index 1a5168c..0f6ee0d 100644 --- a/gpu/command_buffer/client/gles2_impl_export.h +++ b/gpu/command_buffer/client/gles2_impl_export.h
@@ -15,11 +15,7 @@ #endif // defined(GLES2_IMPL_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GLES2_IMPL_IMPLEMENTATION) #define GLES2_IMPL_EXPORT __attribute__((visibility("default"))) -#else -#define GLES2_IMPL_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/command_buffer/client/webgpu_export.h b/gpu/command_buffer/client/webgpu_export.h index b362730..9483a945 100644 --- a/gpu/command_buffer/client/webgpu_export.h +++ b/gpu/command_buffer/client/webgpu_export.h
@@ -15,11 +15,7 @@ #endif // defined(WEBGPU_IMPLEMENTATION) #else // defined(WIN32) -#if defined(WEBGPU_IMPLEMENTATION) #define WEBGPU_EXPORT __attribute__((visibility("default"))) -#else -#define WEBGPU_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/command_buffer/common/gles2_utils_export.h b/gpu/command_buffer/common/gles2_utils_export.h index fcecbb7..bcbe73f 100644 --- a/gpu/command_buffer/common/gles2_utils_export.h +++ b/gpu/command_buffer/common/gles2_utils_export.h
@@ -15,11 +15,7 @@ #endif // defined(GLES2_UTILS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GLES2_UTILS_IMPLEMENTATION) #define GLES2_UTILS_EXPORT __attribute__((visibility("default"))) -#else -#define GLES2_UTILS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc index 16cd766..245adb7 100644 --- a/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -1277,6 +1277,7 @@ switch (feature) { case wgpu::FeatureName::ChromiumExperimentalTimestampQueryInsidePasses: case wgpu::FeatureName::MultiDrawIndirect: + case wgpu::FeatureName::TextureCompressionASTCSliced3D: case wgpu::FeatureName::TextureCompressionBCSliced3D: case wgpu::FeatureName::Unorm16TextureFormats: case wgpu::FeatureName::Snorm16TextureFormats:
diff --git a/gpu/gpu_export.h b/gpu/gpu_export.h index 4bfc01b..8072ba0 100644 --- a/gpu/gpu_export.h +++ b/gpu/gpu_export.h
@@ -15,11 +15,7 @@ #endif // defined(GPU_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GPU_IMPLEMENTATION) #define GPU_EXPORT __attribute__((visibility("default"))) -#else -#define GPU_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/gpu_gles2_export.h b/gpu/gpu_gles2_export.h index f0bd00f..f5cfa470 100644 --- a/gpu/gpu_gles2_export.h +++ b/gpu/gpu_gles2_export.h
@@ -15,11 +15,7 @@ #endif // defined(GPU_GLES2_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GPU_GLES2_IMPLEMENTATION) #define GPU_GLES2_EXPORT __attribute__((visibility("default"))) -#else -#define GPU_GLES2_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/gpu_util_export.h b/gpu/gpu_util_export.h index d6f5b356..fa22faa 100644 --- a/gpu/gpu_util_export.h +++ b/gpu/gpu_util_export.h
@@ -15,11 +15,7 @@ #endif // defined(GPU_UTIL_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GPU_UTIL_IMPLEMENTATION) #define GPU_UTIL_EXPORT __attribute__((visibility("default"))) -#else -#define GPU_UTIL_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/ipc/gl_in_process_context_export.h b/gpu/ipc/gl_in_process_context_export.h index 78cf97b..db9ea37 100644 --- a/gpu/ipc/gl_in_process_context_export.h +++ b/gpu/ipc/gl_in_process_context_export.h
@@ -15,11 +15,7 @@ #endif // defined(GL_IN_PROCESS_CONTEXT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GL_IN_PROCESS_CONTEXT_IMPLEMENTATION) #define GL_IN_PROCESS_CONTEXT_EXPORT __attribute__((visibility("default"))) -#else -#define GL_IN_PROCESS_CONTEXT_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/ipc/service/gpu_ipc_service_export.h b/gpu/ipc/service/gpu_ipc_service_export.h index 04f8eed..65bcd55 100644 --- a/gpu/ipc/service/gpu_ipc_service_export.h +++ b/gpu/ipc/service/gpu_ipc_service_export.h
@@ -15,11 +15,7 @@ #endif // defined(GPU_IPC_SERVICE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GPU_IPC_SERVICE_IMPLEMENTATION) #define GPU_IPC_SERVICE_EXPORT __attribute__((visibility("default"))) -#else -#define GPU_IPC_SERVICE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/gpu/raster_export.h b/gpu/raster_export.h index 3671d1f..a6649cf 100644 --- a/gpu/raster_export.h +++ b/gpu/raster_export.h
@@ -15,11 +15,7 @@ #endif // defined(RASTER_IMPLEMENTATION) #else // defined(WIN32) -#if defined(RASTER_IMPLEMENTATION) #define RASTER_EXPORT __attribute__((visibility("default"))) -#else -#define RASTER_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/headless/lib/browser/headless_content_browser_client.cc b/headless/lib/browser/headless_content_browser_client.cc index 12252b4..0865a115 100644 --- a/headless/lib/browser/headless_content_browser_client.cc +++ b/headless/lib/browser/headless_content_browser_client.cc
@@ -453,21 +453,15 @@ #endif #if defined(HEADLESS_USE_POLICY) -std::vector<std::unique_ptr<content::NavigationThrottle>> -HeadlessContentBrowserClient::CreateThrottlesForNavigation( +void HeadlessContentBrowserClient::CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) { - std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; - // Avoid creating naviagtion throttle if preferences are not available // (happens in tests). content::NavigationHandle& handle = registry.GetNavigationHandle(); if (browser_->GetPrefs()) { - throttles.push_back(std::make_unique<PolicyBlocklistNavigationThrottle>( + registry.AddThrottle(std::make_unique<PolicyBlocklistNavigationThrottle>( &handle, handle.GetWebContents()->GetBrowserContext())); } - - // TODO(https://crbug.com/412524375): NavigationThrottleRegistry migration. - return throttles; } #endif // defined(HEADLESS_USE_POLICY)
diff --git a/headless/lib/browser/headless_content_browser_client.h b/headless/lib/browser/headless_content_browser_client.h index c41428c..9a23173 100644 --- a/headless/lib/browser/headless_content_browser_client.h +++ b/headless/lib/browser/headless_content_browser_client.h
@@ -133,8 +133,7 @@ #endif #if defined(HEADLESS_USE_POLICY) - std::vector<std::unique_ptr<content::NavigationThrottle>> - CreateThrottlesForNavigation( + void CreateThrottlesForNavigation( content::NavigationThrottleRegistry& registry) override; #endif
diff --git a/headless/public/headless_export.h b/headless/public/headless_export.h index 65c6c7e3..36ba5c26 100644 --- a/headless/public/headless_export.h +++ b/headless/public/headless_export.h
@@ -15,11 +15,7 @@ #endif // defined(HEADLESS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(HEADLESS_IMPLEMENTATION) #define HEADLESS_EXPORT __attribute__((visibility("default"))) -#else -#define HEADLESS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/headless/test/headless_protocol_browsertest.cc b/headless/test/headless_protocol_browsertest.cc index 7344a1d..2b675b67 100644 --- a/headless/test/headless_protocol_browsertest.cc +++ b/headless/test/headless_protocol_browsertest.cc
@@ -290,12 +290,24 @@ "emulation/virtual-time-history-navigation-same-doc.js") HEADLESS_PROTOCOL_TEST(VirtualTimeSVG, "emulation/virtual-time-svg.js") -HEADLESS_PROTOCOL_TEST(VirtualTimeWorkerBasic, +// Flaky on Mac. TODO(crbug.com/352304682): Re-enable. +#if BUILDFLAG(IS_MAC) +#define MAYBE_VirtualTimeWorkerBasic DISABLED_VirtualTimeWorkerBasic +#else +#define MAYBE_VirtualTimeWorkerBasic VirtualTimeWorkerBasic +#endif +HEADLESS_PROTOCOL_TEST(MAYBE_VirtualTimeWorkerBasic, "emulation/virtual-time-worker-basic.js") HEADLESS_PROTOCOL_TEST(VirtualTimeWorkerLockstep, "emulation/virtual-time-worker-lockstep.js") -HEADLESS_PROTOCOL_TEST(VirtualTimeWorkerFetch, +// Flaky on Mac. TODO(crbug.com/352304682): Re-enable. +#if BUILDFLAG(IS_MAC) +#define MAYBE_VirtualTimeWorkerFetch DISABLED_VirtualTimeWorkerFetch +#else +#define MAYBE_VirtualTimeWorkerFetch VirtualTimeWorkerFetch +#endif +HEADLESS_PROTOCOL_TEST(MAYBE_VirtualTimeWorkerFetch, "emulation/virtual-time-worker-fetch.js") HEADLESS_PROTOCOL_TEST(VirtualTimeWorkerTerminate, "emulation/virtual-time-worker-terminate.js")
diff --git a/infra/config/console-header.star b/infra/config/console-header.star index f4d0772..a25e179 100644 --- a/infra/config/console-header.star +++ b/infra/config/console-header.star
@@ -167,6 +167,16 @@ alt = "Checks console", ), headers.link( + text = "chromium", + branch_selector = [ + branches.selector.ANDROID_BRANCHES, + branches.selector.DESKTOP_BRANCHES, + branches.selector.FUCHSIA_BRANCHES, + ], + url = "/p/{}/g/chromium".format(settings.project), + alt = "Main Chromium archive console", + ), + headers.link( text = "chromiumos", branch_selector = branches.selector.CROS_LTS_BRANCHES, url = "/p/{}/g/chromium.chromiumos".format(settings.project),
diff --git a/infra/config/generated/builders/ci/GPU FYI Win x64 Builder/targets/chromium.gpu.fyi.json b/infra/config/generated/builders/ci/GPU FYI Win x64 Builder/targets/chromium.gpu.fyi.json index a4231e2..78e7c40 100644 --- a/infra/config/generated/builders/ci/GPU FYI Win x64 Builder/targets/chromium.gpu.fyi.json +++ b/infra/config/generated/builders/ci/GPU FYI Win x64 Builder/targets/chromium.gpu.fyi.json
@@ -3044,6 +3044,30 @@ }, { "args": [ + "--gtest_filter=MediaFoundationEncryptedMediaTest*", + "--use-gpu-in-tests" + ], + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "media_foundation_browser_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "display_attached": "1", + "gpu": "1002:7480-32.0.12033.1030", + "os": "Windows-11-26100", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 1800, + "io_timeout": 1800, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + }, + { + "args": [ "--gtest_filter=WebNN*", "--use-gpu-in-tests" ],
diff --git "a/infra/config/generated/builders/ci/Win11 FYI x64 Release \050AMD RX 7600\051/targets/chromium.gpu.fyi.json" "b/infra/config/generated/builders/ci/Win11 FYI x64 Release \050AMD RX 7600\051/targets/chromium.gpu.fyi.json" index f531e42..21bfc51 100644 --- "a/infra/config/generated/builders/ci/Win11 FYI x64 Release \050AMD RX 7600\051/targets/chromium.gpu.fyi.json" +++ "b/infra/config/generated/builders/ci/Win11 FYI x64 Release \050AMD RX 7600\051/targets/chromium.gpu.fyi.json"
@@ -100,6 +100,30 @@ }, { "args": [ + "--gtest_filter=MediaFoundationEncryptedMediaTest*", + "--use-gpu-in-tests" + ], + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "media_foundation_browser_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "display_attached": "1", + "gpu": "1002:7480-32.0.12033.1030", + "os": "Windows-11-26100", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 1800, + "io_timeout": 1800, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + }, + { + "args": [ "--gtest_filter=WebNN*", "--use-gpu-in-tests" ],
diff --git a/infra/config/generated/builders/try/gpu-fyi-try-win11-amd-rel-64/targets/chromium.gpu.fyi.json b/infra/config/generated/builders/try/gpu-fyi-try-win11-amd-rel-64/targets/chromium.gpu.fyi.json index e8d8046c..6a05ab0 100644 --- a/infra/config/generated/builders/try/gpu-fyi-try-win11-amd-rel-64/targets/chromium.gpu.fyi.json +++ b/infra/config/generated/builders/try/gpu-fyi-try-win11-amd-rel-64/targets/chromium.gpu.fyi.json
@@ -101,6 +101,30 @@ }, { "args": [ + "--gtest_filter=MediaFoundationEncryptedMediaTest*", + "--use-gpu-in-tests" + ], + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "media_foundation_browser_tests", + "swarming": { + "containment_type": "AUTO", + "dimensions": { + "display_attached": "1", + "gpu": "1002:7480-32.0.12033.1030", + "os": "Windows-11-26100", + "pool": "chromium.tests.gpu" + }, + "hard_timeout": 1800, + "io_timeout": 1800, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + }, + { + "args": [ "--gtest_filter=WebNN*", "--use-gpu-in-tests" ],
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index d8ad7229..0b1bb08 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -240,6 +240,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -1181,6 +1186,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -1940,6 +1950,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -2499,6 +2514,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -2876,6 +2896,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -3744,6 +3769,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -4211,6 +4241,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -4643,6 +4678,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -5012,6 +5052,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -5384,6 +5429,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -5756,6 +5806,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -6193,6 +6248,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -7189,6 +7249,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -7951,6 +8016,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -8318,6 +8388,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -8999,6 +9074,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -9381,6 +9461,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -9743,6 +9828,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -10194,6 +10284,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -10626,6 +10721,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -11114,6 +11214,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -11541,6 +11646,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -12143,6 +12253,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -12715,6 +12830,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -13337,6 +13457,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -13824,6 +13949,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -14213,6 +14343,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -14744,6 +14879,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -15373,6 +15513,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -15796,6 +15941,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -16554,6 +16704,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -16949,6 +17104,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -17692,6 +17852,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -18098,6 +18263,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -18544,6 +18714,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -19016,6 +19191,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -19483,6 +19663,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -19850,6 +20035,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -20337,6 +20527,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -20735,6 +20930,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -21137,6 +21337,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -21704,6 +21909,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -22101,6 +22311,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -22539,6 +22754,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -22971,6 +23191,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -23343,6 +23568,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -23715,6 +23945,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -24181,6 +24416,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -24783,6 +25023,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -25176,6 +25421,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -25580,6 +25830,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console" @@ -25962,6 +26217,11 @@ alt: "Checks console" } links { + text: "chromium" + url: "/p/chromium/g/chromium" + alt: "Main Chromium archive console" + } + links { text: "chromiumos" url: "/p/chromium/g/chromium.chromiumos" alt: "ChromiumOS console"
diff --git a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star index 8b854af..00a7674 100644 --- a/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.gpu.fyi.star
@@ -3045,12 +3045,6 @@ "--test-launcher-filter-file=../../testing/buildbot/filters/win.amd.7600.gl_tests_passthrough.filter", ], ), - "media_foundation_browser_tests": targets.remove( - reason = [ - "TODO(crbug.com/40912267): Enable Media Foundation browser tests on ", - "gpu bots once the Windows OS supports HW secure decryption.", - ], - ), }, ), targets_settings = targets.settings(
diff --git a/internal b/internal index 2331975..20b9f62 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 23319755d0789a1e63cc4c1dfb6f38403c9bfa63 +Subproject commit 20b9f62811d76f8f5de0eba491b161f8bb948c6e
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm index ebc69da..ebdb485 100644 --- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm +++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm
@@ -113,34 +113,6 @@ } run_loop_ = std::make_unique<base::RunLoop>(); - sign_in_completion_ = ^(SigninCoordinatorResult result) { - run_loop_->Quit(); - switch (result) { - case SigninCoordinatorResult::SigninCoordinatorResultSuccess: - signin_result_ = signin::Tribool::kTrue; - break; - case SigninCoordinatorResult::SigninCoordinatorResultInterrupted: - case SigninCoordinatorResult::SigninCoordinatorResultCanceledByUser: - case SigninCoordinatorResult::SigninCoordinatorResultDisabled: - case SigninCoordinatorResult::SigninCoordinatorUINotAvailable: - case SigninCoordinatorResult::SigninCoordinatorProfileSwitch: - signin_result_ = signin::Tribool::kFalse; - break; - } - }; - continuation_provider_ = base::BindRepeating( - [](signin_ui::SigninCompletionCallback sign_in_completion) { - ChangeProfileContinuation continuation = base::BindOnce( - [](signin_ui::SigninCompletionCallback sign_in_completion, - SceneState* sceneState, base::OnceClosure closure) { - sign_in_completion( - SigninCoordinatorResult::SigninCoordinatorResultSuccess); - std::move(closure).Run(); - }, - sign_in_completion); - return continuation; - }, - sign_in_completion_); } void TearDown() override { @@ -148,17 +120,6 @@ EXPECT_OCMOCK_VERIFY((id)view_controller_mock_); EXPECT_OCMOCK_VERIFY((id)performer_mock_); } - // Reset the authentication_flow_’s request helper. - // Must be call before each `startSignIn` - void ResetAuthenticationFlowRequestHelper() { - // Each mock expect its methods to be called at most once. - test_authentication_flow_request_helper_ = - [[TestAuthenticationFlowRequest alloc] - initWithSigninCompletionCallback:sign_in_completion_ - changeProfileContinuationProvider:continuation_provider_]; - authentication_flow_.requestHelper = - test_authentication_flow_request_helper_; - } TestProfileIOS* CreateProfile( std::optional<std::string> name = std::nullopt) { @@ -197,6 +158,7 @@ signin_metrics::AccessPoint accessPoint, BOOL shouldHandOverToFlowInProfile) { view_controller_mock_ = OCMClassMock([UIViewController class]); + CHECK(!authentication_flow_); authentication_flow_ = [[AuthenticationFlow alloc] initWithBrowser:personal_browser_.get() identity:identity @@ -230,6 +192,47 @@ }) .andReturn(performer_mock_); } + + signin_ui::SigninCompletionCallback sign_in_completion = + ^(SigninCoordinatorResult result) { + run_loop_->Quit(); + switch (result) { + case SigninCoordinatorResult::SigninCoordinatorResultSuccess: + signin_result_ = signin::Tribool::kTrue; + break; + case SigninCoordinatorResult::SigninCoordinatorResultInterrupted: + case SigninCoordinatorResult::SigninCoordinatorResultCanceledByUser: + case SigninCoordinatorResult::SigninCoordinatorResultDisabled: + case SigninCoordinatorResult::SigninCoordinatorUINotAvailable: + case SigninCoordinatorResult::SigninCoordinatorProfileSwitch: + signin_result_ = signin::Tribool::kFalse; + break; + } + authentication_flow_ = nil; + }; + // Runs the sign_in_completion with Success and the closure. + ChangeProfileContinuationProvider continuation_provider = + base::BindRepeating( + [](signin_ui::SigninCompletionCallback sign_in_completion) { + ChangeProfileContinuation continuation = base::BindOnce( + [](signin_ui::SigninCompletionCallback sign_in_completion, + SceneState* sceneState, base::OnceClosure closure) { + sign_in_completion(SigninCoordinatorResult:: + SigninCoordinatorResultSuccess); + std::move(closure).Run(); + }, + sign_in_completion); + return continuation; + }, + sign_in_completion); + + // Each mock expect its methods to be called at most once. + test_authentication_flow_request_helper_ = + [[TestAuthenticationFlowRequest alloc] + initWithSigninCompletionCallback:sign_in_completion + changeProfileContinuationProvider:continuation_provider]; + authentication_flow_.requestHelper = + test_authentication_flow_request_helper_; } // Checks if the AuthenticationFlow operation has completed, and whether it @@ -393,7 +396,6 @@ browser:final_browser accessPoint:access_point]); - ResetAuthenticationFlowRequestHelper(); [authentication_flow_ startSignIn]; // The completion block should not be called synchronously. EXPECT_EQ(signin::Tribool::kUnknown, signin_result_); @@ -435,8 +437,6 @@ AuthenticationFlowInProfile<AuthenticationFlowPerformerDelegate>* authentication_flow_in_profile_ = nil; AuthenticationFlowPerformer* performer_mock_ = nil; - signin_ui::SigninCompletionCallback sign_in_completion_; - ChangeProfileContinuationProvider continuation_provider_; UIViewController* view_controller_mock_; // Used to verify histogram logging. base::HistogramTester histogram_tester_; @@ -480,7 +480,6 @@ [invocation getArgument:&completionBlock atIndex:3]; completionBlock(); }); - ResetAuthenticationFlowRequestHelper(); [authentication_flow_ startSignIn]; CheckSignInCompletion(/*expected_signed_in=*/false); @@ -580,7 +579,6 @@ run_loop_->Quit(); }); - ResetAuthenticationFlowRequestHelper(); [authentication_flow_ startSignIn]; run_loop_->Run(); } @@ -623,7 +621,6 @@ run_loop_->Quit(); }); - ResetAuthenticationFlowRequestHelper(); [authentication_flow_ startSignIn]; run_loop_->Run(); }
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/account_menu/account_menu_mediator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/account_menu/account_menu_mediator.mm index e4bbaaf..fb1771d 100644 --- a/ios/chrome/browser/authentication/ui_bundled/signin/account_menu/account_menu_mediator.mm +++ b/ios/chrome/browser/authentication/ui_bundled/signin/account_menu/account_menu_mediator.mm
@@ -460,6 +460,8 @@ case AccountMenuAccessPoint::kSettings: return CreateChangeProfileSettingsContinuation(); case AccountMenuAccessPoint::kWeb: { + GetApplicationContext()->GetLocalState()->SetBoolean( + prefs::kHasSwitchedAccountsViaWebFlow, true); if (_prepareChangeProfile) { _prepareChangeProfile(); };
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/signin_history_sync/signin_and_history_sync_coordinator.mm b/ios/chrome/browser/authentication/ui_bundled/signin/signin_history_sync/signin_and_history_sync_coordinator.mm index 2ba6d5d..863c38f 100644 --- a/ios/chrome/browser/authentication/ui_bundled/signin/signin_history_sync/signin_and_history_sync_coordinator.mm +++ b/ios/chrome/browser/authentication/ui_bundled/signin/signin_history_sync/signin_and_history_sync_coordinator.mm
@@ -54,8 +54,10 @@ @end @implementation SignInAndHistorySyncCoordinator { - // Sign-in or history sync coordinator, according to `_currentStep`. - AnimatedCoordinator* _childCoordinator; + // Sign-in coordinator, according to `_currentStep`. + SigninCoordinator* _signinCoordinator; + // HistorySyncPopupCoordinator for SignInHistorySyncStep::kHistorySync. + HistorySyncPopupCoordinator* _historySyncPopupCoordinator; // The current step. SignInHistorySyncStep _currentStep; // Promo button used to trigger the sign-in. @@ -95,7 +97,10 @@ } - (void)dealloc { - DCHECK(!_childCoordinator) << base::SysNSStringToUTF8([self description]); + CHECK(!_signinCoordinator, base::NotFatalUntil::M145) + << base::SysNSStringToUTF8([self description]); + CHECK(!_historySyncPopupCoordinator, base::NotFatalUntil::M145) + << base::SysNSStringToUTF8([self description]); } #pragma mark - ChromeCoordinator @@ -111,8 +116,8 @@ #pragma mark - AnimatedCoordinator - (void)stopAnimated:(BOOL)animated { - [_childCoordinator stopAnimated:animated]; - _childCoordinator = nil; + [self stopSigninCoordinatorAnimated:animated]; + [self stopHistorySyncPopupCoordinatorAnimated:animated]; _syncService = nullptr; _authenticationService = nullptr; [super stopAnimated:animated]; @@ -122,20 +127,31 @@ - (void)historySyncPopupCoordinator:(HistorySyncPopupCoordinator*)coordinator didFinishWithResult:(SigninCoordinatorResult)result { - [self currentStepDidFinishWithResult:result]; + CHECK_EQ(coordinator, _historySyncPopupCoordinator, + base::NotFatalUntil::M145); + [self stopHistorySyncPopupCoordinatorAnimated:YES]; + [self presentNextStepWithPreviousResult:result]; } #pragma mark - Private -- (void)stopChildCoordinator { - [_childCoordinator stop]; - _childCoordinator = nil; +- (void)stopHistorySyncPopupCoordinatorAnimated:(BOOL)animated { + [_historySyncPopupCoordinator stopAnimated:animated]; + _historySyncPopupCoordinator.delegate = nil; + _historySyncPopupCoordinator = nil; +} + +- (void)stopSigninCoordinatorAnimated:(BOOL)animated { + [_signinCoordinator stop]; + _signinCoordinator = nil; } // Moves to the next step and presents the coordinator of that next step. - (void)presentNextStepWithPreviousResult: (SigninCoordinatorResult)previousResult { - CHECK(!_childCoordinator) << base::SysNSStringToUTF8([self description]); + CHECK(!_signinCoordinator) << base::SysNSStringToUTF8([self description]); + CHECK(!_historySyncPopupCoordinator) + << base::SysNSStringToUTF8([self description]); switch (previousResult) { case SigninCoordinatorResultSuccess: case SigninCoordinatorResultDisabled: @@ -154,8 +170,7 @@ NOTREACHED(); } if (_currentStep != SignInHistorySyncStep::kCompleted) { - _childCoordinator = [self createPresentStepChildCoordinator]; - [_childCoordinator start]; + [self createAndPresentStepChildCoordinator]; return; } // If there are no steps remaining, call delegate to stop presenting @@ -181,11 +196,11 @@ } // Creates the current step coordinator according to `_currentStep`. -- (AnimatedCoordinator*)createPresentStepChildCoordinator { +- (void)createAndPresentStepChildCoordinator { switch (_currentStep) { case SignInHistorySyncStep::kFullscreenSignin: { // TODO(crbug.com/375605572) Sends an actual continuation. - SigninCoordinator* coordinator = [[FullscreenSigninCoordinator alloc] + _signinCoordinator = [[FullscreenSigninCoordinator alloc] initWithBaseViewController:self.baseViewController browser:self.browser screenProvider:[[SigninScreenProvider alloc] init] @@ -193,31 +208,32 @@ accessPoint:self.accessPoint changeProfileContinuationProvider:_continuationProvider]; __weak __typeof(self) weakSelf = self; - coordinator.signinCompletion = + _signinCoordinator.signinCompletion = ^(SigninCoordinatorResult result, id<SystemIdentity>) { - [weakSelf currentStepDidFinishWithResult:result]; + [weakSelf currentSigninStepDidFinishWithResult:result]; }; - return coordinator; + [_signinCoordinator start]; + return; } case SignInHistorySyncStep::kBottomSheetSignin: { - SigninCoordinator* coordinator = - [[ConsistencyPromoSigninCoordinator alloc] - initWithBaseViewController:self.baseViewController - browser:self.browser - contextStyle:self.contextStyle - accessPoint:self.accessPoint - prepareChangeProfile:nil - continuationProvider:_continuationProvider]; + _signinCoordinator = [[ConsistencyPromoSigninCoordinator alloc] + initWithBaseViewController:self.baseViewController + browser:self.browser + contextStyle:self.contextStyle + accessPoint:self.accessPoint + prepareChangeProfile:nil + continuationProvider:_continuationProvider]; __weak __typeof(self) weakSelf = self; - coordinator.signinCompletion = + _signinCoordinator.signinCompletion = ^(SigninCoordinatorResult result, id<SystemIdentity>) { - [weakSelf currentStepDidFinishWithResult:result]; + [weakSelf currentSigninStepDidFinishWithResult:result]; }; - return coordinator; + [_signinCoordinator start]; + return; } case SignInHistorySyncStep::kInstantSignin: { // TODO(crbug.com/375605572) Sends an actual continuation. - SigninCoordinator* coordinator = [[InstantSigninCoordinator alloc] + _signinCoordinator = [[InstantSigninCoordinator alloc] initWithBaseViewController:self.baseViewController browser:self.browser identity:nil @@ -226,11 +242,12 @@ promoAction:_promoAction continuationProvider:_continuationProvider]; __weak __typeof(self) weakSelf = self; - coordinator.signinCompletion = + _signinCoordinator.signinCompletion = ^(SigninCoordinatorResult result, id<SystemIdentity>) { - [weakSelf currentStepDidFinishWithResult:result]; + [weakSelf currentSigninStepDidFinishWithResult:result]; }; - return coordinator; + [_signinCoordinator start]; + return; } case SignInHistorySyncStep::kHistorySync: { if (history_sync::GetSkipReason(_syncService, _authenticationService, @@ -239,20 +256,19 @@ history_sync::HistorySyncSkipReason::kNone) { [self presentNextStepWithPreviousResult:SigninCoordinatorResultDisabled]; - return nil; } else { - HistorySyncPopupCoordinator* coordinator = - [[HistorySyncPopupCoordinator alloc] - initWithBaseViewController:self.baseViewController - browser:self.browser - showUserEmail:NO - signOutIfDeclined:NO - isOptional:_optionalHistorySync - contextStyle:self.contextStyle - accessPoint:self.accessPoint]; - coordinator.delegate = self; - return coordinator; + _historySyncPopupCoordinator = [[HistorySyncPopupCoordinator alloc] + initWithBaseViewController:self.baseViewController + browser:self.browser + showUserEmail:NO + signOutIfDeclined:NO + isOptional:_optionalHistorySync + contextStyle:self.contextStyle + accessPoint:self.accessPoint]; + _historySyncPopupCoordinator.delegate = self; + [_historySyncPopupCoordinator start]; } + return; } case SignInHistorySyncStep::kStart: case SignInHistorySyncStep::kCompleted: @@ -262,11 +278,13 @@ } // Stops the child coordinator and prepares the next step to present. -- (void)currentStepDidFinishWithResult:(SigninCoordinatorResult)result { +- (void)currentSigninStepDidFinishWithResult:(SigninCoordinatorResult)result { // TODO(crbug.com/40929259): Turn into CHECK. - DUMP_WILL_BE_CHECK(_childCoordinator) + DUMP_WILL_BE_CHECK(_signinCoordinator) << base::SysNSStringToUTF8([self description]); - [self stopChildCoordinator]; + DUMP_WILL_BE_CHECK(!_historySyncPopupCoordinator) + << base::SysNSStringToUTF8([self description]); + [self stopSigninCoordinatorAnimated:YES]; [self presentNextStepWithPreviousResult:result]; } @@ -301,9 +319,11 @@ - (NSString*)description { return [NSString - stringWithFormat:@"<%@: %p, childcoordinator: %@, currentStep: %d, " + stringWithFormat:@"<%@: %p, signinCoordinator: %@, " + "historySyncPopupCoordinator: %@, currentStep: %d, " @"accessPoint %d, promoAction %d>", - self.class.description, self, _childCoordinator, + self.class.description, self, _signinCoordinator, + _historySyncPopupCoordinator, static_cast<int>(_currentStep), static_cast<int>(self.accessPoint), static_cast<int>(_promoAction)];
diff --git a/ios/chrome/browser/intelligence/glic/ui/BUILD.gn b/ios/chrome/browser/intelligence/glic/ui/BUILD.gn index d2dd9a9..2df0074e 100644 --- a/ios/chrome/browser/intelligence/glic/ui/BUILD.gn +++ b/ios/chrome/browser/intelligence/glic/ui/BUILD.gn
@@ -11,11 +11,21 @@ "glic_promo_display_handler.mm", ] deps = [ + ":constants", "//base", "//components/feature_engagement/public:feature_constants", "//ios/chrome/browser/promos_manager/model:types", "//ios/chrome/browser/promos_manager/ui_bundled:promos", + "//ios/chrome/browser/shared/ui/symbols", + "//ios/chrome/common/ui/colors", "//ios/chrome/common/ui/promo_style", ] frameworks = [ "UIKit.framework" ] } + +source_set("constants") { + sources = [ + "glic_constants.h", + "glic_constants.mm", + ] +}
diff --git a/ios/chrome/browser/intelligence/glic/ui/glic_consent_view_controller.mm b/ios/chrome/browser/intelligence/glic/ui/glic_consent_view_controller.mm index f6a9db3..0e30183e 100644 --- a/ios/chrome/browser/intelligence/glic/ui/glic_consent_view_controller.mm +++ b/ios/chrome/browser/intelligence/glic/ui/glic_consent_view_controller.mm
@@ -5,43 +5,108 @@ #import "ios/chrome/browser/intelligence/glic/ui/glic_consent_view_controller.h" #import "ios/chrome/browser/intelligence/glic/ui/glic_consent_mutator.h" +#import "ios/chrome/browser/intelligence/glic/ui/glic_constants.h" +#import "ios/chrome/browser/shared/ui/symbols/symbols.h" +#import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/promo_style/promo_style_view_controller_delegate.h" @interface GLICConsentViewController () <PromoStyleViewControllerDelegate> - @end -@implementation GLICConsentViewController +@implementation GLICConsentViewController { + UIStackView* _mainStackView; +} #pragma mark - UIViewController // TODO(crbug.com/414777915): Implement a basic UI. - (void)viewDidLoad { self.delegate = self; + [self configureSheetPresentation]; + [self configurePromoStyleProperties]; + [super viewDidLoad]; + // The stackview should be added after `viewDidLoad`, so that the + // `UIScrollView` is not placed on top of the stackview. + [self setupStackView]; +} + +#pragma mark - Private + +// Configure all the stacks. +- (void)setupStackView { + [self configureMainStackView]; +} + +// Configure the differents detents for the expanded and collapsed view. +- (void)configureSheetPresentation { + self.modalPresentationStyle = UIModalPresentationPageSheet; + + self.sheetPresentationController.detents = @[ + [self customHeightDetentWithIdentifier:kGLICConsentPartialDetentIdentifier + height:kGLICConsentPartialDetentHeight], + [self customHeightDetentWithIdentifier:kGLICConsentFullDetentIdentifier + height:kGLICConsentFullDetentHeight] + ]; + + self.sheetPresentationController.selectedDetentIdentifier = + kGLICConsentPartialDetentIdentifier; + + self.sheetPresentationController.preferredCornerRadius = + kGLICConsentPreferredCornerRadius; + self.sheetPresentationController.prefersScrollingExpandsWhenScrolledToEdge = + NO; +} + +// Create a custom sheet presentation controller detent with a fixed height. +- (UISheetPresentationControllerDetent*) + customHeightDetentWithIdentifier:(NSString*)identifier + height:(CGFloat)height { + auto resolver = ^CGFloat( + id<UISheetPresentationControllerDetentResolutionContext> context) { + return height; + }; + + return + [UISheetPresentationControllerDetent customDetentWithIdentifier:identifier + resolver:resolver]; +} + +// Configure promo style properties to add buttons. Ignores header image type. +- (void)configurePromoStyleProperties { self.layoutBehindNavigationBar = YES; self.shouldHideBanner = YES; self.headerImageType = PromoStyleImageType::kNone; - self.modalPresentationStyle = UIModalPresentationPageSheet; + self.primaryActionString = kGLICConsentPrimaryAction; + self.secondaryActionString = kGLICConsentSecondaryAction; +} - // TODO(crbug.com/414777890): Use a custom detent. - self.sheetPresentationController.detents = @[ - [UISheetPresentationControllerDetent mediumDetent], - [UISheetPresentationControllerDetent largeDetent] - ]; +// Configure the main stack view. +- (void)configureMainStackView { + _mainStackView = [[UIStackView alloc] init]; + _mainStackView.axis = UILayoutConstraintAxisVertical; + _mainStackView.distribution = UIStackViewDistributionFill; + _mainStackView.alignment = UIStackViewAlignmentFill; + _mainStackView.spacing = kGLICConsentMainStackSpacing; - self.sheetPresentationController.preferredCornerRadius = 16.0; + _mainStackView.translatesAutoresizingMaskIntoConstraints = NO; - UIView* rootView = [[UIView alloc] initWithFrame:UIScreen.mainScreen.bounds]; - rootView.backgroundColor = [UIColor systemBackgroundColor]; - [self.view addSubview:rootView]; + [self.view addSubview:_mainStackView]; - // TODO(crbug.com/414778685): Add strings. - self.primaryActionString = @"Yes, I'm in"; - self.secondaryActionString = @"No thanks"; - - self.bannerSize = BannerImageSizeType::kStandard; - [super viewDidLoad]; + [NSLayoutConstraint activateConstraints:@[ + [_mainStackView.leadingAnchor + constraintEqualToAnchor:self.view.leadingAnchor + constant:kGLICConsentMainStackHorizontalInset], + [_mainStackView.trailingAnchor + constraintEqualToAnchor:self.view.trailingAnchor + constant:-kGLICConsentMainStackHorizontalInset], + [_mainStackView.topAnchor + constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor + constant:kGLICConsentMainStackTopInset], + [_mainStackView.bottomAnchor + constraintLessThanOrEqualToAnchor:self.view.safeAreaLayoutGuide + .bottomAnchor] + ]]; } #pragma mark - PromoStyleViewControllerDelegate
diff --git a/ios/chrome/browser/intelligence/glic/ui/glic_constants.h b/ios/chrome/browser/intelligence/glic/ui/glic_constants.h new file mode 100644 index 0000000..de0642a --- /dev/null +++ b/ios/chrome/browser/intelligence/glic/ui/glic_constants.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_GLIC_UI_GLIC_CONSTANTS_H_ +#define IOS_CHROME_BROWSER_INTELLIGENCE_GLIC_UI_GLIC_CONSTANTS_H_ + +#import <Foundation/Foundation.h> +#import <UIKit/UIKit.h> + +// Sheet detents. +extern NSString* const kGLICConsentPartialDetentIdentifier; +extern NSString* const kGLICConsentFullDetentIdentifier; +extern const CGFloat kGLICConsentPartialDetentHeight; +extern const CGFloat kGLICConsentFullDetentHeight; +extern const CGFloat kGLICConsentPreferredCornerRadius; + +// Stack view insets and spacing. +extern const CGFloat kGLICConsentMainStackHorizontalInset; +extern const CGFloat kGLICConsentMainStackTopInset; +extern const CGFloat kGLICConsentMainStackSpacing; + +// Promo style strings. +extern NSString* const kGLICConsentPrimaryAction; +extern NSString* const kGLICConsentSecondaryAction; + +#endif // IOS_CHROME_BROWSER_INTELLIGENCE_GLIC_UI_GLIC_CONSTANTS_H_
diff --git a/ios/chrome/browser/intelligence/glic/ui/glic_constants.mm b/ios/chrome/browser/intelligence/glic/ui/glic_constants.mm new file mode 100644 index 0000000..17cbd85 --- /dev/null +++ b/ios/chrome/browser/intelligence/glic/ui/glic_constants.mm
@@ -0,0 +1,24 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/intelligence/glic/ui/glic_constants.h" + +// Sheet detents. +NSString* const kGLICConsentPartialDetentIdentifier = + @"GLICConsentPartialDetentIdentifier"; +NSString* const kGLICConsentFullDetentIdentifier = + @"GLICConsentFullDetentIdentifier"; +const CGFloat kGLICConsentPartialDetentHeight = 300.0; +const CGFloat kGLICConsentFullDetentHeight = 500.0; +const CGFloat kGLICConsentPreferredCornerRadius = 10.0; + +// Stack view insets and spacing. +const CGFloat kGLICConsentMainStackHorizontalInset = 20.0; +const CGFloat kGLICConsentMainStackTopInset = 24.0; +const CGFloat kGLICConsentMainStackSpacing = 16.0; + +// Promo style strings. +// TODO(crbug.com/414778685): Add strings. +NSString* const kGLICConsentPrimaryAction = @"Yes, I'm in"; +NSString* const kGLICConsentSecondaryAction = @"No thanks";
diff --git a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_coordinator.mm b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_coordinator.mm index 4e88298..0345f7b 100644 --- a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_coordinator.mm +++ b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_coordinator.mm
@@ -301,7 +301,14 @@ - (void)searchWithLensImageMetadata:(id<LensImageMetadata>)metadata entrypoint:(LensOverlayEntrypoint)entrypoint completion:(void (^)(BOOL))completion { - [self prepareOverlayWithEntrypoint:entrypoint]; + BOOL success = [self prepareOverlayWithEntrypoint:entrypoint]; + if (!success) { + if (completion) { + completion(NO); + } + + return; + } // Even if the image is already prepared at this point, the snapshotting // infrastructure still needs to be built to allow the restoration window to // be displayed when exiting and re-entering the experience. @@ -316,7 +323,13 @@ - (void)searchImageWithLens:(UIImage*)image entrypoint:(LensOverlayEntrypoint)entrypoint completion:(void (^)(BOOL))completion { - [self prepareOverlayWithEntrypoint:entrypoint]; + BOOL success = [self prepareOverlayWithEntrypoint:entrypoint]; + if (!success) { + if (completion) { + completion(NO); + } + return; + } // Even if the image is already prepared at this point, the snapshotting // infrastructure still needs to be built to allow the restoration window to // be displayed when exiting and re-entering the experience. @@ -331,7 +344,13 @@ - (void)createAndShowLensUI:(BOOL)animated entrypoint:(LensOverlayEntrypoint)entrypoint completion:(void (^)(BOOL))completion { - [self prepareOverlayWithEntrypoint:entrypoint]; + BOOL success = [self prepareOverlayWithEntrypoint:entrypoint]; + if (!success) { + if (completion) { + completion(NO); + } + return; + } __weak __typeof(self) weakSelf = self; [self captureSnapshotWithCompletion:^(UIImage* snapshot) { LensImageSource* imageSource = @@ -945,7 +964,7 @@ #pragma mark - private // Prepares the lens overlay for display from the given entrypoint. -- (void)prepareOverlayWithEntrypoint:(LensOverlayEntrypoint)entrypoint { +- (BOOL)prepareOverlayWithEntrypoint:(LensOverlayEntrypoint)entrypoint { if (self.isUICreated) { // The UI is probably associated with the non-active tab. Destroy it with no // animation. @@ -960,7 +979,12 @@ object:nil]; _entrypoint = entrypoint; - _associatedTabHelper = self.activeTabHelper->GetWeakPtr(); + + LensOverlayTabHelper* tabHelper = self.activeTabHelper; + if (!tabHelper) { + return NO; + } + _associatedTabHelper = tabHelper->GetWeakPtr(); _metricsRecorder = [[LensOverlayMetricsRecorder alloc] initWithEntrypoint:entrypoint @@ -970,6 +994,8 @@ // handler for the associated tab. _associatedTabHelper->SetLensOverlayCommandsHandler(self); _associatedTabHelper->SetLensOverlayUIAttachedAndAlive(true); + + return YES; } // Opens a given URL in a new tab.
diff --git a/ios/chrome/browser/omnibox/model/omnibox_controller_ios.h b/ios/chrome/browser/omnibox/model/omnibox_controller_ios.h index 1802767f..3d11428 100644 --- a/ios/chrome/browser/omnibox/model/omnibox_controller_ios.h +++ b/ios/chrome/browser/omnibox/model/omnibox_controller_ios.h
@@ -93,12 +93,6 @@ bool hidden) const; private: - // Stores the bitmap, using `icon_url` as the key in - // `edit_model_->icon_bitmaps_` if provided, or `result_index` in - // `edit_model_->rich_suggestion_bitmaps_` otherwise. - void SetRichSuggestionBitmap(int result_index, - const GURL& icon_url, - const SkBitmap& bitmap); // Called when the prefs for the visibility of groups changes. void OnSuggestionGroupVisibilityPrefChanged();
diff --git a/ios/chrome/browser/omnibox/model/omnibox_controller_ios.mm b/ios/chrome/browser/omnibox/model/omnibox_controller_ios.mm index 36fcb09..f70913b 100644 --- a/ios/chrome/browser/omnibox/model/omnibox_controller_ios.mm +++ b/ios/chrome/browser/omnibox/model/omnibox_controller_ios.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/omnibox/model/omnibox_controller_ios.h" #import "base/functional/bind.h" +#import "base/functional/callback_helpers.h" #import "base/metrics/histogram.h" #import "base/strings/utf_string_conversions.h" #import "base/trace_event/trace_event.h" @@ -144,11 +145,10 @@ // passed in to eliminate the potential for crashes on shutdown. // `should_preload` is set to `controller->done()` as prerender may only want // to start preloading a result after all Autocomplete results are ready. - client_->OnResultChanged( - autocomplete_controller_->result(), default_match_changed, - /*should_preload=*/controller->done(), - base::BindRepeating(&OmniboxControllerIOS::SetRichSuggestionBitmap, - weak_ptr_factory_.GetWeakPtr())); + client_->OnResultChanged(autocomplete_controller_->result(), + default_match_changed, + /*should_preload=*/controller->done(), + /*on_bitmap_fetched=*/base::DoNothing()); } void OmniboxControllerIOS::ClearPopupKeywordMode() const { @@ -198,16 +198,6 @@ } } -void OmniboxControllerIOS::SetRichSuggestionBitmap(int result_index, - const GURL& icon_url, - const SkBitmap& bitmap) { - if (!icon_url.is_empty()) { - edit_model_->SetIconBitmap(icon_url, bitmap); - } else { - edit_model_->SetPopupRichSuggestionBitmap(result_index, bitmap); - } -} - void OmniboxControllerIOS::OnSuggestionGroupVisibilityPrefChanged() { for (size_t i = 0; i < autocomplete_controller_->result().size(); ++i) { const AutocompleteMatch& match =
diff --git a/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios.h b/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios.h index 790774e81..bc0c264 100644 --- a/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios.h +++ b/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios.h
@@ -39,31 +39,6 @@ class OmniboxEditModelIOS { public: - struct State { - State(bool user_input_in_progress, - const std::u16string& user_text, - const std::u16string& keyword, - const std::u16string& keyword_placeholder, - bool is_keyword_hint, - metrics::OmniboxEventProto::KeywordModeEntryMethod - keyword_mode_entry_method, - OmniboxFocusState focus_state, - const AutocompleteInput& autocomplete_input); - State(const State& other); - ~State(); - State& operator=(const State&) = delete; - - bool user_input_in_progress; - const std::u16string user_text; - const std::u16string keyword; - const std::u16string keyword_placeholder; - const bool is_keyword_hint; - metrics::OmniboxEventProto::KeywordModeEntryMethod - keyword_mode_entry_method; - OmniboxFocusState focus_state; - const AutocompleteInput autocomplete_input; - }; - OmniboxEditModelIOS(OmniboxControllerIOS* controller, OmniboxViewBase* view); virtual ~OmniboxEditModelIOS(); OmniboxEditModelIOS(const OmniboxEditModelIOS&) = delete; @@ -75,14 +50,6 @@ metrics::OmniboxEventProto::PageClassification GetPageClassification() const; - // Returns the current state. This assumes we are switching tabs, and changes - // the internal state appropriately. - State GetStateForTabSwitch() const; - - // Resets the tab state, then restores local state from `state`. `state` may - // be nullptr if there is no saved state. - void RestoreState(const State* state); - // Returns the match for the current text. If the user has not edited the text // this is the match corresponding to the permanent text. Returns the // alternate nav URL, if `alternate_nav_url` is non-NULL and there is such a @@ -127,16 +94,6 @@ bool user_input_in_progress() const { return user_input_in_progress_; } - // Encapsulates all the varied conditions for whether to override the - // permanent page icon (associated with the currently displayed page), - // with a temporary icon (associated with the current match or user text). - bool ShouldShowCurrentPageIcon() const; - - // Returns the SuperGIcon for chrome builds. Otherwise return an empty - // ImageModel. If `dark_mode` is enabled, return the monochrome version of the - // icon. - ui::ImageModel GetSuperGIcon(int image_size, bool dark_mode) const; - // Sets the state of user_input_in_progress_, and notifies the observer if // that state has changed. void SetInputInProgress(bool in_progress); @@ -387,15 +344,6 @@ // Returns true if the destination URL of the match is bookmarked. bool IsStarredMatch(const AutocompleteMatch& match) const; -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - // Gets the icon for the given `match`. - gfx::Image GetMatchIcon(const AutocompleteMatch& match, - SkColor vector_icon_color) const; - // Gets the icon for the given `match` if the match was provided by an omnibox - // API extension, otherwise returns empty image. - gfx::Image GetMatchIconIfExtension(const AutocompleteMatch& match) const; -#endif - // Returns true if the popup exists and is open. Virtual for testing. virtual bool PopupIsOpen() const; @@ -451,32 +399,6 @@ // preserved here only to prevent possible behavior change while refactoring. void OnPopupResultChanged(); - // Lookup the bitmap for `result_index`. Returns nullptr if not found. - const SkBitmap* GetPopupRichSuggestionBitmap(int result_index) const; - - // Lookup the bitmap for the first `match` in - // `autocomplete_controller()->result()` that has `keyword` as its - // `associated_keyword`. Used to fetch bitmap where the `result_index` is - // unknown. Returns nullptr if not found. - const SkBitmap* GetPopupRichSuggestionBitmap( - const std::u16string& keyword) const; - - // Lookup the bitmap based on the image URL. Similar to above, - // but used to fetch bitmap where the `result_index` is unknown and where - // there are possibly multiple suggestions with the same `keyword` but not the - // `image_url` being looked up. Returns nullptr if not found. - const SkBitmap* GetPopupRichSuggestionBitmap(const GURL& image_url) const; - - // Lookup the icon bitmap based on the icon URL. Returns nullptr - // if not found. - const SkBitmap* GetIconBitmap(const GURL& icon_url) const; - - // Stores the image in a local data member and schedules a repaint. - void SetPopupRichSuggestionBitmap(int result_index, const SkBitmap& bitmap); - - // Stores the icon in a local data member and schedules a repaint. - void SetIconBitmap(const GURL& icon_url, const SkBitmap& bitmap); - // Updates the popup view when the visibility of a group changes. void SetPopupSuggestionGroupVisibility(size_t match_index, bool suggestion_group_hidden); @@ -513,12 +435,6 @@ FRIEND_TEST_ALL_PREFIXES(OmniboxEditModelIOSTest, ConsumeCtrlKeyOnRequestFocus); FRIEND_TEST_ALL_PREFIXES(OmniboxEditModelIOSTest, ConsumeCtrlKeyOnCtrlAction); - FRIEND_TEST_ALL_PREFIXES( - OmniboxEditModelIOSPopupTest, - GetPopupRichSuggestionBitmapForMatchWithoutAssociatedKeyword); - FRIEND_TEST_ALL_PREFIXES( - OmniboxEditModelIOSPopupTest, - GetPopupRichSuggestionBitmapForMatchWithAssociatedKeyword); enum PasteState { NONE, // Most recent edit was not a paste. @@ -643,10 +559,6 @@ // the view. void SetFocusState(OmniboxFocusState state, OmniboxFocusChangeReason reason); - // This is an event handler that notifies the popup view of match icon - // changes. - void OnFaviconFetched(const GURL& page_url, const gfx::Image& icon) const; - // Returns view text if there is a view. Until the model is made the // primary data source, this should not be called when there's no view. std::u16string GetText() const; @@ -680,12 +592,11 @@ std::u16string url_for_editing_; // This flag is true when the user has modified the contents of the edit, but - // not yet accepted them. We use this to determine when we need to save - // state (on switching tabs) and whether changes to the page URL should be - // immediately displayed. - // This flag *should* be true in a superset of the cases where the popup is - // open. Except (crbug.com/1340378) for zero suggestions when the popup was - // opened with ctrl+L or a mouse click (as opposed to the down arrow). + // not yet accepted them. We use this to determine whether changes to the + // page URL should be immediately displayed. This flag *should* be true in a + // superset of the cases where the popup is open. Except (crbug.com/1340378) + // for zero suggestions when the popup was opened with ctrl+L or a mouse click + // (as opposed to the down arrow). bool user_input_in_progress_; // The text that the user has entered. This does not include inline @@ -815,18 +726,6 @@ // `input_` to differ from the one currently stored in AutocompleteController. AutocompleteInput input_; - // Rich suggestion bitmaps for popup keyed by `result_index`. These are - // cleared when `OmniboxPopupViewViews` is initialized and destroyed, and on - // `OnPopupResultChanged()`. - std::map<int, SkBitmap> rich_suggestion_bitmaps_; - - // Icon bitmaps for popup keyed by `icon_url`. These are cleared when - // `OmniboxPopupViewViews` is initialized and destroyed. This differs from - // `rich_suggestion_bitmaps_` since they are not cleared on - // `OnPopupResultChanged()`, which allows for fetching the icon even when the - // popup is closed. - std::map<GURL, SkBitmap> icon_bitmaps_; - // The popup view is nullptr when there's no popup, and is non-null when // a popup view exists (i.e. between calls to `set_popup_view`). raw_ptr<OmniboxPopupViewBase> popup_view_ = nullptr;
diff --git a/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios.mm b/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios.mm index 2c693dd..6292a54 100644 --- a/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios.mm +++ b/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios.mm
@@ -71,7 +71,6 @@ #import "third_party/icu/source/common/unicode/ubidi.h" #import "third_party/metrics_proto/omnibox_event.pb.h" #import "third_party/metrics_proto/omnibox_focus_type.pb.h" -#import "third_party/skia/include/core/SkBitmap.h" #import "ui/base/l10n/l10n_util.h" #import "ui/gfx/color_palette.h" #import "ui/gfx/geometry/rect.h" @@ -79,11 +78,6 @@ #import "url/third_party/mozilla/url_parse.h" #import "url/url_util.h" -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -#import "ui/gfx/paint_vector_icon.h" -#import "ui/gfx/vector_icon_types.h" -#endif - constexpr bool kIsDesktop = !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS); using bookmarks::BookmarkModel; @@ -312,31 +306,6 @@ } // namespace -// OmniboxEditModelIOS::State -// ---------------------------------------------------- - -OmniboxEditModelIOS::State::State( - bool user_input_in_progress, - const std::u16string& user_text, - const std::u16string& keyword, - const std::u16string& keyword_placeholder, - bool is_keyword_hint, - OmniboxEventProto::KeywordModeEntryMethod keyword_mode_entry_method, - OmniboxFocusState focus_state, - const AutocompleteInput& autocomplete_input) - : user_input_in_progress(user_input_in_progress), - user_text(user_text), - keyword(keyword), - keyword_placeholder(keyword_placeholder), - is_keyword_hint(is_keyword_hint), - keyword_mode_entry_method(keyword_mode_entry_method), - focus_state(focus_state), - autocomplete_input(autocomplete_input) {} - -OmniboxEditModelIOS::State::State(const State& other) = default; - -OmniboxEditModelIOS::State::~State() = default; - // OmniboxEditModelIOS // ----------------------------------------------------------- @@ -362,8 +331,6 @@ popup_view_ = popup_view; // Clear/reset popup-related state. - rich_suggestion_bitmaps_.clear(); - icon_bitmaps_.clear(); old_focused_url_ = GURL(); popup_selection_ = OmniboxPopupSelection(OmniboxPopupSelection::kNoMatch, OmniboxPopupSelection::NORMAL); @@ -374,93 +341,6 @@ return controller_->client()->GetPageClassification(/*is_prefetch=*/false); } -OmniboxEditModelIOS::State OmniboxEditModelIOS::GetStateForTabSwitch() const { - // NOTE: it's important this doesn't attempt to access any state that - // may come from the active WebContents. At the time this is called, the - // active WebContents has already changed. - - // Like typing, switching tabs "accepts" the temporary text as the user - // text, because it makes little sense to have temporary text when the - // popup is closed. - std::u16string user_text; - if (user_input_in_progress_) { - const std::u16string display_text = GetText(); - if (!MaybePrependKeyword(display_text).empty()) { - user_text = display_text; - } - // Else case is user deleted all the text. The expectation (which matches - // other browsers) is when the user restores the state a revert happens as - // well as a select all. The revert shouldn't be done here, as at the time - // this is called a revert would revert to the url of the newly activated - // tab (because at the time this is called, the WebContents has already - // changed). By leaving the `user_text` empty downstream code is able to - // detect this and select all. - } else { - user_text = user_text_; - } - return State(user_input_in_progress_, user_text, keyword_, - keyword_placeholder_, is_keyword_hint_, - keyword_mode_entry_method_, focus_state_, input_); -} - -void OmniboxEditModelIOS::RestoreState(const State* state) { - // We need to update the permanent display texts correctly and revert the - // view regardless of whether there is saved state. - ResetDisplayTexts(); - - if (view_) { - view_->RevertAll(); - } - // Restore the autocomplete controller's input, or clear it if this is a new - // tab. - input_ = state ? state->autocomplete_input : AutocompleteInput(); - if (!state) { - return; - } - - // The tab-management system saves the last-focused control for each tab and - // restores it. That operation also updates this edit model's focus_state_ - // if necessary. This occurs before we reach this point in the code. - // - // The only reason we need to separately save and restore our focus state is - // to preserve our special "invisible focus" state used for the fakebox. - // - // However, in some circumstances (if the last-focused control was destroyed), - // the Omnibox will be focused by default, and the edit model's saved state - // may be invalid. We make a check to guard against that. - bool saved_focus_state_invalid = focus_state_ == OMNIBOX_FOCUS_VISIBLE && - state->focus_state == OMNIBOX_FOCUS_NONE; - if (!saved_focus_state_invalid) { - SetFocusState(state->focus_state, OMNIBOX_FOCUS_CHANGE_TAB_SWITCH); - } - - // Restore any user editing. - if (state->user_input_in_progress) { - // NOTE: Be sure to set keyword-related state AFTER invoking - // SetUserText(), as SetUserText() clears the keyword state. - if ((!state->user_text.empty() || !state->keyword.empty()) && view_) { - view_->SetUserText(state->user_text, false); - } - SetKeyword(state->keyword); - SetKeywordPlaceholder(state->keyword_placeholder); - is_keyword_hint_ = state->is_keyword_hint; - keyword_mode_entry_method_ = state->keyword_mode_entry_method; - if (view_) { - view_->OnKeywordPlaceholderTextChange(); - } - } else if (!state->user_text.empty()) { - // If the `user_input_in_progress` is false but we have `user_text`, - // restore the `user_text` to the model and the view. It's likely unelided - // text that the user has not made any modifications to. - InternalSetUserText(state->user_text); - - // We let the View manage restoring the cursor position afterwards. - if (view_) { - view_->SetWindowTextAndCaretPos(state->user_text, 0, false, false); - } - } -} - AutocompleteMatch OmniboxEditModelIOS::CurrentMatch( GURL* alternate_nav_url) const { // If we have a valid match use it. Otherwise get one for the current text. @@ -678,34 +558,6 @@ } } -bool OmniboxEditModelIOS::ShouldShowCurrentPageIcon() const { - // If the popup is open, don't show the current page's icon. The caller is - // instead expected to show the current match's icon. - if (PopupIsOpen()) { - return false; - } - - // On the New Tab Page, the omnibox textfield is empty. We want to display - // the default search provider favicon instead of the NTP security icon. - if (GetText().empty()) { - return false; - } - - // If user input is not in progress, always show the current page's icon. - if (!user_input_in_progress()) { - return true; - } - - // If user input is in progress, keep showing the current page's icon so long - // as the text matches the current page's URL, elided or unelided. - return GetText() == display_text_ || GetText() == url_for_editing_; -} - -ui::ImageModel OmniboxEditModelIOS::GetSuperGIcon(int image_size, - bool dark_mode) const { - return ui::ImageModel(); -} - void OmniboxEditModelIOS::UpdateInput(bool has_selected_text, bool prevent_inline_autocomplete) { bool changed_to_user_input_in_progress = SetInputInProgressNoNotify(true); @@ -1810,103 +1662,6 @@ return bookmark_model && bookmark_model->IsBookmarked(match.destination_url); } -// Android and iOS have their own platform-specific icon logic. -#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) -gfx::Image OmniboxEditModelIOS::GetMatchIcon(const AutocompleteMatch& match, - SkColor vector_icon_color) const { - if (!match.icon_url.is_empty()) { - const SkBitmap* bitmap = GetIconBitmap(match.icon_url); - if (bitmap) { - return controller_->client()->GetSizedIcon(bitmap); - } - } - - gfx::Image extension_icon = GetMatchIconIfExtension(match); - if (!extension_icon.IsEmpty()) { - return extension_icon; - } - - const TemplateURL* turl = - match.associated_keyword - ? controller_->client() - ->GetTemplateURLService() - ->GetTemplateURLForKeyword(match.associated_keyword->keyword) - : nullptr; - - // Get the favicon for navigational suggestions. - // - // The starter pack suggestions are a unique case. These suggestions - // normally use a favicon image that cannot be styled further by client - // code. In order to apply custom styling to the icon (e.g. colors), we ignore - // this favicon in favor of using a vector icon which has better styling - // support. - if (!AutocompleteMatch::IsSearchType(match.type) && - match.type != AutocompleteMatchType::DOCUMENT_SUGGESTION && - match.type != AutocompleteMatchType::HISTORY_CLUSTER && - match.type != AutocompleteMatchType::HISTORY_EMBEDDINGS_ANSWER && - !AutocompleteMatch::IsStarterPackType(match.type)) { - // Because the Views UI code calls GetMatchIcon in both the layout and - // painting code, we may generate multiple `OnFaviconFetched` callbacks, - // all run one after another. This seems to be harmless as the callback - // just flips a flag to schedule a repaint. However, if it turns out to be - // costly, we can optimize away the redundant extra callbacks. - gfx::Image favicon; - auto on_icon_fetched = - base::BindOnce(&OmniboxEditModelIOS::OnFaviconFetched, - weak_factory_.GetWeakPtr(), match.destination_url); - favicon = - (turl && AutocompleteMatch::IsFeaturedEnterpriseSearchType(match.type)) - ? controller_->client()->GetFaviconForKeywordSearchProvider( - turl, std::move(on_icon_fetched)) - : controller_->client()->GetFaviconForPageUrl( - match.destination_url, std::move(on_icon_fetched)); - - // Extension icons are the correct size for non-touch UI but need to be - // adjusted to be the correct size for touch mode. - if (!favicon.IsEmpty()) { - return controller_->client()->GetSizedIcon(favicon); - } - } - - bool is_starred_match = IsStarredMatch(match); - const auto& vector_icon_type = match.GetVectorIcon(is_starred_match, turl); - - return controller_->client()->GetSizedIcon(vector_icon_type, - vector_icon_color); -} - -gfx::Image OmniboxEditModelIOS::GetMatchIconIfExtension( - const AutocompleteMatch& match) const { - // Return an empty image if not an extension match. - TemplateURLService* service = controller_->client()->GetTemplateURLService(); - const TemplateURL* template_url = match.GetTemplateURL(service, false); - if (!template_url || - template_url->type() != TemplateURL::OMNIBOX_API_EXTENSION) { - return gfx::Image(); - } - - // Return the image specified in the suggestion match if set by looking it up - // in the rich suggestions bitmaps. Fall back to the extension icon if empty - // or not found. - if (match.provider && - match.provider->type() == AutocompleteProvider::TYPE_UNSCOPED_EXTENSION && - !match.ImageUrl().is_empty()) { - const SkBitmap* bitmap = GetPopupRichSuggestionBitmap(match.image_url); - if (bitmap) { - return controller_->client()->GetSizedIcon(bitmap); - } - } - - gfx::Image extension_icon = - controller_->client()->GetExtensionIcon(template_url); - // Extension icons are the correct size for non-touch UI but need to be - // adjusted to be the correct size for touch mode - return extension_icon.IsEmpty() - ? extension_icon - : controller_->client()->GetSizedIcon(extension_icon); -} -#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) - bool OmniboxEditModelIOS::PopupIsOpen() const { return popup_view_ && popup_view_->IsOpen(); } @@ -2270,7 +2025,6 @@ if (!popup_view_) { return; } - rich_suggestion_bitmaps_.clear(); const AutocompleteResult& result = autocomplete_controller()->result(); size_t old_selected_line = GetPopupSelection().line; @@ -2296,71 +2050,6 @@ popup_view_->UpdatePopupAppearance(); } -const SkBitmap* OmniboxEditModelIOS::GetPopupRichSuggestionBitmap( - int result_index) const { - DCHECK(popup_view_); - - const auto iter = rich_suggestion_bitmaps_.find(result_index); - if (iter == rich_suggestion_bitmaps_.end()) { - return nullptr; - } - return &iter->second; -} - -const SkBitmap* OmniboxEditModelIOS::GetPopupRichSuggestionBitmap( - const std::u16string& keyword) const { - DCHECK(popup_view_); - - auto it = std::ranges::find_if(autocomplete_controller()->result(), - [&keyword](const AutocompleteMatch& match) { - return match.associated_keyword && - match.associated_keyword->keyword == - keyword; - }); - return it == autocomplete_controller()->result().end() - ? nullptr - : GetPopupRichSuggestionBitmap(std::distance( - autocomplete_controller()->result().begin(), it)); -} - -const SkBitmap* OmniboxEditModelIOS::GetPopupRichSuggestionBitmap( - const GURL& image_url) const { - DCHECK(popup_view_); - auto iter = - std::ranges::find_if(autocomplete_controller()->result(), - [&image_url](const AutocompleteMatch& result_match) { - return (!result_match.ImageUrl().is_empty() && - result_match.ImageUrl() == image_url); - }); - return iter == autocomplete_controller()->result().end() - ? nullptr - : GetPopupRichSuggestionBitmap(std::distance( - autocomplete_controller()->result().begin(), iter)); -} - -const SkBitmap* OmniboxEditModelIOS::GetIconBitmap(const GURL& icon_url) const { - DCHECK(popup_view_); - auto iter = icon_bitmaps_.find(icon_url); - if (iter == icon_bitmaps_.end()) { - return nullptr; - } - return &iter->second; -} - -void OmniboxEditModelIOS::SetPopupRichSuggestionBitmap(int result_index, - const SkBitmap& bitmap) { - DCHECK(popup_view_); - rich_suggestion_bitmaps_[result_index] = bitmap; - popup_view_->UpdatePopupAppearance(); -} - -void OmniboxEditModelIOS::SetIconBitmap(const GURL& icon_url, - const SkBitmap& bitmap) { - DCHECK(popup_view_ && !icon_url.is_empty()); - icon_bitmaps_[icon_url] = bitmap; - popup_view_->UpdatePopupAppearance(); -} - void OmniboxEditModelIOS::SetPopupSuggestionGroupVisibility( size_t match_index, bool suggestion_group_hidden) { @@ -3075,22 +2764,6 @@ controller_->client()->OnFocusChanged(focus_state_, reason); } -void OmniboxEditModelIOS::OnFaviconFetched(const GURL& page_url, - const gfx::Image& icon) const { - if (icon.IsEmpty() || !PopupIsOpen()) { - return; - } - - // Notify all affected matches. - for (size_t i = 0; i < autocomplete_controller()->result().size(); ++i) { - auto& match = autocomplete_controller()->result().match_at(i); - if (!AutocompleteMatch::IsSearchType(match.type) && - match.destination_url == page_url) { - popup_view_->OnMatchIconUpdated(i); - } - } -} - std::u16string OmniboxEditModelIOS::GetText() const { // Once the model owns primary text, the check for `view_` won't be needed. if (view_) {
diff --git a/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios_unittest.mm b/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios_unittest.mm index 4163e9f9..2876ea0a 100644 --- a/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios_unittest.mm +++ b/ios/chrome/browser/omnibox/model/omnibox_edit_model_ios_unittest.mm
@@ -42,7 +42,6 @@ #import "testing/platform_test.h" #import "third_party/metrics_proto/omnibox_event.pb.h" #import "third_party/omnibox_proto/answer_type.pb.h" -#import "third_party/skia/include/core/SkBitmap.h" #import "ui/base/l10n/l10n_util.h" #import "ui/base/window_open_disposition.h" @@ -454,11 +453,6 @@ EXPECT_EQ(u"https://www.example.com/", view()->GetText()); EXPECT_TRUE(model()->CurrentTextIsURL()); - - // We should still show the current page's icon until the URL is modified. - EXPECT_TRUE(model()->ShouldShowCurrentPageIcon()); - view()->SetUserText(u"something else"); - EXPECT_FALSE(model()->ShouldShowCurrentPageIcon()); } TEST_F(OmniboxEditModelIOSTest, UnelideDoesNothingWhenFullURLAlreadyShown) { @@ -477,24 +471,6 @@ EXPECT_FALSE(model()->user_input_in_progress()); EXPECT_FALSE(view()->IsSelectAll()); EXPECT_TRUE(model()->CurrentTextIsURL()); - EXPECT_TRUE(model()->ShouldShowCurrentPageIcon()); -} - -// The tab-switching system sometimes focuses the Omnibox even if it was not -// previously focused. In those cases, ignore the saved focus state. -TEST_F(OmniboxEditModelIOSTest, IgnoreInvalidSavedFocusStates) { - // The Omnibox starts out unfocused. Save that state. - ASSERT_FALSE(model()->has_focus()); - OmniboxEditModelIOS::State state = model()->GetStateForTabSwitch(); - ASSERT_EQ(OMNIBOX_FOCUS_NONE, state.focus_state); - - // Simulate the tab-switching system focusing the Omnibox. - model()->OnSetFocus(false); - - // Restoring the old saved state should not clobber the model's focus state. - model()->RestoreState(&state); - EXPECT_TRUE(model()->has_focus()); - EXPECT_TRUE(model()->is_caret_visible()); } // Tests ConsumeCtrlKey() consumes ctrl key when down, but does not affect ctrl @@ -585,9 +561,8 @@ model()->OnControlKeyChanged(true); model()->OpenSelection(); - OmniboxEditModelIOS::State state = model()->GetStateForTabSwitch(); EXPECT_EQ(GURL("http://www.foo.com/"), - state.autocomplete_input.canonicalized_url()); + model()->GetInputForTesting().canonicalized_url()); } TEST_F(OmniboxEditModelIOSTest, CtrlEnterNavigatesToDesiredTLDTemporaryText) { @@ -601,9 +576,8 @@ model()->OnControlKeyChanged(true); model()->OpenSelection(); - OmniboxEditModelIOS::State state = model()->GetStateForTabSwitch(); EXPECT_EQ(GURL("http://www.foobar.com/"), - state.autocomplete_input.canonicalized_url()); + model()->GetInputForTesting().canonicalized_url()); } TEST_F(OmniboxEditModelIOSTest, @@ -616,9 +590,8 @@ model()->OnControlKeyChanged(true); model()->OpenSelection(); - OmniboxEditModelIOS::State state = model()->GetStateForTabSwitch(); EXPECT_EQ(GURL("https://www.example.com/"), - state.autocomplete_input.canonicalized_url()); + model()->GetInputForTesting().canonicalized_url()); } /////////////////////////////////////////////////////////////////////////////// @@ -1501,22 +1474,3 @@ 8, 1); } -// Tests `GetPopupRichSuggestionBitmap()` method, verifying that no bitmap is -// fetched when there is no match with an `associated_keyword`. -TEST_F(OmniboxEditModelIOSPopupTest, - GetPopupRichSuggestionBitmapForMatchWithoutAssociatedKeyword) { - // Setup match with no bitmap. - ACMatches matches; - AutocompleteMatch match_without_associated_keyword( - nullptr, 1000, false, AutocompleteMatchType::URL_WHAT_YOU_TYPED); - match_without_associated_keyword.keyword = - u"match_without_associated_keyword"; - matches.push_back(match_without_associated_keyword); - AutocompleteResult* result = published_result(); - result->AppendMatches(matches); - - const SkBitmap* actual_bitmap = model()->GetPopupRichSuggestionBitmap( - u"match_without_associated_keyword"); - - EXPECT_FALSE(actual_bitmap); -}
diff --git a/ios/chrome/browser/omnibox/model/omnibox_view_base.h b/ios/chrome/browser/omnibox/model/omnibox_view_base.h index c332334..a6a1755 100644 --- a/ios/chrome/browser/omnibox/model/omnibox_view_base.h +++ b/ios/chrome/browser/omnibox/model/omnibox_view_base.h
@@ -28,8 +28,6 @@ class OmniboxViewBase { public: - using IconFetchedCallback = base::OnceCallback<void(const gfx::Image& icon)>; - // Represents the changes between two State objects. This is used by the // model to determine how its internal state should be updated after the view // state changes. See OmniboxEditModelIOS::OnAfterPossibleChange(). @@ -67,27 +65,6 @@ // the field is empty. bool IsEditingOrEmpty() const; - // Returns the icon to display as the location icon. If a favicon is - // available, `on_icon_fetched` may be called later asynchronously. - // `color_current_page_icon` is used for the page icon (i.e. when the popup is - // closed, there is no input in progress, and there's a URL displayed) (e.g. - // the secure page lock). `color_vectors` is used for vector icons e.g. the - // history clock or bookmark star. `color_bright_vectors` is used for special - // vector icons e.g. the history cluster squiggle. - // `color_vectors_with_background` is used for vector icons that are drawn - // atop a background e.g. action suggestions. Favicons aren't custom-colored. - // `dark_mode` returns the dark_mode version of an icon. This should usually - // be handled by `color_current_page_icon` but in cases where the icon has - // hardcoded colors this can be used to return a different icon. E.g., the - // SuperGIcon will return different icons in dark and light modes. - ui::ImageModel GetIcon(int dip_size, - SkColor color_current_page_icon, - SkColor color_vectors, - SkColor color_bright_vectors, - SkColor color_vectors_with_background, - IconFetchedCallback on_icon_fetched, - bool dark_mode) const; - // The user text is the text the user has manually keyed in. When present, // this is shown in preference to the permanent text; hitting escape will // revert to the permanent text.
diff --git a/ios/chrome/browser/omnibox/model/omnibox_view_base.mm b/ios/chrome/browser/omnibox/model/omnibox_view_base.mm index 447d165..667161e 100644 --- a/ios/chrome/browser/omnibox/model/omnibox_view_base.mm +++ b/ios/chrome/browser/omnibox/model/omnibox_view_base.mm
@@ -159,22 +159,6 @@ model()->PopupIsOpen()); } -// OmniboxViewBase::GetIcon is very similar to -// OmniboxPopupModel::GetMatchIcon. They contain certain inconsistencies -// concerning what flags are required to display url favicons and bookmark star -// icons. OmniboxPopupModel::GetMatchIcon also doesn't display default search -// provider icons. It's possible they have other inconsistencies as well. We may -// want to consider reusing the same code for both the popup and omnibox icons. -ui::ImageModel OmniboxViewBase::GetIcon(int dip_size, - SkColor color_current_page_icon, - SkColor color_vectors, - SkColor color_bright_vectors, - SkColor color_vectors_with_background, - IconFetchedCallback on_icon_fetched, - bool dark_mode) const { - NOTREACHED(); -} - void OmniboxViewBase::SetUserText(const std::u16string& text) { SetUserText(text, true); }
diff --git a/ios/chrome/browser/shared/model/browser/browser_user_data.h b/ios/chrome/browser/shared/model/browser/browser_user_data.h index a6491dc..4e2c112 100644 --- a/ios/chrome/browser/shared/model/browser/browser_user_data.h +++ b/ios/chrome/browser/shared/model/browser/browser_user_data.h
@@ -58,6 +58,10 @@ return &kId; } + protected: + BrowserUserData() {} + explicit BrowserUserData(Browser* browser) {} + private: // Default factory for T that invoke T's constructor. Can be overloaded // by sub-class if they want to create a sub-class of T instead.
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/BUILD.gn index 76a4e2d..b699b4a 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/BUILD.gn +++ b/ios/chrome/browser/tab_switcher/ui_bundled/BUILD.gn
@@ -27,6 +27,7 @@ deps = [ "//base", "//components/favicon/ios", + "//ios/chrome/browser/favicon/model", "//ios/chrome/browser/shared/model/url", "//ios/chrome/browser/shared/model/web_state_list", "//ios/chrome/browser/shared/ui/symbols", @@ -76,6 +77,7 @@ "//base", "//components/favicon/ios", "//components/tab_groups", + "//ios/chrome/browser/favicon/model", "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/url", "//ios/chrome/browser/shared/model/web_state_list",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/BUILD.gn index 5613059..f091c87 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/BUILD.gn +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/BUILD.gn
@@ -70,9 +70,11 @@ "//ios/chrome/browser/bookmarks/model", "//ios/chrome/browser/bubble/model", "//ios/chrome/browser/collaboration/model", + "//ios/chrome/browser/collaboration/model:features", "//ios/chrome/browser/commerce/model", "//ios/chrome/browser/default_browser/model:utils", "//ios/chrome/browser/drag_and_drop/model", + "//ios/chrome/browser/favicon/model", "//ios/chrome/browser/main/model", "//ios/chrome/browser/menu/ui_bundled", "//ios/chrome/browser/reading_list/model", @@ -276,6 +278,8 @@ source_set("grid_mediator_item_provider") { sources = [ "base_grid_mediator_items_provider.h" ] + + deps = [ "//ios/chrome/browser/tab_switcher/ui_bundled:items" ] } source_set("grid_toolbars_configuration_provider") {
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.mm index 65dd677..ba8e69d 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.mm
@@ -2007,4 +2007,9 @@ return nil; } +- (void)fetchTabGroupItemInfo:(TabGroupItem*)tabGroupItem + completion:(GroupTabInfosFetchingCompletionBlock)completion { + [tabGroupItem fetchGroupTabInfos:completion faviconLoader:nil]; +} + @end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_items_provider.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_items_provider.h index 8640ad7..c0b2655 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_items_provider.h +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_items_provider.h
@@ -5,9 +5,10 @@ #ifndef IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_GRID_GRID_BASE_GRID_MEDIATOR_ITEMS_PROVIDER_H_ #define IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_GRID_GRID_BASE_GRID_MEDIATOR_ITEMS_PROVIDER_H_ -@class GridItemIdentifier; +#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h" @class ActivityLabelData; +@class GridItemIdentifier; namespace web { class WebStateID; } // namespace web @@ -25,6 +26,10 @@ // Returns the facePile view associated with the `itemID`. - (UIView*)facePileViewForItem:(GridItemIdentifier*)itemID; +// Fetches the `tabGroupItem` info and executes the given `completion` block. +- (void)fetchTabGroupItemInfo:(TabGroupItem*)tabGroupItem + completion:(GroupTabInfosFetchingCompletionBlock)completion; + @end #endif // IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_GRID_GRID_BASE_GRID_MEDIATOR_ITEMS_PROVIDER_H_
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_unittest.mm index 3c9358f..d12f864 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_unittest.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_unittest.mm
@@ -95,10 +95,11 @@ nullptr, nullptr, nullptr, tab_group_service_); mediator_ = [[RegularGridMediator alloc] - initWithModeHolder:mode_holder_ - tabGroupSyncService:tab_group_sync_service_.get() - shareKitService:share_kit_service_.get() - messagingService:nil]; + initWithModeHolder:mode_holder_ + tabGroupSyncService:tab_group_sync_service_.get() + shareKitService:share_kit_service_.get() + messagingService:nil + faviconLoader:nil]; } mediator_.consumer = consumer_; mediator_.browser = browser_.get();
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.mm index 9c30183..e1e91cc 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.mm
@@ -1682,13 +1682,14 @@ cell.activityLabelData = [self.gridProvider activityLabelDataForItem:groupItemIdentifier]; - [item fetchGroupTabInfos:^(TabGroupItem* innerItem, - NSArray<GroupTabInfo*>* groupTabInfos) { + auto completionBlock = ^(TabGroupItem* innerItem, + NSArray<GroupTabInfo*>* groupTabInfos) { if ([cell.itemIdentifier.tabGroupItem isEqual:innerItem]) { [cell configureWithGroupTabInfos:groupTabInfos totalTabsCount:innerItem.numberOfTabsInGroup]; } - }]; + }; + [self.gridProvider fetchTabGroupItemInfo:item completion:completionBlock]; } // Configures `cell`'s identifier and title synchronously, and favicon and
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/BUILD.gn index 17b0b1b..57a7be3e 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/BUILD.gn +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/BUILD.gn
@@ -19,6 +19,7 @@ "//ios/chrome/browser/collaboration/model", "//ios/chrome/browser/collaboration/model:features", "//ios/chrome/browser/collaboration/model/messaging", + "//ios/chrome/browser/favicon/model", "//ios/chrome/browser/policy/model:policy_util", "//ios/chrome/browser/saved_tab_groups/model", "//ios/chrome/browser/share_kit/model",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.mm index cca5105..894b082 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.mm
@@ -4,7 +4,10 @@ #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.h" +#import "ios/chrome/browser/collaboration/model/collaboration_service_factory.h" +#import "ios/chrome/browser/collaboration/model/features.h" #import "ios/chrome/browser/collaboration/model/messaging/messaging_backend_service_factory.h" +#import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h" #import "ios/chrome/browser/policy/model/policy_util.h" #import "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h" #import "ios/chrome/browser/share_kit/model/share_kit_service_factory.h" @@ -139,14 +142,23 @@ self.gridViewController = gridViewController; + FaviconLoader* faviconLoader = nil; + collaboration::CollaborationService* collaborationService = + collaboration::CollaborationServiceFactory::GetForProfile(profile); + // Fetch favicons if shared tab groups is enabled. + if (IsSharedTabGroupsJoinEnabled(collaborationService)) { + faviconLoader = IOSChromeFaviconLoaderFactory::GetForProfile(profile); + } + _mediator = [[RegularGridMediator alloc] - initWithModeHolder:self.modeHolder - tabGroupSyncService:tab_groups::TabGroupSyncServiceFactory:: - GetForProfile(profile) - shareKitService:ShareKitServiceFactory::GetForProfile(profile) - messagingService:collaboration::messaging:: - MessagingBackendServiceFactory::GetForProfile( - profile)]; + initWithModeHolder:self.modeHolder + tabGroupSyncService:tab_groups::TabGroupSyncServiceFactory::GetForProfile( + profile) + shareKitService:ShareKitServiceFactory::GetForProfile(profile) + messagingService:collaboration::messaging:: + MessagingBackendServiceFactory::GetForProfile( + profile) + faviconLoader:faviconLoader]; _mediator.consumer = gridViewController; gridViewController.dragDropHandler = _mediator;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator.h index 9c399d4..a1c2b74a 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator.h +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator.h
@@ -15,6 +15,7 @@ class TabGroupSyncService; } // namespace tab_groups +class FaviconLoader; class ShareKitService; // Mediates between model layer and regular grid UI layer. @@ -27,14 +28,15 @@ @property(nonatomic, weak) id<GridCommands> inactiveTabsGridCommands; // Designated initialized. `tabGroupSyncService`, `shareKitService` and -// `messagingService` can be nullptr. +// `messagingService`: can be `nullptr`. +// `faviconLoader`: used to fetch favicons on Google server, can be `nullptr`. - (instancetype) - initWithModeHolder:(TabGridModeHolder*)modeHolder - tabGroupSyncService:(tab_groups::TabGroupSyncService*)tabGroupSyncService - shareKitService:(ShareKitService*)shareKitService - messagingService: - (collaboration::messaging::MessagingBackendService*)messagingService - NS_DESIGNATED_INITIALIZER; + initWithModeHolder:(TabGridModeHolder*)modeHolder + tabGroupSyncService:(tab_groups::TabGroupSyncService*)tabGroupSyncService + shareKitService:(ShareKitService*)shareKitService + messagingService: + (collaboration::messaging::MessagingBackendService*)messagingService + faviconLoader:(FaviconLoader*)faviconLoader NS_DESIGNATED_INITIALIZER; - (instancetype)initWithModeHolder:(TabGridModeHolder*)modeHolder NS_UNAVAILABLE; - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator.mm index dcf62c71..06354fc 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator.mm
@@ -83,17 +83,21 @@ // The bridge between the C++ MessagingBackendService observer and this // Objective-C class. std::unique_ptr<MessagingBackendServiceBridge> _messagingBackendServiceBridge; + // FaviconLoader used to fetch favicons on Google server. + raw_ptr<FaviconLoader> _faviconLoader; } - (instancetype) - initWithModeHolder:(TabGridModeHolder*)modeHolder - tabGroupSyncService:(tab_groups::TabGroupSyncService*)tabGroupSyncService - shareKitService:(ShareKitService*)shareKitService - messagingService:(collaboration::messaging::MessagingBackendService*) - messagingService { + initWithModeHolder:(TabGridModeHolder*)modeHolder + tabGroupSyncService:(tab_groups::TabGroupSyncService*)tabGroupSyncService + shareKitService:(ShareKitService*)shareKitService + messagingService: + (collaboration::messaging::MessagingBackendService*)messagingService + faviconLoader:(FaviconLoader*)faviconLoader { if ((self = [super initWithModeHolder:modeHolder])) { _tabGroupSyncService = tabGroupSyncService; _shareKitService = shareKitService; + _faviconLoader = faviconLoader; _syncServiceObserver = std::make_unique<TabGroupSyncServiceObserverBridge>(self); @@ -503,6 +507,11 @@ return _shareKitService->FacePileView(config); } +- (void)fetchTabGroupItemInfo:(TabGroupItem*)tabGroupItem + completion:(GroupTabInfosFetchingCompletionBlock)completion { + [tabGroupItem fetchGroupTabInfos:completion faviconLoader:_faviconLoader]; +} + #pragma mark - MessagingBackendServiceObserving - (void)onMessagingBackendServiceInitialized {
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator_unittest.mm index 4f50f54c..d1fd147 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator_unittest.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator_unittest.mm
@@ -68,10 +68,11 @@ nullptr, nullptr, nullptr, tab_group_service_); mediator_ = [[TestRegularGridMediator alloc] - initWithModeHolder:mode_holder_ - tabGroupSyncService:tab_group_sync_service_.get() - shareKitService:share_kit_service_.get() - messagingService:&messaging_backend_]; + initWithModeHolder:mode_holder_ + tabGroupSyncService:tab_group_sync_service_.get() + shareKitService:share_kit_service_.get() + messagingService:&messaging_backend_ + faviconLoader:nil]; mediator_.consumer = consumer_; mediator_.browser = browser_.get(); mediator_.toolbarsMutator = fake_toolbars_mediator_;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/BUILD.gn index cff672b..27a17f88 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/BUILD.gn +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/BUILD.gn
@@ -107,6 +107,9 @@ ":tab_groups_ui", "//base", "//components/tab_groups", + "//ios/chrome/browser/collaboration/model", + "//ios/chrome/browser/collaboration/model:features", + "//ios/chrome/browser/favicon/model", "//ios/chrome/browser/saved_tab_groups/ui:utils", "//ios/chrome/browser/shared/coordinator/chrome_coordinator", "//ios/chrome/browser/shared/model/browser",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_coordinator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_coordinator.mm index af71537..a364b6e 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_coordinator.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_coordinator.mm
@@ -9,6 +9,9 @@ #import "components/sync/base/user_selectable_type.h" #import "components/sync/service/sync_service.h" #import "components/sync/service/sync_user_settings.h" +#import "ios/chrome/browser/collaboration/model/collaboration_service_factory.h" +#import "ios/chrome/browser/collaboration/model/features.h" +#import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/profile/profile_ios.h" #import "ios/chrome/browser/shared/model/web_state_list/tab_group.h" @@ -106,17 +109,27 @@ [[CreateTabGroupViewController alloc] initWithEditMode:editMode tabSynced:tabSynced]; + FaviconLoader* faviconLoader = nil; + collaboration::CollaborationService* collaborationService = + collaboration::CollaborationServiceFactory::GetForProfile(profile); + // Fetch favicons if shared tab groups is enabled. + if (IsSharedTabGroupsJoinEnabled(collaborationService)) { + faviconLoader = IOSChromeFaviconLoaderFactory::GetForProfile(profile); + } + if (_tabGroup) { _mediator = [[CreateTabGroupMediator alloc] initTabGroupEditionWithConsumer:_viewController tabGroup:_tabGroup - webStateList:browser->GetWebStateList()]; + webStateList:browser->GetWebStateList() + faviconLoader:faviconLoader]; _mediator.delegate = self; } else { _mediator = [[CreateTabGroupMediator alloc] initTabGroupCreationWithConsumer:_viewController selectedTabs:_identifiers - browser:browser]; + browser:browser + faviconLoader:faviconLoader]; } _viewController.mutator = _mediator; _viewController.delegate = self;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator.h index ea20391b..805efacd 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator.h +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator.h
@@ -13,6 +13,7 @@ class Browser; @protocol CreateTabGroupMediatorDelegate; +class FaviconLoader; class TabGroup; @protocol TabGroupCreationConsumer; class WebStateList; @@ -31,19 +32,23 @@ // - `consumer` the UI that will receive updates. // - `identifiers` the list of selected tabs ID // - `browser` the browser containing the selected tabs. +// `faviconLoader`: used to fetch favicons on Google server, can be `nullptr`. - (instancetype) initTabGroupCreationWithConsumer:(id<TabGroupCreationConsumer>)consumer selectedTabs:(std::set<web::WebStateID>&)identifiers - browser:(Browser*)browser; + browser:(Browser*)browser + faviconLoader:(FaviconLoader*)faviconLoader; // Init the tab group creation mediator with: // - `consumer` the UI that will receive updates. // - `tabGroup` the group to edit. // - `webStateList` the web state list containing `tabGroup`. +// `faviconLoader`: used to fetch favicons on Google server, can be `nullptr`. - (instancetype)initTabGroupEditionWithConsumer: (id<TabGroupCreationConsumer>)consumer tabGroup:(const TabGroup*)tabGroup - webStateList:(WebStateList*)webStateList; + webStateList:(WebStateList*)webStateList + faviconLoader:(FaviconLoader*)faviconLoader; // Disconnects the mediator's dependencies. - (void)disconnect;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator.mm index b050773..eec78ed 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator.mm
@@ -13,6 +13,7 @@ #import "base/scoped_multi_source_observation.h" #import "base/strings/sys_string_conversions.h" #import "components/tab_groups/tab_group_color.h" +#import "ios/chrome/browser/favicon/model/favicon_loader.h" #import "ios/chrome/browser/saved_tab_groups/ui/tab_group_utils.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/browser/browser_list_factory.h" @@ -63,7 +64,8 @@ - (instancetype) initTabGroupCreationWithConsumer:(id<TabGroupCreationConsumer>)consumer selectedTabs:(std::set<web::WebStateID>&)identifiers - browser:(Browser*)browser { + browser:(Browser*)browser + faviconLoader:(FaviconLoader*)faviconLoader { CHECK(IsTabGroupInGridEnabled()) << "You should not be able to create a tab group outside the Tab Groups " "experiment."; @@ -114,6 +116,7 @@ [TabGroupUtils fetchTabGroupInfoFromWebState:currentWebStateList->GetWebStateAt( index) + faviconLoader:faviconLoader completion:^(GroupTabInfo* info) { [weakSelf addInfo:info]; [weakSelf updateConsumer]; @@ -127,7 +130,8 @@ - (instancetype)initTabGroupEditionWithConsumer: (id<TabGroupCreationConsumer>)consumer tabGroup:(const TabGroup*)tabGroup - webStateList:(WebStateList*)webStateList { + webStateList:(WebStateList*)webStateList + faviconLoader:(FaviconLoader*)faviconLoader { CHECK(IsTabGroupInGridEnabled()) << "You should not be able to create a tab group outside the Tab Groups " "experiment."; @@ -149,11 +153,13 @@ _groupItem = [[TabGroupItem alloc] initWithTabGroup:_tabGroup webStateList:_webStateList]; __weak CreateTabGroupMediator* weakSelf = self; - [_groupItem fetchGroupTabInfos:^(TabGroupItem* item, - NSArray<GroupTabInfo*>* groupTabInfos) { - [weakSelf setGroupTabInfos:groupTabInfos]; - [weakSelf updateConsumer]; - }]; + [_groupItem + fetchGroupTabInfos:^(TabGroupItem* item, + NSArray<GroupTabInfo*>* groupTabInfos) { + [weakSelf setGroupTabInfos:groupTabInfos]; + [weakSelf updateConsumer]; + } + faviconLoader:faviconLoader]; // Do not use the helper to get the following values as the title helper do // not return nil but the number of tabs. In this case, we want nil so it do
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator_unittest.mm index 309b845..c45353ce 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator_unittest.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/create_tab_group_mediator_unittest.mm
@@ -91,7 +91,8 @@ CreateTabGroupMediator* mediator = [[CreateTabGroupMediator alloc] initTabGroupEditionWithConsumer:consumer_ tabGroup:tab_group - webStateList:&web_state_list_]; + webStateList:&web_state_list_ + faviconLoader:nil]; mediator.delegate = delegate_; EXPECT_EQ(delegate_.editedGroupWasExternallyMutatedCallCount, 0); @@ -115,7 +116,8 @@ CreateTabGroupMediator* mediator = [[CreateTabGroupMediator alloc] initTabGroupEditionWithConsumer:consumer_ tabGroup:tab_group_0 - webStateList:&web_state_list_]; + webStateList:&web_state_list_ + faviconLoader:nil]; mediator.delegate = delegate_; EXPECT_EQ(delegate_.editedGroupWasExternallyMutatedCallCount, 0); @@ -138,7 +140,8 @@ CreateTabGroupMediator* mediator = [[CreateTabGroupMediator alloc] initTabGroupEditionWithConsumer:consumer_ tabGroup:tab_group - webStateList:&web_state_list_]; + webStateList:&web_state_list_ + faviconLoader:nil]; mediator.delegate = delegate_; EXPECT_EQ(delegate_.editedGroupWasExternallyMutatedCallCount, 0); tab_groups::TabGroupVisualData visual_data(u"Updated Group Name", @@ -164,7 +167,8 @@ CreateTabGroupMediator* mediator = [[CreateTabGroupMediator alloc] initTabGroupEditionWithConsumer:consumer_ tabGroup:tab_group_0 - webStateList:&web_state_list_]; + webStateList:&web_state_list_ + faviconLoader:nil]; mediator.delegate = delegate_; EXPECT_EQ(delegate_.editedGroupWasExternallyMutatedCallCount, 0); tab_groups::TabGroupVisualData visual_data(u"Updated Group Name",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h index eac479fd..a26f2d0 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h
@@ -7,10 +7,10 @@ #import <UIKit/UIKit.h> -@class TabGroupItem; - @class GroupTabInfo; +@class TabGroupItem; #ifdef __cplusplus +class FaviconLoader; class TabGroup; class WebStateList; #endif @@ -44,10 +44,14 @@ @property(nonatomic, readonly) NSInteger numberOfTabsInGroup; @property(nonatomic, readonly) BOOL collapsed; +#ifdef __cplusplus // Fetches the groupTabInfos (pair of snapshots and favicons), calling // `completion` on the calling sequence when the operation completes. +// `faviconLoader`: used to fetch favicons on Google server, can be `nullptr`. - (void)fetchGroupTabInfos: - (nonnull GroupTabInfosFetchingCompletionBlock)completion; + (GroupTabInfosFetchingCompletionBlock _Nonnull)completion + faviconLoader:(FaviconLoader* _Nullable)faviconLoader; +#endif @end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.mm index 1ec1d4f5..29d08a9 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.mm
@@ -6,6 +6,7 @@ #import "base/memory/raw_ptr.h" #import "base/task/sequenced_task_runner.h" +#import "ios/chrome/browser/favicon/model/favicon_loader.h" #import "ios/chrome/browser/shared/model/web_state_list/tab_group.h" #import "ios/chrome/browser/shared/model/web_state_list/tab_group_range.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" @@ -78,7 +79,8 @@ return _tabGroup->visual_data().is_collapsed(); } -- (void)fetchGroupTabInfos:(GroupTabInfosFetchingCompletionBlock)completion { +- (void)fetchGroupTabInfos:(GroupTabInfosFetchingCompletionBlock)completion + faviconLoader:(FaviconLoader*)faviconLoader { if (!_tabGroup) { __weak TabGroupItem* weakSelf = self; base::SequencedTaskRunner::GetCurrentDefault()->PostTask( @@ -101,6 +103,7 @@ CHECK(webState); __weak TabGroupItem* weakSelf = self; [TabGroupUtils fetchTabGroupInfoFromWebState:webState + faviconLoader:faviconLoader completion:^(GroupTabInfo* info) { [weakSelf groupTabInfoFetched:info
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_utils.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_utils.h index 635c529..c67f7e71 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_utils.h +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_utils.h
@@ -7,6 +7,7 @@ #import <Foundation/Foundation.h> +class FaviconLoader; @class GroupTabInfo; namespace web { class WebState; @@ -15,7 +16,10 @@ @interface TabGroupUtils : NSObject // Retrieves GroupTabInfo from the given `webState`. +// `faviconLoader`: used to fetch favicons on Google server, can be `nullptr`. +// `completion`: the block is executed with the fetched GroupTabInfo. + (void)fetchTabGroupInfoFromWebState:(web::WebState*)webState + faviconLoader:(FaviconLoader*)faviconLoader completion:(void (^)(GroupTabInfo*))completion; @end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_utils.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_utils.mm index fdee0822..7c55ff5e 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_utils.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_group_utils.mm
@@ -8,6 +8,7 @@ #import "base/memory/weak_ptr.h" #import "components/favicon/ios/web_favicon_driver.h" +#import "ios/chrome/browser/favicon/model/favicon_loader.h" #import "ios/chrome/browser/shared/model/url/url_util.h" #import "ios/chrome/browser/shared/ui/symbols/symbols.h" #import "ios/chrome/browser/snapshots/model/snapshot_tab_helper.h" @@ -21,24 +22,32 @@ @implementation TabGroupUtils + (void)fetchTabGroupInfoFromWebState:(web::WebState*)webState + faviconLoader:(FaviconLoader*)faviconLoader completion:(void (^)(GroupTabInfo*))completion { CHECK(webState); base::WeakPtr<web::WebState> weakWebState = webState->GetWeakPtr(); SnapshotTabHelper::FromWebState(webState)->RetrieveColorSnapshot( ^(UIImage* snapshot) { - GroupTabInfo* info = [[GroupTabInfo alloc] init]; - info.snapshot = snapshot; - info.favicon = [TabGroupUtils faviconFromWebState:weakWebState]; - completion(info); + GroupTabInfo* groupTabInfo = [[GroupTabInfo alloc] init]; + groupTabInfo.snapshot = snapshot; + [TabGroupUtils fetchFaviconFromWebState:weakWebState + groupTabInfo:groupTabInfo + faviconLoader:faviconLoader + completion:completion]; }); } #pragma mark - Private helpers -// Returns the favicon for the given `webState` or nil otherwise. -+ (UIImage*)faviconFromWebState:(base::WeakPtr<web::WebState>)webState { +// Fetches the favicon for the given `webState` and executes the `completion` +// block. ++ (void)fetchFaviconFromWebState:(base::WeakPtr<web::WebState>)webState + groupTabInfo:(GroupTabInfo*)groupTabInfo + faviconLoader:(FaviconLoader*)faviconLoader + completion:(void (^)(GroupTabInfo*))completion { if (!webState) { - return nil; + completion(groupTabInfo); + return; } UIImageConfiguration* configuration = [UIImageSymbolConfiguration @@ -47,7 +56,10 @@ scale:UIImageSymbolScaleMedium]; if (IsUrlNtp(webState->GetVisibleURL())) { - return CustomSymbolWithConfiguration(kChromeProductSymbol, configuration); + groupTabInfo.favicon = + CustomSymbolWithConfiguration(kChromeProductSymbol, configuration); + completion(groupTabInfo); + return; } // Use the page favicon. @@ -57,12 +69,21 @@ if (faviconDriver) { gfx::Image favicon = faviconDriver->GetFavicon(); if (!favicon.IsEmpty()) { - return favicon.ToUIImage(); + groupTabInfo.favicon = favicon.ToUIImage(); + completion(groupTabInfo); + return; } } - // Return the default favicon. - return DefaultSymbolWithConfiguration(kGlobeAmericasSymbol, configuration); + // Use the default favicon. + groupTabInfo.favicon = + DefaultSymbolWithConfiguration(kGlobeAmericasSymbol, configuration); + if (!faviconLoader) { + completion(groupTabInfo); + return; + } + // TODO(crbug.com/400966281): Fetch favicon on Google server. + completion(groupTabInfo); } @end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.mm index 0ed31b70..d084203 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.mm
@@ -238,10 +238,23 @@ NSArray<UITrait>* traits = TraitCollectionSetForTraits(nil); [self registerForTraitChanges:traits withAction:@selector(updateColors)]; } + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(handleFocusUpdate:) + name:UIFocusDidUpdateNotification + object:nil]; } return self; } +- (void)dealloc { + [[NSNotificationCenter defaultCenter] + removeObserver:self + name:UIFocusDidUpdateNotification + object:nil]; +} + - (void)setFaviconImage:(UIImage*)image { if (!image) { _faviconView.image = DefaultFavicon(); @@ -593,9 +606,11 @@ // Updates view colors. - (void)updateColors { BOOL isSelected = self.isSelected; - - if (self.isHighlighted || self.configurationState.cellDragState != - UICellConfigurationDragStateNone) { + if (self.focused) { + _selectedBackground.backgroundColor = [UIColor clearColor]; + _accessibilityContainerView.backgroundColor = [UIColor clearColor]; + } else if (self.highlighted || self.configurationState.cellDragState != + UICellConfigurationDragStateNone) { // Before a cell is dragged, it is highlighted. // The cell's background color must be updated at this moment, otherwise it // will not be applied correctly. @@ -1232,4 +1247,13 @@ _blueDotView.hidden = YES; } +- (void)handleFocusUpdate:(NSNotification*)notification { + UIFocusUpdateContext* context = + notification.userInfo[UIFocusUpdateContextKey]; + if (context.nextFocusedView == self || + context.previouslyFocusedView == self) { + [self updateColors]; + } +} + @end
diff --git a/ios/chrome/browser/tips_notifications/model/tips_notification_client_unittest.mm b/ios/chrome/browser/tips_notifications/model/tips_notification_client_unittest.mm index 97ee06d..3a0050c 100644 --- a/ios/chrome/browser/tips_notifications/model/tips_notification_client_unittest.mm +++ b/ios/chrome/browser/tips_notifications/model/tips_notification_client_unittest.mm
@@ -757,4 +757,16 @@ EXPECT_EQ(order[0], TipsNotificationType::kEnhancedSafeBrowsing); EXPECT_EQ(order[1], TipsNotificationType::kLens); EXPECT_EQ(order[2], TipsNotificationType::kWhatsNew); + + // Test Expanded Tips order param. + feature_list.Reset(); + feature_list.InitAndEnableFeatureWithParameters( + kIOSExpandedTips, { + {kIOSExpandedTipsOrderParam, "4,5,6"}, + }); + order = TipsNotificationsTypesOrder(false); + EXPECT_EQ(order.size(), 3u); + EXPECT_EQ(order[0], TipsNotificationType::kSetUpListContinuation); + EXPECT_EQ(order[1], TipsNotificationType::kDocking); + EXPECT_EQ(order[2], TipsNotificationType::kOmniboxPosition); }
diff --git a/ios/chrome/browser/tips_notifications/model/utils.mm b/ios/chrome/browser/tips_notifications/model/utils.mm index 4577e25..c6cecee 100644 --- a/ios/chrome/browser/tips_notifications/model/utils.mm +++ b/ios/chrome/browser/tips_notifications/model/utils.mm
@@ -205,6 +205,19 @@ TipsNotificationType::kEnhancedSafeBrowsing, TipsNotificationType::kWhatsNew, }); + } else if (IsIOSExpandedTipsEnabled()) { + return GetFieldTrialParamByFeatureAsVector<TipsNotificationType>( + kIOSExpandedTips, kIOSExpandedTipsOrderParam, + { + TipsNotificationType::kEnhancedSafeBrowsing, + TipsNotificationType::kWhatsNew, + TipsNotificationType::kLens, + TipsNotificationType::kOmniboxPosition, + TipsNotificationType::kSetUpListContinuation, + TipsNotificationType::kDefaultBrowser, + TipsNotificationType::kDocking, + TipsNotificationType::kSignin, + }); } return { TipsNotificationType::kEnhancedSafeBrowsing,
diff --git a/ios/chrome/browser/variations/model/variations_app_interface.mm b/ios/chrome/browser/variations/model/variations_app_interface.mm index 07158bfa..a6fc001 100644 --- a/ios/chrome/browser/variations/model/variations_app_interface.mm +++ b/ios/chrome/browser/variations/model/variations_app_interface.mm
@@ -76,9 +76,11 @@ ->GetVariationsService() ->GetSeedStoreForTesting() ->GetSafeSeedReaderWriterForTesting() - ->StoreValidatedSeedInfo(variations::kTestSeedData.GetCompressedData(), - variations::kTestSeedData.base64_compressed_data, - variations::kTestSeedData.base64_signature); + ->StoreValidatedSeedInfo(variations::ValidatedSeedInfo{ + .compressed_seed_data = variations::kTestSeedData.GetCompressedData(), + .base64_seed_data = variations::kTestSeedData.base64_compressed_data, + .signature = variations::kTestSeedData.base64_signature, + .milestone = 92}); } + (void)setCrashingRegularSeedAndSignature { @@ -86,10 +88,13 @@ ->GetVariationsService() ->GetSeedStoreForTesting() ->GetSeedReaderWriterForTesting() - ->StoreValidatedSeedInfo( - variations::kCrashingSeedData.GetCompressedData(), - variations::kCrashingSeedData.base64_compressed_data, - variations::kCrashingSeedData.base64_signature); + ->StoreValidatedSeedInfo(variations::ValidatedSeedInfo{ + .compressed_seed_data = + variations::kCrashingSeedData.GetCompressedData(), + .base64_seed_data = + variations::kCrashingSeedData.base64_compressed_data, + .signature = variations::kCrashingSeedData.base64_signature, + .milestone = 92}); } + (int)crashStreak {
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 f51b5ae8..e2c432fc 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 @@ -6959c752079f4f6cef33f25136f2d0d25eee9d61 \ No newline at end of file +95e6978b4d65d1d36670da01f67a10f1f48f67e0 \ 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 504a21b..23389b1e 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 @@ -5666b7d57650eba7f436186c99ca28127042f0ca \ No newline at end of file +982ed659e3dd4c25f32f0d86ba9fbfe102c3dea7 \ 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 ae4dae9..2a68a49 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 @@ -0a8e945e34aedcf11271e1a28f1a8a5e05bea827 \ No newline at end of file +f2a63289d3a9e3b4866ed0902ba1b0bfe33c35ba \ 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 6f043ae..1fa9c6e 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 @@ -26eaf1e0bef0b21ee2fc036e0e7317544a7b269b \ No newline at end of file +e8956ed1fc5f152f204b51cb58ebbfbc3c55c78f \ 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 871ab9e..03e294e4 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 @@ -b13b6d2c45bde9258ede90a23c4001691af0cf20 \ No newline at end of file +aa56f949981c08348e424c79f73d55639ddadce3 \ 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 dd49c6f..6c034f2d 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 @@ -4ca4da2459239335296e9a95540621f1a9191936 \ No newline at end of file +4cf4f502f20d97ba754441ef01af032c7a7b19c5 \ 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 3465cc9b..67ddf1e 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 @@ -103c193727cfd5efc75cf0b84d4e6592dc36ec68 \ No newline at end of file +4436d4d9bdf8d814ae9cf7c8fbc8d0a1d1428cb8 \ 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 ebf0a402..d543414 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 @@ -0deeb7c46f4ca9c7f6217dedd9b4ecae2b930e59 \ No newline at end of file +4a8bdedb83b8e2f33830a5c8f5b07d5b03e02cf2 \ 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 51c5a25..79fded4c 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 @@ -db3fa543aa392ad9ff64a5c2e6829152ed33006c \ No newline at end of file +66c5368c4b087ae4496bd5c2d54f1486cf91d7cb \ 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 7884d82..084377f 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 @@ -04ab3945b99c3323fb097f3e0d222fa13fca742b \ No newline at end of file +a7df80cf9e95f53cc7412f0cd2b30545ac0bfe15 \ 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 2269a1f..858166b1 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 @@ -facd40adbb4b0b28426450ab6b9ace455c7a8e0d \ No newline at end of file +2765ec0306e371794906484249320b88e45f2606 \ 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 43ae9eda..ea44ffe 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 @@ -b46874a15f4c7fce0ca682588b3578446515698d \ No newline at end of file +270e580cbf56f9d7c8eef30a39c5c344641060dd \ 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 cdd9e7ec..4e0bc07 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 @@ -21898bc0d6597fa2719a6cdbc58a193e90e721e9 \ No newline at end of file +e16730370c818c8cc6fed42b8c0b76cb99d92c72 \ 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 62cb5d1..755f0f0 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 @@ -4bfe81b57c04eef43ed6a7997ad2673830e73eeb \ No newline at end of file +e3ef9ff77206196672ba1aaca43052f7a5732043 \ 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 8a447af..58a94585 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 @@ -0b1eeee752bcc5b98e7ba2563bc8fdb0c571c760 \ No newline at end of file +3e06f7e8f6da9a67816cda40a7108a02d0e8cca2 \ 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 cb21251..c470ff9 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 @@ -e6633213b3d3839edf6d45992b56761f02f498a8 \ No newline at end of file +9cd5b03798009c9fb57c8e7ea4b176a0523fbef4 \ 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 da663f75..0847b31a 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 @@ -22009072ad9e8379af1d7fd79ab84b7084b44aaf \ No newline at end of file +a18858a586f02ea18466f98d2c4a44f608d114c1 \ 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 2ef1594..be7ffdc 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 @@ -257423a14b0f6851fb0c104a67b79db0886c404a \ No newline at end of file +ed042fbd62fdfe4c8eabbd9fa74818ad0da3f909 \ 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 19b97d5..c43b7c6 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 @@ -494c692aebe7745bc23a902031f8bb92975d6741 \ No newline at end of file +b6ad5a943a47834d75f2987e641b6decbf04f34e \ 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 4252b8b..e7b3b25 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 @@ -7a1f0275cbc88939ba5c6642de252eedd5f5887a \ No newline at end of file +be77c08b55b4dc65f1b80b2848cafcdf1d4e2755 \ 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 8182e7171..feb1647d 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 @@ -cd3a6877c4f343ef611d9e2a9f4c38d4a482884f \ No newline at end of file +0f000f849843c189d82a71d3d490629b127b184c \ 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 1f72688c..3ddfbfb 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 @@ -7689b7c4761cb0730f5ef6648234518fa4bf3f29 \ No newline at end of file +81a9ae657c8b476a6c4a58f38c7aa446faf85d74 \ 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 fa469bd..b7b7719 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 @@ -2d8d1ef3d0445fb5b7d3d3f41902d0fe8c770328 \ No newline at end of file +c8751ab6cebf149cf901a07dd461eeb5685bccb8 \ 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 7c6143d..5b520ac 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 @@ -9c9531d8d277dcacde9414f233df1dde21fc6a2c \ No newline at end of file +89c8e1967608d6960879fefd092eec22925d422b \ 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 5c2a0025..4f27820 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 @@ -ba228c9cf8442590ec951ac6558187420865b73d \ No newline at end of file +766d5cbbe8b80bd71b90d3a8fac1e07a25d1eab0 \ 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 ea3fb248..5542d7e 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 @@ -f7ca0b352c2637c33e7bc9c7717ff27ca26793ff \ No newline at end of file +602c8a893511f9d23a754a71ad71b915a3d5d578 \ 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 9a2395e..fd9761a3 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 @@ -244c92fe0d1533c739d3b555c631da10a2cd7c1c \ No newline at end of file +2976328b9622721acd4337b186c38cea392ddbc3 \ 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 90a2a225..76e254ac 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 @@ -e411885d8b7d97378b8f5471048c27f8be165004 \ No newline at end of file +4fda076ca60e25c1d474e7d8f18f6dfd4f92d15e \ No newline at end of file
diff --git a/ios/web_view/public/cwv_export.h b/ios/web_view/public/cwv_export.h index 2c9c6591..ca0e813 100644 --- a/ios/web_view/public/cwv_export.h +++ b/ios/web_view/public/cwv_export.h
@@ -15,10 +15,6 @@ // This makes it possible to export symbols only when *building* the dynamic // library (by checking CWV_IMPLEMENTATION), not when *using* the dynamic // library. -#if defined(CWV_IMPLEMENTATION) #define CWV_EXPORT __attribute__((visibility("default"))) -#else -#define CWV_EXPORT -#endif #endif // IOS_WEB_VIEW_PUBLIC_CWV_EXPORT_H_
diff --git a/ios_internal b/ios_internal index 56c2b01..c32f192 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 56c2b01d07aad9c323ad655a8cb07b849923ac99 +Subproject commit c32f19290092f9592d3be32943becfab3f52a9cd
diff --git a/ipc/ipc_message_support_export.h b/ipc/ipc_message_support_export.h index d74b52e..0b45100 100644 --- a/ipc/ipc_message_support_export.h +++ b/ipc/ipc_message_support_export.h
@@ -16,11 +16,7 @@ #else // defined(WIN32) -#if defined(IPC_MESSAGE_SUPPORT_IMPL) #define IPC_MESSAGE_SUPPORT_EXPORT __attribute__((visibility("default"))) -#else -#define IPC_MESSAGE_SUPPORT_EXPORT -#endif #endif
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn index 8bcbb66..4f663e2 100644 --- a/media/audio/BUILD.gn +++ b/media/audio/BUILD.gn
@@ -253,6 +253,8 @@ "android/aaudio_output.h", "android/aaudio_stream_wrapper.cc", "android/aaudio_stream_wrapper.h", + "android/audio_device_id.cc", + "android/audio_device_id.h", "android/audio_manager_android.cc", "android/audio_manager_android.h", "android/audio_track_output_stream.cc", @@ -454,7 +456,10 @@ ] if (is_android) { - sources += [ "android/audio_android_unittest.cc" ] + sources += [ + "android/audio_android_unittest.cc", + "android/audio_device_id_unittest.cc", + ] deps += [ "//media/gpu:gpu", "//ui/gl",
diff --git a/media/audio/android/aaudio_input.cc b/media/audio/android/aaudio_input.cc index b739ec4..13aae7c 100644 --- a/media/audio/android/aaudio_input.cc +++ b/media/audio/android/aaudio_input.cc
@@ -5,6 +5,7 @@ #include "media/audio/android/aaudio_input.h" #include "base/task/bind_post_task.h" +#include "media/audio/android/audio_device_id.h" #include "media/audio/android/audio_manager_android.h" #include "media/base/amplitude_peak_detector.h" #include "media/base/audio_bus.h" @@ -12,9 +13,11 @@ namespace media { AAudioInputStream::AAudioInputStream(AudioManagerAndroid* manager, - const AudioParameters& params) + const AudioParameters& params, + android::AudioDeviceId device_id) : audio_manager_(manager), params_(params), + device_id_(std::move(device_id)), peak_detector_(base::BindRepeating(&AudioManager::TraceAmplitudePeak, base::Unretained(audio_manager_), /*trace_start=*/true)) { @@ -30,7 +33,7 @@ void AAudioInputStream::CreateStreamWrapper() { CHECK(!stream_wrapper_); stream_wrapper_ = std::make_unique<AAudioStreamWrapper>( - this, AAudioStreamWrapper::StreamType::kInput, params_, + this, AAudioStreamWrapper::StreamType::kInput, params_, device_id_, AAUDIO_USAGE_VOICE_COMMUNICATION); }
diff --git a/media/audio/android/aaudio_input.h b/media/audio/android/aaudio_input.h index cecbac9..bcb4a67 100644 --- a/media/audio/android/aaudio_input.h +++ b/media/audio/android/aaudio_input.h
@@ -13,6 +13,7 @@ #include "base/sequence_checker.h" #include "base/synchronization/lock.h" #include "media/audio/android/aaudio_stream_wrapper.h" +#include "media/audio/android/audio_device_id.h" #include "media/audio/audio_io.h" #include "media/base/amplitude_peak_detector.h" #include "media/base/audio_parameters.h" @@ -27,7 +28,8 @@ public AAudioStreamWrapper::DataCallback { public: AAudioInputStream(AudioManagerAndroid* manager, - const AudioParameters& params); + const AudioParameters& params, + android::AudioDeviceId device_id); AAudioInputStream(const AAudioInputStream&) = delete; AAudioInputStream& operator=(const AAudioInputStream&) = delete; @@ -60,6 +62,7 @@ const raw_ptr<AudioManagerAndroid> audio_manager_; const AudioParameters params_; + const android::AudioDeviceId device_id_; AmplitudePeakDetector peak_detector_;
diff --git a/media/audio/android/aaudio_output.cc b/media/audio/android/aaudio_output.cc index f52efd6..5c28085c 100644 --- a/media/audio/android/aaudio_output.cc +++ b/media/audio/android/aaudio_output.cc
@@ -8,6 +8,7 @@ #include "base/memory/raw_ptr.h" #include "base/numerics/checked_math.h" #include "base/task/sequenced_task_runner.h" +#include "media/audio/android/audio_device_id.h" #include "media/audio/android/audio_manager_android.h" #include "media/audio/audio_manager.h" #include "media/base/amplitude_peak_detector.h" @@ -17,6 +18,7 @@ AAudioOutputStream::AAudioOutputStream(AudioManagerAndroid* manager, const AudioParameters& params, + android::AudioDeviceId device_id, aaudio_usage_t usage) : audio_manager_(manager), params_(params), @@ -26,6 +28,7 @@ stream_wrapper_(this, AAudioStreamWrapper::StreamType::kOutput, params, + std::move(device_id), usage) { CHECK(manager); CHECK(params_.IsValid());
diff --git a/media/audio/android/aaudio_output.h b/media/audio/android/aaudio_output.h index 230d0e5f..0d5805b 100644 --- a/media/audio/android/aaudio_output.h +++ b/media/audio/android/aaudio_output.h
@@ -13,6 +13,7 @@ #include "base/synchronization/lock.h" #include "base/thread_annotations.h" #include "media/audio/android/aaudio_stream_wrapper.h" +#include "media/audio/android/audio_device_id.h" #include "media/audio/android/muteable_audio_output_stream.h" #include "media/base/amplitude_peak_detector.h" #include "media/base/audio_parameters.h" @@ -28,6 +29,7 @@ public: AAudioOutputStream(AudioManagerAndroid* manager, const AudioParameters& params, + android::AudioDeviceId device_id, aaudio_usage_t usage); AAudioOutputStream(const AAudioOutputStream&) = delete;
diff --git a/media/audio/android/aaudio_stream_wrapper.cc b/media/audio/android/aaudio_stream_wrapper.cc index 875c8b6..7941adec 100644 --- a/media/audio/android/aaudio_stream_wrapper.cc +++ b/media/audio/android/aaudio_stream_wrapper.cc
@@ -9,11 +9,14 @@ #include "media/audio/android/aaudio_stream_wrapper.h" +#include <aaudio/AAudio.h> + #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/task/sequenced_task_runner.h" #include "base/thread_annotations.h" #include "base/trace_event/trace_event.h" +#include "media/audio/android/audio_device_id.h" #include "media/base/audio_parameters.h" #include "media/base/channel_layout.h" @@ -158,8 +161,10 @@ AAudioStreamWrapper::AAudioStreamWrapper(DataCallback* callback, StreamType stream_type, const AudioParameters& params, + android::AudioDeviceId device_id, aaudio_usage_t usage) : params_(params), + device_id_(std::move(device_id)), stream_type_(stream_type), usage_(usage), callback_(callback), @@ -236,6 +241,7 @@ AAudioStreamBuilder_setPerformanceMode(builder, performance_mode_); AAudioStreamBuilder_setFramesPerDataCallback(builder, params_.frames_per_buffer()); + AAudioStreamBuilder_setDeviceId(builder, device_id_.ToAAudioDeviceId()); if (__builtin_available(android AAUDIO_CHANNEL_MASK_MIN_API, *)) { SetChannelMask(builder, params_); @@ -276,6 +282,18 @@ CHECK_EQ(AAUDIO_FORMAT_PCM_FLOAT, AAudioStream_getFormat(aaudio_stream_)); + if (!device_id_.IsDefault()) { + // `AAudioStreamBuilder_setDeviceId` is not guaranteed to set the specified + // device. + const int32_t expected_device_id = device_id_.ToAAudioDeviceId(); + const int32_t actual_device_id = AAudioStream_getDeviceId(aaudio_stream_); + if (expected_device_id != actual_device_id) { + DLOG(WARNING) << "Failed to set device ID for AAudio stream. Expected: " + << expected_device_id << "; actual: " << actual_device_id; + return false; + } + } + // After opening the stream, sets the effective buffer size to 3X the burst // size to prevent glitching if the burst is small (e.g. < 128). On some // devices you can get by with 1X or 2X, but 3X is safer.
diff --git a/media/audio/android/aaudio_stream_wrapper.h b/media/audio/android/aaudio_stream_wrapper.h index db1e871f..3b8c556 100644 --- a/media/audio/android/aaudio_stream_wrapper.h +++ b/media/audio/android/aaudio_stream_wrapper.h
@@ -12,6 +12,7 @@ #include "base/memory/raw_ptr_exclusion.h" #include "base/sequence_checker.h" #include "base/synchronization/lock.h" +#include "media/audio/android/audio_device_id.h" #include "media/base/audio_bus.h" #include "media/base/audio_parameters.h" @@ -48,6 +49,7 @@ AAudioStreamWrapper(DataCallback* callback, StreamType stream_type, const AudioParameters& params, + android::AudioDeviceId device_id, aaudio_usage_t usage); AAudioStreamWrapper(const AAudioStreamWrapper&) = delete; @@ -78,6 +80,7 @@ SEQUENCE_CHECKER(sequence_checker_); const AudioParameters params_; + const android::AudioDeviceId device_id_; // Whether this class is using an input or an output stream. StreamType stream_type_;
diff --git a/media/audio/android/audio_android_unittest.cc b/media/audio/android/audio_android_unittest.cc index 550a2b7b..df761d9c 100644 --- a/media/audio/android/audio_android_unittest.cc +++ b/media/audio/android/audio_android_unittest.cc
@@ -163,12 +163,19 @@ return os; } -enum class AudioApi { AAudio, OpenSLES }; +enum class AudioApi { + AAudioWithPerStreamDeviceSelection, + AAudioWithCommunicationDevices, + OpenSLES +}; std::ostream& operator<<(std::ostream& os, const AudioApi& audio_api) { switch (audio_api) { - case AudioApi::AAudio: - os << "AAudio"; + case AudioApi::AAudioWithPerStreamDeviceSelection: + os << "AAudioWithPerStreamDeviceSelection"; + break; + case AudioApi::AAudioWithCommunicationDevices: + os << "AAudioWithCommunicationDevices"; break; case AudioApi::OpenSLES: os << "OpenSLES"; @@ -488,22 +495,37 @@ } void InitFeatures(AudioApi audio_api) { - const std::vector<base::test::FeatureRef> aaudio_features = { - features::kUseAAudioDriver, features::kUseAAudioInput}; + bool enable_aaudio = false; + bool enable_aaudio_per_stream_device_selection = false; switch (audio_api) { - case AudioApi::AAudio: - if (!__builtin_available(android AAUDIO_MIN_API, *)) { - GTEST_SKIP() << "AAudio is not available."; - } - feature_list_.InitWithFeatures(aaudio_features, {}); + case AudioApi::AAudioWithPerStreamDeviceSelection: + enable_aaudio = true; + enable_aaudio_per_stream_device_selection = true; + break; + case AudioApi::AAudioWithCommunicationDevices: + enable_aaudio = true; break; case AudioApi::OpenSLES: -#if !BUILDFLAG(USE_OPENSLES) - GTEST_SKIP() << "OpenSLES is disabled."; -#endif - feature_list_.InitWithFeatures({}, aaudio_features); break; } + + if (enable_aaudio) { + if (!__builtin_available(android AAUDIO_MIN_API, *)) { + GTEST_SKIP() << "AAudio is not available."; + } + } else { + // Use OpenSL ES fallback +#if !BUILDFLAG(USE_OPENSLES) + GTEST_SKIP() << "OpenSLES is not available."; +#endif + } + + base::flat_map<base::test::FeatureRef, bool> feature_states( + {{features::kUseAAudioDriver, enable_aaudio}, + {features::kUseAAudioInput, enable_aaudio}, + {features::kAAudioPerStreamDeviceSelection, + enable_aaudio_per_stream_device_selection}}); + feature_list_.InitWithFeatureStates(feature_states); } // Synchronously runs the provided callback/closure on the audio thread. @@ -551,9 +573,11 @@ return devices; } - void MakeAudioOutputStreamOnAudioThread(const AudioParameters& params) { + void MakeAudioOutputStreamOnAudioThread( + const AudioParameters& params, + const std::string& device_id = AudioDeviceDescription::kDefaultDeviceId) { RunOnAudioThread(base::BindOnce(&AudioAndroidOutputTest::MakeOutputStream, - base::Unretained(this), params)); + base::Unretained(this), params, device_id)); } void CloseAudioOutputStreamOnAudioThread(raw_ptr<AudioOutputStream> stream) { @@ -623,10 +647,17 @@ 2 * expected_time_between_callbacks_ms); } - void MakeOutputStream(const AudioParameters& params) { + std::optional<AudioDeviceDescription> GetFirstNonDefaultOutputDevice() { + AudioDeviceDescriptions devices = + GetAudioOutputDeviceDescriptionsOnAudioThread(); + return GetFirstNonDefaultDeviceFromDescriptions(devices); + } + + void MakeOutputStream(const AudioParameters& params, + const std::string& device_id) { DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); audio_output_stream_ = audio_manager()->MakeAudioOutputStream( - params, std::string(), AudioManager::LogCallback()); + params, device_id, AudioManager::LogCallback()); EXPECT_TRUE(audio_output_stream_); } @@ -650,6 +681,17 @@ audio_output_stream_ = nullptr; } + std::optional<AudioDeviceDescription> + GetFirstNonDefaultDeviceFromDescriptions( + const AudioDeviceDescriptions& devices) { + for (AudioDeviceDescription device : devices) { + if (!AudioDeviceDescription::IsDefaultDevice(device.unique_id)) { + return device; + } + } + return std::nullopt; + } + base::test::ScopedFeatureList feature_list_; base::test::SingleThreadTaskEnvironment task_environment_; std::unique_ptr<AudioManager> audio_manager_; @@ -686,9 +728,11 @@ return devices; } - void MakeAudioInputStreamOnAudioThread(const AudioParameters& params) { + void MakeAudioInputStreamOnAudioThread( + const AudioParameters& params, + const std::string& device_id = AudioDeviceDescription::kDefaultDeviceId) { RunOnAudioThread(base::BindOnce(&AudioAndroidInputTest::MakeInputStream, - base::Unretained(this), params)); + base::Unretained(this), params, device_id)); } void CloseAudioInputStreamOnAudioThread(raw_ptr<AudioInputStream> stream) { @@ -759,11 +803,17 @@ AudioDeviceDescription::kDefaultDeviceId); } - void MakeInputStream(const AudioParameters& params) { + std::optional<AudioDeviceDescription> GetFirstNonDefaultInputDevice() { + AudioDeviceDescriptions devices = + GetAudioInputDeviceDescriptionsOnAudioThread(); + return GetFirstNonDefaultDeviceFromDescriptions(devices); + } + + void MakeInputStream(const AudioParameters& params, + const std::string& device_id) { DCHECK(audio_manager()->GetTaskRunner()->BelongsToCurrentThread()); audio_input_stream_ = audio_manager()->MakeAudioInputStream( - params, AudioDeviceDescription::kDefaultDeviceId, - AudioManager::LogCallback()); + params, device_id, AudioManager::LogCallback()); EXPECT_TRUE(audio_input_stream_); } @@ -828,6 +878,19 @@ CloseAudioInputStreamOnAudioThread(audio_input_stream_); } +// Ensure that an input stream with a non-default device can be created and +// closed. +TEST_P(AudioAndroidInputTest, CreateAndCloseInputStreamWithDevice) { + std::optional<AudioDeviceDescription> device = + GetFirstNonDefaultInputDevice(); + if (!device.has_value()) { + GTEST_SKIP() << "Missing non-default input device."; + } + AudioParameters params = GetDefaultInputStreamParametersOnAudioThread(); + MakeAudioInputStreamOnAudioThread(params, device->unique_id); + CloseAudioInputStreamOnAudioThread(audio_input_stream_); +} + // Ensure that a default output stream can be created and closed. // TODO(henrika): should we also verify that this API changes the audio mode // to communication mode, and calls RegisterHeadsetReceiver, the first time @@ -838,6 +901,20 @@ CloseAudioOutputStreamOnAudioThread(audio_output_stream_); } +// Ensure that an output stream with a non-default device can be created and +// closed. This test is only relevant for AAudioWithPerStreamDeviceSelection. +TEST_F(AudioAndroidOutputTest, CreateAndCloseOutputStreamWithDevice) { + InitFeatures(AudioApi::AAudioWithPerStreamDeviceSelection); + std::optional<AudioDeviceDescription> device = + GetFirstNonDefaultOutputDevice(); + if (!device.has_value()) { + GTEST_SKIP() << "Missing non-default output device."; + } + AudioParameters params = GetDefaultOutputStreamParametersOnAudioThread(); + MakeAudioOutputStreamOnAudioThread(params, device->unique_id); + CloseAudioOutputStreamOnAudioThread(audio_output_stream_); +} + // Ensure that a default input stream can be opened and closed. TEST_P(AudioAndroidInputTest, OpenAndCloseInputStream) { AudioParameters params = GetDefaultInputStreamParametersOnAudioThread(); @@ -845,6 +922,19 @@ OpenAndCloseAudioInputStreamOnAudioThread(); } +// Ensure that an input stream with a non-default device can be opened and +// closed. +TEST_P(AudioAndroidInputTest, OpenAndCloseInputStreamWithDevice) { + std::optional<AudioDeviceDescription> device = + GetFirstNonDefaultInputDevice(); + if (!device.has_value()) { + GTEST_SKIP() << "Missing non-default input device."; + } + AudioParameters params = GetDefaultInputStreamParametersOnAudioThread(); + MakeAudioInputStreamOnAudioThread(params, device->unique_id); + OpenAndCloseAudioInputStreamOnAudioThread(); +} + // Ensure that a default output stream can be opened and closed. TEST_P(AudioAndroidOutputTest, OpenAndCloseOutputStream) { AudioParameters params = GetDefaultOutputStreamParametersOnAudioThread(); @@ -852,6 +942,20 @@ OpenAndCloseAudioOutputStreamOnAudioThread(); } +// Ensure that an output stream with a non-default device can be opened and +// closed. This test is only relevant for AAudioWithPerStreamDeviceSelection. +TEST_F(AudioAndroidOutputTest, OpenAndCloseOutputStreamWithDevice) { + InitFeatures(AudioApi::AAudioWithPerStreamDeviceSelection); + std::optional<AudioDeviceDescription> device = + GetFirstNonDefaultOutputDevice(); + if (!device.has_value()) { + GTEST_SKIP() << "Missing non-default output device."; + } + AudioParameters params = GetDefaultOutputStreamParametersOnAudioThread(); + MakeAudioOutputStreamOnAudioThread(params, device->unique_id); + OpenAndCloseAudioOutputStreamOnAudioThread(); +} + // Start input streaming using default input parameters and ensure that the // callback sequence is sane. TEST_P(AudioAndroidInputTest, StartInputStreamCallbacks) { @@ -990,14 +1094,20 @@ StopAndCloseAudioInputStreamOnAudioThread(); } -INSTANTIATE_TEST_SUITE_P(, - AudioAndroidOutputTest, - testing::Values(AudioApi::AAudio, AudioApi::OpenSLES), - testing::PrintToStringParamName()); +INSTANTIATE_TEST_SUITE_P( + , + AudioAndroidOutputTest, + testing::Values(AudioApi::AAudioWithPerStreamDeviceSelection, + AudioApi::AAudioWithCommunicationDevices, + AudioApi::OpenSLES), + testing::PrintToStringParamName()); -INSTANTIATE_TEST_SUITE_P(, - AudioAndroidInputTest, - testing::Values(AudioApi::AAudio, AudioApi::OpenSLES), - testing::PrintToStringParamName()); +INSTANTIATE_TEST_SUITE_P( + , + AudioAndroidInputTest, + testing::Values(AudioApi::AAudioWithPerStreamDeviceSelection, + AudioApi::AAudioWithCommunicationDevices, + AudioApi::OpenSLES), + testing::PrintToStringParamName()); } // namespace media
diff --git a/media/audio/android/audio_device_id.cc b/media/audio/android/audio_device_id.cc new file mode 100644 index 0000000..3831902 --- /dev/null +++ b/media/audio/android/audio_device_id.cc
@@ -0,0 +1,59 @@ +// 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 "media/audio/android/audio_device_id.h" + +#include <aaudio/AAudio.h> + +#include <optional> +#include <string_view> + +#include "base/logging.h" +#include "base/strings/string_number_conversions.h" +#include "media/audio/audio_device_description.h" + +namespace media::android { + +AudioDeviceId::AudioDeviceId(int32_t id) : id_(id) {} + +AudioDeviceId AudioDeviceId::Default() { + return AudioDeviceId(AAUDIO_UNSPECIFIED); +} + +std::optional<AudioDeviceId> AudioDeviceId::Parse( + const std::string_view device_id_string) { + if (AudioDeviceDescription::IsDefaultDevice(device_id_string)) { + return AudioDeviceId::Default(); + } + + int32_t parsed_number; + bool success = base::StringToInt(device_id_string, &parsed_number); + if (!success) { + DLOG(ERROR) << "Failed to parse device_id_string as number: " + << device_id_string; + return std::nullopt; + } + + // An Android device ID string containing the numeric value of + // `AAUDIO_UNSPECIFIED` is invalid, as this value is reserved for the + // "default" device case, for which a string matching + // `AudioDeviceDescription::IsDefaultDevice` should always be used. + if (parsed_number == AAUDIO_UNSPECIFIED) { + DLOG(ERROR) << "device_id_string unexpectedly contained the numeric value " + "reserved for the default device"; + return std::nullopt; + } + + return AudioDeviceId(parsed_number); +} + +bool AudioDeviceId::IsDefault() const { + return id_ == AAUDIO_UNSPECIFIED; +} + +int32_t AudioDeviceId::ToAAudioDeviceId() const { + return id_; +} + +} // namespace media::android
diff --git a/media/audio/android/audio_device_id.h b/media/audio/android/audio_device_id.h new file mode 100644 index 0000000..57b2cb9 --- /dev/null +++ b/media/audio/android/audio_device_id.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 MEDIA_AUDIO_ANDROID_AUDIO_DEVICE_ID_H_ +#define MEDIA_AUDIO_ANDROID_AUDIO_DEVICE_ID_H_ + +#include <optional> +#include <string_view> + +#include "media/base/media_export.h" + +namespace media::android { + +// Wrapper around Android audio device IDs which handles the virtual "default" +// device and string conversion. +class MEDIA_EXPORT AudioDeviceId { + public: + static AudioDeviceId Default(); + + // Parses a string representation of a device ID to an `AudioDeviceId`. + // Returns std::nullopt if parsing fails. + static std::optional<AudioDeviceId> Parse(std::string_view device_id_string); + + bool IsDefault() const; + + // Converts the device ID to a value compatible with + // `AAudioStreamBuilder_setDeviceId`. + int32_t ToAAudioDeviceId() const; + + private: + explicit AudioDeviceId(int32_t id); + + // Numeric ID compatible with AAudio and Java Android APIs, or + // `AAUDIO_UNSPECIFIED` in the case of the "default" device. + int32_t id_; +}; + +} // namespace media::android + +#endif // MEDIA_AUDIO_ANDROID_AUDIO_DEVICE_ID_H_
diff --git a/media/audio/android/audio_device_id_unittest.cc b/media/audio/android/audio_device_id_unittest.cc new file mode 100644 index 0000000..fe1a1b47 --- /dev/null +++ b/media/audio/android/audio_device_id_unittest.cc
@@ -0,0 +1,51 @@ +// 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 "media/audio/android/audio_device_id.h" + +#include <aaudio/AAudio.h> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace media::android { + +TEST(AudioAndroidAudioDeviceIdTest, CreateDefaultDeviceId) { + const AudioDeviceId id = AudioDeviceId::Default(); + EXPECT_TRUE(id.IsDefault()); +} + +TEST(AudioAndroidAudioDeviceIdTest, ParseDefaultDeviceId) { + for (std::string id_string : {"", "default"}) { + const std::optional<AudioDeviceId> id = AudioDeviceId::Parse(id_string); + ASSERT_TRUE(id.has_value()); + EXPECT_TRUE(id->IsDefault()); + } +} + +TEST(AudioAndroidAudioDeviceIdTest, ParseValidNonDefaultDeviceId) { + const std::optional<AudioDeviceId> id = AudioDeviceId::Parse("100"); + ASSERT_TRUE(id.has_value()); + EXPECT_FALSE(id->IsDefault()); + EXPECT_EQ(id->ToAAudioDeviceId(), 100); +} + +TEST(AudioAndroidAudioDeviceIdTest, ParseInvalidNonDefaultDeviceId) { + for (const std::string& id_string : {"0", "999999999999", " 4", "x"}) { + const std::optional<AudioDeviceId> id = AudioDeviceId::Parse(id_string); + EXPECT_FALSE(id.has_value()); + } +} + +TEST(AudioAndroidAudioDeviceIdTest, ConvertDefaultDeviceIdToAAudioDeviceId) { + const AudioDeviceId id = AudioDeviceId::Default(); + EXPECT_EQ(id.ToAAudioDeviceId(), AAUDIO_UNSPECIFIED); +} + +TEST(AudioAndroidAudioDeviceIdTest, ConvertNonDefaultDeviceIdToAAudioDeviceId) { + const std::optional<AudioDeviceId> id = AudioDeviceId::Parse("123"); + ASSERT_TRUE(id.has_value()); + EXPECT_EQ(id->ToAAudioDeviceId(), 123); +} + +} // namespace media::android
diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc index 83bbbeb..21be136 100644 --- a/media/audio/android/audio_manager_android.cc +++ b/media/audio/android/audio_manager_android.cc
@@ -10,12 +10,12 @@ #include "base/android/jni_array.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" +#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "build/android_buildflags.h" -#include "media/media_buildflags.h" #include "media/audio/android/aaudio_input.h" #include "media/audio/android/aaudio_output.h" #include "media/audio/android/audio_track_output_stream.h" @@ -25,6 +25,7 @@ #include "media/audio/fake_audio_input_stream.h" #include "media/base/audio_parameters.h" #include "media/base/channel_layout.h" +#include "media/media_buildflags.h" #if BUILDFLAG(USE_OPENSLES) #include "media/audio/android/opensles_input.h" @@ -41,6 +42,7 @@ using base::android::JavaParamRef; using base::android::JavaRef; using base::android::ScopedJavaLocalRef; +using media::android::AudioDeviceId; namespace media { namespace { @@ -63,10 +65,18 @@ } bool UseAAudioOutput() { + if (!__builtin_available(android AAUDIO_MIN_API, *)) { + return false; + } + return base::FeatureList::IsEnabled(features::kUseAAudioDriver); } bool UseAAudioInput() { + if (!__builtin_available(android AAUDIO_MIN_API, *)) { + return false; + } + if (!base::FeatureList::IsEnabled(features::kUseAAudioInput)) { return false; } @@ -84,6 +94,12 @@ return true; } +bool UseAAudioPerStreamDeviceSelection() { + return UseAAudioInput() && UseAAudioOutput() && + base::FeatureList::IsEnabled( + features::kAAudioPerStreamDeviceSelection); +} + } // namespace std::unique_ptr<AudioManager> CreateAudioManager( @@ -137,34 +153,83 @@ AudioDeviceNames* device_names) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); + if (UseAAudioPerStreamDeviceSelection()) { + GetDeviceNames(device_names, AudioDeviceDirection::kInput); + return; + } + + // Android devices in general do not have robust support for specifying + // devices individually per input or output stream, and as such + // `AAudioPerStreamDeviceSelection` is usually disabled. Instead, if a + // specific device is requested, we set a single input/output pair (a.k.a. a + // "communication device") to be used for streams. Note that it is possible + // for a communication device to be an output-only device. In these cases, + // the framework seems to choose some other available input device for + // communication streams. It's not clear whether this is a real issue, + // considering how long this code has been around for... + // + // For compatibility with Android R-, which predates the concept of + // Android communication devices, the externally exposed devices are + // "synthetic" devices which abstract away the internal device IDs and + // manufacturer-given names provided by the Android framework (e.g. + // "Bluetooth headset" instead of "FooBuds Pro 2.0"): + // * On Android S+, these devices correspond to actual communication + // devices. + // * On Android R-, these devices don't correspond to devices from a list, + // but each one can be controlled via appropriate Android API calls, e.g. + // AudioManager#startBluetoothSco() for Bluetooth. + GetDeviceNames(device_names, AudioDeviceDirection::kCommunication); +} + +void AudioManagerAndroid::GetAudioOutputDeviceNames( + AudioDeviceNames* device_names) { + DCHECK(GetTaskRunner()->BelongsToCurrentThread()); + + if (UseAAudioPerStreamDeviceSelection()) { + GetDeviceNames(device_names, AudioDeviceDirection::kOutput); + return; + } + + // Android devices in general do not have robust support for specifying + // devices individually per input or output stream, and as such + // `AAudioPerStreamDeviceSelection` is usually disabled. In these + // situations, if a specific device is requested, we set a single + // input/output pair (a.k.a. a "communication device") to be used for + // streams system-wide. + // + // We've only returned "default" here for quite some time, relying on output + // device selection being controlled by input device selection (see + // `GetAudioInputDeviceNames`). Populating this list with other devices has + // prevented confusion for users; it would've given them the option to set a + // different input and output device, which wouldn't actually work. However, + // since communication devices on Android are technically output devices for + // which an input device is automatically chosen, it could be more + // appropriate to invert the input and output device lists. + AddDefaultDevice(device_names); +} + +void AudioManagerAndroid::GetDeviceNames(AudioDeviceNames* device_names, + AudioDeviceDirection direction) { + DCHECK(GetTaskRunner()->BelongsToCurrentThread()); + // Always add default device parameters as first element. DCHECK(device_names->empty()); AddDefaultDevice(device_names); - // Android devices in general do not have robust support for specifying - // devices individually per input or output stream. Instead, if a specific - // device is requested, we set a single input/output pair (a.k.a. a - // "communication device") to be used for streams. Note that it is possible - // for a communication device to be an output-only device. In these cases, the - // framework seems to choose some other available input device for - // communication streams. It's not clear whether this is a real issue, - // considering how long this code has been around for... - // - // For compatibility with Android R-, which predates the concept of Android - // communication devices, the externally exposed devices are "synthetic" - // devices which abstract away the internal device IDs and manufacturer-given - // names provided by the Android framework (e.g. "Bluetooth headset" instead - // of "FooBuds Pro 2.0"): - // * On Android S+, these devices correspond to actual communication devices. - // * On Android R-, these devices don't correspond to devices from a list, but - // each one can be controlled via appropriate Android API calls, e.g. - // AudioManager#startBluetoothSco() for Bluetooth. - // TODO(b/373305023): Expose specific model names here, and allow for - // per-stream device selection. JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobjectArray> j_device_array = - Java_AudioManagerAndroid_getCommunicationDevices(env, - GetJavaAudioManager()); + ScopedJavaLocalRef<jobjectArray> j_device_array; + switch (direction) { + case AudioDeviceDirection::kInput: + case AudioDeviceDirection::kOutput: + j_device_array = Java_AudioManagerAndroid_getDevices( + env, GetJavaAudioManager(), + /*inputs=*/direction == AudioDeviceDirection::kInput); + break; + case AudioDeviceDirection::kCommunication: + j_device_array = Java_AudioManagerAndroid_getCommunicationDevices( + env, GetJavaAudioManager()); + break; + } if (j_device_array.is_null()) { // Most probable reason for a NULL result here is that the process lacks // MODIFY_AUDIO_SETTINGS or RECORD_AUDIO permissions. @@ -174,10 +239,19 @@ for (auto j_device : j_device_array.ReadElements<jobject>()) { ScopedJavaLocalRef<jstring> j_device_name = Java_AudioDevice_name(env, j_device); - ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name); + if (!j_device_name.is_null()) { + ConvertJavaStringToUTF8(env, j_device_name.obj(), &device.device_name); + } else { + device.device_name = + "Audio device"; // TODO(crbug.com/409028970): Also return the device + // type and provide a localized, type-specific + // fallback string. + } + ScopedJavaLocalRef<jstring> j_device_id = Java_AudioDevice_id(env, j_device); ConvertJavaStringToUTF8(env, j_device_id.obj(), &device.unique_id); + device_names->push_back(device); } @@ -187,26 +261,6 @@ } } -void AudioManagerAndroid::GetAudioOutputDeviceNames( - AudioDeviceNames* device_names) { - // Android devices in general do not have robust support for specifying - // devices individually per input or output stream. Instead, if a specific - // device is requested, we set a single input/output pair (a.k.a. a - // "communication device") to be used for streams. - // - // We've only returned "default" here for quite some time, relying on output - // device selection being controlled by input device selection (see - // `GetAudioInputDeviceNames`). Populating this list with other devices has - // prevented confusion for users; it would've given them the option to set a - // different input and output device, which wouldn't actually work. However, - // since communication devices on Android are technically output devices for - // which an input device is automatically chosen, it could be more appropriate - // to invert the input and output device lists. - // TODO(b/373305023): Populate `device_names` with the real list of output - // devices and allow for per-stream device selection. - AddDefaultDevice(device_names); -} - AudioParameters AudioManagerAndroid::GetInputStreamParameters( const std::string& device_id) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); @@ -226,8 +280,9 @@ : AudioParameters::NO_EFFECTS; int user_buffer_size = GetUserBufferSize(); - if (user_buffer_size) + if (user_buffer_size) { buffer_size = user_buffer_size; + } AudioParameters params(AudioParameters::AUDIO_PCM_LOW_LATENCY, ChannelLayoutConfig::FromLayout<channel_layout>(), @@ -248,8 +303,9 @@ DCHECK(GetTaskRunner()->BelongsToCurrentThread()); AudioOutputStream* stream = AudioManagerBase::MakeAudioOutputStream( params, device_id, AudioManager::LogCallback()); - if (stream) + if (stream) { streams_.insert(static_cast<MuteableAudioOutputStream*>(stream)); + } return stream; } @@ -259,11 +315,10 @@ const LogCallback& log_callback) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); bool has_input_streams = !HasNoAudioInputStreams(); - bool force_communication_mode = false; AudioInputStream* stream = AudioManagerBase::MakeAudioInputStream( params, device_id, AudioManager::LogCallback()); // Avoid changing the communication mode if there are existing input streams. - if (!stream || has_input_streams) { + if (!stream || has_input_streams || UseAAudioPerStreamDeviceSelection()) { return stream; } @@ -279,6 +334,7 @@ // MODE_IN_COMMUNICATION. Failing to activate communication mode can result // in audio being routed incorrectly, leading to no sound output from the // Bluetooth headset. + bool force_communication_mode = false; #if BUILDFLAG(IS_DESKTOP_ANDROID) force_communication_mode = IsBluetoothMicrophoneOn(); #endif @@ -316,7 +372,8 @@ if (__builtin_available(android AAUDIO_MIN_API, *)) { if (UseAAudioOutput()) { - return new AAudioOutputStream(this, params, AAUDIO_USAGE_MEDIA); + return new AAudioOutputStream(this, params, AudioDeviceId::Default(), + AAUDIO_USAGE_MEDIA); } } #if BUILDFLAG(USE_OPENSLES) @@ -334,10 +391,18 @@ if (__builtin_available(android AAUDIO_MIN_API, *)) { if (UseAAudioOutput()) { + AudioDeviceId parsed_device_id = + AudioDeviceId::Parse(device_id).value_or(AudioDeviceId::Default()); + DCHECK(UseAAudioPerStreamDeviceSelection() || + parsed_device_id.IsDefault()) + << "Non-default output device chosen for output communication " + "stream."; + const aaudio_usage_t usage = communication_mode_is_on_ ? AAUDIO_USAGE_VOICE_COMMUNICATION : AAUDIO_USAGE_MEDIA; - return new AAudioOutputStream(this, params, usage); + return new AAudioOutputStream(this, params, std::move(parsed_device_id), + usage); } } @@ -366,14 +431,16 @@ const AudioParameters& params, const std::string& device_id, const LogCallback& log_callback) { - // TODO(henrika): add support for device selection if/when any client - // needs it. - DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); if (__builtin_available(android AAUDIO_MIN_API, *)) { if (UseAAudioInput()) { - return new AAudioInputStream(this, params); + AudioDeviceId parsed_device_id = + UseAAudioPerStreamDeviceSelection() + ? AudioDeviceId::Parse(device_id).value_or( + AudioDeviceId::Default()) + : AudioDeviceId::Default(); + return new AAudioInputStream(this, params, std::move(parsed_device_id)); } } @@ -393,20 +460,27 @@ DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); DLOG_IF(ERROR, device_id.empty()) << "Invalid device ID!"; - // Use the device ID to select the correct communication device. If the - // default device is requested, a communication device will be chosen based on - // an internal selection scheme. Note that a communication device is an output - // device that the system associates with an input device, and this - // selection switches the device used for all input and output streams with - // communication usage set. - if (!SetCommunicationDevice(device_id)) { - LOG(ERROR) << "Unable to select communication device!"; - return nullptr; + if (!UseAAudioPerStreamDeviceSelection()) { + // Use the device ID to select the correct communication device. If the + // default device is requested, a communication device will be chosen based + // on an internal selection scheme. Note that a communication device is an + // output device that the system associates with an input device, and this + // selection switches the device used for all input and output streams with + // communication usage set. + if (!SetCommunicationDevice(device_id)) { + LOG(ERROR) << "Unable to select communication device!"; + return nullptr; + } } if (__builtin_available(android AAUDIO_MIN_API, *)) { if (UseAAudioInput()) { - return new AAudioInputStream(this, params); + AudioDeviceId parsed_device_id = + UseAAudioPerStreamDeviceSelection() + ? AudioDeviceId::Parse(device_id).value_or( + AudioDeviceId::Default()) + : AudioDeviceId::Default(); + return new AAudioInputStream(this, params, std::move(parsed_device_id)); } } @@ -463,8 +537,9 @@ // AudioManager APIs for GetOptimalOutputFrameSize() don't support channel // layouts greater than stereo unless low latency audio is supported. - if (input_params.channels() <= 2 || IsAudioLowLatencySupported()) + if (input_params.channels() <= 2 || IsAudioLowLatencySupported()) { channel_layout_config = input_params.channel_layout_config(); + } // For high latency playback on supported platforms, pass through the // requested buffer size; this provides significant power savings (~25%) and @@ -478,8 +553,9 @@ } int user_buffer_size = GetUserBufferSize(); - if (user_buffer_size) + if (user_buffer_size) { buffer_size = user_buffer_size; + } // Check if device supports additional audio encodings. if (IsAudioSinkConnected()) { @@ -555,13 +631,14 @@ int AudioManagerAndroid::GetOptimalOutputFrameSize(int sample_rate, int channels) { - if (IsAudioLowLatencySupported()) + if (IsAudioLowLatencySupported()) { return GetAudioLowLatencyOutputFrameSize(); + } - return std::max(kDefaultOutputBufferSize, - Java_AudioManagerAndroid_getMinOutputFrameSize( - base::android::AttachCurrentThread(), - sample_rate, channels)); + return std::max( + kDefaultOutputBufferSize, + Java_AudioManagerAndroid_getMinOutputFrameSize( + base::android::AttachCurrentThread(), sample_rate, channels)); } // Returns a bit mask of AudioParameters::Format enum values sink device @@ -591,9 +668,8 @@ void AudioManagerAndroid::DoSetMuteOnAudioThread(bool muted) { DCHECK(GetTaskRunner()->BelongsToCurrentThread()); - for (OutputStreams::iterator it = streams_.begin(); - it != streams_.end(); ++it) { - (*it)->SetMute(muted); + for (auto stream : streams_) { + stream->SetMute(muted); } } @@ -602,9 +678,8 @@ output_volume_override_ = volume; DCHECK(GetTaskRunner()->BelongsToCurrentThread()); - for (OutputStreams::iterator it = streams_.begin(); it != streams_.end(); - ++it) { - (*it)->SetVolume(volume); + for (auto stream : streams_) { + stream->SetVolume(volume); } }
diff --git a/media/audio/android/audio_manager_android.h b/media/audio/android/audio_manager_android.h index f8058e1..e6a5333 100644 --- a/media/audio/android/audio_manager_android.h +++ b/media/audio/android/audio_manager_android.h
@@ -96,8 +96,16 @@ const AudioParameters& input_params) override; private: + enum class AudioDeviceDirection { + kInput, // Audio source + kOutput, // Audio sink + kCommunication // Communication device, i.e. an input/output pair. + }; + const base::android::JavaRef<jobject>& GetJavaAudioManager(); bool HasNoAudioInputStreams(); + void GetDeviceNames(AudioDeviceNames* device_names, + AudioDeviceDirection direction); void SetCommunicationAudioModeOn(bool on); bool SetCommunicationDevice(const std::string& device_id); int GetNativeOutputSampleRate();
diff --git a/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java b/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java index 33c0bf4..c141af2b 100644 --- a/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java +++ b/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java
@@ -30,6 +30,8 @@ import org.chromium.build.annotations.Nullable; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; @JNINamespace("media") @@ -44,9 +46,9 @@ /** Simple container for device information. */ public static class AudioDevice { private final int mId; - private final String mName; + private final @Nullable String mName; - public AudioDevice(int id, String name) { + public AudioDevice(int id, @Nullable String name) { mId = id; mName = name; } @@ -57,7 +59,7 @@ } @CalledByNative("AudioDevice") - private String name() { + private @Nullable String name() { return mName; } } @@ -257,11 +259,57 @@ } /** + * @param inputs If true, input devices will be returned; otherwise, output devices will be + * returned. + * @return The current list of available audio devices. Note that this call does not trigger any + * update of the list of devices, it only copies the current state into the output array. + */ + @CalledByNative + private AudioDevice @Nullable [] getDevices(boolean inputs) { + if (DEBUG) logd("getDevices"); + + AudioDeviceInfo[] deviceInfos = + mAudioManager.getDevices( + inputs + ? AudioManager.GET_DEVICES_INPUTS + : AudioManager.GET_DEVICES_OUTPUTS); + + List<AudioDevice> devices = new ArrayList<>(); + for (int deviceIndex = 0; deviceIndex < deviceInfos.length; deviceIndex++) { + AudioDeviceInfo deviceInfo = deviceInfos[deviceIndex]; + + int type = deviceInfo.getType(); + switch (type) { + case 28: // AudioDeviceInfo.TYPE_ECHO_REFERENCE + case AudioDeviceInfo.TYPE_REMOTE_SUBMIX: + case AudioDeviceInfo.TYPE_TELEPHONY: + // Unusable device types. + continue; + case AudioDeviceInfo.TYPE_BLUETOOTH_A2DP: + case AudioDeviceInfo.TYPE_BLUETOOTH_SCO: + // TODO(crbug.com/405955144): Bluetooth Classic streams do not work correctly, + // as they do not manage or react to SCO state changes. + continue; + } + + int id = deviceInfo.getId(); + String name = deviceInfo.getProductName().toString(); + if (name.equals(android.os.Build.MODEL)) { + // Undo the Android framework's substitution of a missing name with + // `android.os.Build.MODEL` to facilitate providing a custom fallback name instead. + name = null; + } + devices.add(new AudioDevice(id, name)); + } + return devices.toArray(new AudioDevice[0]); + } + + /** * Required permissions: android.Manifest.permission.MODIFY_AUDIO_SETTINGS and * android.Manifest.permission.RECORD_AUDIO. * - * @return the current list of available communication devices. Note that this call does not - * trigger any update of the list of devices, it only copies the current state in to the + * @return The current list of available communication devices. Note that this call does not + * trigger any update of the list of devices, it only copies the current state into the * output array. */ @CalledByNative
diff --git a/media/base/android/java/src/org/chromium/media/MediaFormatBuilder.java b/media/base/android/java/src/org/chromium/media/MediaFormatBuilder.java index 8fc3250..ed4c170 100644 --- a/media/base/android/java/src/org/chromium/media/MediaFormatBuilder.java +++ b/media/base/android/java/src/org/chromium/media/MediaFormatBuilder.java
@@ -28,7 +28,6 @@ boolean allowAdaptivePlayback, int profile) { MediaFormat format = MediaFormat.createVideoFormat(mime, width, height); - if (format == null) return null; setCodecSpecificData(format, csds); if (hdrMetadata != null) { hdrMetadata.addMetadataToFormat(format);
diff --git a/media/base/media_shmem_export.h b/media/base/media_shmem_export.h index 352d219a..52c3e7a 100644 --- a/media/base/media_shmem_export.h +++ b/media/base/media_shmem_export.h
@@ -18,11 +18,7 @@ #endif // defined(MEDIA_SHMEM_IMPLEMENTATION) #else // defined(WIN32) -#if defined(MEDIA_SHMEM_IMPLEMENTATION) #define MEDIA_SHMEM_EXPORT __attribute__((visibility("default"))) -#else -#define MEDIA_SHMEM_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index e164751..2fe23aa 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -1721,10 +1721,11 @@ std::optional<base::TimeDelta> GetAecAddedDelay() { #if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION) && \ (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)) - return base::Milliseconds(kAddedProcessingDelay.Get()); -#else - return std::nullopt; + if (IsSystemLoopbackAsAecReferenceEnabled()) { + return base::Milliseconds(kAddedProcessingDelay.Get()); + } #endif + return std::nullopt; } bool IsSystemEchoCancellationEnforced() {
diff --git a/media/capture/capture_export.h b/media/capture/capture_export.h index 980fd10..5c07a4c8 100644 --- a/media/capture/capture_export.h +++ b/media/capture/capture_export.h
@@ -15,11 +15,7 @@ #endif // defined(CAPTURE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CAPTURE_IMPLEMENTATION) #define CAPTURE_EXPORT __attribute__((visibility("default"))) -#else -#define CAPTURE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/media/gpu/android/ndk_video_encode_accelerator.cc b/media/gpu/android/ndk_video_encode_accelerator.cc index 4408018..d6706a0e 100644 --- a/media/gpu/android/ndk_video_encode_accelerator.cc +++ b/media/gpu/android/ndk_video_encode_accelerator.cc
@@ -507,7 +507,7 @@ VideoCodec codec = VideoCodecProfileToVideoCodec(config.output_profile); // These should already be filtered out by VideoEncodeAcceleratorUtil. - if (codec != VideoCodec::kH264 && codec == VideoCodec::kHEVC) { + if (codec != VideoCodec::kH264) { config_.required_encoder_type = EncoderType::kHardware; }
diff --git a/media/gpu/chromeos/image_processor_perf_test.cc b/media/gpu/chromeos/image_processor_perf_test.cc index a8bb939..0a6709d 100644 --- a/media/gpu/chromeos/image_processor_perf_test.cc +++ b/media/gpu/chromeos/image_processor_perf_test.cc
@@ -126,7 +126,7 @@ constexpr base::TimeDelta kNullTimestamp; if (type == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) { CHECK(test_sii); - return CreateGmbOrMappableSIVideoFrame( + return CreateMappableVideoFrame( VideoPixelFormat::PIXEL_FORMAT_NV12, size, visible_rect, size, kNullTimestamp, gfx::BufferUsage::SCANOUT_CPU_READ_WRITE, test_sii); } else if (type == VideoFrame::STORAGE_DMABUFS) {
diff --git a/media/gpu/chromeos/image_processor_test.cc b/media/gpu/chromeos/image_processor_test.cc index 37d2998..be4e5bfb1 100644 --- a/media/gpu/chromeos/image_processor_test.cc +++ b/media/gpu/chromeos/image_processor_test.cc
@@ -281,7 +281,7 @@ const gfx::Rect visible_rect(size); constexpr base::TimeDelta kNullTimestamp; if (type == VideoFrame::STORAGE_GPU_MEMORY_BUFFER) { - return CreateGmbOrMappableSIVideoFrame( + return CreateMappableVideoFrame( VideoPixelFormat::PIXEL_FORMAT_NV12, size, visible_rect, size, kNullTimestamp, gfx::BufferUsage::SCANOUT_CPU_READ_WRITE, test_sii); } else {
diff --git a/media/gpu/chromeos/platform_video_frame_utils.cc b/media/gpu/chromeos/platform_video_frame_utils.cc index ded50ab..5551f45 100644 --- a/media/gpu/chromeos/platform_video_frame_utils.cc +++ b/media/gpu/chromeos/platform_video_frame_utils.cc
@@ -27,7 +27,6 @@ #include "base/strings/stringprintf.h" #include "base/synchronization/lock.h" #include "components/viz/common/resources/shared_image_format_utils.h" -#include "gpu/ipc/common/gpu_memory_buffer_support.h" #include "media/base/color_plane_layout.h" #include "media/base/format_utils.h" #include "media/base/media_switches.h" @@ -387,7 +386,7 @@ return gfx::GpuMemoryBufferId(next_gpu_memory_buffer_id++); } -scoped_refptr<VideoFrame> CreateGmbOrMappableSIVideoFrame( +scoped_refptr<VideoFrame> CreateMappableVideoFrame( VideoPixelFormat pixel_format, const gfx::Size& coded_size, const gfx::Rect& visible_rect, @@ -416,14 +415,13 @@ base::TimeDelta timestamp, gfx::BufferUsage buffer_usage, gpu::SharedImageInterface* sii) { + CHECK(sii); const bool supports_zero_copy_webgpu_import = gmb_handle.native_pixmap_handle().supports_zero_copy_webgpu_import; auto buffer_format = VideoPixelFormatToGfxBufferFormat(pixel_format); DCHECK(buffer_format); - scoped_refptr<VideoFrame> video_frame; - if (sii) { const auto si_usage = gpu::SHARED_IMAGE_USAGE_CPU_WRITE_ONLY | gpu::SHARED_IMAGE_USAGE_DISPLAY_READ; auto shared_image = sii->CreateSharedImage( @@ -432,28 +430,14 @@ "PlatformVideoFrameUtils"}, gpu::kNullSurfaceHandle, buffer_usage, std::move(gmb_handle)); - video_frame = media::VideoFrame::WrapMappableSharedImage( + auto video_frame = media::VideoFrame::WrapMappableSharedImage( std::move(shared_image), sii->GenVerifiedSyncToken(), base::NullCallback(), visible_rect, natural_size, timestamp); - } else { - gpu::GpuMemoryBufferSupport support; - std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer = - support.CreateGpuMemoryBufferImplFromHandle( - std::move(gmb_handle), coded_size, *buffer_format, buffer_usage, - base::NullCallback()); - if (!gpu_memory_buffer) { + + if (!video_frame) { return nullptr; } - // It is not necessary to pass a SharedImage because this VideoFrame is not - // rendered. - video_frame = VideoFrame::WrapExternalGpuMemoryBuffer( - visible_rect, natural_size, std::move(gpu_memory_buffer), timestamp); - } - if (!video_frame) { - return nullptr; - } - // We only support importing non-DISJOINT multi-planar GbmBuffer right now. // TODO(crbug.com/40201271): Add DISJOINT support. video_frame->metadata().is_webgpu_compatible =
diff --git a/media/gpu/chromeos/platform_video_frame_utils.h b/media/gpu/chromeos/platform_video_frame_utils.h index a524f50..0609aea 100644 --- a/media/gpu/chromeos/platform_video_frame_utils.h +++ b/media/gpu/chromeos/platform_video_frame_utils.h
@@ -74,14 +74,14 @@ // GpuMemoryBuffer or Mappable SharedImage allocated with |buffer_usage|. // See //media/base/video_frame.h for the other parameters. This function is // thread-safe. -MEDIA_GPU_EXPORT scoped_refptr<VideoFrame> CreateGmbOrMappableSIVideoFrame( +MEDIA_GPU_EXPORT scoped_refptr<VideoFrame> CreateMappableVideoFrame( VideoPixelFormat pixel_format, const gfx::Size& coded_size, const gfx::Rect& visible_rect, const gfx::Size& natural_size, base::TimeDelta timestamp, gfx::BufferUsage buffer_usage, - gpu::SharedImageInterface* sii = nullptr); + gpu::SharedImageInterface* sii); // Creates a STORAGE_GPU_MEMORY_BUFFER VideoFrame from a GpuMemoryBufferHandle. // See //media/base/video_frame.h for the other parameters. This function is @@ -94,7 +94,7 @@ const gfx::Size& natural_size, base::TimeDelta timestamp, gfx::BufferUsage buffer_usage, - gpu::SharedImageInterface* sii = nullptr); + gpu::SharedImageInterface* sii); // Creates a STORAGE_DMABUFS VideoFrame whose buffer is allocated with // |buffer_usage|. See //media/base/video_frame.h for the other parameters. This
diff --git a/media/gpu/chromeos/platform_video_frame_utils_unittest.cc b/media/gpu/chromeos/platform_video_frame_utils_unittest.cc index 304c505..b08f851 100644 --- a/media/gpu/chromeos/platform_video_frame_utils_unittest.cc +++ b/media/gpu/chromeos/platform_video_frame_utils_unittest.cc
@@ -133,7 +133,7 @@ // TODO(b/230370976): remove this #if/#endif guard. To do so, we need to be able // to mock/fake the allocator used by CreatePlatformVideoFrame() and -// CreateGmbOrMappableSIVideoFrame() so that those functions return a +// CreateMappableVideoFrame() so that those functions return a // non-nullptr frame on platforms where allocating NV12 buffers is not // supported. #if BUILDFLAG(IS_CHROMEOS) @@ -160,9 +160,9 @@ kNaturalSize, kTimeStamp, kBufferUsage); break; case VideoFrame::STORAGE_GPU_MEMORY_BUFFER: - frame = CreateGmbOrMappableSIVideoFrame( - kPixelFormat, kCodedSize, kVisibleRect, kNaturalSize, kTimeStamp, - kBufferUsage, test_sii.get()); + frame = CreateMappableVideoFrame(kPixelFormat, kCodedSize, kVisibleRect, + kNaturalSize, kTimeStamp, kBufferUsage, + test_sii.get()); break; default: NOTREACHED();
diff --git a/media/gpu/chromeos/vulkan_overlay_adaptor_test.cc b/media/gpu/chromeos/vulkan_overlay_adaptor_test.cc index 05d4b8c..3430eaa2 100644 --- a/media/gpu/chromeos/vulkan_overlay_adaptor_test.cc +++ b/media/gpu/chromeos/vulkan_overlay_adaptor_test.cc
@@ -705,7 +705,7 @@ kMM21TileHeight) * bpp_numerator / bpp_denom); - scoped_refptr<VideoFrame> frame = CreateGmbOrMappableSIVideoFrame( + scoped_refptr<VideoFrame> frame = CreateMappableVideoFrame( VideoPixelFormat::PIXEL_FORMAT_NV12, alloc_size, visible_rect, alloc_size, kNullTimestamp, gfx::BufferUsage::SCANOUT_CPU_READ_WRITE, test_sii_.get()); @@ -746,7 +746,7 @@ bool is_10bit) { constexpr base::TimeDelta kNullTimestamp; - scoped_refptr<VideoFrame> frame = CreateGmbOrMappableSIVideoFrame( + scoped_refptr<VideoFrame> frame = CreateMappableVideoFrame( is_10bit ? VideoPixelFormat::PIXEL_FORMAT_XR30 : VideoPixelFormat::PIXEL_FORMAT_ARGB, coded_size, gfx::Rect(coded_size), coded_size, kNullTimestamp,
diff --git a/media/gpu/media_gpu_export.h b/media/gpu/media_gpu_export.h index 8c364dc..7ed33b7 100644 --- a/media/gpu/media_gpu_export.h +++ b/media/gpu/media_gpu_export.h
@@ -18,11 +18,7 @@ #endif // defined(MEDIA_GPU_IMPLEMENTATION) #else // defined(WIN32) -#if defined(MEDIA_GPU_IMPLEMENTATION) #define MEDIA_GPU_EXPORT __attribute__((visibility("default"))) -#else -#define MEDIA_GPU_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/media/gpu/test/video_player/test_vda_video_decoder.cc b/media/gpu/test/video_player/test_vda_video_decoder.cc index 99a9d27..5f6b76d 100644 --- a/media/gpu/test/video_player/test_vda_video_decoder.cc +++ b/media/gpu/test/video_player/test_vda_video_decoder.cc
@@ -211,7 +211,7 @@ // Create a video frame for each of the picture buffers and provide memory // handles to the video frame's data to the decoder. for (const PictureBuffer& picture_buffer : picture_buffers) { - scoped_refptr<VideoFrame> video_frame = CreateGmbOrMappableSIVideoFrame( + scoped_refptr<VideoFrame> video_frame = CreateMappableVideoFrame( format, dimensions, visible_rect, visible_rect.size(), base::TimeDelta(), linear_output_ ? gfx::BufferUsage::SCANOUT_CPU_READ_WRITE
diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn index 43bcf037..f5dcc83 100644 --- a/media/gpu/v4l2/BUILD.gn +++ b/media/gpu/v4l2/BUILD.gn
@@ -100,6 +100,7 @@ "//gpu/ipc/service", "//media", "//media/gpu:buildflags", + "//media/gpu:command_buffer_helper", "//media/gpu:common", "//media/gpu:video_frame_mapper_common", "//media/gpu/chromeos:common",
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc index bedb24a..e23cb08 100644 --- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -36,6 +36,8 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/trace_event/trace_event.h" +#include "gpu/ipc/service/gpu_channel_shared_image_interface.h" +#include "gpu/ipc/service/shared_image_stub.h" #include "media/base/bitstream_buffer.h" #include "media/base/color_plane_layout.h" #include "media/base/encoder_status.h" @@ -47,6 +49,7 @@ #include "media/gpu/chromeos/fourcc.h" #include "media/gpu/chromeos/image_processor_factory.h" #include "media/gpu/chromeos/platform_video_frame_utils.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/v4l2/v4l2_utils.h" @@ -555,11 +558,12 @@ for (size_t i = 0; i < count; i++) { switch (output_config.storage_type) { case VideoFrame::STORAGE_GPU_MEMORY_BUFFER: - image_processor_output_buffers_[i] = CreateGmbOrMappableSIVideoFrame( + CHECK(sii_); + image_processor_output_buffers_[i] = CreateMappableVideoFrame( output_config.fourcc.ToVideoPixelFormat(), output_config.size, output_config.visible_rect, output_config.visible_rect.size(), base::TimeDelta(), - gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE); + gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE, sii_.get()); break; default: LOG(ERROR) << "Unsupported output storage type of image processor: " @@ -705,6 +709,33 @@ return is_flush_supported_; } +void V4L2VideoEncodeAccelerator::OnSharedImageInterfaceAvailable( + scoped_refptr<gpu::SharedImageInterface> sii) { + sii_ = std::move(sii); +} + +void V4L2VideoEncodeAccelerator::SetCommandBufferHelperCB( + base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> + get_command_buffer_helper_cb, + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner) { + gpu_task_runner->PostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce( + [](base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> + get_command_buffer_helper_cb) + -> scoped_refptr<gpu::SharedImageInterface> { + auto helper = get_command_buffer_helper_cb.Run(); + if (helper && helper->GetSharedImageStub()) { + return helper->GetSharedImageStub()->shared_image_interface(); + } + return nullptr; + }, + get_command_buffer_helper_cb), + base::BindOnce( + &V4L2VideoEncodeAccelerator::OnSharedImageInterfaceAvailable, + weak_this_)); +} + VideoEncodeAccelerator::SupportedProfiles V4L2VideoEncodeAccelerator::GetSupportedProfiles() { auto device = base::MakeRefCounted<V4L2Device>();
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.h b/media/gpu/v4l2/v4l2_video_encode_accelerator.h index 0fd38f1..914a665 100644 --- a/media/gpu/v4l2/v4l2_video_encode_accelerator.h +++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.h
@@ -21,6 +21,8 @@ #include "base/sequence_checker.h" #include "base/threading/thread.h" #include "base/time/time.h" +#include "gpu/command_buffer/client/shared_image_interface.h" +#include "gpu/ipc/service/command_buffer_stub.h" #include "media/base/encoder_status.h" #include "media/gpu/chromeos/image_processor.h" #include "media/gpu/media_gpu_export.h" @@ -71,6 +73,10 @@ void Destroy() override; void Flush(FlushCallback flush_callback) override; bool IsFlushSupported() override; + void SetCommandBufferHelperCB( + base::RepeatingCallback<scoped_refptr<CommandBufferHelper>()> + get_command_buffer_helper_cb, + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner) override; private: // Auto-destroy reference for BitstreamBuffer, for tracking buffers passed to @@ -276,6 +282,9 @@ // Initializes input_memory_type_. bool InitInputMemoryType(const Config& config); + void OnSharedImageInterfaceAvailable( + scoped_refptr<gpu::SharedImageInterface> sii); + // Having too many encoder instances at once may cause us to run out of FDs // and subsequently crash (crbug.com/1289465). To avoid that, we limit the // maximum number of encoder instances that can exist at once. @@ -388,6 +397,7 @@ // |child_task_runner_|. base::WeakPtr<Client> client_; std::unique_ptr<base::WeakPtrFactory<Client>> client_ptr_factory_; + scoped_refptr<gpu::SharedImageInterface> sii_; // WeakPtr<> pointing to |this| for use in posting tasks to // |encoder_task_runner_|.
diff --git a/media/midi/midi_export.h b/media/midi/midi_export.h index 705b238..bb4b533 100644 --- a/media/midi/midi_export.h +++ b/media/midi/midi_export.h
@@ -15,11 +15,7 @@ #endif // defined(MIDI_IMPLEMENTATION) #else // defined(WIN32) -#if defined(MIDI_IMPLEMENTATION) #define MIDI_EXPORT __attribute__((visibility("default"))) -#else -#define MIDI_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/media/renderers/video_resource_updater.cc b/media/renderers/video_resource_updater.cc index 627f399..9e8ed53 100644 --- a/media/renderers/video_resource_updater.cc +++ b/media/renderers/video_resource_updater.cc
@@ -886,65 +886,54 @@ int bits_per_channel, const gfx::ColorSpace& input_frame_color_space, bool& texture_needs_rgb_conversion_out) { - // TODO(crbug.com/332564976, hitawala): Simplify this format conversion - // process. if (software_compositor()) { return viz::SinglePlaneFormat::kBGRA_8888; } - - viz::SharedImageFormat output_si_format; if (IsFrameFormat32BitRGB(input_frame_format)) { - texture_needs_rgb_conversion_out = false; - output_si_format = GetRGBSharedImageFormat(input_frame_format); - } else if (input_frame_format == PIXEL_FORMAT_Y16) { + return GetRGBSharedImageFormat(input_frame_format); + } + + if (input_frame_format == PIXEL_FORMAT_Y16) { // Unable to display directly as yuv planes so convert it to RGB. texture_needs_rgb_conversion_out = true; - } else if (context_provider_->ContextCapabilities() - .disable_one_component_textures) { + return PaintCanvasVideoRenderer::GetRGBPixelsOutputFormat(); + } + const auto& caps = context_provider_->ContextCapabilities(); + if (caps.disable_one_component_textures) { // If GPU compositing is enabled, we need to convert texture to RGB if one // component textures are disabled. texture_needs_rgb_conversion_out = true; - } else { - // Can be composited directly from yuv planes. - output_si_format = YuvSharedImageFormat(bits_per_channel); + return PaintCanvasVideoRenderer::GetRGBPixelsOutputFormat(); + } - // Some YUV resources have different sized planes. If we lack the proper - // SharedImageFormat just convert to RGB. We could do something better like - // unpacking to I420/I016, but texture_rg and r16 support should be pretty - // universal and we expect these frames to be rare. - if (input_frame_format == PIXEL_FORMAT_NV12) { - if (output_si_format != viz::SinglePlaneFormat::kR_8) { - texture_needs_rgb_conversion_out = true; - } - } else { - DCHECK_EQ(VideoFrame::BytesPerElement(input_frame_format, 0), - VideoFrame::BytesPerElement(input_frame_format, 1)); - } - - // If it is multiplanar and does not need RGB conversion, go through - // RasterDecoder WritePixelsYUV path. - if (!texture_needs_rgb_conversion_out) { - // Get the supported channel format for the `output_si_format`'s first - // plane. - auto channel_format = SupportedMultiPlaneChannelFormat(output_si_format); - // Now get the multiplanar shared image format for `input_frame_format`. - output_si_format = - VideoPixelFormatToMultiPlanarSharedImageFormat(input_frame_format); - if (output_si_format.channel_format() != channel_format) { - // If the requested channel format is not supported, use the supported - // channel format and downsample later if needed. - output_si_format = viz::SharedImageFormat::MultiPlane( - output_si_format.plane_config(), output_si_format.subsampling(), - channel_format); - } + // Get the multiplanar shared image format for `input_frame_format`. + auto yuv_si_format = + VideoPixelFormatToMultiPlanarSharedImageFormat(input_frame_format); + if (yuv_si_format.plane_config() == + viz::SharedImageFormat::PlaneConfig::kY_UV) { + // Only 8-bit formats are supported with UV planes for software decoding. + CHECK_EQ(yuv_si_format.channel_format(), + viz::SharedImageFormat::ChannelFormat::k8); + const auto& shared_image_caps = + context_provider_->SharedImageInterface()->GetCapabilities(); + // Two channel formats are supported only with texture_rg. + if (!caps.texture_rg || shared_image_caps.disable_r8_shared_images) { + texture_needs_rgb_conversion_out = true; + return PaintCanvasVideoRenderer::GetRGBPixelsOutputFormat(); } } - if (texture_needs_rgb_conversion_out) { - output_si_format = PaintCanvasVideoRenderer::GetRGBPixelsOutputFormat(); + // Get the supported channel format for `yuv_si_format`'s first plane. + auto channel_format = + SupportedMultiPlaneChannelFormat(YuvSharedImageFormat(bits_per_channel)); + if (yuv_si_format.channel_format() != channel_format) { + // If the requested channel format is not supported, use the supported + // channel format and downsample later if needed. + yuv_si_format = viz::SharedImageFormat::MultiPlane( + yuv_si_format.plane_config(), yuv_si_format.subsampling(), + channel_format); } - - return output_si_format; + return yuv_si_format; } void VideoResourceUpdater::TransferRGBPixelsToPaintCanvas(
diff --git a/mojo/core/system_impl_export.h b/mojo/core/system_impl_export.h index 40e51cdd..717f442 100644 --- a/mojo/core/system_impl_export.h +++ b/mojo/core/system_impl_export.h
@@ -18,11 +18,7 @@ #endif // defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION) #else // defined(WIN32) -#if defined(MOJO_SYSTEM_IMPL_IMPLEMENTATION) #define MOJO_SYSTEM_IMPL_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_SYSTEM_IMPL_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/mojo/public/c/system/system_export.h b/mojo/public/c/system/system_export.h index 1bf5d5a..6529e192 100644 --- a/mojo/public/c/system/system_export.h +++ b/mojo/public/c/system/system_export.h
@@ -16,11 +16,7 @@ #else // !defined(WIN32) -#if defined(MOJO_SYSTEM_IMPLEMENTATION) #define MOJO_SYSTEM_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_SYSTEM_EXPORT -#endif #endif // defined(WIN32)
diff --git a/mojo/public/cpp/bindings/tests/mojo_test_blink_export.h b/mojo/public/cpp/bindings/tests/mojo_test_blink_export.h index 864d2190..0295395 100644 --- a/mojo/public/cpp/bindings/tests/mojo_test_blink_export.h +++ b/mojo/public/cpp/bindings/tests/mojo_test_blink_export.h
@@ -15,11 +15,7 @@ #endif // defined(MOJO_TEST_BLINK_IMPLEMENTATION) #else // defined(WIN32) -#if defined(MOJO_TEST_BLINK_IMPLEMENTATION) #define MOJO_TEST_BLINK_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_TEST_BLINK_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/mojo/public/cpp/bindings/tests/mojo_test_export.h b/mojo/public/cpp/bindings/tests/mojo_test_export.h index 802f808..c872602 100644 --- a/mojo/public/cpp/bindings/tests/mojo_test_export.h +++ b/mojo/public/cpp/bindings/tests/mojo_test_export.h
@@ -15,11 +15,7 @@ #endif // defined(MOJO_TEST_IMPLEMENTATION) #else // defined(WIN32) -#if defined(MOJO_TEST_IMPLEMENTATION) #define MOJO_TEST_EXPORT __attribute__((visibility("default"))) -#else -#define MOJO_TEST_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/net/base/net_export.h b/net/base/net_export.h index 35e1773..ca64828 100644 --- a/net/base/net_export.h +++ b/net/base/net_export.h
@@ -21,13 +21,8 @@ #endif // defined(NET_IMPLEMENTATION) #else // defined(WIN32) -#if defined(NET_IMPLEMENTATION) #define NET_EXPORT __attribute__((visibility("default"))) #define NET_EXPORT_PRIVATE __attribute__((visibility("default"))) -#else -#define NET_EXPORT -#define NET_EXPORT_PRIVATE -#endif #endif #else /// defined(COMPONENT_BUILD)
diff --git a/net/http/http_stream_pool_attempt_manager.cc b/net/http/http_stream_pool_attempt_manager.cc index be2d487..aa05b77 100644 --- a/net/http/http_stream_pool_attempt_manager.cc +++ b/net/http/http_stream_pool_attempt_manager.cc
@@ -1666,19 +1666,8 @@ StreamSocketCloseReason refresh_group_reason) { CHECK(!is_failing_); CHECK(!quic_attempt_); - // TODO(crbug.com/415127271): Remove debug alias and change CHECK to DCHECK - // once we identify why this doesn't always hold. - bool is_ip_based_pooling_enabled = IsIpBasedPoolingEnabled(); - bool is_alternative_service_enabled = IsAlternativeServiceEnabled(); - bool requires_h1 = RequiresHTTP11(); - QuicChromiumClientSession* quic_session = - quic_session_pool()->FindExistingSession( - quic_session_alias_key().session_key(), - quic_session_alias_key().destination()); - base::debug::Alias(&is_ip_based_pooling_enabled); - base::debug::Alias(&is_alternative_service_enabled); - base::debug::Alias(&requires_h1); - base::debug::Alias(quic_session); + // TODO(crbug.com/415488524): Change to DCHECK once we confirm the bug is + // fixed. CHECK(CanUseExistingQuicSession()); TRACE_EVENT_INSTANT("net.stream", "AttemptManager::QuicSessionReady", track_);
diff --git a/net/http/http_stream_pool_attempt_manager_quic_attempt.cc b/net/http/http_stream_pool_attempt_manager_quic_attempt.cc index 38bd84be..0e5660c 100644 --- a/net/http/http_stream_pool_attempt_manager_quic_attempt.cc +++ b/net/http/http_stream_pool_attempt_manager_quic_attempt.cc
@@ -148,11 +148,8 @@ void HttpStreamPool::AttemptManager::QuicAttempt::OnSessionAttemptComplete( int rv) { if (rv == OK) { - QuicChromiumClientSession* session = - GetQuicSessionPool()->FindExistingSession(GetKey().session_key(), - GetKey().destination()); - if (!session) { - // QUIC session is closed before stream can be created. + if (!manager_->CanUseExistingQuicSession()) { + // QUIC session is closed or marked broken before stream can be created. rv = ERR_CONNECTION_CLOSED; } }
diff --git a/net/http/http_stream_pool_attempt_manager_unittest.cc b/net/http/http_stream_pool_attempt_manager_unittest.cc index 22c51ab5c..f276dc2 100644 --- a/net/http/http_stream_pool_attempt_manager_unittest.cc +++ b/net/http/http_stream_pool_attempt_manager_unittest.cc
@@ -7487,4 +7487,41 @@ EXPECT_THAT(requester.result(), Optional(IsOk())); } +// Regression test for crbug.com/415488524. A QUIC destination may be marked +// broken after a successful QUIC session attempt. Ensure that a request +// doesn't use QUIC in a such situation. +TEST_F(HttpStreamPoolAttemptManagerTest, QuicBrokenWhenSessionCreated) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(net::features::kAsyncQuicSession); + + resolver() + ->AddFakeRequest() + ->add_endpoint(ServiceEndpointBuilder().add_v4("192.0.2.1").endpoint()) + .CompleteStartSynchronously(OK); + + MockConnectCompleter quic_completer; + AddQuicData(/*host=*/kDefaultDestination, &quic_completer); + + SequencedSocketData tcp_data; + socket_factory()->AddSocketDataProvider(&tcp_data); + SSLSocketDataProvider ssl(ASYNC, OK); + socket_factory()->AddSSLSocketDataProvider(&ssl); + + StreamRequester requester; + requester.set_destination(kDefaultDestination) + .set_quic_version(quic_version()) + .RequestStream(pool()); + ASSERT_FALSE(requester.result().has_value()); + + AlternativeService alternative_service(NextProto::kProtoQUIC, + "www.example.org", 443); + http_server_properties()->MarkAlternativeServiceBroken( + alternative_service, NetworkAnonymizationKey()); + + quic_completer.Complete(OK); + requester.WaitForResult(); + EXPECT_THAT(requester.result(), Optional(IsOk())); + EXPECT_NE(requester.negotiated_protocol(), NextProto::kProtoQUIC); +} + } // namespace net
diff --git a/net/log/net_log.cc b/net/log/net_log.cc index f05cd9c..fb5a17ad 100644 --- a/net/log/net_log.cc +++ b/net/log/net_log.cc
@@ -255,10 +255,11 @@ "after NextID() or called multiple times"; } -void NetLog::AddEntryInternal(NetLogEventType type, - const NetLogSource& source, - NetLogEventPhase phase, - const GetParamsInterface* get_params) { +void NetLog::AddEntryInternal( + NetLogEventType type, + const NetLogSource& source, + NetLogEventPhase phase, + base::FunctionRef<base::Value::Dict(NetLogCaptureMode)> get_params) { NetLogCaptureModeSet observer_capture_modes = GetObserverCaptureModes(); for (int i = 0; i <= static_cast<int>(NetLogCaptureMode::kLast); ++i) { @@ -266,7 +267,7 @@ if (!NetLogCaptureModeSetContains(capture_mode, observer_capture_modes)) continue; - base::Value::Dict params = get_params->GetParams(capture_mode); + base::Value::Dict params = get_params(capture_mode); if (capture_mode == NetLogCaptureMode::kHeavilyRedacted) { HeavilyRedactParams(params); }
diff --git a/net/log/net_log.h b/net/log/net_log.h index 45f169d..bebc9d8 100644 --- a/net/log/net_log.h +++ b/net/log/net_log.h
@@ -13,6 +13,7 @@ #include <vector> #include "base/compiler_specific.h" +#include "base/functional/function_ref.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ref.h" #include "base/synchronization/lock.h" @@ -235,22 +236,7 @@ return; } - // Indirect through virtual dispatch to reduce code bloat, as this is - // inlined in a number of places. - class GetParamsImpl : public GetParamsInterface { - public: - explicit GetParamsImpl(const ParametersCallback& get_params) - : get_params_(get_params) {} - base::Value::Dict GetParams(NetLogCaptureMode mode) const override { - return (*get_params_)(mode); - } - - private: - const raw_ref<const ParametersCallback> get_params_; - }; - - GetParamsImpl wrapper(get_params); - AddEntryInternal(type, source, phase, &wrapper); + AddEntryInternal(type, source, phase, get_params); } // Emits a global event to the log stream, with its own unique source ID. @@ -336,18 +322,13 @@ static const char* EventPhaseToString(NetLogEventPhase event_phase); private: - class GetParamsInterface { - public: - virtual base::Value::Dict GetParams(NetLogCaptureMode mode) const = 0; - virtual ~GetParamsInterface() = default; - }; - // Helper for implementing AddEntry() that indirects parameter getting through // virtual dispatch. - void AddEntryInternal(NetLogEventType type, - const NetLogSource& source, - NetLogEventPhase phase, - const GetParamsInterface* get_params); + NOINLINE void AddEntryInternal( + NetLogEventType type, + const NetLogSource& source, + NetLogEventPhase phase, + base::FunctionRef<base::Value::Dict(NetLogCaptureMode)> get_params); // Returns the set of all capture modes being observed. NetLogCaptureModeSet GetObserverCaptureModes() const {
diff --git a/net/quic/dedicated_web_transport_http3_client.cc b/net/quic/dedicated_web_transport_http3_client.cc index b1c857e..9879fd4 100644 --- a/net/quic/dedicated_web_transport_http3_client.cc +++ b/net/quic/dedicated_web_transport_http3_client.cc
@@ -28,6 +28,7 @@ #include "net/third_party/quiche/src/quiche/quic/core/quic_connection.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_types.h" #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h" +#include "net/third_party/quiche/src/quiche/web_transport/web_transport_headers.h" #include "net/url_request/url_request_context.h" #include "url/scheme_host_port.h" @@ -365,6 +366,7 @@ : url_(url), origin_(origin), anonymization_key_(anonymization_key), + application_protocols_(parameters.application_protocols), context_(context), visitor_(visitor), quic_context_(context->quic_context()), @@ -748,6 +750,14 @@ headers[":protocol"] = "webtransport"; headers["sec-webtransport-http3-draft02"] = "1"; headers["origin"] = origin_.Serialize(); + if (!application_protocols_.empty()) { + absl::StatusOr<std::string> protocols_header = + webtransport::SerializeSubprotocolRequestHeader(application_protocols_); + if (protocols_header.ok()) { + headers[webtransport::kSubprotocolRequestHeader] = + *std::move(protocols_header); + } + } stream->WriteHeaders(std::move(headers), /*fin=*/false, nullptr); web_transport_session_ = stream->web_transport();
diff --git a/net/quic/dedicated_web_transport_http3_client.h b/net/quic/dedicated_web_transport_http3_client.h index 30d000ce..516bef6 100644 --- a/net/quic/dedicated_web_transport_http3_client.h +++ b/net/quic/dedicated_web_transport_http3_client.h
@@ -150,6 +150,7 @@ const GURL url_; const url::Origin origin_; const NetworkAnonymizationKey anonymization_key_; + const std::vector<std::string> application_protocols_; const raw_ptr<URLRequestContext> context_; // Unowned. const raw_ptr<WebTransportClientVisitor> visitor_; // Unowned.
diff --git a/net/quic/dedicated_web_transport_http3_client_test.cc b/net/quic/dedicated_web_transport_http3_client_test.cc index de28319..26adffd 100644 --- a/net/quic/dedicated_web_transport_http3_client_test.cc +++ b/net/quic/dedicated_web_transport_http3_client_test.cc
@@ -210,7 +210,7 @@ GetURL("/echo"), origin_, &visitor_, anonymization_key_, context_.get(), WebTransportParameters()); - EXPECT_CALL(visitor_, OnConnected(_)).WillOnce(StopRunning()); + EXPECT_CALL(visitor_, OnConnected).WillOnce(StopRunning()); client_->Connect(); Run(); ASSERT_TRUE(client_->session() != nullptr); @@ -251,7 +251,7 @@ GetURL("/echo"), origin_, &visitor_, anonymization_key_, context_.get(), WebTransportParameters()); - EXPECT_CALL(visitor_, OnConnected(_)).WillOnce(StopRunning()); + EXPECT_CALL(visitor_, OnConnected).WillOnce(StopRunning()); client_->Connect(); Run(); ASSERT_TRUE(client_->session() != nullptr); @@ -277,7 +277,7 @@ GetURL("/session-close"), origin_, &visitor_, anonymization_key_, context_.get(), WebTransportParameters()); - EXPECT_CALL(visitor_, OnConnected(_)).WillOnce(StopRunning()); + EXPECT_CALL(visitor_, OnConnected).WillOnce(StopRunning()); client_->Connect(); Run(); ASSERT_TRUE(client_->session() != nullptr); @@ -296,5 +296,42 @@ EXPECT_THAT(received_close_info, Optional(close_info)); } +// Test negotiation of the application protocol via +// https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-12.html#name-application-protocol-negoti +TEST_F(DedicatedWebTransportHttp3Test, SubprotocolHeader) { + StartServer(); + WebTransportParameters parameters; + parameters.application_protocols = {"first", "second", "third"}; + // The selected-subprotocol endpoint selects the first of the offered + // protocols by default, and echoes it on a unidirectional stream. + client_ = std::make_unique<DedicatedWebTransportHttp3Client>( + GetURL("/selected-subprotocol"), origin_, &visitor_, anonymization_key_, + context_.get(), parameters); + + bool stream_received = false; + EXPECT_CALL(visitor_, OnConnected).WillOnce(StopRunning()); + EXPECT_CALL(visitor_, OnIncomingUnidirectionalStreamAvailable).WillOnce([&] { + stream_received = true; + StopRunning(); + }); + client_->Connect(); + Run(); + ASSERT_TRUE(client_->session() != nullptr); + + EXPECT_EQ(client_->session()->GetNegotiatedSubprotocol(), "first"); + + if (!stream_received) { + Run(); + } + + quic::WebTransportStream* stream = + client_->session()->AcceptIncomingUnidirectionalStream(); + ASSERT_TRUE(stream != nullptr); + std::string read_buffer; + webtransport::Stream::ReadResult read_result = stream->Read(&read_buffer); + ASSERT_TRUE(read_result.fin); + EXPECT_EQ(read_buffer, "first"); +} + } // namespace } // namespace net::test
diff --git a/net/quic/web_transport_client.h b/net/quic/web_transport_client.h index f597a4dc..7b7e187 100644 --- a/net/quic/web_transport_client.h +++ b/net/quic/web_transport_client.h
@@ -106,9 +106,13 @@ bool enable_web_transport_http3 = false; // A vector of fingerprints for expected server certificates, as described in - // https://wicg.github.io/web-transport/#dom-quictransportconfiguration-server_certificate_fingerprints + // https://w3c.github.io/webtransport/#dom-webtransportoptions-servercertificatehashes // When empty, Web PKI is used. std::vector<quic::CertificateFingerprint> server_certificate_fingerprints; + + // A vector of strings offered by client as a list of potential subprotocols. + // https://w3c.github.io/webtransport/#dom-webtransportoptions-protocols + std::vector<std::string> application_protocols; }; // An abstract base for a WebTransport client. Most of the useful operations
diff --git a/pdf/pdf_ink_module.cc b/pdf/pdf_ink_module.cc index 28bb1812..2af8a969 100644 --- a/pdf/pdf_ink_module.cc +++ b/pdf/pdf_ink_module.cc
@@ -54,6 +54,7 @@ #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/cursor/cursor.h" +#include "ui/base/cursor/mojom/cursor_type.mojom.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point_conversions.h" #include "ui/gfx/geometry/point_f.h" @@ -370,6 +371,10 @@ } void PdfInkModule::OnGeometryChanged() { + // If the highlighter tool is selected, and zooming moves the cursor onto + // text, the cursor should be an I-beam, but it will instead be the drawing + // cursor until a mousemove event occurs. There is not a way to get the new + // mouse position on geometry change. MaybeSetCursor(); } @@ -470,11 +475,11 @@ return false; } + gfx::PointF position = event.PositionInWidget(); if (features::kPdfInk2TextHighlighting.Get() && is_text_highlighting()) { - return FinishTextHighlight(); + return FinishTextHighlight(position); } - gfx::PointF position = event.PositionInWidget(); return is_drawing_stroke() ? FinishStroke(position, event.TimeStamp(), ink::StrokeInput::ToolType::kMouse) @@ -484,10 +489,8 @@ bool PdfInkModule::OnMouseMove(const blink::WebMouseEvent& event) { CHECK(enabled()); - // TODO(crbug.com/342445982): Set the cursor for hovering over text with the - // highlighter brush while not drawing. - gfx::PointF position = event.PositionInWidget(); + bool still_interacting_with_ink = event.GetModifiers() & blink::WebInputEvent::kLeftButtonDown; if (still_interacting_with_ink) { @@ -507,6 +510,7 @@ // that now, and compensate by synthesizing a mouse-up input event at the // last known input position. Intentionally do not use `position`. if (is_drawing_stroke()) { + MaybeSetCursorOnMouseMove(position); DrawingStrokeState& state = drawing_stroke_state(); if (!state.input_last_event.has_value()) { // Ignore when not drawing. @@ -772,7 +776,12 @@ state.page_index = -1; state.input_last_event.reset(); - if (MaybeSetDrawingBrush()) { + bool set_drawing_brush = MaybeSetDrawingBrush(); + if (features::kPdfInk2TextHighlighting.Get() && + state.brush_type == PdfInkBrush::Type::kHighlighter && + client_->IsSelectableTextOrLinkArea(position)) { + client_->UpdateInkCursor(ui::mojom::CursorType::kIBeam); + } else if (set_drawing_brush) { MaybeSetCursor(); } @@ -984,7 +993,7 @@ return true; } -bool PdfInkModule::FinishTextHighlight() { +bool PdfInkModule::FinishTextHighlight(const gfx::PointF& position) { CHECK(is_text_highlighting()); auto& highlight_strokes = text_highlight_state().highlight_strokes; @@ -1018,6 +1027,10 @@ drawing_stroke_state().brush_type = PdfInkBrush::Type::kHighlighter; client_->ClearSelection(); + + if (!client_->IsSelectableTextOrLinkArea(position)) { + MaybeSetCursor(); + } return true; } @@ -1609,7 +1622,6 @@ } if (features::kPdfInk2TextHighlighting.Get() && is_text_highlighting()) { - // TODO(crbug.com/342445982): Set the cursor for text highlighting. return; } @@ -1633,6 +1645,25 @@ ui::Cursor::NewCustom(std::move(bitmap), std::move(hotspot))); } +void PdfInkModule::MaybeSetCursorOnMouseMove(const gfx::PointF& position) { + if (!features::kPdfInk2TextHighlighting.Get()) { + return; + } + + CHECK(is_drawing_stroke()); + if (drawing_stroke_state().brush_type != PdfInkBrush::Type::kHighlighter || + !client_->IsSelectableTextOrLinkArea(position)) { + if (client_->GetCursor().type() == ui::mojom::CursorType::kIBeam) { + MaybeSetCursor(); + } + return; + } + + if (client_->GetCursor().type() != ui::mojom::CursorType::kIBeam) { + client_->UpdateInkCursor(ui::mojom::CursorType::kIBeam); + } +} + PdfInkModule::DrawingStrokeState::DrawingStrokeState() = default; PdfInkModule::DrawingStrokeState::~DrawingStrokeState() = default;
diff --git a/pdf/pdf_ink_module.h b/pdf/pdf_ink_module.h index 14ff977..45adf9d 100644 --- a/pdf/pdf_ink_module.h +++ b/pdf/pdf_ink_module.h
@@ -356,7 +356,7 @@ int click_count, base::TimeTicks timestamp); bool ContinueTextHighlight(const gfx::PointF& position); - bool FinishTextHighlight(); + bool FinishTextHighlight(const gfx::PointF& position); // Returns a highlighter stroke that matches the position and size of // `selection_rect`. `selection_rect` must be in screen coordinates. @@ -455,8 +455,14 @@ void ApplyUndoRedoDiscards( const PdfInkUndoRedoModel::DiscardedDrawCommands& discards); + // Sets the cursor to a drawing/erasing brush cursor when necessary. void MaybeSetCursor(); + // Handles setting the cursor only for mousemove events at `position`. This + // differs from `MaybeSetCursor()` in that it may also set the cursor to an + // I-beam for text highlighting. + void MaybeSetCursorOnMouseMove(const gfx::PointF& position); + // Returns whether the drawing brush was set or not. bool MaybeSetDrawingBrush();
diff --git a/pdf/pdf_ink_module_client.h b/pdf/pdf_ink_module_client.h index 731e5b2..a4a2807 100644 --- a/pdf/pdf_ink_module_client.h +++ b/pdf/pdf_ink_module_client.h
@@ -12,6 +12,7 @@ #include "pdf/pdf_ink_ids.h" #include "pdf/ui/thumbnail.h" #include "third_party/ink/src/ink/geometry/partitioned_mesh.h" +#include "ui/base/cursor/cursor.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/vector2d.h" @@ -55,6 +56,9 @@ // `point`. `point` must be in device coordinates. virtual void ExtendSelectionByPoint(const gfx::PointF& point) {} + // Returns the current cursor. + virtual ui::Cursor GetCursor() = 0; + // Gets the current page orientation. virtual PageOrientation GetOrientation() const = 0;
diff --git a/pdf/pdf_ink_module_unittest.cc b/pdf/pdf_ink_module_unittest.cc index 5a3225d3..434cdba 100644 --- a/pdf/pdf_ink_module_unittest.cc +++ b/pdf/pdf_ink_module_unittest.cc
@@ -199,6 +199,13 @@ return visible_stroke_shapes; } +blink::WebMouseEvent CreateMouseMoveEventAtPoint(const gfx::PointF& point) { + return MouseEventBuilder() + .SetType(blink::WebInputEvent::Type::kMouseMove) + .SetPosition(point) + .Build(); +} + blink::WebMouseEvent CreateMouseMoveWithLeftButtonEventAtPoint( const gfx::PointF& point) { return MouseEventBuilder() @@ -261,6 +268,8 @@ (const gfx::PointF& point), (override)); + MOCK_METHOD(ui::Cursor, GetCursor, (), (override)); + PageOrientation GetOrientation() const override { return orientation_; } MOCK_METHOD(std::vector<gfx::Rect>, GetSelectionRects, (), (override)); @@ -3098,6 +3107,8 @@ .WillRepeatedly(Return(selection_rects)); EXPECT_CALL(client(), IsSelectableTextOrLinkArea(kStartPointInsidePage0)) .WillRepeatedly(Return(true)); + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(kEndPointInsidePage0)) + .WillRepeatedly(Return(true)); EXPECT_CALL(client(), OnTextOrLinkAreaClick(kStartPointInsidePage0, /*click_count=*/1)); @@ -3330,10 +3341,12 @@ .WillRepeatedly(Return(selection_rects)); EXPECT_CALL(client(), IsSelectableTextOrLinkArea(kStartPointInsidePage0)) .WillRepeatedly(Return(true)); + constexpr gfx::PointF kEndPoint2InsidePage0{25.0, 30.0}; + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(kEndPoint2InsidePage0)) + .WillRepeatedly(Return(true)); EXPECT_CALL(client(), OnTextOrLinkAreaClick(kStartPointInsidePage0, /*click_count=*/1)); - constexpr gfx::PointF kEndPoint2InsidePage0{25.0, 30.0}; EXPECT_CALL(client(), ExtendSelectionByPoint(kEndPoint2InsidePage0)); // Apply a text highlight stroke at the given points. @@ -3663,7 +3676,7 @@ std::vector<gfx::Rect> selection_rects{gfx::Rect(9, 14, 5, 10)}; EXPECT_CALL(client(), GetSelectionRects()) .WillRepeatedly(Return(selection_rects)); - EXPECT_CALL(client(), IsSelectableTextOrLinkArea(kMouseDownPoint)) + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(_)) .WillRepeatedly(Return(true)); // There should not be any text selection extension after the miss, as the @@ -3673,6 +3686,173 @@ RunStrokeMissedEndEventThenMouseMoveTest(); } +TEST_P(PdfInkModuleTextHighlightTest, CursorOnMouseMove) { + EnableAnnotationMode(); + InitializeSimpleSinglePageBasicLayout(); + + // Select the pen tool with a "Light Red" color. The cursor should be the + // custom pen cursor. + EXPECT_CALL(client(), + UpdateInkCursor(CursorBitmapImageSizeEq(SkISize(8, 8)))); + + TestAnnotationBrushMessageParams params = {/*color_r=*/0xF2, /*color_g=*/0x8B, + /*color_b=*/0x82, /*size=*/6.0f}; + SelectBrushTool(PdfInkBrush::Type::kPen, params); + + // `kStartPointInsidePage0` will be the selectable text area position, while + // all other positions will be non-text areas. + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(_)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(kStartPointInsidePage0)) + .WillRepeatedly(Return(true)); + + // Move to a text position. The cursor should remain as the custom pen cursor. + blink::WebMouseEvent mouse_move_event = + CreateMouseMoveEventAtPoint(kEndPointInsidePage0); + // The event will be considered not handled, but the cursor will still update. + EXPECT_FALSE(ink_module().HandleInputEvent(mouse_move_event)); + + VerifyAndClearExpectations(); + + // Select the highlighter tool. The cursor should be the custom highlighter + // cursor. + EXPECT_CALL(client(), + UpdateInkCursor(CursorBitmapImageSizeEq(SkISize(10, 10)))); + params.size = 8.0f; + SelectBrushTool(PdfInkBrush::Type::kHighlighter, params); + + VerifyAndClearExpectations(); + + // Move to a text position. The cursor should be an I-beam. + EXPECT_CALL(client(), + UpdateInkCursor(ui::Cursor(ui::mojom::CursorType::kIBeam))); + mouse_move_event = CreateMouseMoveEventAtPoint(kStartPointInsidePage0); + EXPECT_FALSE(ink_module().HandleInputEvent(mouse_move_event)); + + VerifyAndClearExpectations(); + + // Move to a non-text position. The cursor should restore to the custom + // highlighter cursor. + { + InSequence seq; + EXPECT_CALL(client(), GetCursor()) + .WillOnce(Return(ui::mojom::CursorType::kIBeam)); + EXPECT_CALL(client(), + UpdateInkCursor(CursorBitmapImageSizeEq(SkISize(10, 10)))); + } + mouse_move_event = CreateMouseMoveEventAtPoint(kEndPointInsidePage0); + EXPECT_FALSE(ink_module().HandleInputEvent(mouse_move_event)); +} + +TEST_P(PdfInkModuleTextHighlightTest, CursorOnMouseMoveWhileTextSelecting) { + EnableAnnotationMode(); + InitializeSimpleSinglePageBasicLayout(); + + // Select the highlighter tool. The cursor should be the custom highlighter + // cursor. + EXPECT_CALL(client(), + UpdateInkCursor(CursorBitmapImageSizeEq(SkISize(10, 10)))); + TestAnnotationBrushMessageParams params = {/*color_r=*/0xF2, /*color_g=*/0x8B, + /*color_b=*/0x82, /*size=*/8.0f}; + SelectBrushTool(PdfInkBrush::Type::kHighlighter, params); + + VerifyAndClearExpectations(); + + // `kStartPointInsidePage0` will be the selectable text area position, while + // all other positions will be non-text areas. + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(_)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(kStartPointInsidePage0)) + .WillRepeatedly(Return(true)); + + // Move to a text position. The cursor should be an I-beam. + EXPECT_CALL(client(), + UpdateInkCursor(ui::Cursor(ui::mojom::CursorType::kIBeam))); + blink::WebMouseEvent mouse_move_event = + CreateMouseMoveEventAtPoint(kStartPointInsidePage0); + EXPECT_FALSE(ink_module().HandleInputEvent(mouse_move_event)); + + VerifyAndClearExpectations(); + + // Start text highlighting and move to a non-text position. The cursor should + // remain as an I-beam. + EXPECT_CALL(client(), UpdateInkCursor(_)).Times(0); + blink::WebMouseEvent mouse_down_event = + MouseEventBuilder() + .CreateLeftClickAtPosition(kStartPointInsidePage0) + .Build(); + EXPECT_TRUE(ink_module().HandleInputEvent(mouse_down_event)); + mouse_move_event = + CreateMouseMoveWithLeftButtonEventAtPoint(kEndPointInsidePage0); + EXPECT_TRUE(ink_module().HandleInputEvent(mouse_move_event)); + + VerifyAndClearExpectations(); + + // End text highlighting. The cursor should restore to the custom highlighter + // cursor. + EXPECT_CALL(client(), + UpdateInkCursor(CursorBitmapImageSizeEq(SkISize(10, 10)))); + blink::WebMouseEvent mouse_up_event = + MouseEventBuilder() + .CreateLeftMouseUpAtPosition(kEndPointInsidePage0) + .Build(); + EXPECT_TRUE(ink_module().HandleInputEvent(mouse_up_event)); +} + +TEST_P(PdfInkModuleTextHighlightTest, CursorOnMouseMoveWhileBrushDrawing) { + EnableAnnotationMode(); + InitializeSimpleSinglePageBasicLayout(); + + // Select the highlighter tool. The cursor should be the custom highlighter + // cursor. + EXPECT_CALL(client(), + UpdateInkCursor(CursorBitmapImageSizeEq(SkISize(10, 10)))); + TestAnnotationBrushMessageParams params = {/*color_r=*/0xF2, /*color_g=*/0x8B, + /*color_b=*/0x82, /*size=*/8.0f}; + SelectBrushTool(PdfInkBrush::Type::kHighlighter, params); + + VerifyAndClearExpectations(); + + // `kEndPointInsidePage0` will be the selectable text area position, while + // all other positions will be non-text areas. + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(_)) + .WillRepeatedly(Return(false)); + EXPECT_CALL(client(), IsSelectableTextOrLinkArea(kEndPointInsidePage0)) + .WillRepeatedly(Return(true)); + + // Move to a non-text position. The cursor should remain as the custom + // highlighter cursor. + EXPECT_CALL(client(), UpdateInkCursor(_)).Times(0); + blink::WebMouseEvent mouse_move_event = + CreateMouseMoveEventAtPoint(kStartPointInsidePage0); + EXPECT_FALSE(ink_module().HandleInputEvent(mouse_move_event)); + + VerifyAndClearExpectations(); + + // Start drawing and move to a text position. The cursor should remain as the + // custom highlighter cursor. + EXPECT_CALL(client(), UpdateInkCursor(_)).Times(0); + blink::WebMouseEvent mouse_down_event = + MouseEventBuilder() + .CreateLeftClickAtPosition(kStartPointInsidePage0) + .Build(); + EXPECT_TRUE(ink_module().HandleInputEvent(mouse_down_event)); + mouse_move_event = + CreateMouseMoveWithLeftButtonEventAtPoint(kEndPointInsidePage0); + EXPECT_TRUE(ink_module().HandleInputEvent(mouse_move_event)); + + VerifyAndClearExpectations(); + + // End drawing. The cursor should be an I-beam. + EXPECT_CALL(client(), + UpdateInkCursor(ui::Cursor(ui::mojom::CursorType::kIBeam))); + blink::WebMouseEvent mouse_up_event = + MouseEventBuilder() + .CreateLeftMouseUpAtPosition(kEndPointInsidePage0) + .Build(); + EXPECT_TRUE(ink_module().HandleInputEvent(mouse_up_event)); +} + INSTANTIATE_TEST_SUITE_P(All, PdfInkModuleTest, testing::ValuesIn(GetAllInkTestVariations()));
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc index 7eed5a2..bcb7097 100644 --- a/pdf/pdf_view_web_plugin.cc +++ b/pdf/pdf_view_web_plugin.cc
@@ -300,6 +300,8 @@ plugin_->engine_->ExtendSelectionByPoint(point); } + ui::Cursor GetCursor() override { return plugin_->cursor_; } + PageOrientation GetOrientation() const override { return plugin_->engine_->GetCurrentOrientation(); }
diff --git a/pdf/pdf_view_web_plugin_unittest.cc b/pdf/pdf_view_web_plugin_unittest.cc index 9d6d226d..87ade8d6 100644 --- a/pdf/pdf_view_web_plugin_unittest.cc +++ b/pdf/pdf_view_web_plugin_unittest.cc
@@ -3049,6 +3049,16 @@ SendThumbnail(/*message_id=*/"foo", /*page_size=*/{50, 25}); } +TEST_P(PdfViewWebPluginInkTest, GetCursor) { + plugin_->set_cursor_type_for_testing(ui::mojom::CursorType::kPointer); + EXPECT_EQ(ui::mojom::CursorType::kPointer, + plugin_->ink_module_client_for_testing()->GetCursor().type()); + + plugin_->set_cursor_type_for_testing(ui::mojom::CursorType::kIBeam); + EXPECT_EQ(ui::mojom::CursorType::kIBeam, + plugin_->ink_module_client_for_testing()->GetCursor().type()); +} + TEST_P(PdfViewWebPluginInkTest, UpdateCursor) { UpdatePluginGeometryWithoutWaiting(2.0f, {0, 0, 20, 20});
diff --git a/ppapi/host/ppapi_host_export.h b/ppapi/host/ppapi_host_export.h index 6bab7e9a7..18c674a 100644 --- a/ppapi/host/ppapi_host_export.h +++ b/ppapi/host/ppapi_host_export.h
@@ -15,11 +15,7 @@ #endif // defined(PPAPI_HOST_IMPLEMENTATION) #else // defined(WIN32) -#if defined(PPAPI_HOST_IMPLEMENTATION) #define PPAPI_HOST_EXPORT __attribute__((visibility("default"))) -#else -#define PPAPI_HOST_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ppapi/proxy/ppapi_proxy_export.h b/ppapi/proxy/ppapi_proxy_export.h index de76892..d5aa604 100644 --- a/ppapi/proxy/ppapi_proxy_export.h +++ b/ppapi/proxy/ppapi_proxy_export.h
@@ -15,11 +15,7 @@ #endif // defined(PPAPI_PROXY_IMPLEMENTATION) #else // defined(WIN32) -#if defined(PPAPI_PROXY_IMPLEMENTATION) #define PPAPI_PROXY_EXPORT __attribute__((visibility("default"))) -#else -#define PPAPI_PROXY_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ppapi/shared_impl/ppapi_shared_export.h b/ppapi/shared_impl/ppapi_shared_export.h index dd3686d..e7308a2 100644 --- a/ppapi/shared_impl/ppapi_shared_export.h +++ b/ppapi/shared_impl/ppapi_shared_export.h
@@ -15,11 +15,7 @@ #endif // defined(PPAPI_SHARED_IMPLEMENTATION) #else // defined(WIN32) -#if defined(PPAPI_SHARED_IMPLEMENTATION) #define PPAPI_SHARED_EXPORT __attribute__((visibility("default"))) -#else -#define PPAPI_SHARED_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ppapi/thunk/ppapi_thunk_export.h b/ppapi/thunk/ppapi_thunk_export.h index 9073469..7c13557 100644 --- a/ppapi/thunk/ppapi_thunk_export.h +++ b/ppapi/thunk/ppapi_thunk_export.h
@@ -15,11 +15,7 @@ #endif // defined(PPAPI_THUNK_IMPLEMENTATION) #else // defined(WIN32) -#if defined(PPAPI_THUNK_IMPLEMENTATION) #define PPAPI_THUNK_EXPORT __attribute__((visibility("default"))) -#else -#define PPAPI_THUNK_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/remoting/host/host_export.h b/remoting/host/host_export.h index 37a50de..a2476318 100644 --- a/remoting/host/host_export.h +++ b/remoting/host/host_export.h
@@ -14,11 +14,7 @@ #endif // defined(HOST_IMPLEMENTATION) #else // !defined(WIN32) -#if defined(HOST_IMPLEMENTATION) #define HOST_EXPORT __attribute__((visibility("default"))) -#else -#define HOST_EXPORT -#endif // defined(HOST_IMPLEMENTATION) #endif // !defined(WIN32) #endif // REMOTING_HOST_HOST_EXPORT_H_
diff --git a/remoting/host/installer/mac/Scripts/remoting_postflight.sh b/remoting/host/installer/mac/Scripts/remoting_postflight.sh index 202a2d3..76b3d9e 100755 --- a/remoting/host/installer/mac/Scripts/remoting_postflight.sh +++ b/remoting/host/installer/mac/Scripts/remoting_postflight.sh
@@ -22,6 +22,7 @@ REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=@@REMOTE_ASSISTANCE_HOST_BUNDLE_NAME@@ HOST_EXE="$HELPERTOOLS/$HOST_BUNDLE_NAME/Contents/MacOS/remoting_me2me_host" USERS_TMP_FILE="$HOST_SERVICE_BINARY.users" +BROKER_SERVICE_TARGET="system/org.chromium.chromoting.broker" # ksadmin moved from MacOS to Helpers in Keystone 1.2.13.112, 2019-11-12. A # symbolic link from the old location was left in place, but may not remain @@ -138,6 +139,8 @@ # started until a host process connects to # chromoting.agent_process_broker_mojo_ipc. logger Loading broker service +logger launchctl enable $BROKER_SERVICE_TARGET +launchctl enable $BROKER_SERVICE_TARGET logger launchctl bootstrap system $BROKER_PLIST launchctl bootstrap system $BROKER_PLIST
diff --git a/remoting/host/linux/BUILD.gn b/remoting/host/linux/BUILD.gn index 0082130..6236b58 100644 --- a/remoting/host/linux/BUILD.gn +++ b/remoting/host/linux/BUILD.gn
@@ -154,6 +154,8 @@ "keyboard_layout_monitor_utils.h", "pipewire_capture_stream.cc", "pipewire_capture_stream.h", + "pipewire_desktop_capturer.cc", + "pipewire_desktop_capturer.h", ] deps = [ ":x11",
diff --git a/remoting/host/linux/pipewire_desktop_capturer.cc b/remoting/host/linux/pipewire_desktop_capturer.cc new file mode 100644 index 0000000..d3d6ce9 --- /dev/null +++ b/remoting/host/linux/pipewire_desktop_capturer.cc
@@ -0,0 +1,119 @@ +// 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 "remoting/host/linux/pipewire_desktop_capturer.h" + +#include <cstdint> +#include <memory> +#include <utility> + +#include "base/check.h" +#include "base/functional/bind.h" +#include "base/location.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/notreached.h" +#include "base/task/sequenced_task_runner.h" +#include "remoting/host/linux/pipewire_capture_stream.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" + +namespace remoting { + +PipewireDesktopCapturer::PipewireDesktopCapturer( + base::WeakPtr<PipewireCaptureStream> stream) + : stream_(std::move(stream)) {} + +PipewireDesktopCapturer::~PipewireDesktopCapturer() { + if (!creating_sequence_->RunsTasksInCurrentSequence()) { + creating_sequence_->PostTask( + FROM_HERE, + base::BindOnce(&PipewireCaptureStream::StopVideoCapture, stream_)); + // The callback proxy may continue to receive frames until StopVideoCapture + // is called, so ensure it is deleted after that. + creating_sequence_->DeleteSoon(FROM_HERE, callback_proxy_.release()); + } else if (stream_) { + stream_->StopVideoCapture(); + } +} + +bool PipewireDesktopCapturer::SupportsFrameCallbacks() { + return true; +} + +void PipewireDesktopCapturer::Start(Callback* callback) { + // The capturer is created by GnomeInteractionStrategy on its sequence, but + // is potentially passed to and owned by a different sequence, which will be + // the sequence that calls Start(). + capture_sequence_ = base::SequencedTaskRunner::GetCurrentDefault(); + callback_ = callback; + callback_proxy_ = std::make_unique<CallbackProxy>( + capture_sequence_, weak_ptr_factory_.GetWeakPtr()); + if (!creating_sequence_->RunsTasksInCurrentSequence()) { + // Unretained is safe because callback_proxy_ is always deleted on the + // creating sequence after StopVideoCapture is called. + creating_sequence_->PostTask( + FROM_HERE, + base::BindOnce(&PipewireCaptureStream::StartVideoCapture, stream_, + base::Unretained(callback_proxy_.get()))); + } else if (stream_) { + stream_->StartVideoCapture(callback_proxy_.get()); + } +} + +void PipewireDesktopCapturer::CaptureFrame() { + // Capturer will push frames as they are ready. + DCHECK(capture_sequence_->RunsTasksInCurrentSequence()); +} + +bool PipewireDesktopCapturer::GetSourceList(SourceList* sources) { + NOTREACHED(); +} + +bool PipewireDesktopCapturer::SelectSource(SourceId id) { + NOTREACHED(); +} + +void PipewireDesktopCapturer::SetMaxFrameRate(std::uint32_t max_frame_rate) { + if (!creating_sequence_->RunsTasksInCurrentSequence()) { + creating_sequence_->PostTask( + FROM_HERE, base::BindOnce(&PipewireCaptureStream::SetMaxFrameRate, + stream_, max_frame_rate)); + } else if (stream_) { + stream_->SetMaxFrameRate(max_frame_rate); + } +} + +PipewireDesktopCapturer::CallbackProxy::CallbackProxy( + scoped_refptr<base::SequencedTaskRunner> capture_sequence, + base::WeakPtr<PipewireDesktopCapturer> capturer) + : capture_sequence_(std::move(capture_sequence)), + capturer_(std::move(capturer)) {} + +PipewireDesktopCapturer::CallbackProxy::~CallbackProxy() = default; + +void PipewireDesktopCapturer::CallbackProxy::OnFrameCaptureStart() { + capture_sequence_->PostTask( + FROM_HERE, + base::BindOnce(&PipewireDesktopCapturer::OnFrameCaptureStart, capturer_)); +} + +void PipewireDesktopCapturer::CallbackProxy::OnCaptureResult( + Result result, + std::unique_ptr<webrtc::DesktopFrame> frame) { + capture_sequence_->PostTask( + FROM_HERE, base::BindOnce(&PipewireDesktopCapturer::OnCaptureResult, + capturer_, result, std::move(frame))); +} + +void PipewireDesktopCapturer::OnFrameCaptureStart() { + callback_->OnFrameCaptureStart(); +} + +void PipewireDesktopCapturer::OnCaptureResult( + Result result, + std::unique_ptr<webrtc::DesktopFrame> frame) { + callback_->OnCaptureResult(result, std::move(frame)); +} + +} // namespace remoting
diff --git a/remoting/host/linux/pipewire_desktop_capturer.h b/remoting/host/linux/pipewire_desktop_capturer.h new file mode 100644 index 0000000..a1e80fbc --- /dev/null +++ b/remoting/host/linux/pipewire_desktop_capturer.h
@@ -0,0 +1,88 @@ +// 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 REMOTING_HOST_LINUX_PIPEWIRE_DESKTOP_CAPTURER_H_ +#define REMOTING_HOST_LINUX_PIPEWIRE_DESKTOP_CAPTURER_H_ + +#include <cstdint> +#include <memory> + +#include "base/memory/raw_ptr.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/task/sequenced_task_runner.h" +#include "remoting/host/linux/pipewire_capture_stream.h" +#include "remoting/protocol/desktop_capturer.h" +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" + +namespace remoting { + +// DesktopCapturer implementation that allows capturing a single screen via the +// provided PipewireCaptureStream. +class PipewireDesktopCapturer : public DesktopCapturer { + public: + explicit PipewireDesktopCapturer(base::WeakPtr<PipewireCaptureStream> stream); + PipewireDesktopCapturer(const PipewireDesktopCapturer&) = delete; + PipewireDesktopCapturer& operator=(const PipewireDesktopCapturer&) = delete; + ~PipewireDesktopCapturer() override; + + // DesktopCapturer interface. + bool SupportsFrameCallbacks() override; + void Start(Callback* callback) override; + void CaptureFrame() override; + void SetMaxFrameRate(std::uint32_t max_frame_rate) override; + + // Unimplemented DesktopCapturer methods that should not be called. Rather, + // the appropriate PipewireCaptureStream is provided to the constructor by the + // DesktopInteractionStrategy based on the screen ID passed to + // DesktopInteractionStrategy::CreateVideoCapturer(). + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; + + private: + // SharedScreencastStream runs the pipewire loop, and invokes frame callbacks, + // on a separate thread. This class is responsible for bouncing them back to + // the capture thread. + class CallbackProxy : public Callback { + public: + CallbackProxy(scoped_refptr<base::SequencedTaskRunner> capture_sequence, + base::WeakPtr<PipewireDesktopCapturer> capturer); + ~CallbackProxy() override; + + // Callback interface + void OnFrameCaptureStart() override; + void OnCaptureResult(Result result, + std::unique_ptr<webrtc::DesktopFrame> frame) override; + + private: + scoped_refptr<base::SequencedTaskRunner> capture_sequence_; + base::WeakPtr<PipewireDesktopCapturer> capturer_; + }; + + // Invoke the corresponding method on callback_. + void OnFrameCaptureStart(); + void OnCaptureResult(Result result, + std::unique_ptr<webrtc::DesktopFrame> frame); + + scoped_refptr<base::SequencedTaskRunner> creating_sequence_ = + base::SequencedTaskRunner::GetCurrentDefault(); + scoped_refptr<base::SequencedTaskRunner> capture_sequence_; + + // Must only be tested for validity and dereferenced on the creating sequence. + base::WeakPtr<PipewireCaptureStream> stream_; + + // Per the webrtc::DesktopCapturer interface, callback is required to remain + // valid until this is destroyed. + raw_ptr<Callback> callback_; + + std::unique_ptr<CallbackProxy> callback_proxy_; + + // Will be bound to the capture sequence when Start() is called and used by + // tasks posted by CallbackProxy. + base::WeakPtrFactory<PipewireDesktopCapturer> weak_ptr_factory_{this}; +}; + +} // namespace remoting + +#endif // REMOTING_HOST_LINUX_PIPEWIRE_DESKTOP_CAPTURER_H_
diff --git a/sandbox/mac/seatbelt_export.h b/sandbox/mac/seatbelt_export.h index 4f3c196..4167d930 100644 --- a/sandbox/mac/seatbelt_export.h +++ b/sandbox/mac/seatbelt_export.h
@@ -7,11 +7,7 @@ #if defined(COMPONENT_BUILD) -#if defined(SEATBELT_IMPLEMENTATION) #define SEATBELT_EXPORT __attribute__((visibility("default"))) -#else -#define SEATBELT_EXPORT -#endif // defined(SEATBELT_IMPLEMENTATION) #else // defined(COMPONENT_BUILD)
diff --git a/sandbox/policy/export.h b/sandbox/policy/export.h index fcef8f6..5546afb7 100644 --- a/sandbox/policy/export.h +++ b/sandbox/policy/export.h
@@ -15,11 +15,7 @@ #endif // defined(SANDBOX_POLICY_IMPL) #else // defined(WIN32) -#if defined(SANDBOX_POLICY_IMPL) #define SANDBOX_POLICY_EXPORT __attribute__((visibility("default"))) -#else -#define SANDBOX_POLICY_EXPORT -#endif // defined(SANDBOX_POLICY_IMPL) #endif #else // defined(COMPONENT_BUILD)
diff --git a/sandbox/sandbox_export.h b/sandbox/sandbox_export.h index 06a2aab..443da7b 100644 --- a/sandbox/sandbox_export.h +++ b/sandbox/sandbox_export.h
@@ -11,11 +11,7 @@ #if defined(COMPONENT_BUILD) -#if defined(SANDBOX_IMPLEMENTATION) #define SANDBOX_EXPORT __attribute__((visibility("default"))) -#else -#define SANDBOX_EXPORT -#endif // defined(SANDBOX_IMPLEMENTATION) #else // defined(COMPONENT_BUILD)
diff --git a/services/device/public/cpp/device_features_export.h b/services/device/public/cpp/device_features_export.h index 7a66542..b13a9ce 100644 --- a/services/device/public/cpp/device_features_export.h +++ b/services/device/public/cpp/device_features_export.h
@@ -17,11 +17,7 @@ #else // !defined(WIN32) -#if defined(DEVICE_FEATURES_IMPLEMENTATION) #define DEVICE_FEATURES_EXPORT __attribute__((visibility("default"))) -#else -#define DEVICE_FEATURES_EXPORT -#endif #endif
diff --git a/services/metrics/public/cpp/metrics_export.h b/services/metrics/public/cpp/metrics_export.h index 21e4970..5c61fcda 100644 --- a/services/metrics/public/cpp/metrics_export.h +++ b/services/metrics/public/cpp/metrics_export.h
@@ -15,11 +15,7 @@ #endif // defined(METRICS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(METRICS_IMPLEMENTATION) #define METRICS_EXPORT __attribute__((visibility("default"))) -#else -#define METRICS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index 4f39a458..536ed91 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -281,7 +281,7 @@ // integrity enforced. BASE_FEATURE(kIntegrityPolicyScript, "IntegrityPolicyScript", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kVisibilityAwareResourceScheduler, "VisibilityAwareResourceScheduler",
diff --git a/services/on_device_model/fake/fake_chrome_ml_api.cc b/services/on_device_model/fake/fake_chrome_ml_api.cc index a19daf28..6ec2976 100644 --- a/services/on_device_model/fake/fake_chrome_ml_api.cc +++ b/services/on_device_model/fake/fake_chrome_ml_api.cc
@@ -241,23 +241,12 @@ for (size_t i = 0; i < options->input_size; i++) { // SAFETY: `options->input_size` describes how big `options->input` is. const ml::InputPiece& piece = UNSAFE_BUFFERS(options->input[i]); - if (!std::holds_alternative<std::string>(piece) && - !std::holds_alternative<ml::Token>(piece)) { - // We could write code to handle token options and non-text inputs being - // passed together, but it would only be exercised by unit tests so would - // not improve real-world coverage. - CHECK(options->token_offset == 0); - } - CHECK(!std::holds_alternative<SkBitmap>(piece) || instance->enable_image_input); CHECK(!std::holds_alternative<ml::AudioBuffer>(piece) || instance->enable_audio_input); text += PieceToString(piece); } - if (options->token_offset > 0) { - text.erase(text.begin(), text.begin() + options->token_offset); - } if (options->max_tokens < text.size()) { text.resize(options->max_tokens); } @@ -328,7 +317,6 @@ ChromeMLAppendOptions append_opts{ .input = options->input, .input_size = options->input_size, - .token_offset = options->token_offset, .max_tokens = options->max_tokens, .context_saved_fn = options->context_saved_fn, };
diff --git a/services/on_device_model/ml/chrome_ml_api.h b/services/on_device_model/ml/chrome_ml_api.h index 65377e3..1e577ac 100644 --- a/services/on_device_model/ml/chrome_ml_api.h +++ b/services/on_device_model/ml/chrome_ml_api.h
@@ -213,8 +213,6 @@ const ml::InputPiece* input; // Number of pieces in input. size_t input_size; - // A number of tokens to skip in input before adding tokens to the context. - uint32_t token_offset; // The maximum number of tokens to add to the context. uint32_t max_tokens; // How to return the result on completion. @@ -236,7 +234,6 @@ struct ChromeMLExecuteOptions { int context_mode; uint32_t max_tokens; - uint32_t token_offset; uint32_t max_output_tokens; const ChromeMLContextSavedFn* context_saved_fn; const ChromeMLExecutionOutputFn* execution_output_fn;
diff --git a/services/on_device_model/ml/session_accessor.cc b/services/on_device_model/ml/session_accessor.cc index 33d6c1e..dec12b5 100644 --- a/services/on_device_model/ml/session_accessor.cc +++ b/services/on_device_model/ml/session_accessor.cc
@@ -211,7 +211,6 @@ ChromeMLAppendOptions options{ .input = append_options->input->pieces.data(), .input_size = append_options->input->pieces.size(), - .token_offset = append_options->token_offset, .max_tokens = append_options->max_tokens, .context_saved_fn = &context_saved_fn, };
diff --git a/services/on_device_model/on_device_model_service_unittest.cc b/services/on_device_model/on_device_model_service_unittest.cc index c7ea840..802fbfee 100644 --- a/services/on_device_model/on_device_model_service_unittest.cc +++ b/services/on_device_model/on_device_model_service_unittest.cc
@@ -380,16 +380,15 @@ ContextClientWaiter client2; auto offset_input = MakeInput("big cheese"); - offset_input->token_offset = 4; session->Append(std::move(offset_input), client2.BindRemote()); - EXPECT_EQ(client2.WaitForCompletion(), 6); + EXPECT_EQ(client2.WaitForCompletion(), 10); session->Append(MakeInput("cheddar"), {}); session->Generate(mojom::GenerateOptions::New(), response.BindRemote()); response.WaitForCompletion(); EXPECT_THAT(response.responses(), - ElementsAre("Context: big \n", "Context: cheese\n", + ElementsAre("Context: big \n", "Context: big cheese\n", "Context: cheddar\n")); }
diff --git a/services/on_device_model/public/cpp/test_support/fake_service.cc b/services/on_device_model/public/cpp/test_support/fake_service.cc index d5565f8..44c08c8c3 100644 --- a/services/on_device_model/public/cpp/test_support/fake_service.cc +++ b/services/on_device_model/public/cpp/test_support/fake_service.cc
@@ -75,10 +75,6 @@ const Capabilities& capabilities) { std::string suffix; std::string context = OnDeviceInputToString(*input.input, capabilities); - if (input.token_offset > 0) { - context.erase(context.begin(), context.begin() + input.token_offset); - } - suffix += " off:" + base::NumberToString(input.token_offset); if (input.max_tokens > 0) { if (input.max_tokens < context.size()) { context.resize(input.max_tokens); @@ -245,8 +241,7 @@ OnDeviceInputToString(*options->input, capabilities_).size()); uint32_t max_tokens = options->max_tokens > 0 ? options->max_tokens : input_tokens; - uint32_t token_offset = options->token_offset; - uint32_t tokens_processed = std::min(input_tokens - token_offset, max_tokens); + uint32_t tokens_processed = std::min(input_tokens, max_tokens); context_.emplace_back(std::move(options)); if (client) { client->OnComplete(tokens_processed);
diff --git a/services/on_device_model/public/mojom/on_device_model.mojom b/services/on_device_model/public/mojom/on_device_model.mojom index 499c6fe..286630b0 100644 --- a/services/on_device_model/public/mojom/on_device_model.mojom +++ b/services/on_device_model/public/mojom/on_device_model.mojom
@@ -132,10 +132,12 @@ // probable. // `top_k` should be a value from 1 to the max top K value the model was // initialized with. - [MinVersion=1] uint32 top_k; + [MinVersion=1] + uint32 top_k; // `temperature` should be a value greater than 0.0. Values above 1.0 may give // poor results. - [MinVersion=1] float temperature; + [MinVersion=1] + float temperature; }; // The set of tokens that can be added as part of an input. @@ -191,8 +193,7 @@ // process all tokens from this input. uint32 max_tokens = 0; - // After text is tokenized, the offset into that vector to start processing. - // If zero, will start at the first token. + // Deprecated. Does nothing. uint32 token_offset = 0; }; @@ -223,11 +224,13 @@ float? temperature; // Deprecated: use `constraint` instead. - [MinVersion=1] string? response_json_schema; + [MinVersion=1] + string? response_json_schema; // Specifies any constraints on the output for this Generate() call. Note that // only one of the JSON schema or regex constraints should be provided. - [MinVersion=2] ResponseConstraint? constraint; + [MinVersion=2] + ResponseConstraint? constraint; }; // Priorities which determine how requests to a session are scheduled. @@ -290,7 +293,7 @@ // Starts a session with this model. Sessions are logically independent, // but requests may block progress of other sessions. StartSession@0(pending_receiver<Session> session, - [MinVersion=1] SessionParams? params); + [MinVersion=1] SessionParams? params); // DEPRECATED: Does nothing ClassifyTextSafety@1(string text) => (SafetyInfo? safety_info);
diff --git a/services/screen_ai/screen_ai_service_impl.cc b/services/screen_ai/screen_ai_service_impl.cc index ff7609b..8103785 100644 --- a/services/screen_ai/screen_ai_service_impl.cc +++ b/services/screen_ai/screen_ai_service_impl.cc
@@ -445,8 +445,6 @@ result.has_value()); base::UmaHistogramCounts100("Accessibility.ScreenAI.OCR.LinesCount", lines_count); - base::UmaHistogramCounts10M("Accessibility.ScreenAI.OCR.ImageSize10M", - image.width() * image.height()); if (image.width() < max_dimension && image.height() < max_dimension) { base::UmaHistogramTimes("Accessibility.ScreenAI.OCR.Latency.NotDownsampled", elapsed_time);
diff --git a/services/service_manager/public/cpp/export.h b/services/service_manager/public/cpp/export.h index 33229a6..5a3f5c3 100644 --- a/services/service_manager/public/cpp/export.h +++ b/services/service_manager/public/cpp/export.h
@@ -15,11 +15,7 @@ #endif // defined(SERVICE_MANAGER_PUBLIC_CPP_IMPL) #else // defined(WIN32) -#if defined(SERVICE_MANAGER_PUBLIC_CPP_IMPL) #define SERVICE_MANAGER_PUBLIC_CPP_EXPORT __attribute__((visibility("default"))) -#else -#define SERVICE_MANAGER_PUBLIC_CPP_EXPORT -#endif // defined(SERVICE_MANAGER_PUBLIC_CPP_IMPL) #endif #else // defined(COMPONENT_BUILD)
diff --git a/services/webnn/tflite/graph_builder_tflite.cc b/services/webnn/tflite/graph_builder_tflite.cc index 2504c4d3..d4ef9f4 100644 --- a/services/webnn/tflite/graph_builder_tflite.cc +++ b/services/webnn/tflite/graph_builder_tflite.cc
@@ -1642,6 +1642,43 @@ } std::optional<GraphBuilderTflite::TensorInfo> +GraphBuilderTflite::CanFuseQuantizeAndGetOutput(const mojom::Elu& elu) { + if (!IsDequantizeOutput(elu.input_operand_id)) { + return std::nullopt; + } + + // TODO(crbug.com/413083273): Consider the restriction in GPU delegate. + // For XNNPack delegate, the input must be dequantized from int8, the input + // and output scale must be scaler. + // https://source.chromium.org/chromium/chromium/src/+/main:third_party/tflite/src/tensorflow/lite/delegates/xnnpack/xnnpack_delegate.cc;l=4136;drc=f667feb8a5c6f227b49328ce78a062acc4f81187 + const mojom::DequantizeLinear& input_dequantize = + GetDequantizeOp(elu.input_operand_id); + if (GetOperand(input_dequantize.input_operand_id).descriptor.data_type() != + OperandDataType::kInt8) { + return std::nullopt; + } + + if (GetOperand(input_dequantize.scale_operand_id) + .descriptor.NumberOfElements() != 1) { + return std::nullopt; + } + + std::optional<size_t> next_op = + IsNextOpQuantize(elu.output_operand_id, {OperandDataType::kInt8}); + if (!next_op) { + return std::nullopt; + } + + const mojom::QuantizeLinear& output_quantize = GetQuantizeOp(*next_op); + if (GetOperand(output_quantize.scale_operand_id) + .descriptor.NumberOfElements() != 1) { + return std::nullopt; + } + + return TrySerializeQuantizedOutput(*next_op); +} + +std::optional<GraphBuilderTflite::TensorInfo> GraphBuilderTflite::CanFuseQuantizeAndGetOutput( const mojom::Transpose& transpose) { if (!IsDequantizeOutput(transpose.input_operand_id)) { @@ -3456,13 +3493,24 @@ "Setting a custom alpha is not supported in tflite schema."); } + std::optional<TensorInfo> quantized_output = CanFuseQuantizeAndGetOutput(elu); + const bool fuse_dequantize = quantized_output.has_value(); ASSIGN_OR_RETURN(const TensorInfo& input_tensor_info, - SerializeInputTensorInfo(elu.input_operand_id)); - ASSIGN_OR_RETURN(const TensorInfo& output_tensor_info, - SerializeOutputTensorInfo(elu.output_operand_id)); + SerializeInputTensorInfo( + elu.input_operand_id, /*quantize_params=*/0, + /*operation_supports_float16=*/false, fuse_dequantize)); + + TensorIndex output_tensor_index; + if (fuse_dequantize) { + output_tensor_index = quantized_output->index; + } else { + ASSIGN_OR_RETURN(const TensorInfo& output_tensor_info, + SerializeOutputTensorInfo(elu.output_operand_id)); + output_tensor_index = output_tensor_info.index; + } + return SerializeUnaryOperation(::tflite::BuiltinOperator_ELU, - input_tensor_info.index, - output_tensor_info.index); + input_tensor_info.index, output_tensor_index); } auto GraphBuilderTflite::SerializeErf(const TensorInfo& input_tensor_info,
diff --git a/services/webnn/tflite/graph_builder_tflite.h b/services/webnn/tflite/graph_builder_tflite.h index 45273dd3..bf39351 100644 --- a/services/webnn/tflite/graph_builder_tflite.h +++ b/services/webnn/tflite/graph_builder_tflite.h
@@ -721,6 +721,7 @@ const mojom::Concat& concat); std::optional<TensorInfo> CanFuseQuantizeAndGetOutput( const mojom::ElementWiseBinary& binary); + std::optional<TensorInfo> CanFuseQuantizeAndGetOutput(const mojom::Elu& elu); std::optional<TensorInfo> CanFuseQuantizeAndGetOutput( const mojom::Transpose& transpose); std::optional<TensorInfo> CanFuseQuantizeAndGetOutput(
diff --git a/skia/ext/switches_export.h b/skia/ext/switches_export.h index 2301d3c..720a1f6 100644 --- a/skia/ext/switches_export.h +++ b/skia/ext/switches_export.h
@@ -15,11 +15,7 @@ #endif // defined(SKIA_SWITCHES_IMPLEMENTATION) #else // defined(WIN32) -#if defined(SKIA_SWITCHES_IMPLEMENTATION) #define SKIA_SWITCHES_EXPORT __attribute__((visibility("default"))) -#else -#define SKIA_SWITCHES_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/storage/browser/quota/quota_database_migrations.cc b/storage/browser/quota/quota_database_migrations.cc index 81abe40..b69fbcc5 100644 --- a/storage/browser/quota/quota_database_migrations.cc +++ b/storage/browser/quota/quota_database_migrations.cc
@@ -27,6 +27,9 @@ // The name for the implicit/default bucket before V10. constexpr char kDefaultNamePreV10[] = "default"; +// Quota type for deprecated persistent quota. +constexpr int kDeprecatedPersistentQuotaType = 1; + // Overwrites the buckets table with the new_buckets table after data has been // copied from the former into the latter. bool OverwriteBucketsTableSetUpIndexes(sql::Database* db) { @@ -351,8 +354,7 @@ "DELETE FROM buckets WHERE type = ? "; sql::Statement delete_statement( db->GetCachedStatement(SQL_FROM_HERE, kDeletePersistentTypeBuckets)); - delete_statement.BindInt( - 0, static_cast<int>(blink::mojom::StorageType::kDeprecatedPersistent)); + delete_statement.BindInt(0, kDeprecatedPersistentQuotaType); if (!delete_statement.Run()) { return false; }
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc index 85ddf5ee..26fc10b 100644 --- a/storage/browser/quota/quota_manager_impl.cc +++ b/storage/browser/quota/quota_manager_impl.cc
@@ -74,7 +74,6 @@ #include "url/origin.h" using ::blink::StorageKey; -using ::blink::mojom::StorageType; namespace storage {
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc index faa1f42..9748daba 100644 --- a/storage/browser/quota/quota_manager_unittest.cc +++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -60,7 +60,6 @@ using ::blink::StorageKey; using ::blink::mojom::QuotaStatusCode; -using ::blink::mojom::StorageType; namespace storage {
diff --git a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc index 744d5465..a02de9b 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -25,8 +25,6 @@ #include "storage/browser/quota/quota_temporary_storage_evictor.h" #include "testing/gtest/include/gtest/gtest.h" -using ::blink::mojom::StorageType; - namespace storage { class QuotaTemporaryStorageEvictorTest;
diff --git a/storage/browser/quota/usage_tracker_unittest.cc b/storage/browser/quota/usage_tracker_unittest.cc index 7736f06..bc85c90 100644 --- a/storage/browser/quota/usage_tracker_unittest.cc +++ b/storage/browser/quota/usage_tracker_unittest.cc
@@ -32,7 +32,6 @@ using ::blink::StorageKey; using ::blink::mojom::QuotaStatusCode; -using ::blink::mojom::StorageType; namespace storage {
diff --git a/testing/buildbot/filters/android.desktop.emulator_15.chrome_public_test_apk.filter b/testing/buildbot/filters/android.desktop.emulator_15.chrome_public_test_apk.filter index fbeeb350..ef747dc 100644 --- a/testing/buildbot/filters/android.desktop.emulator_15.chrome_public_test_apk.filter +++ b/testing/buildbot/filters/android.desktop.emulator_15.chrome_public_test_apk.filter
@@ -81,7 +81,9 @@ -org.chromium.chrome.browser.page_info.PageInfoViewDarkModeTest.testShowOnSecureWebsiteDark # crbug.com/415101606 +-org.chromium.chrome.browser.contextmenu.ContextMenuTest.testPrintPage -org.chromium.chrome.browser.contextmenu.ContextMenuTest.testSavePage +-org.chromium.chrome.browser.contextmenu.ContextMenuTest.testSharePage # crbug.com/415118264 -org.chromium.chrome.browser.customtabs.CustomTabActivityIncognitoTest.ensureAddCustomMenuItemHasNoEffect
diff --git a/testing/buildbot/filters/ozone-linux.browser_tests_mutter.filter b/testing/buildbot/filters/ozone-linux.browser_tests_mutter.filter index d0e958d..ea4f9e6d 100644 --- a/testing/buildbot/filters/ozone-linux.browser_tests_mutter.filter +++ b/testing/buildbot/filters/ozone-linux.browser_tests_mutter.filter
@@ -28,6 +28,3 @@ # in mutter with some additional steps. -All/WebRtcScreenCaptureBrowserTestWithPicker.ScreenCaptureVideo/1 -All/WebRtcScreenCaptureBrowserTestWithPicker.ScreenCaptureVideoAndAudio/1 - -# TODO(crbug.com/395595608) Failing on exit due to dangling ptr --IFrameTest.FileChooserInDestroyedSubframe
diff --git a/testing/buildbot/filters/trees_in_viz.cc_unittests.filter b/testing/buildbot/filters/trees_in_viz.cc_unittests.filter index 605b84d..a60592d60 100644 --- a/testing/buildbot/filters/trees_in_viz.cc_unittests.filter +++ b/testing/buildbot/filters/trees_in_viz.cc_unittests.filter
@@ -42,25 +42,9 @@ -LayerTreeHostImplTest.ScrollCheckerboardsIncompleteRecording/CommitToActiveTree -LayerTreeHostImplTest.ScrollCheckerboardsIncompleteRecording/CommitToPendingTree -# TODO(crbug.com/401566971) implement ThrottleDecider updates for TreesInViz mode. --OccludedSurfaceThrottlingLayerTreeHostImplTest.ThrottleOccludedSurface/CommitToActiveTree --OccludedSurfaceThrottlingLayerTreeHostImplTest.ThrottleOccludedSurface/CommitToPendingTree - # TODO(crbug.com/401567193) LayerImpl WillDraw and DidDraw implementation for TreesInViz mode. --LayerTreeHostImplTest.WillDrawNotCalledOnOccludedLayer/CommitToActiveTree --LayerTreeHostImplTest.WillDrawNotCalledOnOccludedLayer/CommitToPendingTree -LayerTreeHostImplTest.WillDrawReturningFalseDoesNotCall/CommitToActiveTree -LayerTreeHostImplTest.WillDrawReturningFalseDoesNotCall/CommitToPendingTree --LayerTreeHostImplTest.DidDrawCalledOnAllLayers/CommitToActiveTree --LayerTreeHostImplTest.DidDrawCalledOnAllLayers/CommitToPendingTree --LayerTreeHostImplTest.DidDrawNotCalledOnHiddenLayer/CommitToActiveTree --LayerTreeHostImplTest.DidDrawNotCalledOnHiddenLayer/CommitToPendingTree --LayerTreeHostImplTest.ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers/CommitToActiveTree --LayerTreeHostImplTest.ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers/CommitToPendingTree - -# TODO(crbug.com/401568010) Investigate LayerTreeHostImplTest.LayersFreeTextures --LayerTreeHostImplTest.LayersFreeTextures/CommitToActiveTree --LayerTreeHostImplTest.LayersFreeTextures/CommitToPendingTree # TODO (crbug.com/404940328) Fix LayerTreeHostTestInvisibleLayersSkipRenderPass -LayerTreeHostTestInvisibleLayersSkipRenderPass.RunSingleThread_DelegatingRenderer
diff --git a/testing/buildbot/filters/trees_in_viz.content_browsertests.filter b/testing/buildbot/filters/trees_in_viz.content_browsertests.filter index 0728785..5eb7e30 100644 --- a/testing/buildbot/filters/trees_in_viz.content_browsertests.filter +++ b/testing/buildbot/filters/trees_in_viz.content_browsertests.filter
@@ -10,8 +10,6 @@ -All/NavigationBrowserTestPaintHoldingSubframe.BasicInProcessIframe/0 -All/NavigationBrowserTestPaintHoldingSubframe.BasicInProcessIframe/1 -All/RenderWidgetHostItemSequenceNumberInRenderFrameMetadataTest.ItemSequenceNumberExpectedNoContentChange/SameDoc --All/SitePerProcessBrowserTest.ScrollOopifInPinchZoomedPage/0 --All/SitePerProcessBrowserTest.ScrollOopifInPinchZoomedPage/1 -PrerenderBrowserDeathTest.PrerenderCannotHaveInnerContents -RenderFrameHostImplDeathTest.ReloadInPendingDeletionOrBFCache --SecurityExploitBrowserTest.AllowBindingsForNonWebUIProcess \ No newline at end of file +-SecurityExploitBrowserTest.AllowBindingsForNonWebUIProcess
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 6aae15b..2819f4d90 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -12496,26 +12496,6 @@ ] } ], - "IntegrityPolicyScript": [ - { - "platforms": [ - "android", - "android_webview", - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "IntegrityPolicyScript" - ] - } - ] - } - ], "InvalidateSearchEngineChoiceOnDeviceRestoreDetection": [ { "platforms": [ @@ -17356,6 +17336,26 @@ ] } ], + "PreloadingNoSamePageFragmentAnchorTracking": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "NoSamePageFragmentPreloadingAnchorTracking" + ] + } + ] + } + ], "Prerender2BookmarkBarTriggerV2": [ { "platforms": [ @@ -23870,6 +23870,25 @@ ] } ], + "UseSharedRebindServiceConnection": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "EnabledDeferredBindings10", + "params": { + "max-deferred-bindings": "10" + }, + "enable_features": [ + "GroupRebindingForGroupImportance", + "UseSharedRebindServiceConnection" + ] + } + ] + } + ], "UseSmartRefForGPUFenceHandle": [ { "platforms": [
diff --git a/third_party/abseil-cpp/MODULE.bazel b/third_party/abseil-cpp/MODULE.bazel index 405d2c6..29e624a 100644 --- a/third_party/abseil-cpp/MODULE.bazel +++ b/third_party/abseil-cpp/MODULE.bazel
@@ -39,5 +39,5 @@ # intended to be used by Abseil users depend on GoogleTest. bazel_dep( name = "googletest", - version = "1.16.0.bcr.1", + version = "1.17.0", )
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium index 595721d..3f47276 100644 --- a/third_party/abseil-cpp/README.chromium +++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@ License: Apache-2.0 License File: LICENSE Version: N/A -Revision: 5f3435aba00bcd7f12062d2e8e1839b4eaf1a575 +Revision: 2bbec17a3f20da4d908e5627aa72b46f48e064ac Security Critical: yes Shipped: yes
diff --git a/third_party/abseil-cpp/absl/algorithm/container.h b/third_party/abseil-cpp/absl/algorithm/container.h index 3193656..913268d 100644 --- a/third_party/abseil-cpp/absl/algorithm/container.h +++ b/third_party/abseil-cpp/absl/algorithm/container.h
@@ -44,7 +44,6 @@ #include <cassert> #include <iterator> #include <numeric> -#include <random> #include <type_traits> #include <unordered_map> #include <unordered_set> @@ -847,25 +846,9 @@ typename UniformRandomBitGenerator> OutputIterator c_sample(const C& c, OutputIterator result, Distance n, UniformRandomBitGenerator&& gen) { -#if defined(__cpp_lib_sample) && __cpp_lib_sample >= 201603L return std::sample(container_algorithm_internal::c_begin(c), container_algorithm_internal::c_end(c), result, n, std::forward<UniformRandomBitGenerator>(gen)); -#else - // Fall back to a stable selection-sampling implementation. - auto first = container_algorithm_internal::c_begin(c); - Distance unsampled_elements = c_distance(c); - n = (std::min)(n, unsampled_elements); - for (; n != 0; ++first) { - Distance r = - std::uniform_int_distribution<Distance>(0, --unsampled_elements)(gen); - if (r < n) { - *result++ = *first; - --n; - } - } - return result; -#endif } //------------------------------------------------------------------------------
diff --git a/third_party/abseil-cpp/absl/container/internal/hash_policy_testing.h b/third_party/abseil-cpp/absl/container/internal/hash_policy_testing.h index 66bb12e..e9f5757 100644 --- a/third_party/abseil-cpp/absl/container/internal/hash_policy_testing.h +++ b/third_party/abseil-cpp/absl/container/internal/hash_policy_testing.h
@@ -119,7 +119,11 @@ using propagate_on_container_swap = std::true_type; // Using old paradigm for this to ensure compatibility. - explicit Alloc(size_t id = 0) : id_(id) {} + // + // NOTE: As of 2025-05, this constructor cannot be explicit in order to work + // with the libstdc++ that ships with GCC15. + // NOLINTNEXTLINE(google-explicit-constructor) + Alloc(size_t id = 0) : id_(id) {} Alloc(const Alloc&) = default; Alloc& operator=(const Alloc&) = default;
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc index f66f486..f19e87b 100644 --- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc +++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc
@@ -617,7 +617,7 @@ void ResizeNonSooImpl(CommonFields& common, const PolicyFunctions& policy, size_t new_capacity, HashtablezInfoHandle infoz) { ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity)); - ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity); + ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity()); const size_t old_capacity = common.capacity(); [[maybe_unused]] ctrl_t* old_ctrl = common.control(); @@ -643,7 +643,7 @@ size_t total_probe_length = 0; ResetCtrl(common, slot_size); ABSL_SWISSTABLE_ASSERT(kMode != ResizeNonSooMode::kGuaranteedEmpty || - old_capacity == policy.soo_capacity); + old_capacity == policy.soo_capacity()); ABSL_SWISSTABLE_ASSERT(kMode != ResizeNonSooMode::kGuaranteedAllocated || old_capacity > 0); if constexpr (kMode == ResizeNonSooMode::kGuaranteedAllocated) { @@ -670,9 +670,9 @@ const PolicyFunctions& policy, size_t new_capacity, bool force_infoz) { ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity)); - ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity); - ABSL_SWISSTABLE_ASSERT(!force_infoz || policy.soo_capacity > 0); - ABSL_SWISSTABLE_ASSERT(common.capacity() <= policy.soo_capacity); + ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity()); + ABSL_SWISSTABLE_ASSERT(!force_infoz || policy.soo_enabled); + ABSL_SWISSTABLE_ASSERT(common.capacity() <= policy.soo_capacity()); ABSL_SWISSTABLE_ASSERT(common.empty()); const size_t slot_size = policy.slot_size; HashtablezInfoHandle infoz; @@ -680,7 +680,7 @@ policy.is_hashtablez_eligible && (force_infoz || ShouldSampleNextTable()); if (ABSL_PREDICT_FALSE(should_sample)) { infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size, - policy.soo_capacity); + policy.soo_capacity()); } ResizeNonSooImpl<ResizeNonSooMode::kGuaranteedEmpty>(common, policy, new_capacity, infoz); @@ -694,8 +694,8 @@ const PolicyFunctions& policy, size_t hash, ctrl_t* new_ctrl, void* new_slots) { - ABSL_SWISSTABLE_ASSERT(c.size() == policy.soo_capacity); - ABSL_SWISSTABLE_ASSERT(policy.soo_capacity == SooCapacity()); + ABSL_SWISSTABLE_ASSERT(c.size() == policy.soo_capacity()); + ABSL_SWISSTABLE_ASSERT(policy.soo_enabled); size_t new_capacity = c.capacity(); c.generate_new_seed(); @@ -717,12 +717,21 @@ kForceSampleNoResizeIfUnsampled, }; +void AssertSoo([[maybe_unused]] CommonFields& common, + [[maybe_unused]] const PolicyFunctions& policy) { + ABSL_SWISSTABLE_ASSERT(policy.soo_enabled); + ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity()); +} +void AssertFullSoo([[maybe_unused]] CommonFields& common, + [[maybe_unused]] const PolicyFunctions& policy) { + AssertSoo(common, policy); + ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity()); +} + void ResizeFullSooTable(CommonFields& common, const PolicyFunctions& policy, size_t new_capacity, ResizeFullSooTableSamplingMode sampling_mode) { - ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity); - ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity); - ABSL_SWISSTABLE_ASSERT(policy.soo_capacity == SooCapacity()); + AssertFullSoo(common, policy); const size_t slot_size = policy.slot_size; const size_t slot_align = policy.slot_align; @@ -731,7 +740,7 @@ ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled) { if (ABSL_PREDICT_FALSE(policy.is_hashtablez_eligible)) { infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size, - policy.soo_capacity); + policy.soo_capacity()); } if (!infoz.IsSampled()) { @@ -1218,11 +1227,11 @@ ABSL_SWISSTABLE_ASSERT(common.growth_left() == 0); const size_t old_capacity = common.capacity(); ABSL_SWISSTABLE_ASSERT(old_capacity == 0 || - old_capacity > policy.soo_capacity); + old_capacity > policy.soo_capacity()); const size_t new_capacity = NextCapacity(old_capacity); ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity)); - ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity); + ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity()); ctrl_t* old_ctrl = common.control(); void* old_slots = common.slot_array(); @@ -1238,7 +1247,7 @@ policy.is_hashtablez_eligible && ShouldSampleNextTable(); if (ABSL_PREDICT_FALSE(should_sample)) { infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size, - policy.soo_capacity); + policy.soo_capacity()); } } const bool has_infoz = infoz.IsSampled(); @@ -1291,7 +1300,7 @@ find_info = find_first_non_full(common, new_hash); SetCtrlInLargeTable(common, find_info.offset, new_h2, policy.slot_size); } - ABSL_SWISSTABLE_ASSERT(old_capacity > policy.soo_capacity); + ABSL_SWISSTABLE_ASSERT(old_capacity > policy.soo_capacity()); (*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align, has_infoz); } @@ -1415,9 +1424,9 @@ // Resizes empty non-allocated table to the capacity to fit new_size elements. // Requires: -// 1. `c.capacity() == policy.soo_capacity`. +// 1. `c.capacity() == policy.soo_capacity()`. // 2. `c.empty()`. -// 3. `new_size > policy.soo_capacity`. +// 3. `new_size > policy.soo_capacity()`. // The table will be attempted to be sampled. void ReserveEmptyNonAllocatedTableToFitNewSize(CommonFields& common, const PolicyFunctions& policy, @@ -1435,7 +1444,7 @@ // allocated backing array. // // Requires: -// 1. `c.capacity() > policy.soo_capacity` OR `!c.empty()`. +// 1. `c.capacity() > policy.soo_capacity()` OR `!c.empty()`. // Reserving already allocated tables is considered to be a rare case. ABSL_ATTRIBUTE_NOINLINE void ReserveAllocatedTable( CommonFields& common, const PolicyFunctions& policy, size_t new_size) { @@ -1443,12 +1452,12 @@ ValidateMaxSize(new_size, policy.slot_size); ABSL_ASSUME(new_size > 0); const size_t new_capacity = SizeToCapacity(new_size); - if (cap == policy.soo_capacity) { + if (cap == policy.soo_capacity()) { ABSL_SWISSTABLE_ASSERT(!common.empty()); ResizeFullSooTable(common, policy, new_capacity, ResizeFullSooTableSamplingMode::kNoSampling); } else { - ABSL_SWISSTABLE_ASSERT(cap > policy.soo_capacity); + ABSL_SWISSTABLE_ASSERT(cap > policy.soo_capacity()); // TODO(b/382423690): consider using GrowToNextCapacity, when applicable. ResizeAllocatedTableWithSeedChange(common, policy, new_capacity); } @@ -1486,16 +1495,14 @@ const PolicyFunctions& policy, size_t new_hash, ctrl_t soo_slot_ctrl) { - ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity); - ABSL_SWISSTABLE_ASSERT(policy.soo_capacity == SooCapacity()); + AssertSoo(common, policy); if (ABSL_PREDICT_FALSE(soo_slot_ctrl == ctrl_t::kEmpty)) { // The table is empty, it is only used for forced sampling of SOO tables. return GrowEmptySooTableToNextCapacityForceSamplingAndPrepareInsert( common, policy, new_hash); } - ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity); + ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity()); static constexpr size_t kNewCapacity = NextCapacity(SooCapacity()); - ABSL_SWISSTABLE_ASSERT(kNewCapacity > policy.soo_capacity); const size_t slot_size = policy.slot_size; const size_t slot_align = policy.slot_align; common.set_capacity(kNewCapacity); @@ -1560,9 +1567,7 @@ void GrowFullSooTableToNextCapacityForceSampling( CommonFields& common, const PolicyFunctions& policy) { - ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity); - ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity); - ABSL_SWISSTABLE_ASSERT(policy.soo_capacity == SooCapacity()); + AssertFullSoo(common, policy); ResizeFullSooTable( common, policy, NextCapacity(SooCapacity()), ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled); @@ -1573,18 +1578,18 @@ auto clear_backing_array = [&]() { ClearBackingArray(common, policy, policy.get_char_alloc(common), - /*reuse=*/false, policy.soo_capacity > 0); + /*reuse=*/false, policy.soo_enabled); }; const size_t slot_size = policy.slot_size; if (n == 0) { - if (cap <= policy.soo_capacity) return; + if (cap <= policy.soo_capacity()) return; if (common.empty()) { clear_backing_array(); return; } - if (common.size() <= policy.soo_capacity) { + if (common.size() <= policy.soo_capacity()) { // When the table is already sampled, we keep it sampled. if (common.infoz().IsSampled()) { static constexpr size_t kInitialSampledCapacity = @@ -1618,7 +1623,7 @@ NormalizeCapacity(n | SizeToCapacity(common.size())); // n == 0 unconditionally rehashes as per the standard. if (n == 0 || new_capacity > cap) { - if (cap == policy.soo_capacity) { + if (cap == policy.soo_capacity()) { if (common.empty()) { ResizeEmptyNonAllocatedTableImpl(common, policy, new_capacity, /*force_infoz=*/false); @@ -1640,7 +1645,7 @@ absl::FunctionRef<void(void*, const void*)> copy_fn) { const size_t size = other.size(); ABSL_SWISSTABLE_ASSERT(size > 0); - const size_t soo_capacity = policy.soo_capacity; + const size_t soo_capacity = policy.soo_capacity(); const size_t slot_size = policy.slot_size; if (size <= soo_capacity) { ABSL_SWISSTABLE_ASSERT(size == 1); @@ -1714,17 +1719,17 @@ const PolicyFunctions& policy, size_t new_size) { common.reset_reserved_growth(new_size); common.set_reservation_size(new_size); - ABSL_SWISSTABLE_ASSERT(new_size > policy.soo_capacity); + ABSL_SWISSTABLE_ASSERT(new_size > policy.soo_capacity()); const size_t cap = common.capacity(); - if (ABSL_PREDICT_TRUE(common.empty() && cap <= policy.soo_capacity)) { + if (ABSL_PREDICT_TRUE(common.empty() && cap <= policy.soo_capacity())) { return ReserveEmptyNonAllocatedTableToFitNewSize(common, policy, new_size); } - ABSL_SWISSTABLE_ASSERT(!common.empty() || cap > policy.soo_capacity); + ABSL_SWISSTABLE_ASSERT(!common.empty() || cap > policy.soo_capacity()); ABSL_SWISSTABLE_ASSERT(cap > 0); const size_t max_size_before_growth = - cap <= policy.soo_capacity ? policy.soo_capacity - : common.size() + common.growth_left(); + cap <= policy.soo_capacity() ? policy.soo_capacity() + : common.size() + common.growth_left(); if (new_size <= max_size_before_growth) { return; }
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h index f8c0731d..512c946 100644 --- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h +++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -514,6 +514,8 @@ // Sets the has_infoz bit. void set_has_infoz() { data_ |= kHasInfozMask; } + void set_no_seed_for_testing() { data_ &= ~kSeedMask; } + private: static constexpr size_t kSizeShift = 64 - kSizeBitCount; static constexpr uint64_t kSizeOneNoMetadata = uint64_t{1} << kSizeShift; @@ -1037,6 +1039,7 @@ // `kGenerateSeed && !empty() && !is_single_group(capacity())` because H1 is // being changed. In such cases, we will need to rehash the table. void generate_new_seed() { size_.generate_new_seed(); } + void set_no_seed_for_testing() { size_.set_no_seed_for_testing(); } // The total number of available slots. size_t capacity() const { return capacity_; } @@ -1637,7 +1640,7 @@ uint32_t value_size; uint32_t slot_size; uint16_t slot_align; - uint8_t soo_capacity; + bool soo_enabled; bool is_hashtablez_eligible; // Returns the pointer to the hash function stored in the set. @@ -1675,6 +1678,10 @@ void* probed_storage, void (*encode_probed_element)(void* probed_storage, h2_t h2, size_t source_offset, size_t h1)); + + uint8_t soo_capacity() const { + return static_cast<uint8_t>(soo_enabled ? SooCapacity() : 0); + } }; // Returns the maximum valid size for a table with 1-byte slots. @@ -3606,8 +3613,7 @@ static_cast<uint32_t>(sizeof(key_type)), static_cast<uint32_t>(sizeof(value_type)), static_cast<uint16_t>(sizeof(slot_type)), - static_cast<uint16_t>(alignof(slot_type)), - static_cast<uint8_t>(SooEnabled() ? SooCapacity() : 0), + static_cast<uint16_t>(alignof(slot_type)), SooEnabled(), ShouldSampleHashtablezInfoForAlloc<CharAlloc>(), // TODO(b/328722020): try to type erase // for standard layout and alignof(Hash) <= alignof(CommonFields).
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc index 404d1eb..9a323c41b 100644 --- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc +++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc
@@ -4238,9 +4238,8 @@ // artificially update growth info to force resize. absl::flat_hash_set<uint8_t, ConstUint8Hash> t(63, ConstUint8Hash{&hash}); CommonFields& common = RawHashSetTestOnlyAccess::GetCommon(t); - // Assign value to the seed, so that H1 is always 0. - // That helps to test all buffer overflows in GrowToNextCapacity. - hash = common.seed().seed() << 7; + // Set 0 seed so that H1 is always 0. + common.set_no_seed_for_testing(); ASSERT_EQ(H1(t.hash_function()(75), common.seed()), 0); uint8_t inserted_till = 210; for (uint8_t i = 0; i < inserted_till; ++i) {
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc index 25073f7..1746b5d4 100644 --- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc +++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -134,17 +134,13 @@ if ((reinterpret_cast<uintptr_t>(new_frame_pointer) & 7) != 0) return nullptr; - // Check that alleged frame pointer is actually readable. This is to - // prevent "double fault" in case we hit the first fault due to e.g. - // stack corruption. - if (!absl::debugging_internal::AddressIsReadable( - new_frame_pointer)) { - return nullptr; - } - + uintptr_t new_fp_comparable = reinterpret_cast<uintptr_t>(new_frame_pointer); // Only check the size if both frames are in the same stack. - if (InsideSignalStack(new_frame_pointer, stack_info) == - InsideSignalStack(old_frame_pointer, stack_info)) { + const bool old_inside_signal_stack = + InsideSignalStack(old_frame_pointer, stack_info); + const bool new_inside_signal_stack = + InsideSignalStack(new_frame_pointer, stack_info); + if (new_inside_signal_stack == old_inside_signal_stack) { // Check frame size. In strict mode, we assume frames to be under // 100,000 bytes. In non-strict mode, we relax the limit to 1MB. const size_t max_size = STRICT_UNWINDING ? 100000 : 1000000; @@ -158,16 +154,15 @@ if (frame_size > max_size) { size_t stack_low = stack_info->stack_low; size_t stack_high = stack_info->stack_high; - if (InsideSignalStack(new_frame_pointer, stack_info)) { + if (new_inside_signal_stack) { stack_low = stack_info->sig_stack_low; stack_high = stack_info->sig_stack_high; } if (stack_high < kUnknownStackEnd && static_cast<size_t>(getpagesize()) < stack_low) { - const uintptr_t new_fp_u = - reinterpret_cast<uintptr_t>(new_frame_pointer); // Stack bounds are known. - if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) { + if (!(stack_low < new_fp_comparable && + new_fp_comparable <= stack_high)) { // new_frame_pointer is not within a known stack. return nullptr; } @@ -177,8 +172,19 @@ } } } + // New frame pointer is valid if it is inside either known stack or readable. + // This assumes that everything within either known stack is readable. Outside + // either known stack but readable is unexpected, and possibly corrupt, but + // for now assume it is valid. If it isn't actually valid, the next frame will + // be corrupt and we will detect that next iteration. + if (new_inside_signal_stack || + (new_fp_comparable >= stack_info->stack_low && + new_fp_comparable < stack_info->stack_high) || + absl::debugging_internal::AddressIsReadable(new_frame_pointer)) { + return new_frame_pointer; + } - return new_frame_pointer; + return nullptr; } template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
diff --git a/third_party/abseil-cpp/absl/log/check.h b/third_party/abseil-cpp/absl/log/check.h index 50f633d..9e2219b 100644 --- a/third_party/abseil-cpp/absl/log/check.h +++ b/third_party/abseil-cpp/absl/log/check.h
@@ -42,7 +42,8 @@ // CHECK() // -// `CHECK` terminates the program with a fatal error if `condition` is not true. +// `CHECK` enforces that the `condition` is true. If the condition is false, +// the program is terminated with a fatal error. // // The message may include additional information such as stack traces, when // available.
diff --git a/third_party/abseil-cpp/absl/log/check_test_impl.inc b/third_party/abseil-cpp/absl/log/check_test_impl.inc index be58a3d..7a0000e 100644 --- a/third_party/abseil-cpp/absl/log/check_test_impl.inc +++ b/third_party/abseil-cpp/absl/log/check_test_impl.inc
@@ -39,6 +39,7 @@ namespace absl_log_internal { using ::testing::AllOf; +using ::testing::AnyOf; using ::testing::HasSubstr; using ::testing::Not; @@ -634,14 +635,12 @@ TEST(CHECKDeathTest, TestPointerPrintedAsNumberDespiteAbslStringify) { const auto* p = reinterpret_cast<const PointerIsStringifiable*>(0x1234); -#ifdef _MSC_VER EXPECT_DEATH( ABSL_TEST_CHECK_EQ(p, nullptr), - HasSubstr("Check failed: p == nullptr (0000000000001234 vs. (null))")); -#else // _MSC_VER - EXPECT_DEATH(ABSL_TEST_CHECK_EQ(p, nullptr), - HasSubstr("Check failed: p == nullptr (0x1234 vs. (null))")); -#endif // _MSC_VER + AnyOf( + HasSubstr("Check failed: p == nullptr (0000000000001234 vs. (null))"), + HasSubstr("Check failed: p == nullptr (0x1234 vs. (null))") + )); } // An uncopyable object with operator<<.
diff --git a/third_party/abseil-cpp/absl/strings/BUILD.bazel b/third_party/abseil-cpp/absl/strings/BUILD.bazel index 49562f7..bb152ac 100644 --- a/third_party/abseil-cpp/absl/strings/BUILD.bazel +++ b/third_party/abseil-cpp/absl/strings/BUILD.bazel
@@ -329,6 +329,7 @@ visibility = ["//visibility:private"], deps = [ ":internal", + ":string_view", "//absl/base:core_headers", "@googletest//:gtest", "@googletest//:gtest_main", @@ -1316,6 +1317,7 @@ linkopts = ABSL_DEFAULT_LINKOPTS, visibility = ["//visibility:private"], deps = [ + ":internal", ":strings", "//absl/base:config", "//absl/base:core_headers",
diff --git a/third_party/abseil-cpp/absl/strings/BUILD.gn b/third_party/abseil-cpp/absl/strings/BUILD.gn index dbc5f48..51c3e690 100644 --- a/third_party/abseil-cpp/absl/strings/BUILD.gn +++ b/third_party/abseil-cpp/absl/strings/BUILD.gn
@@ -138,6 +138,7 @@ ] visibility = [ ":*" ] deps = [ + ":internal", ":string_view", ":strings", "//third_party/abseil-cpp/absl/base:config",
diff --git a/third_party/abseil-cpp/absl/strings/CMakeLists.txt b/third_party/abseil-cpp/absl/strings/CMakeLists.txt index ee73860..547ef26 100644 --- a/third_party/abseil-cpp/absl/strings/CMakeLists.txt +++ b/third_party/abseil-cpp/absl/strings/CMakeLists.txt
@@ -243,6 +243,7 @@ COPTS ${ABSL_TEST_COPTS} DEPS + absl::string_view absl::strings_internal absl::base absl::core_headers @@ -518,6 +519,7 @@ absl::utility absl::int128 absl::span + absl::strings_internal ) absl_cc_test(
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc index eeb2108..103c85d1 100644 --- a/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc +++ b/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc
@@ -34,6 +34,7 @@ #include "absl/numeric/int128.h" #include "absl/strings/internal/str_format/extension.h" #include "absl/strings/internal/str_format/float_conversion.h" +#include "absl/strings/internal/utf8.h" #include "absl/strings/numbers.h" #include "absl/strings/string_view.h" @@ -311,68 +312,16 @@ conv.has_left_flag()); } -struct ShiftState { - bool saw_high_surrogate = false; - uint8_t bits = 0; -}; - -// Converts `v` from UTF-16 or UTF-32 to UTF-8 and writes to `buf`. `buf` is -// assumed to have enough space for the output. `s` is used to carry state -// between successive calls with a UTF-16 surrogate pair. Returns the number of -// chars written, or `static_cast<size_t>(-1)` on failure. -// -// This is basically std::wcrtomb(), but always outputting UTF-8 instead of -// respecting the current locale. -inline size_t WideToUtf8(wchar_t wc, char *buf, ShiftState &s) { - const auto v = static_cast<uint32_t>(wc); - if (v < 0x80) { - *buf = static_cast<char>(v); - return 1; - } else if (v < 0x800) { - *buf++ = static_cast<char>(0xc0 | (v >> 6)); - *buf = static_cast<char>(0x80 | (v & 0x3f)); - return 2; - } else if (v < 0xd800 || (v - 0xe000) < 0x2000) { - *buf++ = static_cast<char>(0xe0 | (v >> 12)); - *buf++ = static_cast<char>(0x80 | ((v >> 6) & 0x3f)); - *buf = static_cast<char>(0x80 | (v & 0x3f)); - return 3; - } else if ((v - 0x10000) < 0x100000) { - *buf++ = static_cast<char>(0xf0 | (v >> 18)); - *buf++ = static_cast<char>(0x80 | ((v >> 12) & 0x3f)); - *buf++ = static_cast<char>(0x80 | ((v >> 6) & 0x3f)); - *buf = static_cast<char>(0x80 | (v & 0x3f)); - return 4; - } else if (v < 0xdc00) { - s.saw_high_surrogate = true; - s.bits = static_cast<uint8_t>(v & 0x3); - const uint8_t high_bits = ((v >> 6) & 0xf) + 1; - *buf++ = static_cast<char>(0xf0 | (high_bits >> 2)); - *buf = - static_cast<char>(0x80 | static_cast<uint8_t>((high_bits & 0x3) << 4) | - static_cast<uint8_t>((v >> 2) & 0xf)); - return 2; - } else if (v < 0xe000 && s.saw_high_surrogate) { - *buf++ = static_cast<char>(0x80 | static_cast<uint8_t>(s.bits << 4) | - static_cast<uint8_t>((v >> 6) & 0xf)); - *buf = static_cast<char>(0x80 | (v & 0x3f)); - s.saw_high_surrogate = false; - s.bits = 0; - return 2; - } else { - return static_cast<size_t>(-1); - } -} - inline bool ConvertStringArg(const wchar_t *v, size_t len, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { FixedArray<char> mb(len * 4); - ShiftState s; + strings_internal::ShiftState s; size_t chars_written = 0; for (size_t i = 0; i < len; ++i) { - const size_t chars = WideToUtf8(v[i], &mb[chars_written], s); + const size_t chars = + strings_internal::WideToUtf8(v[i], &mb[chars_written], s); if (chars == static_cast<size_t>(-1)) { return false; } chars_written += chars; } @@ -382,8 +331,8 @@ bool ConvertWCharTImpl(wchar_t v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { char mb[4]; - ShiftState s; - const size_t chars_written = WideToUtf8(v, mb, s); + strings_internal::ShiftState s; + const size_t chars_written = strings_internal::WideToUtf8(v, mb, s); return chars_written != static_cast<size_t>(-1) && !s.saw_high_surrogate && ConvertStringArg(string_view(mb, chars_written), conv, sink); }
diff --git a/third_party/abseil-cpp/absl/strings/internal/utf8.cc b/third_party/abseil-cpp/absl/strings/internal/utf8.cc index 7ecb93d..4370c7c 100644 --- a/third_party/abseil-cpp/absl/strings/internal/utf8.cc +++ b/third_party/abseil-cpp/absl/strings/internal/utf8.cc
@@ -16,6 +16,11 @@ #include "absl/strings/internal/utf8.h" +#include <cstddef> +#include <cstdint> + +#include "absl/base/config.h" + namespace absl { ABSL_NAMESPACE_BEGIN namespace strings_internal { @@ -48,6 +53,47 @@ } } +size_t WideToUtf8(wchar_t wc, char *buf, ShiftState &s) { + const auto v = static_cast<uint32_t>(wc); + if (v < 0x80) { + *buf = static_cast<char>(v); + return 1; + } else if (v < 0x800) { + *buf++ = static_cast<char>(0xc0 | (v >> 6)); + *buf = static_cast<char>(0x80 | (v & 0x3f)); + return 2; + } else if (v < 0xd800 || (v - 0xe000) < 0x2000) { + *buf++ = static_cast<char>(0xe0 | (v >> 12)); + *buf++ = static_cast<char>(0x80 | ((v >> 6) & 0x3f)); + *buf = static_cast<char>(0x80 | (v & 0x3f)); + return 3; + } else if ((v - 0x10000) < 0x100000) { + *buf++ = static_cast<char>(0xf0 | (v >> 18)); + *buf++ = static_cast<char>(0x80 | ((v >> 12) & 0x3f)); + *buf++ = static_cast<char>(0x80 | ((v >> 6) & 0x3f)); + *buf = static_cast<char>(0x80 | (v & 0x3f)); + return 4; + } else if (v < 0xdc00) { + s.saw_high_surrogate = true; + s.bits = static_cast<uint8_t>(v & 0x3); + const uint8_t high_bits = ((v >> 6) & 0xf) + 1; + *buf++ = static_cast<char>(0xf0 | (high_bits >> 2)); + *buf = + static_cast<char>(0x80 | static_cast<uint8_t>((high_bits & 0x3) << 4) | + static_cast<uint8_t>((v >> 2) & 0xf)); + return 2; + } else if (v < 0xe000 && s.saw_high_surrogate) { + *buf++ = static_cast<char>(0x80 | static_cast<uint8_t>(s.bits << 4) | + static_cast<uint8_t>((v >> 6) & 0xf)); + *buf = static_cast<char>(0x80 | (v & 0x3f)); + s.saw_high_surrogate = false; + s.bits = 0; + return 2; + } else { + return static_cast<size_t>(-1); + } +} + } // namespace strings_internal ABSL_NAMESPACE_END } // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/utf8.h b/third_party/abseil-cpp/absl/strings/internal/utf8.h index 32fb109..f240408d 100644 --- a/third_party/abseil-cpp/absl/strings/internal/utf8.h +++ b/third_party/abseil-cpp/absl/strings/internal/utf8.h
@@ -43,6 +43,20 @@ enum { kMaxEncodedUTF8Size = 4 }; size_t EncodeUTF8Char(char *buffer, char32_t utf8_char); +struct ShiftState { + bool saw_high_surrogate = false; + uint8_t bits = 0; +}; + +// Converts `wc` from UTF-16 or UTF-32 to UTF-8 and writes to `buf`. `buf` is +// assumed to have enough space for the output. `s` is used to carry state +// between successive calls with a UTF-16 surrogate pair. Returns the number of +// chars written, or `static_cast<size_t>(-1)` on failure. +// +// This is basically std::wcrtomb(), but always outputting UTF-8 instead of +// respecting the current locale. +size_t WideToUtf8(wchar_t wc, char *buf, ShiftState &s); + } // namespace strings_internal ABSL_NAMESPACE_END } // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/utf8_test.cc b/third_party/abseil-cpp/absl/strings/internal/utf8_test.cc index 88dd5036..62322dd1 100644 --- a/third_party/abseil-cpp/absl/strings/internal/utf8_test.cc +++ b/third_party/abseil-cpp/absl/strings/internal/utf8_test.cc
@@ -14,14 +14,29 @@ #include "absl/strings/internal/utf8.h" +#include <cstddef> #include <cstdint> +#include <cstring> +#include <string> +#include <type_traits> #include <utility> +#include <vector> +#include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/port.h" +#include "absl/strings/string_view.h" namespace { +using ::absl::strings_internal::kMaxEncodedUTF8Size; +using ::absl::strings_internal::ShiftState; +using ::absl::strings_internal::WideToUtf8; +using ::testing::StartsWith; +using ::testing::TestParamInfo; +using ::testing::TestWithParam; +using ::testing::ValuesIn; + #if !defined(__cpp_char8_t) #if defined(__clang__) #pragma clang diagnostic push @@ -33,12 +48,12 @@ {0x00010000, u8"\U00010000"}, {0x0000FFFF, u8"\U0000FFFF"}, {0x0010FFFD, u8"\U0010FFFD"}}; - for (auto &test : tests) { + for (auto& test : tests) { char buf0[7] = {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'}; char buf1[7] = {'\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF'}; - char *buf0_written = + char* buf0_written = &buf0[absl::strings_internal::EncodeUTF8Char(buf0, test.first)]; - char *buf1_written = + char* buf1_written = &buf1[absl::strings_internal::EncodeUTF8Char(buf1, test.first)]; int apparent_length = 7; while (buf0[apparent_length - 1] == '\x00' && @@ -63,4 +78,169 @@ #endif #endif // !defined(__cpp_char8_t) +struct WideToUtf8TestCase { + std::string description; + wchar_t input; + std::string expected_utf8_str; + size_t expected_bytes_written; + ShiftState initial_state = {false, 0}; + ShiftState expected_state = {false, 0}; +}; + +std::vector<WideToUtf8TestCase> GetWideToUtf8TestCases() { + constexpr size_t kError = static_cast<size_t>(-1); + std::vector<WideToUtf8TestCase> cases = { + {"ASCII_A", L'A', "A", 1}, + {"NullChar", L'\0', std::string("\0", 1), 1}, + {"ASCII_Max_7F", L'\x7F', "\x7F", 1}, + + {"TwoByte_Min_80", L'\u0080', "\xC2\x80", 2}, + {"PoundSign_A3", L'\u00A3', "\xC2\xA3", 2}, + {"TwoByte_Max_7FF", L'\u07FF', "\xDF\xBF", 2}, + + {"ThreeByte_Min_800", L'\u0800', "\xE0\xA0\x80", 3}, + {"EuroSign_20AC", L'\u20AC', "\xE2\x82\xAC", 3}, + {"BMP_MaxBeforeSurrogates_D7FF", L'\uD7FF', "\xED\x9F\xBF", 3}, + {"BMP_FFFF", L'\uFFFF', "\xEF\xBF\xBF", 3}, + + {"IsolatedHighSurr_D800", L'\xD800', "\xF0\x90", 2, {true, 0}, {true, 0}}, + {"IsolatedHighSurr_DBFF", L'\xDBFF', "\xF4\x8F", 2, {true, 3}, {true, 3}}, + + {"LowSurr_DC00_after_HighD800", L'\xDC00', "\x80\x80", 2, {true, 0}, {}}, + {"LowSurr_DFFD_after_HighDBFF", L'\xDFFD', "\xBF\xBD", 2, {true, 3}, {}}, + {"LowSurr_DC00_with_InitialState_saw_high_bits_1", + L'\xDC00', + "\x90\x80", + 2, + {true, 1}, + {}}, + + // Final state = initial on error. + {"Error_IsolatedLowSurr_DC00_NoPriorHigh", L'\xDC00', "", kError, {}, {}}, + {"Error_IsolatedLowSurr_DFFF_NoPriorHigh", L'\xDFFF', "", kError, {}, {}}, + +#if (defined(WCHAR_MAX) && WCHAR_MAX > 0xFFFF) + {"DirectSupplementaryChars_U10000", static_cast<wchar_t>(0x10000), + "\xF0\x90\x80\x80", 4}, + {"DirectSupplementaryChars_U10FFFD", static_cast<wchar_t>(0x10FFFD), + "\xF4\x8F\xBF\xBD", 4}, +#endif + }; + + wchar_t minus_one = static_cast<wchar_t>(-1); + if constexpr (sizeof(wchar_t) == 2) { + cases.push_back({"WChar_MinusOne_as_FFFF", minus_one, "\xEF\xBF\xBF", 3}); + } else { + cases.push_back( + {"Error_WChar_MinusOne_as_FFFFFFFF", minus_one, "", kError, {}, {}}); + } + + if constexpr (sizeof(wchar_t) >= 4) { +#ifdef WCHAR_MAX + if (static_cast<uintmax_t>(WCHAR_MAX) >= 0x110000UL) { + cases.push_back({"Error_OutOfRange_110000", + static_cast<wchar_t>(0x110000UL), + "", + kError, + {}, + {}}); + } +#else + cases.push_back({"Error_OutOfRange_110000_fallback", + static_cast<wchar_t>(0x110000UL), + "", + kError, + {}, + {}}); +#endif + } + return cases; +} + +class WideToUtf8ParamTest : public TestWithParam<WideToUtf8TestCase> {}; + +TEST_P(WideToUtf8ParamTest, SingleCharConversion) { + const auto& test_case = GetParam(); + ShiftState state = test_case.initial_state; + constexpr char kFillChar = '\xAB'; + std::string buffer(32, kFillChar); + + size_t bytes_written = WideToUtf8(test_case.input, buffer.data(), state); + + EXPECT_EQ(bytes_written, test_case.expected_bytes_written); + EXPECT_THAT(buffer, StartsWith(test_case.expected_utf8_str)); + + // The remaining bytes should be unchanged. + ASSERT_LT(test_case.expected_utf8_str.length(), buffer.size()); + EXPECT_EQ(buffer[test_case.expected_utf8_str.length()], kFillChar); + + EXPECT_EQ(state.saw_high_surrogate, + test_case.expected_state.saw_high_surrogate); + EXPECT_EQ(state.bits, test_case.expected_state.bits); +} + +INSTANTIATE_TEST_SUITE_P(WideCharToUtf8Conversion, WideToUtf8ParamTest, + ValuesIn(GetWideToUtf8TestCases()), + [](auto info) { return info.param.description; }); + +// Comprehensive test string for validating wchar_t to UTF-8 conversion. +// This string is designed to cover a variety of Unicode character types and +// sequences: +// 1. Basic ASCII characters (within names, numbers, and spacing). +// 2. Common 2-byte UTF-8 sequences: +// - Accented Latin characters (e.g., 'á' in "Holá"). +// - Hebrew text with combining vowel points (e.g., "שָׁלוֹם"). +// 3. Common 3-byte UTF-8 sequences: +// - Currency symbols (e.g., '€'). +// - CJK characters (e.g., "你好", "中"). +// - Components of complex emojis like the Zero Width Joiner (ZWJ) and +// Heart symbol. +// 4. Various 4-byte UTF-8 sequences (representing Supplementary Plane +// characters): +// - An emoji with a skin tone modifier ("👍🏻"). +// - A flag emoji composed of regional indicators ("🇺🇸"). +// - A complex ZWJ emoji sequence ("👩❤️💋👨") combining +// SP characters (👩, 💋, 👨) with BMP characters (ZWJ and ❤️). +// - These are critical for testing the correct handling of surrogate pairs +// when wchar_t is 2 bytes (e.g., on Windows). +// The goal is to ensure accurate conversion across a diverse set of +// characters. +// +// clang-format off +#define WIDE_STRING_LITERAL L"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩❤️💋👨 中" +#define UTF8_STRING_LITERAL u8"Holá €1 你好 שָׁלוֹם 👍🏻🇺🇸👩❤️💋👨 中" +// clang-format on + +absl::string_view GetUtf8TestString() { + // `u8""` forces UTF-8 encoding; MSVC will default to e.g. CP1252 (and warn) + // without it. However, the resulting character type differs between pre-C++20 + // (`char`) and C++20 (`char8_t`). So deduce the right character type for all + // C++ versions, init it with UTF-8, then `memcpy()` to get the result as a + // `char*` + static absl::string_view kUtf8TestString = [] { + using ConstChar8T = std::remove_reference_t<decltype(*u8"a")>; + constexpr ConstChar8T kOutputUtf8[] = UTF8_STRING_LITERAL; + static char output[sizeof kOutputUtf8]; + std::memcpy(output, kOutputUtf8, sizeof kOutputUtf8); + return output; + }(); + + return kUtf8TestString; +} + +TEST(WideToUtf8, FullString) { + std::string buffer(kMaxEncodedUTF8Size * sizeof(WIDE_STRING_LITERAL), '\0'); + char* buffer_ptr = buffer.data(); + + ShiftState state; + for (const wchar_t wc : WIDE_STRING_LITERAL) { + buffer_ptr += WideToUtf8(wc, buffer_ptr, state); + } + + EXPECT_THAT(buffer, StartsWith(GetUtf8TestString())); +} + +#undef WIDE_STRING_LITERAL +#undef UTF8_STRING_LITERAL + } // namespace
diff --git a/third_party/abseil-cpp/symbols_arm64_dbg.def b/third_party/abseil-cpp/symbols_arm64_dbg.def index 6d2aa0d..14e46ace 100644 --- a/third_party/abseil-cpp/symbols_arm64_dbg.def +++ b/third_party/abseil-cpp/symbols_arm64_dbg.def
@@ -2072,6 +2072,7 @@ ??0ScopedEnable@SchedulingGuard@base_internal@absl@@QEAA@XZ ??0ScopedMinLogLevel@log_internal@absl@@QEAA@W4LogSeverityAtLeast@2@@Z ??0ScopedStderrThreshold@absl@@QEAA@W4LogSeverityAtLeast@1@@Z + ??0ShiftState@strings_internal@absl@@QEAA@XZ ??0SpinLock@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z ??0SpinLock@base_internal@absl@@QEAA@XZ ??0SpinLockHolder@base_internal@absl@@QEAA@PEAVSpinLock@12@@Z @@ -4290,6 +4291,7 @@ ?WebSafeBase64Escape@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@@Z ?WebSafeBase64Escape@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z ?WebSafeBase64Unescape@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z + ?WideToUtf8@strings_internal@absl@@YA_K_WPEADAEAUShiftState@12@@Z ?WithMetadataFrom@LogMessage@log_internal@absl@@QEAAAEAV123@AEBVLogEntry@3@@Z ?WithPerror@LogMessage@log_internal@absl@@QEAAAEAV123@XZ ?WithThreadID@LogMessage@log_internal@absl@@QEAAAEAV123@I@Z @@ -5388,6 +5390,7 @@ ?slot_array@HeapOrSoo@container_internal@absl@@QEBA?ATMaybeInitializedPtr@23@XZ ?slot_offset@RawHashSetLayout@container_internal@absl@@QEBA_KXZ ?slots_union@CommonFields@container_internal@absl@@QEBA?ATMaybeInitializedPtr@23@XZ + ?soo_capacity@PolicyFunctions@container_internal@absl@@QEBAEXZ ?soo_data@CommonFields@container_internal@absl@@QEAAPEAXXZ ?soo_data@CommonFields@container_internal@absl@@QEBAPEBXXZ ?soo_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAA?AViterator@123@XZ
diff --git a/third_party/abseil-cpp/symbols_arm64_rel.def b/third_party/abseil-cpp/symbols_arm64_rel.def index 47331ae7..c6ad2fa 100644 --- a/third_party/abseil-cpp/symbols_arm64_rel.def +++ b/third_party/abseil-cpp/symbols_arm64_rel.def
@@ -1270,6 +1270,7 @@ ?WebSafeBase64Escape@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@@Z ?WebSafeBase64Escape@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z ?WebSafeBase64Unescape@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z + ?WideToUtf8@strings_internal@absl@@YA_K_WPEADAEAUShiftState@12@@Z ?WithMetadataFrom@LogMessage@log_internal@absl@@QEAAAEAV123@AEBVLogEntry@3@@Z ?WithPerror@LogMessage@log_internal@absl@@QEAAAEAV123@XZ ?WithThreadID@LogMessage@log_internal@absl@@QEAAAEAV123@I@Z
diff --git a/third_party/abseil-cpp/symbols_x64_dbg.def b/third_party/abseil-cpp/symbols_x64_dbg.def index c863925..db9f1cc 100644 --- a/third_party/abseil-cpp/symbols_x64_dbg.def +++ b/third_party/abseil-cpp/symbols_x64_dbg.def
@@ -2074,6 +2074,7 @@ ??0ScopedEnable@SchedulingGuard@base_internal@absl@@QEAA@XZ ??0ScopedMinLogLevel@log_internal@absl@@QEAA@W4LogSeverityAtLeast@2@@Z ??0ScopedStderrThreshold@absl@@QEAA@W4LogSeverityAtLeast@1@@Z + ??0ShiftState@strings_internal@absl@@QEAA@XZ ??0SpinLock@base_internal@absl@@QEAA@W4SchedulingMode@12@@Z ??0SpinLock@base_internal@absl@@QEAA@XZ ??0SpinLockHolder@base_internal@absl@@QEAA@PEAVSpinLock@12@@Z @@ -4294,6 +4295,7 @@ ?WebSafeBase64Escape@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@@Z ?WebSafeBase64Escape@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z ?WebSafeBase64Unescape@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z + ?WideToUtf8@strings_internal@absl@@YA_K_WPEADAEAUShiftState@12@@Z ?WithMetadataFrom@LogMessage@log_internal@absl@@QEAAAEAV123@AEBVLogEntry@3@@Z ?WithPerror@LogMessage@log_internal@absl@@QEAAAEAV123@XZ ?WithThreadID@LogMessage@log_internal@absl@@QEAAAEAV123@I@Z @@ -5393,6 +5395,7 @@ ?slot_array@HeapOrSoo@container_internal@absl@@QEBA?ATMaybeInitializedPtr@23@XZ ?slot_offset@RawHashSetLayout@container_internal@absl@@QEBA_KXZ ?slots_union@CommonFields@container_internal@absl@@QEBA?ATMaybeInitializedPtr@23@XZ + ?soo_capacity@PolicyFunctions@container_internal@absl@@QEBAEXZ ?soo_data@CommonFields@container_internal@absl@@QEAAPEAXXZ ?soo_data@CommonFields@container_internal@absl@@QEBAPEBXXZ ?soo_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AEAA?AViterator@123@XZ
diff --git a/third_party/abseil-cpp/symbols_x64_rel.def b/third_party/abseil-cpp/symbols_x64_rel.def index 4e01aa9..05c9783c 100644 --- a/third_party/abseil-cpp/symbols_x64_rel.def +++ b/third_party/abseil-cpp/symbols_x64_rel.def
@@ -1270,6 +1270,7 @@ ?WebSafeBase64Escape@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@@Z ?WebSafeBase64Escape@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z ?WebSafeBase64Unescape@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z + ?WideToUtf8@strings_internal@absl@@YA_K_WPEADAEAUShiftState@12@@Z ?WithMetadataFrom@LogMessage@log_internal@absl@@QEAAAEAV123@AEBVLogEntry@3@@Z ?WithPerror@LogMessage@log_internal@absl@@QEAAAEAV123@XZ ?WithThreadID@LogMessage@log_internal@absl@@QEAAAEAV123@I@Z
diff --git a/third_party/abseil-cpp/symbols_x64_rel_asan.def b/third_party/abseil-cpp/symbols_x64_rel_asan.def index 00127bfc..456c01a 100644 --- a/third_party/abseil-cpp/symbols_x64_rel_asan.def +++ b/third_party/abseil-cpp/symbols_x64_rel_asan.def
@@ -1307,6 +1307,7 @@ ?WebSafeBase64Escape@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@@Z ?WebSafeBase64Escape@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z ?WebSafeBase64Unescape@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PEAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z + ?WideToUtf8@strings_internal@absl@@YA_K_WPEADAEAUShiftState@12@@Z ?WithMetadataFrom@LogMessage@log_internal@absl@@QEAAAEAV123@AEBVLogEntry@3@@Z ?WithPerror@LogMessage@log_internal@absl@@QEAAAEAV123@XZ ?WithThreadID@LogMessage@log_internal@absl@@QEAAAEAV123@I@Z
diff --git a/third_party/abseil-cpp/symbols_x86_dbg.def b/third_party/abseil-cpp/symbols_x86_dbg.def index 83347e5..3aa6864e 100644 --- a/third_party/abseil-cpp/symbols_x86_dbg.def +++ b/third_party/abseil-cpp/symbols_x86_dbg.def
@@ -2072,6 +2072,7 @@ ??0ScopedEnable@SchedulingGuard@base_internal@absl@@QAE@XZ ??0ScopedMinLogLevel@log_internal@absl@@QAE@W4LogSeverityAtLeast@2@@Z ??0ScopedStderrThreshold@absl@@QAE@W4LogSeverityAtLeast@1@@Z + ??0ShiftState@strings_internal@absl@@QAE@XZ ??0SpinLock@base_internal@absl@@QAE@W4SchedulingMode@12@@Z ??0SpinLock@base_internal@absl@@QAE@XZ ??0SpinLockHolder@base_internal@absl@@QAE@PAVSpinLock@12@@Z @@ -4292,6 +4293,7 @@ ?WebSafeBase64Escape@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@@Z ?WebSafeBase64Escape@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z ?WebSafeBase64Unescape@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z + ?WideToUtf8@strings_internal@absl@@YAI_WPADAAUShiftState@12@@Z ?WithMetadataFrom@LogMessage@log_internal@absl@@QAEAAV123@ABVLogEntry@3@@Z ?WithPerror@LogMessage@log_internal@absl@@QAEAAV123@XZ ?WithThreadID@LogMessage@log_internal@absl@@QAEAAV123@I@Z @@ -5391,6 +5393,7 @@ ?slot_array@HeapOrSoo@container_internal@absl@@QBE?ATMaybeInitializedPtr@23@XZ ?slot_offset@RawHashSetLayout@container_internal@absl@@QBEIXZ ?slots_union@CommonFields@container_internal@absl@@QBE?ATMaybeInitializedPtr@23@XZ + ?soo_capacity@PolicyFunctions@container_internal@absl@@QBEEXZ ?soo_data@CommonFields@container_internal@absl@@QAEPAXXZ ?soo_data@CommonFields@container_internal@absl@@QBEPBXXZ ?soo_iterator@?$raw_hash_set@U?$FlatHashMapPolicy@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@container_internal@absl@@UStringHash@23@UStringEq@23@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAVCommandLineFlag@absl@@@__Cr@std@@@__Cr@std@@@container_internal@absl@@AAE?AViterator@123@XZ
diff --git a/third_party/abseil-cpp/symbols_x86_rel.def b/third_party/abseil-cpp/symbols_x86_rel.def index f5a620f..bb4bb38 100644 --- a/third_party/abseil-cpp/symbols_x86_rel.def +++ b/third_party/abseil-cpp/symbols_x86_rel.def
@@ -1278,6 +1278,7 @@ ?WebSafeBase64Escape@absl@@YA?AV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@__Cr@std@@V?$basic_string_view@DU?$char_traits@D@__Cr@std@@@34@@Z ?WebSafeBase64Escape@absl@@YAXV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z ?WebSafeBase64Unescape@absl@@YA_NV?$basic_string_view@DU?$char_traits@D@__Cr@std@@@__Cr@std@@PAV?$basic_string@DU?$char_traits@D@__Cr@std@@V?$allocator@D@23@@34@@Z + ?WideToUtf8@strings_internal@absl@@YAI_WPADAAUShiftState@12@@Z ?WithMetadataFrom@LogMessage@log_internal@absl@@QAEAAV123@ABVLogEntry@3@@Z ?WithPerror@LogMessage@log_internal@absl@@QAEAAV123@XZ ?WithThreadID@LogMessage@log_internal@absl@@QAEAAV123@I@Z
diff --git a/third_party/angle b/third_party/angle index 1c7fa5f..8357b6a 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit 1c7fa5f847f236cc758f58838a9f5f958c1de0de +Subproject commit 8357b6a24cae20d24058cfef3277066c4993a1ae
diff --git a/third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom b/third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom index 07a2a64..fa5b976 100644 --- a/third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom +++ b/third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom
@@ -71,6 +71,11 @@ // See third_party/blink/renderer/core/lcp_critical_path_predictor/element_locator.proto array<mojo_base.mojom.ByteString> lcp_element_locators; + // `lcp_element_locators_all` has all type of elements where + // the types in `lcp_element_locators` depends + // kLCPCriticalPathPredictorRecordedLcpElementTypes flag. + array<mojo_base.mojom.ByteString> lcp_element_locators_all; + // Script URLs that influence LCP, learned from past loads. array<url.mojom.Url> lcp_influencer_scripts;
diff --git a/third_party/blink/public/mojom/quota/quota_types.mojom b/third_party/blink/public/mojom/quota/quota_types.mojom index d6a982e..dbe6011 100644 --- a/third_party/blink/public/mojom/quota/quota_types.mojom +++ b/third_party/blink/public/mojom/quota/quota_types.mojom
@@ -4,22 +4,6 @@ module blink.mojom; -// Values are persisted to disk. -// Do not renumber or delete existing values, to avoid data loss. -// Eventually `kTemporary` will be the only supported quota storage type, but -// since all enum values may have been persisted to disk, we cannot remove any -// enum values until all other values have been deprecated. -enum StorageType { - kTemporary = 0, - // TODO(https://crbug.com/1175113): Remove this type. - kDeprecatedPersistent = 1, - // TODO(https://crbug.com/1286964): Deprecate and remove this type. - kSyncable = 2, - // TODO(https://crbug.com/1095844): Remove this type. - kDeprecatedQuotaNotManaged = 3, - kUnknown = 4, -}; - // The durability policy to apply to a single StorageBucket. The values are // persisted to the quota DB and must not be changed. enum BucketDurability {
diff --git a/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom index 1b3e0e5..977d5580 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom
@@ -390,6 +390,7 @@ kWindowManagement = 332, kRequestclose = 333, kDRAFT_Uint8ArrayToFromBase64AndHex = 334, + kLineBreak = 335, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type.cc index cdc91738..0311b80cd 100644 --- a/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_dynamic_range_limit_interpolation_type.cc
@@ -63,6 +63,10 @@ ConversionCheckers& conversion_checkers) const { // TODO(crbug.com/40946458): Relative units should not be resolved here, but // that requires InterpolableDynamicRangeLimit to store calc-expressions. + // TODO(crbug.com/415626999): Create a TreeCountingChecker for sibling-index() + // and sibling-count() if necessary. + // TODO(crbug.com/415572412): Create a LengthUnitsChecker for relative units + // if necessary. return ConvertDynamicRangeLimit( StyleBuilderConverter::ConvertDynamicRangeLimit(state, value)); }
diff --git a/third_party/blink/renderer/core/animation/css_font_palette_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_font_palette_interpolation_type.cc index 543f6ee9..4316394 100644 --- a/third_party/blink/renderer/core/animation/css_font_palette_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_font_palette_interpolation_type.cc
@@ -71,6 +71,10 @@ ConversionCheckers& conversion_checkers) const { // TODO(40946458): Don't resolve anything here, rewrite to // interpolate unresolved palettes. + // TODO(crbug.com/415626999): Create a TreeCountingChecker for sibling-index() + // and sibling-count() if necessary. + // TODO(crbug.com/415572412): Create a LengthUnitsChecker for relative units + // if necessary. return ConvertFontPalette(StyleBuilderConverterBase::ConvertFontPalette( state.CssToLengthConversionData(), value)); }
diff --git a/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc index 0a9d491..84d8e145 100644 --- a/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_font_variation_settings_interpolation_type.cc
@@ -144,6 +144,10 @@ const CSSValue& value, const StyleResolverState& state, ConversionCheckers&) const { + // TODO(crbug.com/415626999): Create a TreeCountingChecker for sibling-index() + // and sibling-count() if necessary. + // TODO(crbug.com/415572412): Create a LengthUnitsChecker for relative units + // if necessary. scoped_refptr<FontVariationSettings> settings = StyleBuilderConverter::ConvertFontVariationSettings(state, value); return ConvertFontVariationSettings(settings.get());
diff --git a/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc index 34b7468..f57ccfe 100644 --- a/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_font_weight_interpolation_type.cc
@@ -75,6 +75,10 @@ } // TODO(40946458): Should do a proper interpolation here instead of converting // relative units first. + // TODO(crbug.com/415626999): Create a TreeCountingChecker for sibling-index() + // and sibling-count() if necessary. + // TODO(crbug.com/415572412): Create a LengthUnitsChecker for relative units + // if necessary. return CreateFontWeightValue(StyleBuilderConverterBase::ConvertFontWeight( state.CssToLengthConversionData(), value, inherited_font_weight)); }
diff --git a/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc index 3a6559a..68f1da7 100644 --- a/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_rotate_interpolation_type.cc
@@ -222,6 +222,10 @@ // TODO(crbug.com/328182246): we should not use the resolved angle // here, but doing it for now, since proper fix would require // rewriting Quaternion and Rotation to have unresolved versions. + // TODO(crbug.com/415626999): Create a TreeCountingChecker for sibling-index() + // and sibling-count() if necessary. + // TODO(crbug.com/415572412): Create a LengthUnitsChecker for relative units + // if necessary. return ConvertRotation( OptionalRotation(StyleBuilderConverter::ConvertRotation( CSSToLengthConversionData(&state.GetElement()), value)));
diff --git a/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc index a4ed5454..d24dfa7 100644 --- a/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_scale_interpolation_type.cc
@@ -25,6 +25,10 @@ const CSSValue& value, const CSSLengthResolver& length_resolver) { const auto& primitive_value = To<CSSPrimitiveValue>(value); + // TODO(crbug.com/415626999): Create a TreeCountingChecker for sibling-index() + // and sibling-count() if necessary. + // TODO(crbug.com/415572412): Create a LengthUnitsChecker for relative units + // if necessary. // TODO(crbug.com/41494232): Don't resolve it here, once we can divide units. // The problem now is when we end up with kNumber for neutral keyframe // and kPercentage for non-neutral keyframe, we have to sum number and
diff --git a/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc index 468d80f..9c4bff4a 100644 --- a/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc +++ b/third_party/blink/renderer/core/animation/css_transform_interpolation_type.cc
@@ -118,6 +118,8 @@ LengthUnitsChecker::MaybeCreate(types, state)) { conversion_checkers.push_back(length_units_checker); } + // TODO(crbug.com/415626999): Create a TreeCountingChecker for + // sibling-index() and sibling-count() if necessary. } return InterpolationValue(InterpolableTransformList::ConvertCSSValue(
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc index fe40a11d..52d347ab 100644 --- a/third_party/blink/renderer/core/css/css_image_value.cc +++ b/third_party/blink/renderer/core/css/css_image_value.cc
@@ -167,13 +167,6 @@ return UrlData().IsLocal(document); } -CSSImageValue* CSSImageValue::ComputedCSSValueMaybeLocal() const { - if (UrlData().UnresolvedUrl().StartsWith('#')) { - return Clone(); - } - return ComputedCSSValue(); -} - AtomicString CSSImageValue::NormalizedFragmentIdentifier() const { // Always use KURL's FragmentIdentifier to ensure that we're handling the // fragment in a consistent manner.
diff --git a/third_party/blink/renderer/core/css/css_image_value.h b/third_party/blink/renderer/core/css/css_image_value.h index 41fa958b..d2188598f 100644 --- a/third_party/blink/renderer/core/css/css_image_value.h +++ b/third_party/blink/renderer/core/css/css_image_value.h
@@ -68,10 +68,9 @@ bool Equals(const CSSImageValue&) const; CSSImageValue* ComputedCSSValue() const { - return MakeGarbageCollected<CSSImageValue>(*UrlData().MakeAbsolute(), + return MakeGarbageCollected<CSSImageValue>(*UrlData().MakeComputed(), cached_image_.Get()); } - CSSImageValue* ComputedCSSValueMaybeLocal() const; CSSImageValue* Clone() const { return MakeGarbageCollected<CSSImageValue>(*UrlData().MakeWithoutReferrer(),
diff --git a/third_party/blink/renderer/core/css/css_url_data.cc b/third_party/blink/renderer/core/css/css_url_data.cc index 573db63b..2efe98f 100644 --- a/third_party/blink/renderer/core/css/css_url_data.cc +++ b/third_party/blink/renderer/core/css/css_url_data.cc
@@ -35,9 +35,9 @@ : relative_url_(unresolved_url), absolute_url_(resolved_url.GetString()), referrer_(referrer), + is_local_(unresolved_url.StartsWith('#')), is_from_origin_clean_style_sheet_(is_from_origin_clean_style_sheet), is_ad_related_(is_ad_related), - is_local_(unresolved_url.StartsWith('#')), potentially_dangling_markup_(resolved_url.PotentiallyDanglingMarkup()) {} CSSUrlData::CSSUrlData(const AtomicString& resolved_url) @@ -82,8 +82,8 @@ return true; } -const CSSUrlData* CSSUrlData::MakeAbsolute() const { - if (relative_url_.empty()) { +const CSSUrlData* CSSUrlData::MakeComputed() const { + if (relative_url_.empty() || is_local_ || absolute_url_.empty()) { return this; } return MakeGarbageCollected<CSSUrlData>(
diff --git a/third_party/blink/renderer/core/css/css_url_data.h b/third_party/blink/renderer/core/css/css_url_data.h index f3a7ed5..db94c0b 100644 --- a/third_party/blink/renderer/core/css/css_url_data.h +++ b/third_party/blink/renderer/core/css/css_url_data.h
@@ -56,8 +56,8 @@ // Document. Returns true if the resolved URL changed, otherwise false. bool ReResolveUrl(const Document&) const; - // Returns an absolutized copy of this URL data (suitable for computed value). - const CSSUrlData* MakeAbsolute() const; + // Returns a copy of this URL data suitable for computed value. + const CSSUrlData* MakeComputed() const; // Returns a copy where the unresolved URL has been resolved against // `base_url` (using `charset` encoding if valid). @@ -101,6 +101,9 @@ mutable AtomicString absolute_url_; const Referrer referrer_; + // The 'local url flag': https://drafts.csswg.org/css-values/#local-urls + const bool is_local_; + // Whether the stylesheet that requested this image is origin-clean: // https://drafts.csswg.org/cssom-1/#concept-css-style-sheet-origin-clean-flag const bool is_from_origin_clean_style_sheet_; @@ -108,8 +111,6 @@ // Whether this was created by an ad-related CSSParserContext. const bool is_ad_related_; - const bool is_local_; - // The url passed into the constructor had the PotentiallyDanglingMarkup flag // set. That information needs to be passed on to the fetch code to block such // resources from loading.
diff --git a/third_party/blink/renderer/core/editing/build.gni b/third_party/blink/renderer/core/editing/build.gni index 0645e5e..aa7e993 100644 --- a/third_party/blink/renderer/core/editing/build.gni +++ b/third_party/blink/renderer/core/editing/build.gni
@@ -379,6 +379,7 @@ "commands/editing_command_test.cc", "commands/editing_commands_utilities_test.cc", "commands/insert_incremental_text_command_test.cc", + "commands/insert_line_break_command_test.cc", "commands/insert_list_command_test.cc", "commands/insert_paragraph_separator_command_test.cc", "commands/insert_text_command_test.cc",
diff --git a/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc b/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc index 3db63d2..7c202910 100644 --- a/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc +++ b/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
@@ -812,14 +812,10 @@ upstream_start_.AnchorNode()->IsDescendantOf( downstream_end_.AnchorNode()); - bool end_node_is_selected_from_first_position = false; - if (RuntimeEnabledFeatures:: - RemoveNodeHavingChildrenIfFullySelectedEnabled()) { - end_node_is_selected_from_first_position = - ComparePositions(upstream_start_, - Position::FirstPositionInNode( - *downstream_end_.AnchorNode())) <= 0; - } + bool end_node_is_selected_from_first_position = + ComparePositions( + upstream_start_, + Position::FirstPositionInNode(*downstream_end_.AnchorNode())) <= 0; // The selection to delete spans more than one node. Node* node(start_node); @@ -856,15 +852,12 @@ bool is_node_fully_selected = downstream_end_.AtLastEditingPositionForNode() && !CanHaveChildrenForEditing(downstream_end_.AnchorNode()); - if (RuntimeEnabledFeatures:: - RemoveNodeHavingChildrenIfFullySelectedEnabled()) { - // Even though `downstream_end_` has children, it can be fully selected. - // Update `is_node_fully_selected` if the selection includes the first - // position of the node. - if (!is_node_fully_selected && - downstream_end_.AtLastEditingPositionForNode()) { - is_node_fully_selected = end_node_is_selected_from_first_position; - } + // Even though `downstream_end_` has children, it can be fully selected. + // Update `is_node_fully_selected` if the selection includes the first + // position of the node. + if (!is_node_fully_selected && + downstream_end_.AtLastEditingPositionForNode()) { + is_node_fully_selected = end_node_is_selected_from_first_position; } if (is_node_fully_selected) { // The node itself is fully selected, not just its contents. Delete it. @@ -956,15 +949,12 @@ if (upstream_start_ == downstream_end_) return; - if (RuntimeEnabledFeatures:: - RemoveNodeHavingChildrenIfFullySelectedEnabled()) { - // It can be the same position even though `upstream_start_` and - // `downstream_end_` are not identical. - // Compare them using ParentAnchoredEquivalent(). - if (upstream_start_.ParentAnchoredEquivalent() == - downstream_end_.ParentAnchoredEquivalent()) { - return; - } + // It can be the same position even though `upstream_start_` and + // `downstream_end_` are not identical. + // Compare them using ParentAnchoredEquivalent(). + if (upstream_start_.ParentAnchoredEquivalent() == + downstream_end_.ParentAnchoredEquivalent()) { + return; } GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
diff --git a/third_party/blink/renderer/core/editing/commands/insert_line_break_command.cc b/third_party/blink/renderer/core/editing/commands/insert_line_break_command.cc index ba8d700..b08af54 100644 --- a/third_party/blink/renderer/core/editing/commands/insert_line_break_command.cc +++ b/third_party/blink/renderer/core/editing/commands/insert_line_break_command.cc
@@ -36,6 +36,7 @@ #include "third_party/blink/renderer/core/editing/visible_position.h" #include "third_party/blink/renderer/core/editing/visible_units.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h" #include "third_party/blink/renderer/core/html/forms/text_control_element.h" #include "third_party/blink/renderer/core/html/html_br_element.h" #include "third_party/blink/renderer/core/html/html_element.h" @@ -62,6 +63,10 @@ // the input element, and in that case we need to check the input element's // parent's layoutObject. Position p(insertion_pos.ParentAnchoredEquivalent()); + if (auto* text_control = EnclosingTextControl(p)) { + return RuntimeEnabledFeatures::TextareaLineEndingsAsBrEnabled() && + IsA<HTMLTextAreaElement>(text_control); + } return IsRichlyEditablePosition(p) && p.AnchorNode()->GetLayoutObject() && p.AnchorNode()->GetLayoutObject()->Style()->ShouldCollapseBreaks(); }
diff --git a/third_party/blink/renderer/core/editing/commands/insert_line_break_command.h b/third_party/blink/renderer/core/editing/commands/insert_line_break_command.h index 1488054..6491ca4 100644 --- a/third_party/blink/renderer/core/editing/commands/insert_line_break_command.h +++ b/third_party/blink/renderer/core/editing/commands/insert_line_break_command.h
@@ -26,11 +26,12 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_INSERT_LINE_BREAK_COMMAND_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_INSERT_LINE_BREAK_COMMAND_H_ +#include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/editing/commands/composite_edit_command.h" namespace blink { -class InsertLineBreakCommand final : public CompositeEditCommand { +class CORE_EXPORT InsertLineBreakCommand final : public CompositeEditCommand { public: explicit InsertLineBreakCommand(Document&);
diff --git a/third_party/blink/renderer/core/editing/commands/insert_line_break_command_test.cc b/third_party/blink/renderer/core/editing/commands/insert_line_break_command_test.cc new file mode 100644 index 0000000..e955b6e2 --- /dev/null +++ b/third_party/blink/renderer/core/editing/commands/insert_line_break_command_test.cc
@@ -0,0 +1,40 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/editing/commands/insert_line_break_command.h" + +#include "third_party/blink/renderer/core/editing/frame_selection.h" +#include "third_party/blink/renderer/core/editing/selection_template.h" +#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" +#include "third_party/blink/renderer/core/editing/visible_selection.h" +#include "third_party/blink/renderer/core/html/forms/text_control_element.h" + +namespace blink { + +class InsertLineBreakCommandTest : public EditingTestBase {}; + +TEST_F(InsertLineBreakCommandTest, InsertToTextArea) { + SetBodyContent("<textarea>foobar</textarea>"); + auto* field = To<TextControlElement>(QuerySelector("textarea")); + field->setSelectionEnd(3); + field->setSelectionStart(3); + field->Focus(); + + auto& command = *MakeGarbageCollected<InsertLineBreakCommand>(GetDocument()); + + EXPECT_TRUE(command.Apply()); + if (RuntimeEnabledFeatures::TextareaLineEndingsAsBrEnabled()) { + EXPECT_EQ( + "<textarea><div>foo<br>|bar</div></textarea>", + GetSelectionTextInFlatTreeFromBody( + Selection().ComputeVisibleSelectionInFlatTree().AsSelection())); + } else { + EXPECT_EQ( + "<textarea><div>foo\n|bar</div></textarea>", + GetSelectionTextInFlatTreeFromBody( + Selection().ComputeVisibleSelectionInFlatTree().AsSelection())); + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc b/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc index f65781dc..d2dc9be4 100644 --- a/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc +++ b/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
@@ -54,6 +54,7 @@ #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/forms/html_select_element.h" +#include "third_party/blink/renderer/core/html/forms/html_text_area_element.h" #include "third_party/blink/renderer/core/html/html_base_element.h" #include "third_party/blink/renderer/core/html/html_body_element.h" #include "third_party/blink/renderer/core/html/html_br_element.h" @@ -95,6 +96,8 @@ Node* FirstChild() const; Node* LastChild() const; + String TrivialReplacementText() const { return trivial_text_; } + bool IsEmpty() const; bool HasInterchangeNewlineAtStart() const { @@ -108,6 +111,8 @@ void RemoveNodePreservingChildren(ContainerNode*); private: + void UpdateFragmentForTextArea(); + void UpdateTrivialReplacementText(); HTMLElement* InsertFragmentForTestRendering(Element* root_editable_element); void RemoveUnrenderedNodes(ContainerNode*); void RestoreAndRemoveTestRenderingNodesToFragment(Element*); @@ -117,6 +122,7 @@ Document* document_; DocumentFragment* fragment_; + String trivial_text_; bool has_interchange_newline_at_start_; bool has_interchange_newline_at_end_; }; @@ -226,9 +232,14 @@ selection.ToNormalizedEphemeralRange(), event->GetText()); RemoveInterchangeNodes(fragment_); } + UpdateTrivialReplacementText(); + if (IsA<HTMLTextAreaElement>(EnclosingTextControl(editable_root))) { + UpdateFragmentForTextArea(); + } return; } } + UpdateTrivialReplacementText(); HTMLElement* holder = InsertFragmentForTestRendering(editable_root); if (!holder) { @@ -272,6 +283,52 @@ } } +void ReplacementFragment::UpdateFragmentForTextArea() { + if (!RuntimeEnabledFeatures::TextareaLineEndingsAsBrEnabled()) { + return; + } + DocumentFragment* new_fragment = nullptr; + Node* next = nullptr; + for (Node* node = fragment_->firstChild(); node; node = next) { + // We need to get nextSibling before moving `node`. + next = node->nextSibling(); + if (!node->IsTextNode()) { + if (new_fragment) { + new_fragment->AppendChild(node); + } + continue; + } + String value = node->textContent(); + if (value.find('\n') == kNotFound) { + if (new_fragment) { + new_fragment->AppendChild(node); + } + continue; + } + if (!new_fragment) { + new_fragment = document_->createDocumentFragment(); + Node* inner_next = nullptr; + for (Node* inner_node = fragment_->firstChild(); inner_node != node; + inner_node = inner_next) { + inner_next = inner_node->nextSibling(); + new_fragment->AppendChild(inner_node); + } + } + TextControlElement::AppendTextOrBr(value, *new_fragment); + } + if (new_fragment) { + fragment_ = new_fragment; + } +} + +void ReplacementFragment::UpdateTrivialReplacementText() { + if (!FirstChild() || FirstChild() != LastChild() || + !FirstChild()->IsTextNode()) { + return; + } + trivial_text_ = To<Text>(FirstChild())->data(); +} + bool ReplacementFragment::IsEmpty() const { return (!fragment_ || !fragment_->HasChildren()) && !has_interchange_newline_at_start_ && !has_interchange_newline_at_end_; @@ -2130,13 +2187,13 @@ bool ReplaceSelectionCommand::PerformTrivialReplace( const ReplacementFragment& fragment, EditingState* editing_state) { + // Save the text to set event data for input events. + input_event_data_ = fragment.TrivialReplacementText(); + if (!fragment.FirstChild() || fragment.FirstChild() != fragment.LastChild() || !fragment.FirstChild()->IsTextNode()) return false; - // Save the text to set event data for input events. - input_event_data_ = To<Text>(fragment.FirstChild())->data(); - // FIXME: Would be nice to handle smart replace in the fast path. if (smart_replace_ || fragment.HasInterchangeNewlineAtStart() || fragment.HasInterchangeNewlineAtEnd())
diff --git a/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc b/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc index 5f733e3..1bf7849 100644 --- a/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc +++ b/third_party/blink/renderer/core/editing/commands/replace_selection_command_test.cc
@@ -83,81 +83,6 @@ << "'bar' should have been inserted"; } -TEST_F(ReplaceSelectionCommandTest, - PasteNonEditableSpanInBetweenEditableAndNonEditable) { - Selection().SetSelection( - SetSelectionTextToBody( - "<div contenteditable=\"true\">Editable<span " - "contenteditable=\"false\">Non-Editable</span>|Editable</div>"), - SetSelectionOptions()); - - Element* span_element = QuerySelector("span"); - DocumentFragment* fragment = GetDocument().createDocumentFragment(); - fragment->ParseHTML("<span contenteditable=\"false\">ToPaste</span>", - span_element); - - ReplaceSelectionCommand::CommandOptions options = 0; - auto* command = MakeGarbageCollected<ReplaceSelectionCommand>( - GetDocument(), fragment, options); - - EXPECT_TRUE(command->Apply()) << "the replace command should have succeeded"; - String expected_string; - String assert_comment; - if (RuntimeEnabledFeatures:: - PartialCompletionNotAllowedInMoveParagraphsEnabled()) { - expected_string = - "<div contenteditable=\"true\">Editable<span " - "contenteditable=\"false\">Non-Editable</span><span " - "contenteditable=\"false\">ToPaste</span>Editable</div>"; - assert_comment = "span should have been inserted without losing any data"; - } else { - expected_string = - "<div contenteditable=\"true\">Editable<span " - "contenteditable=\"false\">Non-Editable</span><span " - "contenteditable=\"false\">ToPaste</span></div>"; - assert_comment = "span would be incorrectly inserted with data loss"; - } - EXPECT_EQ(expected_string, GetDocument().body()->innerHTML()) - << assert_comment; -} - -TEST_F(ReplaceSelectionCommandTest, PasteNonEditableSpanInEditableArea) { - Selection().SetSelection( - SetSelectionTextToBody( - "<div contenteditable=\"true\">Editable<span " - "contenteditable=\"false\">Non-Editable</span>Edit|able</div>"), - SetSelectionOptions()); - - Element* span_element = QuerySelector("span"); - DocumentFragment* fragment = GetDocument().createDocumentFragment(); - fragment->ParseHTML("<span contenteditable=\"false\">ToPaste</span>", - span_element); - - ReplaceSelectionCommand::CommandOptions options = 0; - auto* command = MakeGarbageCollected<ReplaceSelectionCommand>( - GetDocument(), fragment, options); - - EXPECT_TRUE(command->Apply()) << "the replace command should have succeeded"; - String expected_string; - String assert_comment; - if (RuntimeEnabledFeatures:: - PartialCompletionNotAllowedInMoveParagraphsEnabled()) { - expected_string = - "<div contenteditable=\"true\">Editable<span " - "contenteditable=\"false\">Non-Editable</span>Edit<span " - "contenteditable=\"false\">ToPaste</span>able</div>"; - assert_comment = "span should have been inserted without duplication"; - } else { - expected_string = - "<div contenteditable=\"true\">Editable<span " - "contenteditable=\"false\">Non-Editable</span>Edit<span " - "contenteditable=\"false\">ToPaste</span>ToPasteable</div>"; - assert_comment = "span would be incorrectly inserted with duplication"; - } - EXPECT_EQ(expected_string, GetDocument().body()->innerHTML()) - << assert_comment; -} - // Helper function to set autosizing multipliers on a document. bool SetTextAutosizingMultiplier(Document* document, float multiplier) { bool multiplier_set = false; @@ -365,4 +290,30 @@ "</div></strong>", GetSelectionTextFromBody()); } + +TEST_F(ReplaceSelectionCommandTest, InsertLineFeedsToTextArea) { + SetBodyContent("<textarea></textarea>"); + Element* field = QuerySelector("textarea"); + field->Focus(); + DocumentFragment& fragment = *GetDocument().createDocumentFragment(); + fragment.appendChild(Text::Create(GetDocument(), "\nfoo\n")); + + auto& command = *MakeGarbageCollected<ReplaceSelectionCommand>( + GetDocument(), &fragment, /* options */ 0, InputEvent::InputType::kNone); + + EXPECT_TRUE(command.Apply()); + if (RuntimeEnabledFeatures::TextareaLineEndingsAsBrEnabled()) { + EXPECT_EQ( + "<textarea><div><br>foo|<br>" + "<br id=\"textarea-placeholder-break\"></div></textarea>", + GetSelectionTextInFlatTreeFromBody( + Selection().ComputeVisibleSelectionInFlatTree().AsSelection())); + } else { + EXPECT_EQ( + "<textarea><div>\nfoo|\n<br></div></textarea>", + GetSelectionTextInFlatTreeFromBody( + Selection().ComputeVisibleSelectionInFlatTree().AsSelection())); + } +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/editing/visible_units_paragraph.cc b/third_party/blink/renderer/core/editing/visible_units_paragraph.cc index bf7bb7b..504d699d 100644 --- a/third_party/blink/renderer/core/editing/visible_units_paragraph.cc +++ b/third_party/blink/renderer/core/editing/visible_units_paragraph.cc
@@ -292,11 +292,6 @@ } } - // If start node is non-editable and we have our candidate same as start node - // return the last position in start node. - if (!start_node_is_editable && candidate_node == start_node) { - candidate_type = PositionAnchorType::kAfterAnchor; - } if (candidate_type == PositionAnchorType::kOffsetInAnchor) return PositionTemplate<Strategy>(candidate_node, candidate_offset);
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 dd0c441..61fd7ff4 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
@@ -3377,7 +3377,8 @@ return; } - lcpp->set_lcp_element_locators(hint->lcp_element_locators); + lcpp->set_lcp_element_locators(hint->lcp_element_locators, + hint->lcp_element_locators_all); HashSet<KURL> lcp_influencer_scripts; for (auto& url : hint->lcp_influencer_scripts) {
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc index e8c7506..b86614ad 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -70,6 +70,7 @@ #include "third_party/blink/renderer/core/html/forms/html_data_list_options_collection.h" #include "third_party/blink/renderer/core/html/forms/html_form_element.h" #include "third_party/blink/renderer/core/html/forms/html_option_element.h" +#include "third_party/blink/renderer/core/html/forms/html_select_element.h" #include "third_party/blink/renderer/core/html/forms/input_type.h" #include "third_party/blink/renderer/core/html/forms/radio_button_group_scope.h" #include "third_party/blink/renderer/core/html/forms/search_input_type.h" @@ -160,6 +161,7 @@ visitor->Trace(input_type_view_); visitor->Trace(list_attribute_target_observer_); visitor->Trace(image_loader_); + visitor->Trace(first_ancestor_select_); TextControlElement::Trace(visitor); } @@ -2474,4 +2476,19 @@ } } +bool HTMLInputElement::IsFirstTextInputInAncestorSelect() const { + if (!RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled() || + !first_ancestor_select_) { + return false; + } + return first_ancestor_select_->FirstDescendantTextInput() == this; +} + +HTMLSelectElement* HTMLInputElement::FirstAncestorSelectElement() const { + if (!RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + return nullptr; + } + return first_ancestor_select_; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.h b/third_party/blink/renderer/core/html/forms/html_input_element.h index cb03e1e8..9c3b0ce 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.h +++ b/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -383,6 +383,18 @@ void SetFocused(bool is_focused, mojom::blink::FocusType) override; + // These methods are used to determine what the nearest ancestor <select> + // element is and whether this is the first <input> in tree order within that + // <select>. These are populated lazily by the select element's + // MutationObserver and are not guaranteed to be correct all of the time + // since that MutationObserver only runs when the select element has base + // appearance. + bool IsFirstTextInputInAncestorSelect() const; + HTMLSelectElement* FirstAncestorSelectElement() const; + void SetFirstAncestorSelectElement(HTMLSelectElement* select) { + first_ancestor_select_ = select; + } + protected: void DefaultEventHandler(Event&) override; bool IsInnerEditorValueEmpty() const final; @@ -514,6 +526,7 @@ // element lives on. Member<HTMLImageLoader> image_loader_; Member<ListAttributeTargetObserver> list_attribute_target_observer_; + Member<HTMLSelectElement> first_ancestor_select_; FRIEND_TEST_ALL_PREFIXES(HTMLInputElementTest, RadioKeyDownDCHECKFailure); };
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.cc b/third_party/blink/renderer/core/html/forms/html_option_element.cc index 7445a9f..3aa6f80 100644 --- a/third_party/blink/renderer/core/html/forms/html_option_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_option_element.cc
@@ -730,6 +730,10 @@ if (key == keywords::kArrowUp) { if (auto* previous_option = options.PreviousFocusableOption(*this)) { previous_option->Focus(focus_params); + } else if (RuntimeEnabledFeatures:: + SelectAccessibilityReparentInputEnabled() && + select->FirstDescendantTextInput()) { + select->FirstDescendantTextInput()->Focus(focus_params); } event.SetDefaultHandled(); return;
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.h b/third_party/blink/renderer/core/html/forms/html_option_element.h index d85c610..1211ba8 100644 --- a/third_party/blink/renderer/core/html/forms/html_option_element.h +++ b/third_party/blink/renderer/core/html/forms/html_option_element.h
@@ -129,9 +129,10 @@ // an HTMLOptionElement. static bool IsLabelContainerElement(const Element& element); + bool IsKeyboardFocusableSlow(UpdateBehavior update_behavior) const override; + private: FocusableState SupportsFocus(UpdateBehavior update_behavior) const override; - bool IsKeyboardFocusableSlow(UpdateBehavior update_behavior) const override; bool MatchesDefaultPseudoClass() const override; bool MatchesEnabledPseudoClass() const override; void ParseAttribute(const AttributeModificationParams&) override;
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.cc b/third_party/blink/renderer/core/html/forms/html_select_element.cc index fbcd3a2..4ffde71d 100644 --- a/third_party/blink/renderer/core/html/forms/html_select_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -130,11 +130,25 @@ if (record->type() == "childList") { CheckAddedNodes(record); CheckRemovedNodes(record); - } else if ((record->type() == "attributes") && - (record->attributeName() == html_names::kTabindexAttr || - record->attributeName() == - html_names::kContenteditableAttr)) { - AddDescendantDisallowedErrorToNode(*record->target()); + } else if (record->type() == "attributes") { + if (record->attributeName() == html_names::kTabindexAttr || + record->attributeName() == html_names::kContenteditableAttr) { + AddDescendantDisallowedErrorToNode(*record->target()); + } else if (RuntimeEnabledFeatures:: + SelectAccessibilityReparentInputEnabled() && + record->attributeName() == html_names::kTypeAttr) { + if (auto* input = DynamicTo<HTMLInputElement>(record->target())) { + if (input->IsTextField()) { + select_->AddDescendantTextInput(input); + } else { + select_->RemoveDescendantTextInput(input); + // If the type attribute was changed in a way that makes the + // <input> no longer an allowed descendant, then we should emit an + // error. + AddDescendantDisallowedErrorToNode(*input); + } + } + } } } } @@ -157,6 +171,7 @@ if (IsWhitespaceOrEmpty(*descendant)) { continue; } + MaybeAddDescendantTextInput(descendant); AddDescendantDisallowedErrorToNode(*descendant); // Check the added node's descendants, if any. TraverseNodeDescendants(descendant); @@ -173,6 +188,7 @@ if (IsWhitespaceOrEmpty(*descendant)) { continue; } + MaybeRemoveDescendantTextInput(descendant); if (!IsAllowedInteractiveElement(*descendant)) { select_->DecreaseContentModelViolationCount(); } @@ -180,6 +196,7 @@ for (Node* nested_descendant = NodeTraversal::FirstWithin(*descendant); nested_descendant; nested_descendant = NodeTraversal::Next( *nested_descendant, descendant)) { + MaybeRemoveDescendantTextInput(descendant); if (!IsWhitespaceOrEmpty(*nested_descendant) && !IsAllowedInteractiveElement(*nested_descendant)) { select_->DecreaseContentModelViolationCount(); @@ -192,11 +209,30 @@ for (Node* descendant = NodeTraversal::FirstWithin(*node); descendant; descendant = NodeTraversal::Next(*descendant, node)) { if (!IsWhitespaceOrEmpty(*descendant)) { + MaybeAddDescendantTextInput(descendant); AddDescendantDisallowedErrorToNode(*descendant); } } } + void MaybeAddDescendantTextInput(Node* node) { + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + if (auto* input = DynamicTo<HTMLInputElement>(node); + input && input->IsTextField()) { + select_->AddDescendantTextInput(input); + } + } + } + + void MaybeRemoveDescendantTextInput(Node* node) { + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + if (auto* input = DynamicTo<HTMLInputElement>(node); + input && input->IsTextField()) { + select_->RemoveDescendantTextInput(input); + } + } + } + void AddDescendantDisallowedErrorToNode(Node& node) { SelectElementAccessibilityIssueReason issue_reason = CheckForIssue(node); if (issue_reason != SelectElementAccessibilityIssueReason::kValidChild) { @@ -282,7 +318,7 @@ "navigating by keyboard or using assistive technology."; } - bool IsAllowedInteractiveElement(const Node& node) { + bool IsAllowedInteractiveElement(Node& node) { if (IsA<HTMLButtonElement>(node)) { // The <button> must have a parent (not being inserted as a child of // `HTMLSelectedContentElement`) and must be the first child of the @@ -291,6 +327,20 @@ return parent && IsA<HTMLSelectElement>(*parent) && !ElementTraversal::PreviousSibling(node); } + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + // <select>s are allowed to have one <input> before the options. We should + // probably find a way to figure out if the <input> is actually placed + // before the <option>s or not. + + if (auto* input = DynamicTo<HTMLInputElement>(node)) { + if (input->IsTextField()) { + select_->AddDescendantTextInput(input); + } + if (input == select_->FirstDescendantTextInput()) { + return true; + } + } + } // If the node isn't a <button> but it is an interactive element, we return // false as interactive elements are disallowed. return !IsInteractiveElement(node); @@ -399,6 +449,13 @@ } bool IsAllowedDescendantOfSelect(const Node& descendant, const Node& parent) { + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + // <select>s are allowed to have one text <input>, although it should be + // placed before any of the <option>s. + if (select_->FirstDescendantTextInput() == descendant) { + return true; + } + } // <button> has to be the first direct descendant of the <select>. return (IsA<HTMLButtonElement>(descendant) && IsA<HTMLSelectElement>(parent) && @@ -1876,6 +1933,7 @@ visitor->Trace(last_on_change_option_); visitor->Trace(suggested_option_); visitor->Trace(descendant_selectedcontents_); + visitor->Trace(descendant_text_inputs_); visitor->Trace(select_type_); visitor->Trace(descendants_observer_); HTMLFormControlElementWithState::Trace(visitor); @@ -2297,6 +2355,31 @@ } } +void HTMLSelectElement::AddDescendantTextInput(HTMLInputElement* input) { + CHECK(RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()); + CHECK(input->IsTextField()); + descendant_text_inputs_.Add(input); + input->SetFirstAncestorSelectElement(this); +} + +void HTMLSelectElement::RemoveDescendantTextInput(HTMLInputElement* input) { + CHECK(RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()); + descendant_text_inputs_.Remove(input); + input->SetFirstAncestorSelectElement(nullptr); +} + +HTMLInputElement* HTMLSelectElement::FirstDescendantTextInput() const { + if (descendant_text_inputs_.IsEmpty()) { + return nullptr; + } + HTMLInputElement* first_input = *descendant_text_inputs_.begin(); + if (!first_input->isConnected() || !first_input->IsTextField() || + Traversal<HTMLSelectElement>::FirstAncestor(*first_input) != this) { + return nullptr; + } + return first_input; +} + HTMLSelectElement::SelectAutofillPreviewElement* HTMLSelectElement::GetAutofillPreviewElement() const { return select_type_->GetAutofillPreviewElement();
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.h b/third_party/blink/renderer/core/html/forms/html_select_element.h index adf2175..3ab56757 100644 --- a/third_party/blink/renderer/core/html/forms/html_select_element.h +++ b/third_party/blink/renderer/core/html/forms/html_select_element.h
@@ -33,6 +33,7 @@ #include "third_party/blink/renderer/core/dom/events/simulated_click_options.h" #include "third_party/blink/renderer/core/dom/tree_ordered_list.h" #include "third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.h" +#include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/forms/html_selected_content_element.h" #include "third_party/blink/renderer/core/html/forms/option_list.h" #include "third_party/blink/renderer/core/html/forms/type_ahead.h" @@ -317,6 +318,13 @@ void SelectedContentElementRemoved( HTMLSelectedContentElement* selectedcontent); + // These methods are used to track all descendant <input>s elements of this + // <select>. This is only used for customizable select and is populated by + // this select's MutationObserver. + void AddDescendantTextInput(HTMLInputElement* input); + void RemoveDescendantTextInput(HTMLInputElement* input); + HTMLInputElement* FirstDescendantTextInput() const; + // This will only return an element if IsAppearanceBase(). The element // is a popover inside the UA shadowroot which is used to show the user a // preview of what is going to be autofilled. This should only be called if @@ -434,6 +442,7 @@ Member<HTMLOptionElement> last_on_change_option_; Member<HTMLOptionElement> suggested_option_; TreeOrderedList<HTMLSelectedContentElement> descendant_selectedcontents_; + TreeOrderedList<HTMLInputElement> descendant_text_inputs_; bool uses_menu_list_ = true; bool is_multiple_; mutable bool should_recalc_list_items_;
diff --git a/third_party/blink/renderer/core/html/forms/option_list.cc b/third_party/blink/renderer/core/html/forms/option_list.cc index 153467d4..76fdd36f 100644 --- a/third_party/blink/renderer/core/html/forms/option_list.cc +++ b/third_party/blink/renderer/core/html/forms/option_list.cc
@@ -171,4 +171,17 @@ } } +HTMLOptionElement* OptionList::FirstKeyboardFocusableOption() { + if (Empty()) { + return nullptr; + } + for (OptionListIterator it = begin(); it; ++it) { + if (it->IsKeyboardFocusableSlow( + Element::UpdateBehavior::kAssertNoLayoutUpdates)) { + return &*it; + } + } + return nullptr; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/forms/option_list.h b/third_party/blink/renderer/core/html/forms/option_list.h index 7684a4d..ae42194 100644 --- a/third_party/blink/renderer/core/html/forms/option_list.h +++ b/third_party/blink/renderer/core/html/forms/option_list.h
@@ -100,6 +100,11 @@ return FindFocusableOption(option, /*forward*/ false, inclusive); } + // This method calls IsKeyboardFocusableSlow with + // Element::UpdateBehavior::kAssertNoLayoutUpdates on each option until it + // finds a focusable one, then returns it. + HTMLOptionElement* FirstKeyboardFocusableOption(); + private: HTMLOptionElement* FindFocusableOption(HTMLOptionElement& option, bool forward,
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 5b8c7ef4c..f81577523 100644 --- a/third_party/blink/renderer/core/html/forms/select_type.cc +++ b/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -148,17 +148,26 @@ control->Focus(FocusParams(FocusTrigger::kScript)); } } else { - HTMLOptionElement* option_to_focus = select->SelectedOption(); - if (!option_to_focus || !option_to_focus->IsFocusable()) { - for (auto& option : select->GetOptionList()) { - if (option.IsFocusable()) { - option_to_focus = &option; - break; + HTMLElement* element_to_focus = nullptr; + if (auto* input = select->FirstDescendantTextInput(); + input && + RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + // If there is a filter input at the top of the picker, then that + // should be focused instead of options when opening. + element_to_focus = input; + } else { + element_to_focus = select->SelectedOption(); + if (!element_to_focus || !element_to_focus->IsFocusable()) { + for (auto& option : select->GetOptionList()) { + if (option.IsFocusable()) { + element_to_focus = &option; + break; + } } } } - if (option_to_focus) { - option_to_focus->Focus(FocusParams(FocusTrigger::kScript)); + if (element_to_focus) { + element_to_focus->Focus(FocusParams(FocusTrigger::kScript)); } } if (AXObjectCache* cache =
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.cc b/third_party/blink/renderer/core/html/forms/text_control_element.cc index 3da7c098..0a82b714 100644 --- a/third_party/blink/renderer/core/html/forms/text_control_element.cc +++ b/third_party/blink/renderer/core/html/forms/text_control_element.cc
@@ -928,25 +928,7 @@ } else { inner_editor->RemoveChildren(); // For <textarea>, \n is replaced with <br>. - wtf_size_t start = 0; - wtf_size_t i = 0; - while (start < value.length()) { - i = value.find('\n', start); - if (i == WTF::kNotFound) { - inner_editor->AppendChild( - Text::Create(GetDocument(), value.Substring(start))); - break; - } - if (start != i) { - // Append [start, i). - inner_editor->AppendChild( - Text::Create(GetDocument(), value.Substring(start, i - start))); - } - // Append a BR. - inner_editor->AppendChild( - MakeGarbageCollected<HTMLBRElement>(GetDocument())); - start = i + 1; - } + AppendTextOrBr(value, *inner_editor); } // Add a placeholder <br> so that we can put the caret at the next line of @@ -959,6 +941,27 @@ } } +void TextControlElement::AppendTextOrBr(const String& value, + ContainerNode& container) { + Document& doc = container.GetDocument(); + wtf_size_t start = 0; + while (start < value.length()) { + wtf_size_t i = value.find('\n', start); + if (i == WTF::kNotFound) { + container.AppendChild(Text::Create(doc, value.Substring(start))); + break; + } + if (start != i) { + // Append [start, i). + container.AppendChild( + Text::Create(doc, value.Substring(start, i - start))); + } + // Append a BR. + container.AppendChild(MakeGarbageCollected<HTMLBRElement>(doc)); + start = i + 1; + } +} + String TextControlElement::InnerEditorValue() const { DCHECK(!OpenShadowRoot()); HTMLElement* inner_editor = InnerEditorElement();
diff --git a/third_party/blink/renderer/core/html/forms/text_control_element.h b/third_party/blink/renderer/core/html/forms/text_control_element.h index 89b4899e..e8c18e4 100644 --- a/third_party/blink/renderer/core/html/forms/text_control_element.h +++ b/third_party/blink/renderer/core/html/forms/text_control_element.h
@@ -145,6 +145,7 @@ bool LastChangeWasUserEdit() const; virtual void SetInnerEditorValue(const String&); + static void AppendTextOrBr(const String& value, ContainerNode& container); String InnerEditorValue() const; Node* CreatePlaceholderBreakElement() const; // Returns true if the specified node was created by
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc index d495897..d63317b 100644 --- a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -43,6 +43,8 @@ #include "third_party/blink/renderer/core/events/text_event.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" +#include "third_party/blink/renderer/core/html/forms/html_option_element.h" +#include "third_party/blink/renderer/core/html/forms/html_select_element.h" #include "third_party/blink/renderer/core/html/forms/text_control_inner_elements.h" #include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h" #include "third_party/blink/renderer/core/html_names.h" @@ -216,6 +218,20 @@ void TextFieldInputType::HandleKeydownEvent(KeyboardEvent& event) { if (!GetElement().IsFocused()) return; + + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + if (auto* select = GetElement().FirstAncestorSelectElement()) { + if (AtomicString(event.key()) == keywords::kArrowDown) { + if (auto* option = + select->GetOptionList().FirstKeyboardFocusableOption()) { + option->Focus(); + event.SetDefaultHandled(); + return; + } + } + } + } + if (ChromeClient* chrome_client = GetChromeClient()) { chrome_client->HandleKeyboardEventOnTextField(GetElement(), event); return;
diff --git a/third_party/blink/renderer/core/html/html_link_element.cc b/third_party/blink/renderer/core/html/html_link_element.cc index 1e63ed3..a9c094f 100644 --- a/third_party/blink/renderer/core/html/html_link_element.cc +++ b/third_party/blink/renderer/core/html/html_link_element.cc
@@ -28,6 +28,7 @@ #include <utility> #include "base/numerics/safe_conversions.h" +#include "base/trace_event/typed_macros.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_icon_sizes_parser.h" #include "third_party/blink/public/platform/web_prescient_networking.h" @@ -102,6 +103,20 @@ UseCounter::Count(&GetDocument(), WebFeature::kLinkRelFacilitatedPayment); MaybeHandlePaymentLink(); } + if (rel_attribute_.IsPreconnect()) { + TRACE_EVENT_INSTANT( + TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "LinkPreconnect", + "data", [&](perfetto::TracedValue context) { + auto dict = std::move(context).WriteDictionary(); + if (GetDocument().GetFrame()) { + dict.Add("frame", + GetDocument().GetFrame()->GetFrameIdForTracing()); + } + dict.Add("node_id", GetDomNodeId()); + const KURL& url = GetNonEmptyURLAttribute(html_names::kHrefAttr); + dict.Add("url", url.GetString()); + }); + } rel_list_->DidUpdateAttributeValue(params.old_value, value); Process(); } else if (name == html_names::kBlockingAttr) {
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 bcd2440..4186808 100644 --- a/third_party/blink/renderer/core/layout/block_break_token.cc +++ b/third_party/blink/renderer/core/layout/block_break_token.cc
@@ -8,6 +8,7 @@ #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" @@ -146,7 +147,8 @@ string_builder.Append(ConsumedBlockSize().ToString()); string_builder.Append("px"); - if (ConsumedBlockSizeForLegacy() != ConsumedBlockSize()) { + if (!RuntimeEnabledFeatures::LayoutBoxVisualLocationEnabled() && + ConsumedBlockSizeForLegacy() != ConsumedBlockSize()) { string_builder.Append(" legacy consumed:"); string_builder.Append(ConsumedBlockSizeForLegacy().ToString()); string_builder.Append("px");
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 edb4cd0..5ab3639 100644 --- a/third_party/blink/renderer/core/layout/block_break_token.h +++ b/third_party/blink/renderer/core/layout/block_break_token.h
@@ -11,6 +11,7 @@ #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" @@ -87,6 +88,7 @@ // 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
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 73da82dc..f203201 100644 --- a/third_party/blink/renderer/core/layout/box_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/box_fragment_builder.h
@@ -29,6 +29,7 @@ #include "third_party/blink/renderer/core/layout/table/table_borders.h" #include "third_party/blink/renderer/core/layout/table/table_fragment_data.h" #include "third_party/blink/renderer/core/style/computed_style_constants.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" @@ -425,6 +426,7 @@ // 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; }
diff --git a/third_party/blink/renderer/core/layout/fragment_builder.h b/third_party/blink/renderer/core/layout/fragment_builder.h index 30951d46..1bd8fb5 100644 --- a/third_party/blink/renderer/core/layout/fragment_builder.h +++ b/third_party/blink/renderer/core/layout/fragment_builder.h
@@ -37,6 +37,7 @@ public: ~FragmentBuilder() { // Clear collections so the backing gets promptly freed, and reused. + children_.clear(); oof_positioned_candidates_.clear(); oof_positioned_fragmentainer_descendants_.clear(); oof_positioned_descendants_.clear();
diff --git a/third_party/blink/renderer/core/layout/fragmentation_utils.cc b/third_party/blink/renderer/core/layout/fragmentation_utils.cc index d94eaa98..b2ee945 100644 --- a/third_party/blink/renderer/core/layout/fragmentation_utils.cc +++ b/third_party/blink/renderer/core/layout/fragmentation_utils.cc
@@ -844,22 +844,25 @@ consumed_block_size += fragmentainer_capacity; builder->SetConsumedBlockSize(consumed_block_size); - // 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 (!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.
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index d294664..a739462 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -3865,7 +3865,7 @@ } else { DCHECK(previous_break_token); size.block_size = fragment_logical_size.block_size + - previous_break_token->ConsumedBlockSizeForLegacy(); + previous_break_token->ConsumedBlockSize(); } previous_break_token = physical_fragment.GetBreakToken(); // Continue in order to update logical height, unless this fragment is
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 8d2a462..d90a4b4 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
@@ -3112,27 +3112,21 @@ void OutOfFlowLayoutPart::SaveStaticPositionOnPaintLayer( LayoutBox* layout_box, - const LogicalStaticPosition& position) const { + LogicalStaticPosition position) const { const LayoutObject* parent = GetLayoutObjectForParentNode<const LayoutObject*>(layout_box); const LayoutObject* container = container_builder_->GetLayoutObject(); if (parent == container || (parent->IsLayoutInline() && parent->ContainingBlock() == container)) { DCHECK(layout_box->Layer()); - layout_box->Layer()->SetStaticPositionFromNG( - ToStaticPositionForLegacy(position)); + if (const auto* break_token = container_builder_->PreviousBreakToken()) { + // Include the block contribution from previous columns. + position.offset.block_offset += break_token->ConsumedBlockSize(); + } + layout_box->Layer()->SetStaticPositionFromNG(position); } } -LogicalStaticPosition OutOfFlowLayoutPart::ToStaticPositionForLegacy( - LogicalStaticPosition position) const { - // Legacy expects the static position to include the block contribution from - // previous columns. - if (const auto* break_token = container_builder_->PreviousBreakToken()) - position.offset.block_offset += break_token->ConsumedBlockSizeForLegacy(); - return position; -} - const PhysicalBoxFragment& OutOfFlowLayoutPart::GetChildFragment( wtf_size_t index) const { const LogicalFragmentLink& link = FragmentationContextChildren()[index];
diff --git a/third_party/blink/renderer/core/layout/out_of_flow_layout_part.h b/third_party/blink/renderer/core/layout/out_of_flow_layout_part.h index 8f92acc..c7869f4 100644 --- a/third_party/blink/renderer/core/layout/out_of_flow_layout_part.h +++ b/third_party/blink/renderer/core/layout/out_of_flow_layout_part.h
@@ -406,11 +406,8 @@ // This saves the static-position for an OOF-positioned object into its // paint-layer. - void SaveStaticPositionOnPaintLayer( - LayoutBox* layout_box, - const LogicalStaticPosition& position) const; - LogicalStaticPosition ToStaticPositionForLegacy( - LogicalStaticPosition position) const; + void SaveStaticPositionOnPaintLayer(LayoutBox* layout_box, + LogicalStaticPosition position) const; const FragmentBuilder::ChildrenVector& FragmentationContextChildren() const { DCHECK(container_builder_->IsBlockFragmentationContextRoot());
diff --git a/third_party/blink/renderer/core/layout/physical_box_fragment.cc b/third_party/blink/renderer/core/layout/physical_box_fragment.cc index 8a3f38f2..413576d0 100644 --- a/third_party/blink/renderer/core/layout/physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/physical_box_fragment.cc
@@ -347,10 +347,10 @@ DCHECK(layout_object_->IsBoxModelObject()); DCHECK(!builder->break_token_ || builder->break_token_->IsBlockType()); - children_.ReserveInitialCapacity(builder->children_.size()); - PhysicalSize size = Size(); const WritingModeConverter converter( - {block_or_line_writing_mode, builder->Direction()}, size); + {block_or_line_writing_mode, builder->Direction()}, Size()); + + children_.ReserveInitialCapacity(builder->children_.size()); for (auto& child : builder->children_) { children_.emplace_back( std::move(child.fragment),
diff --git a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc index be44281..bec2811 100644 --- a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc +++ b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.cc
@@ -58,7 +58,8 @@ } void LCPCriticalPathPredictor::set_lcp_element_locators( - const std::vector<std::string>& lcp_element_locator_strings) { + const std::vector<std::string>& lcp_element_locator_strings, + const std::vector<std::string>& lcp_element_locator_all_strings) { // Clear current set of locators before receiving replacements. lcp_element_locators_.clear(); lcp_element_locator_strings_.clear(); @@ -80,6 +81,21 @@ } } CHECK_EQ(lcp_element_locators_.size(), lcp_element_locator_strings_.size()); + + lcp_element_locator_all_strings_.clear(); + lcp_element_locator_all_strings_.reserve( + base::checked_cast<wtf_size_t>(lcp_element_locator_all_strings.size())); + for (const std::string& serialized_locator : + lcp_element_locator_all_strings) { + bool result = ElementLocator().ParseFromString(serialized_locator); + if (!result) { + // This can happen when the host LCPP database is corrupted or we + // updated the ElementLocator schema in an incompatible way. + LOG(INFO) << "Ignoring an invalid lcp_element_locator hint."; + } else { + lcp_element_locator_all_strings_.push_back(std::move(serialized_locator)); + } + } } void LCPCriticalPathPredictor::set_lcp_influencer_scripts( @@ -183,7 +199,7 @@ // set_lcp_element_locators(lcp_element_locator_strings). // See PredictLcpElementLocators() for the contents detail. const wtf_size_t predicted_lcp_index = - lcp_element_locator_strings_.Find(lcp_element_locator_string); + lcp_element_locator_all_strings_.Find(lcp_element_locator_string); if (predicted_lcp_index != kNotFound) { MayRunPredictedCallbacks(&lcp_element); } @@ -363,7 +379,7 @@ is_outermost_main_frame_document_loaded_ = true; // Call callbacks as fallback because we can not detect // which is lcp in the lcps before onload. - if (has_lcp_occurred_ || lcp_element_locators_.empty()) { + if (has_lcp_occurred_ || lcp_element_locator_all_strings_.empty()) { MayRunPredictedCallbacks(nullptr); } }
diff --git a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.h b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.h index 759ac49..9a3a313 100644 --- a/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.h +++ b/third_party/blink/renderer/core/lcp_critical_path_predictor/lcp_critical_path_predictor.h
@@ -43,7 +43,8 @@ bool HasAnyHintData() const; void set_lcp_element_locators( - const std::vector<std::string>& lcp_element_locator_strings); + const std::vector<std::string>& lcp_element_locator_strings, + const std::vector<std::string>& lcp_element_locator_all_strings); const Vector<ElementLocator>& lcp_element_locators() { return lcp_element_locators_; @@ -102,6 +103,7 @@ Vector<ElementLocator> lcp_element_locators_; Vector<std::string> lcp_element_locator_strings_; + Vector<std::string> lcp_element_locator_all_strings_; HashSet<KURL> lcp_influencer_scripts_; Vector<KURL> fetched_fonts_; Vector<url::Origin> preconnected_origins_;
diff --git a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc index a293858..7cca0ca 100644 --- a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc +++ b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
@@ -547,10 +547,6 @@ return base::FeatureList::IsEnabled(features::kSoftNavigationDetection); } - if (trial_name == "FoldableAPIs") { - return base::FeatureList::IsEnabled(features::kViewportSegments); - } - if (trial_name == "PermissionElement") { return base::FeatureList::IsEnabled(blink::features::kPermissionElement); }
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.cc b/third_party/blink/renderer/core/style/style_fetched_image.cc index 4c26612..d35ebd8 100644 --- a/third_party/blink/renderer/core/style/style_fetched_image.cc +++ b/third_party/blink/renderer/core/style/style_fetched_image.cc
@@ -95,7 +95,7 @@ CSSValue* StyleFetchedImage::CssValue() const { return MakeGarbageCollected<CSSImageValue>( - *url_data_->MakeAbsolute(), const_cast<StyleFetchedImage*>(this)); + *url_data_->MakeComputed(), const_cast<StyleFetchedImage*>(this)); } CSSValue* StyleFetchedImage::ComputedCSSValue(const ComputedStyle&,
diff --git a/third_party/blink/renderer/core/style/style_mask_source_image.cc b/third_party/blink/renderer/core/style/style_mask_source_image.cc index 4eabef3..ae73f17e 100644 --- a/third_party/blink/renderer/core/style/style_mask_source_image.cc +++ b/third_party/blink/renderer/core/style/style_mask_source_image.cc
@@ -36,7 +36,7 @@ const ComputedStyle& style, bool allow_visited_style, CSSValuePhase value_phase) const { - return resource_css_value_->ComputedCSSValueMaybeLocal(); + return resource_css_value_->ComputedCSSValue(); } bool StyleMaskSourceImage::CanRender() const {
diff --git a/third_party/blink/renderer/core/svg/svg_transform_list.cc b/third_party/blink/renderer/core/svg/svg_transform_list.cc index cac2c009..61d34ba 100644 --- a/third_party/blink/renderer/core/svg/svg_transform_list.cc +++ b/third_party/blink/renderer/core/svg/svg_transform_list.cc
@@ -324,21 +324,27 @@ return SVGTransformType::kUnknown; if (*ptr == 's') { - if (SkipToken(ptr, end, "skewX")) + if (UNSAFE_TODO(SkipToken(ptr, end, "skewX"))) { return SVGTransformType::kSkewx; - if (SkipToken(ptr, end, "skewY")) + } + if (UNSAFE_TODO(SkipToken(ptr, end, "skewY"))) { return SVGTransformType::kSkewy; - if (SkipToken(ptr, end, "scale")) + } + if (UNSAFE_TODO(SkipToken(ptr, end, "scale"))) { return SVGTransformType::kScale; + } return SVGTransformType::kUnknown; } - if (SkipToken(ptr, end, "translate")) + if (UNSAFE_TODO(SkipToken(ptr, end, "translate"))) { return SVGTransformType::kTranslate; - if (SkipToken(ptr, end, "rotate")) + } + if (UNSAFE_TODO(SkipToken(ptr, end, "rotate"))) { return SVGTransformType::kRotate; - if (SkipToken(ptr, end, "matrix")) + } + if (UNSAFE_TODO(SkipToken(ptr, end, "matrix"))) { return SVGTransformType::kMatrix; + } return SVGTransformType::kUnknown; }
diff --git a/third_party/blink/renderer/core/svg/svg_view_spec.cc b/third_party/blink/renderer/core/svg/svg_view_spec.cc index b1ecf8b..42779d708 100644 --- a/third_party/blink/renderer/core/svg/svg_view_spec.cc +++ b/third_party/blink/renderer/core/svg/svg_view_spec.cc
@@ -94,22 +94,27 @@ DCHECK_LT(ptr, end); switch (*ptr) { case 'v': - if (SkipToken(ptr, end, "viewBox")) + if (UNSAFE_TODO(SkipToken(ptr, end, "viewBox"))) { return kViewBox; - if (SkipToken(ptr, end, "viewTarget")) + } + if (UNSAFE_TODO(SkipToken(ptr, end, "viewTarget"))) { return kViewTarget; + } break; case 'z': - if (SkipToken(ptr, end, "zoomAndPan")) + if (UNSAFE_TODO(SkipToken(ptr, end, "zoomAndPan"))) { return kZoomAndPan; + } break; case 'p': - if (SkipToken(ptr, end, "preserveAspectRatio")) + if (UNSAFE_TODO(SkipToken(ptr, end, "preserveAspectRatio"))) { return kPreserveAspectRatio; + } break; case 't': - if (SkipToken(ptr, end, "transform")) + if (UNSAFE_TODO(SkipToken(ptr, end, "transform"))) { return kTransform; + } break; } return kUnknown; @@ -121,8 +126,9 @@ bool SVGViewSpec::ParseViewSpecInternal(base::span<const CharType> chars) { const CharType* ptr = chars.data(); const CharType* end = UNSAFE_TODO(ptr + chars.size()); - if (!SkipToken(ptr, end, "svgView")) + if (!UNSAFE_TODO(SkipToken(ptr, end, "svgView"))) { return false; + } size_t position = ptr - chars.data(); if (!SkipExactly<CharType>(chars, '(', position)) { @@ -158,7 +164,7 @@ } case kViewTarget: { // Ignore arguments. - SkipUntil<CharType>(ptr, end, ')'); + UNSAFE_TODO(SkipUntil<CharType>(ptr, end, ')')); break; } case kZoomAndPan:
diff --git a/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc b/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc index 8449ab8..b65147d 100644 --- a/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc +++ b/third_party/blink/renderer/core/svg/svg_zoom_and_pan.cc
@@ -49,10 +49,12 @@ template <typename CharType> static SVGZoomAndPanType ParseZoomAndPanInternal(const CharType*& start, const CharType* end) { - if (SkipToken(start, end, "disable")) + if (UNSAFE_TODO(SkipToken(start, end, "disable"))) { return kSVGZoomAndPanDisable; - if (SkipToken(start, end, "magnify")) + } + if (UNSAFE_TODO(SkipToken(start, end, "magnify"))) { return kSVGZoomAndPanMagnify; + } return kSVGZoomAndPanUnknown; }
diff --git a/third_party/blink/renderer/core/url_pattern/url_pattern_component.cc b/third_party/blink/renderer/core/url_pattern/url_pattern_component.cc index 0c2a89f..9263273 100644 --- a/third_party/blink/renderer/core/url_pattern/url_pattern_component.cc +++ b/third_party/blink/renderer/core/url_pattern/url_pattern_component.cc
@@ -8,6 +8,7 @@ #include <string_view> #include "base/metrics/histogram_functions.h" +#include "base/notreached.h" #include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" #include "components/url_pattern/url_pattern_util.h" @@ -47,9 +48,12 @@ } // Utility method to get the correct encoding callback for a given type. -liburlpattern::EncodeCallback GetEncodeCallback(std::string_view pattern_utf8, - Component::Type type, - Component* protocol_component) { +// `should_treat_as_standard_url` is used if and only if `type` equals +// `kPathname`. +liburlpattern::EncodeCallback GetEncodeCallback( + std::string_view pattern_utf8, + Component::Type type, + std::optional<bool> should_treat_as_standard_url) { switch (type) { case Component::Type::kProtocol: return ::url_pattern::ProtocolEncodeCallback; @@ -73,26 +77,16 @@ // // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state // - // We prefer "standard" URL here by checking to see if the protocol - // pattern matches any of the known standard protocol strings. So - // an exact pattern of `http` will match, but so will `http{s}?` and - // `*`. - // - // If the protocol pattern does not match any of the known standard URL - // protocols then we fall back to the "path" URL behavior. This will - // normally be triggered by `data`, `javascript`, `about`, etc. It - // will also be triggered for custom protocol strings. We favor "path" - // behavior here because its better to under canonicalize since the - // developer can always manually canonicalize the pathname for a custom - // protocol. - // - // ShouldTreatAsStandardURL can by a bit expensive, so only do it if we - // actually have a pathname pattern to compile. - CHECK(protocol_component); - if (protocol_component->ShouldTreatAsStandardURL()) + // In "path" URL cases, we fall back to the opaque pathname behavior. We + // favor this behavior here because it is better to canonicalize less + // since developers can always manually canonicalize inputs for, e.g., + // their custom protocols. + CHECK(should_treat_as_standard_url.has_value()); + if (*should_treat_as_standard_url) { return ::url_pattern::StandardURLPathnameEncodeCallback; - else + } else { return ::url_pattern::PathURLPathnameEncodeCallback; + } case Component::Type::kSearch: return ::url_pattern::SearchEncodeCallback; case Component::Type::kHash: @@ -102,10 +96,11 @@ } // Utility method to get the correct liburlpattern parse options for a given -// type. +// type. `should_treat_as_standard_url` is used if and only if `type` equals +// `kPathname`. const liburlpattern::Options GetOptions( Component::Type type, - Component* protocol_component, + std::optional<bool> should_treat_as_standard_url, const URLPatternOptions& external_options) { using liburlpattern::Options; @@ -126,10 +121,10 @@ // Just like how we select a different encoding callback based on // whether we are treating the pattern string as a standard or // cannot-be-a-base URL, we must also choose the right liburlppatern - // options as well. We should only use use the options that treat - // `/` specially if we are treating this a standard URL. - DCHECK(protocol_component); - if (protocol_component->ShouldTreatAsStandardURL()) { + // options as well. We should only use the options that treat "/" specially + // if we are treating this a standard URL. + CHECK(should_treat_as_standard_url.has_value()); + if (*should_treat_as_standard_url) { // Pathname patterns for "standard" URLs use a "/" delimiter controlling // how far a named group like ":bar" will match. They also use "/" as an // automatic prefix before groups. @@ -188,18 +183,24 @@ Component* protocol_component, const URLPatternOptions& external_options, ExceptionState& exception_state) { - StringView final_pattern = pattern.IsNull() ? "*" : pattern; + std::optional<bool> should_treat_as_standard_url = + protocol_component + ? std::optional(protocol_component->ShouldTreatAsStandardURL()) + : std::nullopt; const liburlpattern::Options& options = - GetOptions(type, protocol_component, external_options); + GetOptions(type, should_treat_as_standard_url, external_options); + StringView final_pattern = pattern.IsNull() ? "*" : pattern; // Parse the pattern. // Lossy UTF8 conversion is fine given the input has come through a // USVString webidl argument. StringUTF8Adaptor utf8(final_pattern); - auto parse_result = liburlpattern::Parse( - utf8.AsStringView(), - GetEncodeCallback(utf8.AsStringView(), type, protocol_component), - options); + + auto parse_result = + liburlpattern::Parse(utf8.AsStringView(), + GetEncodeCallback(utf8.AsStringView(), type, + should_treat_as_standard_url), + options); if (!parse_result.has_value()) { exception_state.ThrowTypeError( "Invalid " + TypeToString(type) + " pattern '" + final_pattern + "'. " +
diff --git a/third_party/blink/renderer/core/url_pattern/url_pattern_component.h b/third_party/blink/renderer/core/url_pattern/url_pattern_component.h index e27382e1..350bef5 100644 --- a/third_party/blink/renderer/core/url_pattern/url_pattern_component.h +++ b/third_party/blink/renderer/core/url_pattern/url_pattern_component.h
@@ -84,7 +84,14 @@ // Method to determine if the URL associated with this component should be // treated as a "standard" URL like `https://foo` vs a "path" URL like - // `data:foo`. This should only be called for kProtocol components. + // `data:foo`. This should only be called for `kProtocol` components. + // + // This function checks if the protocol pattern matches any of the known + // standard protocol strings. So an exact pattern of `http` will match, but + // so will `http{s}?` and `*`. Typical non-standard protocols are `data`, + // `javascript`, `about`, and any other custom protocol strings. The + // computation cost of this function may be a bit expensive for the first + // call, but the result is cached once computed. bool ShouldTreatAsStandardURL() const; // Returns if this component has at least one part that uses an ECMAScript
diff --git a/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc b/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc index f6b6eb5f..b2fa6947 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc +++ b/third_party/blink/renderer/core/workers/shared_worker_reporting_proxy.cc
@@ -38,8 +38,8 @@ std::unique_ptr<SourceLocation>, int exception_id) { DCHECK(!IsMainThread()); - // TODO(nhiroki): Implement the "runtime script errors" algorithm in the HTML - // spec: + // TODO(crbug.com/412384494): Implement the "runtime script errors" algorithm + // in the HTML spec: // "For shared workers, if the error is still not handled afterwards, the // error may be reported to a developer console." // https://html.spec.whatwg.org/C/#runtime-script-errors-2
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 6889692..75c13500 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -555,6 +555,17 @@ node->IsScrollButtonPseudoElement()) { return true; } + + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + // The first descendant <input> in a <select> gets taken out of the listbox + // because it is not an <option>. It controls the listbox. + if (auto* input = DynamicTo<HTMLInputElement>(node)) { + if (input->IsFirstTextInputInAncestorSelect()) { + return true; + } + } + } + return false; } @@ -4448,6 +4459,22 @@ } AXObject* AXNodeObject::ChooserPopup() const { + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + // The first input inside of a select filters the listbox, and therefore + // controls it. + if (auto* input = DynamicTo<HTMLInputElement>(GetNode())) { + if (input->IsTextField()) { + if (auto* select = input->FirstAncestorSelectElement()) { + if (auto* popover = select->PopoverForAppearanceBase()) { + if (auto* axobject = AXObjectCache().Get(popover)) { + return axobject; + } + } + } + } + } + } + // When color & date chooser popups are visible, they can be found in the tree // as a group child of the <input> control itself. switch (native_role_) { @@ -5926,6 +5953,19 @@ } } +void AXNodeObject::AddSelectChildren() { + auto* select = DynamicTo<HTMLSelectElement>(GetNode()); + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled() && + select) { + if (auto* input = select->FirstDescendantTextInput()) { + // Reparent the first descendant <input> element of this <select> to be + // adjacent to the listbox in the a11y tree. + AddNodeChild(input); + } + } + AddNodeChildren(); +} + void AXNodeObject::AddOwnedChildren() { AXObjectVector owned_children; AXObjectCache().ValidatedAriaOwnedChildren(this, owned_children); @@ -5975,7 +6015,9 @@ AddValidationMessageChild(); CHECK_ATTACHED(); - if (HasValidHTMLTableStructureAndLayout()) { + if (IsA<HTMLSelectElement>(GetNode())) { + AddSelectChildren(); + } else if (HasValidHTMLTableStructureAndLayout()) { AddTableChildren(); } else if (GetNode() && GetNode()->IsScrollMarkerGroupPseudoElement()) { AddScrollMarkerGroupChildren();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h index c836238..da30c91 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -416,6 +416,7 @@ void AddPopupChildren(); bool HasValidHTMLTableStructureAndLayout() const; void AddTableChildren(); + void AddSelectChildren(); bool FindAllTableCellsWithRole(ax::mojom::blink::Role, AXObjectVector&) const; void AddValidationMessageChild(); void AddAccessibleNodeChildren();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index d844143..3fe2f18 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -1008,6 +1008,18 @@ : nullptr; } + if (RuntimeEnabledFeatures::SelectAccessibilityReparentInputEnabled()) { + if (auto* input = DynamicTo<HTMLInputElement>(node)) { + if (auto* select = input->FirstAncestorSelectElement()) { + if (input->IsFirstTextInputInAncestorSelect() && input->IsTextField()) { + // The first descendant <input> in a <select> is reparented to be a + // direct child of the <select> in the a11y tree. + return select; + } + } + } + } + return CanComputeAsNaturalParent(parent) ? parent : nullptr; }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc index 4f63a2c..73efa1a 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
@@ -294,7 +294,9 @@ << "\n* Child: " << child << "\n* Actual parent: " << parent << "\n* Natural ax parent: " << object_cache_->Get(natural_parent) << "\n* Natural dom parent: " << natural_parent << " #" - << natural_parent->GetDomNodeId() << "\n* Owners to update:"; + << natural_parent->GetDomNodeId() + << "\n* parent->GetNode(): " << parent->GetNode() + << "\n* Owners to update:"; for (AXID id : owner_axids_to_update_) { msg << " " << id; }
diff --git a/third_party/blink/renderer/modules/ai/language_model.cc b/third_party/blink/renderer/modules/ai/language_model.cc index a4ee52d..edae9ec 100644 --- a/third_party/blink/renderer/modules/ai/language_model.cc +++ b/third_party/blink/renderer/modules/ai/language_model.cc
@@ -532,67 +532,32 @@ const V8LanguageModelPromptInput* input, const LanguageModelPromptOptions* options, ExceptionState& exception_state) { - if (!script_state->ContextIsValid()) { - ThrowInvalidContextException(exception_state); - return ScriptPromise<IDLString>(); + std::optional<ValidateAndProcessPromptInputResult> processed_input = + ValidateAndProcessPromptInput(script_state, input, options, + exception_state); + if (!processed_input.has_value()) { + return EmptyPromise(); } + base::UmaHistogramEnumeration(AIMetrics::GetAIAPIUsageMetricName( + AIMetrics::AISessionType::kLanguageModel), + AIMetrics::AIAPI::kSessionPrompt); ScriptPromiseResolver<IDLString>* resolver = MakeGarbageCollected<ScriptPromiseResolver<IDLString>>(script_state); auto promise = resolver->Promise(); - // The API impl only accepts a string by default for now, more to come soon! - if (!input->IsString() && - !RuntimeEnabledFeatures::AIPromptAPIMultimodalInputEnabled()) { - resolver->RejectWithTypeError("Input type not supported"); - return promise; - } - - auto prompts = BuildPrompts(input, script_state, exception_state, - GetExecutionContext(), input_types_); - if (!prompts.has_value()) { - return promise; - } - - base::UmaHistogramEnumeration(AIMetrics::GetAIAPIUsageMetricName( - AIMetrics::AISessionType::kLanguageModel), - AIMetrics::AIAPI::kSessionPrompt); - - // TODO(crbug.com/411470034): Aggregate other input type sizes for UMA. - if (input->IsString()) { - base::UmaHistogramCounts1M( - AIMetrics::GetAISessionRequestSizeMetricName( - AIMetrics::AISessionType::kLanguageModel), - int(input->GetAsString().CharactersSizeInBytes())); - } - - if (!language_model_remote_) { - ThrowSessionDestroyedException(exception_state); - return promise; - } - - AbortSignal* signal = options->getSignalOr(nullptr); - if (signal && signal->aborted()) { - resolver->Reject(signal->reason(script_state)); - return promise; - } - - on_device_model::mojom::blink::ResponseConstraintPtr constraint; - if (!ParseConstraint(script_state, options, exception_state, constraint)) { - // ParseConstraint will throw an exception when false is returned. - return promise; - } - auto pending_remote = CreateModelExecutionResponder( - script_state, signal, resolver, task_runner_, + script_state, options->getSignalOr(nullptr), resolver, task_runner_, AIMetrics::AISessionType::kLanguageModel, WTF::BindOnce(&LanguageModel::OnResponseComplete, WrapWeakPersistent(this)), WTF::BindRepeating(&LanguageModel::OnQuotaOverflow, WrapWeakPersistent(this))); - language_model_remote_->Prompt(std::move(prompts).value(), - std::move(constraint), - std::move(pending_remote)); + + language_model_remote_->Prompt( + std::move(processed_input->processed_prompts), + std::move(processed_input->processed_constraint), + std::move(pending_remote)); return promise; } @@ -601,65 +566,82 @@ const V8LanguageModelPromptInput* input, const LanguageModelPromptOptions* options, ExceptionState& exception_state) { - if (!script_state->ContextIsValid()) { - ThrowInvalidContextException(exception_state); + std::optional<ValidateAndProcessPromptInputResult> processed_input = + ValidateAndProcessPromptInput(script_state, input, options, + exception_state); + if (!processed_input.has_value()) { return nullptr; } + base::UmaHistogramEnumeration(AIMetrics::GetAIAPIUsageMetricName( + AIMetrics::AISessionType::kLanguageModel), + AIMetrics::AIAPI::kSessionPromptStreaming); - // The API impl only accepts a string by default for now, more to come soon! + auto [stream, remote] = CreateModelExecutionStreamingResponder( + script_state, options->getSignalOr(nullptr), task_runner_, + AIMetrics::AISessionType::kLanguageModel, + WTF::BindOnce(&LanguageModel::OnResponseComplete, + WrapWeakPersistent(this)), + WTF::BindRepeating(&LanguageModel::OnQuotaOverflow, + WrapWeakPersistent(this))); + + language_model_remote_->Prompt( + std::move(processed_input->processed_prompts), + std::move(processed_input->processed_constraint), std::move(remote)); + + return stream; +} + +std::optional<LanguageModel::ValidateAndProcessPromptInputResult> +LanguageModel::ValidateAndProcessPromptInput( + ScriptState* script_state, + const V8LanguageModelPromptInput* input, + const LanguageModelPromptOptions* options, + ExceptionState& exception_state) { + if (!script_state->ContextIsValid()) { + ThrowInvalidContextException(exception_state); + return std::nullopt; + } + if (!input->IsString() && !RuntimeEnabledFeatures::AIPromptAPIMultimodalInputEnabled()) { exception_state.ThrowTypeError("Input type not supported"); - return nullptr; + return std::nullopt; + } + + AbortSignal* signal = options->getSignalOr(nullptr); + if (HandleAbortSignal(signal, script_state, exception_state)) { + return std::nullopt; + } + + on_device_model::mojom::blink::ResponseConstraintPtr constraint; + if (!ParseConstraint(script_state, options, exception_state, constraint)) { + // ParseConstraint will throw an exception when false is returned. + return std::nullopt; } auto prompts = BuildPrompts(input, script_state, exception_state, GetExecutionContext(), input_types_); if (!prompts.has_value()) { - return nullptr; + return std::nullopt; } - base::UmaHistogramEnumeration(AIMetrics::GetAIAPIUsageMetricName( - AIMetrics::AISessionType::kLanguageModel), - AIMetrics::AIAPI::kSessionPromptStreaming); - // TODO(crbug.com/411470034): Aggregate other input type sizes for UMA. if (input->IsString()) { base::UmaHistogramCounts1M( AIMetrics::GetAISessionRequestSizeMetricName( AIMetrics::AISessionType::kLanguageModel), - int(input->GetAsString().CharactersSizeInBytes())); + static_cast<int>(input->GetAsString().CharactersSizeInBytes())); } if (!language_model_remote_) { ThrowSessionDestroyedException(exception_state); - return nullptr; + return std::nullopt; } - AbortSignal* signal = options->getSignalOr(nullptr); - if (HandleAbortSignal(signal, script_state, exception_state)) { - return nullptr; - } - - on_device_model::mojom::blink::ResponseConstraintPtr constraint; - if (!ParseConstraint(script_state, options, exception_state, constraint)) { - // ParseConstraint will throw an exception when false is returned. - return nullptr; - } - - auto [readable_stream, pending_remote] = - CreateModelExecutionStreamingResponder( - script_state, signal, task_runner_, - AIMetrics::AISessionType::kLanguageModel, - WTF::BindOnce(&LanguageModel::OnResponseComplete, - WrapWeakPersistent(this)), - WTF::BindRepeating(&LanguageModel::OnQuotaOverflow, - WrapWeakPersistent(this))); - - language_model_remote_->Prompt(std::move(prompts).value(), - std::move(constraint), - std::move(pending_remote)); - return readable_stream; + return ValidateAndProcessPromptInputResult{ + .processed_constraint = std::move(constraint), + .processed_prompts = std::move(prompts).value(), + }; } ScriptPromise<LanguageModel> LanguageModel::clone(
diff --git a/third_party/blink/renderer/modules/ai/language_model.h b/third_party/blink/renderer/modules/ai/language_model.h index 9ee2c4a..b3a7dae 100644 --- a/third_party/blink/renderer/modules/ai/language_model.h +++ b/third_party/blink/renderer/modules/ai/language_model.h
@@ -94,6 +94,19 @@ mojom::blink::ModelExecutionContextInfoPtr context_info); void OnQuotaOverflow(); + struct ValidateAndProcessPromptInputResult { + on_device_model::mojom::blink::ResponseConstraintPtr processed_constraint; + WTF::Vector<mojom::blink::AILanguageModelPromptPtr> processed_prompts; + }; + + // Validates and processed prompt input and returns the processed results. + // Returns std::nullopt on failure. + std::optional<ValidateAndProcessPromptInputResult> + ValidateAndProcessPromptInput(ScriptState* script_state, + const V8LanguageModelPromptInput* input, + const LanguageModelPromptOptions* options, + ExceptionState& exception_state); + uint64_t input_usage_; uint64_t input_quota_ = 0; uint32_t top_k_ = 0;
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc index b10cfed..20811c9e 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc +++ b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
@@ -695,6 +695,8 @@ return wgpu::FeatureName::TextureCompressionETC2; case V8GPUFeatureName::Enum::kTextureCompressionAstc: return wgpu::FeatureName::TextureCompressionASTC; + case V8GPUFeatureName::Enum::kTextureCompressionAstcSliced3d: + return wgpu::FeatureName::TextureCompressionASTCSliced3D; case V8GPUFeatureName::Enum::kTimestampQuery: return wgpu::FeatureName::TimestampQuery; case V8GPUFeatureName::Enum::
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc index 83063f4..2f6c329 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -28,7 +28,6 @@ namespace { -// TODO(crbug.com/351564777): should be UNSAFE_BUFFER_USAGE GPUSupportedFeatures* MakeFeatureNameSet(wgpu::Adapter adapter) { GPUSupportedFeatures* features = MakeGarbageCollected<GPUSupportedFeatures>(); DCHECK(features->FeatureNameSet().empty()); @@ -51,7 +50,6 @@ } // anonymous namespace -// TODO(crbug.com/351564777): should be UNSAFE_BUFFER_USAGE GPUAdapter::GPUAdapter( GPU* gpu, wgpu::Adapter handle, @@ -63,9 +61,8 @@ wgpu::AdapterPropertiesSubgroups subgroupsProperties = {}; *propertiesChain = &subgroupsProperties; propertiesChain = &(*propertiesChain)->nextInChain; - wgpu::AdapterPropertiesMemoryHeaps memoryHeapProperties = {}; if (GetHandle().HasFeature(wgpu::FeatureName::AdapterPropertiesMemoryHeaps)) { - *propertiesChain = &memoryHeapProperties; + *propertiesChain = &memory_heaps_; propertiesChain = &(*propertiesChain)->nextInChain; } if (GetHandle().HasFeature( @@ -108,10 +105,6 @@ } description_ = String::FromUTF8(info.device); driver_ = String::FromUTF8(info.description); - for (size_t i = 0; i < memoryHeapProperties.heapCount; ++i) { - memory_heaps_.push_back(MakeGarbageCollected<GPUMemoryHeapInfo>( - UNSAFE_TODO(memoryHeapProperties.heapInfo[i]))); - } if (supportsPropertiesD3D) { d3d_shader_model_ = d3dProperties.shaderModel; } @@ -141,8 +134,13 @@ is_fallback_adapter_, device_, description_, driver_, FromDawnEnum(backend_type_), FromDawnEnum(adapter_type_), d3d_shader_model_, vk_driver_version_, FromDawnEnum(power_preference_)); - for (GPUMemoryHeapInfo* memory_heap : memory_heaps_) { - info->AppendMemoryHeapInfo(memory_heap); + + // SAFETY: Required from caller + const auto memory_heaps_span = + UNSAFE_BUFFERS(base::span<const wgpu::MemoryHeapInfo>( + memory_heaps_.heapInfo, memory_heaps_.heapCount)); + for (const auto& m : memory_heaps_span) { + info->AppendMemoryHeapInfo(MakeGarbageCollected<GPUMemoryHeapInfo>(m)); } } else { info = MakeGarbageCollected<GPUAdapterInfo>( @@ -354,7 +352,6 @@ visitor->Trace(features_); visitor->Trace(limits_); visitor->Trace(info_); - visitor->Trace(memory_heaps_); ScriptWrappable::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.h b/third_party/blink/renderer/modules/webgpu/gpu_adapter.h index e60b30c..83b5aed 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.h
@@ -23,7 +23,6 @@ class GPURequestAdapterOptions; class GPUSupportedFeatures; class GPUSupportedLimits; -class GPUMemoryHeapInfo; class GPUAdapter final : public ScriptWrappable, DawnObject<wgpu::Adapter> { DEFINE_WRAPPERTYPEINFO(); @@ -90,10 +89,10 @@ uint32_t subgroup_min_size_; uint32_t subgroup_max_size_; String driver_; - HeapVector<Member<GPUMemoryHeapInfo>> memory_heaps_; std::optional<uint32_t> d3d_shader_model_; std::optional<uint32_t> vk_driver_version_; wgpu::PowerPreference power_preference_; + wgpu::AdapterPropertiesMemoryHeaps memory_heaps_ = {}; wgpu::AdapterPropertiesSubgroupMatrixConfigs subgroup_matrix_configs_ = {}; static constexpr int kMaxAllowedConsoleWarnings = 50;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_supported_features.cc b/third_party/blink/renderer/modules/webgpu/gpu_supported_features.cc index 91dde2a..c6dbae1 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_supported_features.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_supported_features.cc
@@ -24,6 +24,8 @@ return V8GPUFeatureName::Enum::kTextureCompressionEtc2; case wgpu::FeatureName::TextureCompressionASTC: return V8GPUFeatureName::Enum::kTextureCompressionAstc; + case wgpu::FeatureName::TextureCompressionASTCSliced3D: + return V8GPUFeatureName::Enum::kTextureCompressionAstcSliced3d; case wgpu::FeatureName::IndirectFirstInstance: return V8GPUFeatureName::Enum::kIndirectFirstInstance; case wgpu::FeatureName::DepthClipControl:
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl b/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl index 7e6f09cf..e558141 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl
@@ -11,6 +11,7 @@ "texture-compression-bc-sliced-3d", "texture-compression-etc2", "texture-compression-astc", + "texture-compression-astc-sliced-3d", "timestamp-query", "indirect-first-instance", "shader-f16",
diff --git a/third_party/blink/renderer/modules/xr/xr_cube_map.cc b/third_party/blink/renderer/modules/xr/xr_cube_map.cc index c323a2e31..a1f74ce 100644 --- a/third_party/blink/renderer/modules/xr/xr_cube_map.cc +++ b/third_party/blink/renderer/modules/xr/xr_cube_map.cc
@@ -33,19 +33,20 @@ return static_cast<uint8_t>(255.0f * cs + 0.5f); } -void Rgba16fToSrgba8(base::span<const device::RgbaTupleF16> input, +void Rgba16fToSrgba8(base::span<const uint16_t> input, base::span<uint8_t> output) { - DCHECK_EQ(input.size() * 4, output.size()); + CHECK_EQ(input.size(), output.size()); + CHECK_EQ(input.size() % 4, 0u); for (size_t i = 0; i < input.size(); ++i) { - const auto& in = input[i]; - auto [out_pixel, rest] = output.split_at<4>(); - out_pixel[0] = LinearToSrgb(HalfFloatToFloat(in.red())); - out_pixel[1] = LinearToSrgb(HalfFloatToFloat(in.green())); - out_pixel[2] = LinearToSrgb(HalfFloatToFloat(in.blue())); - // We won't support non-opaque alpha to make the conversion a bit faster. - out_pixel[3] = 255; - output = rest; + // Every fourth input element is the alpha channel, which should remain in + // standard space. + if ((i + 1) % 4 == 0) { + // We won't support non-opaque alpha to make the conversion a bit faster. + output[i] = 255; + } else { + output[i] = LinearToSrgb(HalfFloatToFloat(input[i])); + } } } @@ -59,17 +60,20 @@ static_assert(kNumComponentsPerPixel == 4, "XRCubeMaps are expected to be in the RGBA16F format"); - // Cube map sides must all be a power-of-two image + // Cube map sides must all be a power-of-two image. Note that we can skip the + // division by |kNumComponentsPerPixel| at this time, since it is *also* a + // power-of-two. bool valid = std::has_single_bit(cube_map.width_and_height); - const size_t expected_size = - cube_map.width_and_height * cube_map.width_and_height; + const size_t expected_size = cube_map.width_and_height * + cube_map.width_and_height * + kNumComponentsPerPixel; valid &= cube_map.positive_x.size() == expected_size; valid &= cube_map.negative_x.size() == expected_size; valid &= cube_map.positive_y.size() == expected_size; valid &= cube_map.negative_y.size() == expected_size; valid &= cube_map.positive_z.size() == expected_size; valid &= cube_map.negative_z.size() == expected_size; - DCHECK(valid); + CHECK(valid); width_and_height_ = cube_map.width_and_height; positive_x_ = cube_map.positive_x; @@ -100,7 +104,7 @@ gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); gl->TexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - const std::array<base::span<const device::RgbaTupleF16>, 6> cubemap_images = { + const std::array<base::span<const uint16_t>, 6> cubemap_images = { positive_x_, negative_x_, positive_y_, negative_y_, positive_z_, negative_z_, };
diff --git a/third_party/blink/renderer/modules/xr/xr_cube_map.h b/third_party/blink/renderer/modules/xr/xr_cube_map.h index 01ef17b4..fd38578f 100644 --- a/third_party/blink/renderer/modules/xr/xr_cube_map.h +++ b/third_party/blink/renderer/modules/xr/xr_cube_map.h
@@ -6,7 +6,6 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_CUBE_MAP_H_ #include "base/types/pass_key.h" -#include "device/vr/public/mojom/rgba_tuple_f16.h" #include "device/vr/public/mojom/vr_service.mojom-blink-forward.h" #include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" @@ -30,12 +29,12 @@ private: uint32_t width_and_height_ = 0; - WTF::Vector<device::RgbaTupleF16> positive_x_; - WTF::Vector<device::RgbaTupleF16> negative_x_; - WTF::Vector<device::RgbaTupleF16> positive_y_; - WTF::Vector<device::RgbaTupleF16> negative_y_; - WTF::Vector<device::RgbaTupleF16> positive_z_; - WTF::Vector<device::RgbaTupleF16> negative_z_; + WTF::Vector<uint16_t> positive_x_; + WTF::Vector<uint16_t> negative_x_; + WTF::Vector<uint16_t> positive_y_; + WTF::Vector<uint16_t> negative_y_; + WTF::Vector<uint16_t> positive_z_; + WTF::Vector<uint16_t> negative_z_; }; } // namespace blink
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 22468747..4488e31 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -399,6 +399,7 @@ RasterInterface()->WritePixels(client_si->mailbox(), x, y, client_si->GetTextureTarget(), SkPixmap(orig_info, pixels, row_bytes)); + resource()->GetSyncToken(); // If the overdraw optimization kicked in, we need to indicate that the // pixels do not need to be cleared, otherwise the subsequent
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 7d2ae929..4d024f8 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1067,7 +1067,7 @@ { // Enables alignment properties for block and inline out-of-flow elements. name: "CSSAlignBlockAndInlineOutOfFlows", - status: "test", + status: "stable", }, { // Remember the scroll offset of the default anchor when initially @@ -2541,7 +2541,7 @@ }, { name: "IgnoreLetterSpacingInCursiveScripts", - status: "experimental", + status: "stable", }, { name: "ImageDataPixelFormat", @@ -2667,7 +2667,7 @@ }, { name: "IntegrityPolicyScript", - status: "experimental", + status: "stable", base_feature: "none", public: true, }, @@ -3815,12 +3815,6 @@ name: "RemoveDataUrlInSvgUse", status: "stable", }, - // Remove a node if it's selected fully even though it has children. See - // https://crbug.com/331074432 - { - name: "RemoveNodeHavingChildrenIfFullySelected", - status: "stable", - }, { // crbug.com/41047725 name: "RemovePlaceholderBRForDisplayInline", @@ -4169,6 +4163,14 @@ base_feature: "none", }, { + // Implements improved accessibility mappings for having an <input> + // inside of a <select> by reparenting the child <input> in the + // accessibility tree to be a sibling of the menu list popup. + name: "SelectAccessibilityReparentInput", + status: "test", + depends_on: ["CustomizableSelect"], + }, + { // SelectAudioOutput API // https://chromestatus.com/feature/5164535504437248 name: "SelectAudioOutput", @@ -4920,7 +4922,6 @@ // This flag uses the original DOM text for input when the password // echo is enabled to create the offset_map. name: "UseOriginalDomOffsetsForOffsetMap", - status: "stable", }, { name: "UsePositionForPointInFlexibleBoxWithSingleChildElement", @@ -5000,11 +5001,7 @@ }, { name: "ViewportSegments", - status: "experimental", - public: true, - base_feature_status: "enabled", - copied_from_base_feature_if: "overridden", - origin_trial_feature_name: "FoldableAPIs", + status: "stable", }, { name: "ViewTransitionDisableSnapBrowserControlsOnHidden",
diff --git a/third_party/blink/renderer/platform/wtf/text/parsing_utilities.h b/third_party/blink/renderer/platform/wtf/text/parsing_utilities.h index 2330aa9..534c42378 100644 --- a/third_party/blink/renderer/platform/wtf/text/parsing_utilities.h +++ b/third_party/blink/renderer/platform/wtf/text/parsing_utilities.h
@@ -28,16 +28,12 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_PARSING_UTILITIES_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TEXT_PARSING_UTILITIES_H_ #include <string_view> +#include "base/compiler_specific.h" #include "base/containers/span.h" namespace WTF { @@ -53,15 +49,6 @@ return false; } -template <typename CharType, bool characterPredicate(CharType)> -bool SkipExactly(const CharType*& position, const CharType* end) { - if (position < end && characterPredicate(*position)) { - ++position; - return true; - } - return false; -} - template <typename CharType, bool predicate(CharType)> bool SkipExactly(base::span<const CharType> chars, size_t& position) { if (position < chars.size() && predicate(chars[position])) { @@ -71,16 +58,17 @@ return false; } +// Use a span version instead. template <typename CharType> -bool SkipToken(const CharType*& position, - const CharType* end, - const char* token) { +UNSAFE_BUFFER_USAGE bool SkipToken(const CharType*& position, + const CharType* end, + const char* token) { const CharType* current = position; while (current < end && *token) { if (*current != *token) return false; - ++current; - ++token; + UNSAFE_TODO(++current); + UNSAFE_TODO(++token); } if (*token) return false; @@ -102,18 +90,13 @@ return true; } +// Use a span version instead. template <typename CharType> -void SkipUntil(const CharType*& position, - const CharType* end, - CharType delimiter) { +UNSAFE_BUFFER_USAGE void SkipUntil(const CharType*& position, + const CharType* end, + CharType delimiter) { while (position < end && *position != delimiter) - ++position; -} - -template <typename CharType, bool characterPredicate(CharType)> -void SkipUntil(const CharType*& position, const CharType* end) { - while (position < end && !characterPredicate(*position)) - ++position; + UNSAFE_TODO(++position); } template <typename CharType, bool predicate(CharType)> @@ -134,12 +117,6 @@ return position; } -template <typename CharType, bool characterPredicate(CharType)> -void ReverseSkipWhile(const CharType*& position, const CharType* start) { - while (position >= start && characterPredicate(*position)) - --position; -} - template <typename CharType, bool predicate(CharType)> [[nodiscard]] size_t ReverseSkipWhile(base::span<const CharType> chars, size_t position,
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 80c0a73f..aab7fff 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2641,6 +2641,7 @@ crbug.com/413411328 external/wpt/css/css-values/urls/referrer-policy/unsafe-url/url-image-referrerpolicy-same-origin.sub.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/416129743 [ Mac15-arm64 ] external/wpt/css/css-flexbox/overflow-auto-005.html [ Failure ] crbug.com/415669416 [ Mac15 ] external/wpt/css/css-position/sticky/position-sticky-fractional-offset.html [ Failure ] crbug.com/415738357 [ Linux ] external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/error.py [ Failure ] crbug.com/415738357 [ Linux ] external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/invalid.py [ Failure ] @@ -2833,7 +2834,7 @@ crbug.com/392927987 [ Mac14 ] external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html?5-6 [ Crash ] crbug.com/392927987 [ Mac15 ] external/wpt/html/cross-origin-opener-policy/iframe-popup-same-origin-to-same-origin.https.html?5-6 [ Crash ] crbug.com/392180059 [ Linux ] external/wpt/digital-credentials/disabled-by-permissions-policy.https.sub.html [ Failure Timeout ] -crbug.com/391728750 [ Win11 ] external/wpt/ai/translator/translator-translate.tentative.https.window.html [ Skip Timeout ] +crbug.com/391728750 [ Win11 ] external/wpt/ai/translator/translator.optional.https.window.html [ Skip Timeout ] crbug.com/390467419 [ Mac15-arm64 ] external/wpt/geolocation/enabled-by-permission-policy-attribute-redirect-on-load.https.sub.html [ Timeout ] crbug.com/390467419 [ Mac15 ] external/wpt/geolocation/enabled-by-permission-policy-attribute-redirect-on-load.https.sub.html [ Failure Timeout ] crbug.com/390467419 [ Mac14-arm64 ] external/wpt/geolocation/enabled-by-permission-policy-attribute-redirect-on-load.https.sub.html [ Timeout ] @@ -6299,6 +6300,8 @@ crbug.com/40146374 virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-picker-interactive-element-focus.tentative.html [ Failure ] crbug.com/40146374 virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-parsing.tentative.html [ Failure ] +crbug.com/415205686 editing/input/selectall-in-input-with-text-security.html [ Crash Failure ] + # Flaky on headless_shell_wpt_tests crbug.com/40146374 external/wpt/html/semantics/forms/the-select-element/customizable-select/select-option-images.tentative.html [ Failure Pass ] @@ -9077,7 +9080,7 @@ crbug.com/383946052 [ Linux ] external/wpt/screen-capture/tentative/getdisplaymedia-captured-surface-resolution.https.html [ Failure ] # Also failing on Linux ASAN -crbug.com/391728750 [ Linux ] external/wpt/ai/translator/translator-translate.tentative.https.window.html [ Failure Timeout ] +crbug.com/391728750 [ Linux ] external/wpt/ai/translator/translator.optional.https.window.html [ Failure Timeout ] #Gardener 2025-02-12 crbug.com/392640451 [ Win11 ] editing/pasteboard/4947130.html [ Failure Pass ] @@ -9214,3 +9217,6 @@ crbug.com/415747471 [ Mac ] virtual/text-antialias/font-fallback.html [ Failure ] crbug.com/415747471 [ Mac ] virtual/text-antialias/complex-text-opacity.html [ Failure ] crbug.com/415747471 [ Mac ] svg/text/bidi-textlength.html [ Failure ] + +# Gardener 2025-05-07 +crbug.com/416123241 [ Linux ] fast/forms/select/customizable-select/disallowed-select-descendants-console-message.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/editing/pasteboard/copy-image-with-alt-text-expected.txt b/third_party/blink/web_tests/editing/pasteboard/copy-image-with-alt-text-expected.txt index 5a0017a..d9af5d8 100644 --- a/third_party/blink/web_tests/editing/pasteboard/copy-image-with-alt-text-expected.txt +++ b/third_party/blink/web_tests/editing/pasteboard/copy-image-with-alt-text-expected.txt
@@ -3,8 +3,8 @@ Dump of markup 1: | <shadow:root> | <div> -| "Here is an emoticon [], some more text [], an empty alt tag [], no alt tag [] and two consecutive images []. -" +| "Here is an emoticon [], some more text [], an empty alt tag [], no alt tag [] and two consecutive images []." +| <br> | <br> | id="textarea-placeholder-break" @@ -18,8 +18,8 @@ Dump of markup 3: | <shadow:root> | <div> -| "Here is an emoticon [:)], some more text [sample text], an empty alt tag [], no alt tag [] and two consecutive images [firstsecond]. -" +| "Here is an emoticon [:)], some more text [sample text], an empty alt tag [], no alt tag [] and two consecutive images [firstsecond]." +| <br> | <br> | id="textarea-placeholder-break"
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 8f74d0c..981d3b34 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -5870,6 +5870,13 @@ {} ] ], + "root-replace-crash.html": [ + "165eec41b6bc56db131cc7fc19f23701bc291b8c", + [ + null, + {} + ] + ], "scoped": { "crashtests": { "shadow-dom.html": [ @@ -132348,6 +132355,19 @@ {} ] ], + "font-variant-emoji-005.html": [ + "0f5c2d7a98a615323b1adc0babb479fdb738537d", + [ + null, + [ + [ + "/css/css-fonts/font-variant-emoji-005-ref.html", + "==" + ] + ], + {} + ] + ], "font-variant-emoji-1.html": [ "53cf539edd8b61a7f08f8b95ae83f4f7a5179308", [ @@ -134507,6 +134527,71 @@ ], {} ] + ], + "grid-gap-decorations-029.html": [ + "6da75548d94b5e17e1ad7ba1011662c42b818d83", + [ + null, + [ + [ + "/css/css-gaps/grid/grid-gap-decorations-029-ref.html", + "==" + ] + ], + {} + ] + ], + "grid-gap-decorations-030.html": [ + "ef4507ef92638eeff660e67e2024bbce323c1aa8", + [ + null, + [ + [ + "/css/css-gaps/grid/grid-gap-decorations-030-ref.html", + "==" + ] + ], + {} + ] + ], + "grid-gap-decorations-031.html": [ + "530b661bfe32c5af7687954f3f4b2cbdfa61380a", + [ + null, + [ + [ + "/css/css-gaps/grid/grid-gap-decorations-031-ref.html", + "==" + ] + ], + {} + ] + ], + "grid-gap-decorations-032.html": [ + "ac2d38fdda0ec6a1f4a3b7b091d03c896e3e5e47", + [ + null, + [ + [ + "/css/css-gaps/grid/grid-gap-decorations-032-ref.html", + "==" + ] + ], + {} + ] + ], + "grid-gap-decorations-033.html": [ + "47ef35cc3688b2fcd2329558b1d0a27880983b38", + [ + null, + [ + [ + "/css/css-gaps/grid/grid-gap-decorations-033-ref.html", + "==" + ] + ], + {} + ] ] }, "multicol": { @@ -224560,6 +224645,35 @@ {} ] ], + "css-scale-of-clip-path.html": [ + "dda72c0d139979213741174da8c9572f1237bcc3", + [ + null, + [ + [ + "/css/css-transforms/css-scale-of-clip-path-ref.html", + "==" + ] + ], + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 40 + ], + [ + 0, + 3000 + ] + ] + ] + ] + } + ] + ], "css-skew-001.html": [ "f209834121bb00ff3542029d44ba1ce878b0dd77", [ @@ -319840,7 +319954,13 @@ "OWNERS": [ "ada9e7044f494a9db911e640fd69b83bdb5e854a", [] - ] + ], + "resources": { + "util.js": [ + "ad06086a123bccbe2c852dffd1a36ffde0613ada", + [] + ] + } } }, "ambient-light": { @@ -342823,6 +342943,10 @@ "633a94c4e51f32328bc68eeb74837aada6f4aff0", [] ], + "font-variant-emoji-005-ref.html": [ + "d4275b5c951c05ea270f1a2a474ff4ccaf9afc4a", + [] + ], "font-variant-emoji-1-notref.html": [ "bbf3654ccfcdd415fe5a28468e3329ba94ce63da", [] @@ -349941,6 +350065,26 @@ "grid-gap-decorations-027-ref.html": [ "7e0d9cbcd6ff64b17bc8fe57616a37ba29a9fd8e", [] + ], + "grid-gap-decorations-029-ref.html": [ + "35450e07ae5579707c94b4a0a58f29eb83d7f7fa", + [] + ], + "grid-gap-decorations-030-ref.html": [ + "d4953ae2ddda701324d350ccf25a113b8e67fc37", + [] + ], + "grid-gap-decorations-031-ref.html": [ + "0615305bc9f8de791f1c2061ad6d90039932b157", + [] + ], + "grid-gap-decorations-032-ref.html": [ + "f90e3dd68132078e2557f33b7e32605d278cd0eb", + [] + ], + "grid-gap-decorations-033-ref.html": [ + "e26143a6b93e9fdd53d4055234d89e40d98dc2af", + [] ] }, "multicol": { @@ -368831,6 +368975,10 @@ "54940566cd107ba443d3183dccecb505a811d14e", [] ], + "css-scale-of-clip-path-ref.html": [ + "d6fa480b0408ffc9c3687515e25a30ddc68f199f", + [] + ], "css-skew-001-ref.html": [ "70c256ebec653128a2d91555e817b54880666a35", [] @@ -380750,7 +380898,7 @@ [] ], "testdriver.md": [ - "67757af63f2ed6af4026577dd35000c183509d44", + "e0fae529875ee89d5e8a2457cdab35e1866f663b", [] ], "testharness-api.md": [ @@ -381429,6 +381577,10 @@ } }, "observable": { + "WEB_FEATURES.yml": [ + "3e872791165e41402949da13fedd7a8780aaf660", + [] + ], "tentative": { "observable-from.any-expected.txt": [ "90faca59d59d4199fa430ee25c80f061257f089b", @@ -387354,6 +387506,30 @@ ] } }, + "local-network-access": { + "META.yml": [ + "4c5c6983ed0467f3ebca3182a6b5d095270f85d2", + [] + ], + "README.md": [ + "95066cdcd0ba6f2baed3cd02d67610420367b6df", + [] + ], + "resources": { + "fetch-private.html": [ + "ede16badf338dc50defad0251f83f8b02f1d3fec", + [] + ], + "support.sub.js": [ + "299f004ecc362e29202b80b68d8e47b1300b8604", + [] + ], + "target.py": [ + "eabcdd47517c8938d12cd08a0d66f0db2e518456", + [] + ] + } + }, "metadata": { "META.yml": [ "85f0a7d2ee12616aa7a5698b346954829d8a8bb0", @@ -419584,7 +419760,7 @@ [] ], "report-helper.js": [ - "5b5438903de11c346ac3901a9de81a96e4446386", + "216da22eae8c0ccde223c70a110a7a892676c14f", [] ], "report.py": [ @@ -420397,7 +420573,7 @@ [] ], "testdriver.js": [ - "6e8410b7ea46064438c8d276274b6fbb689f81d2", + "992b9e3ab2ce0b63b94be2a5aa671b321f65e334", [] ], "testdriver.js.headers": [ @@ -432997,11 +433173,11 @@ ], "set_geolocation_override": { "__init__.py": [ - "7861734b5087e3486ef0a03c2b8cc8364682c5fd", + "5e1fd1aa8637529a20b48356fe20e4f970b8428c", [] ], "conftest.py": [ - "a90895c74ed90c04b5f181af22c3bddec9ac132d", + "5fb9451f0a23821bbd7d25ac59efeb928f84b5ac", [] ] } @@ -466835,10 +467011,10 @@ ] }, "translator": { - "translator-bad-input.tentative.https.window.js": [ - "53a184bfd196f6006e7df9c908518ba47deacda6", + "translator-bad-input.https.window.js": [ + "db8905a61f660f8dc0aa7666c044794d22683799", [ - "ai/translator/translator-bad-input.tentative.https.window.html", + "ai/translator/translator-bad-input.https.window.html", { "script_metadata": [ [ @@ -466858,15 +467034,15 @@ } ] ], - "translator-translate.tentative.https.window.js": [ - "a8aad5e03e1f46db43a47966d66f7aecc526b255", + "translator.optional.https.window.js": [ + "96eca09d28bd61ccc4d31b746216f1f252d0bf3b", [ - "ai/translator/translator-translate.tentative.https.window.html", + "ai/translator/translator.optional.https.window.html", { "script_metadata": [ [ "title", - "Translate from English to Japanese" + "Translator Translate" ], [ "global", @@ -466887,6 +467063,10 @@ [ "script", "/resources/testdriver.js" + ], + [ + "script", + "resources/util.js" ] ], "timeout": "long" @@ -528768,6 +528948,13 @@ {} ] ], + "sibling-index-keyframe-value-dynamic.html": [ + "286e0d3d3e2eecdd091df74c8c47f738cb700dd1", + [ + null, + {} + ] + ], "tree-scoped-sibling-function.html": [ "979466bb7cf3d5e5c4e9a2681f02f969858953e6", [ @@ -532276,7 +532463,7 @@ ] ], "getBoundingClientRect-newline.html": [ - "40e29181d6fed001b641b0b0050cf21d6f3c589c", + "ce82b7237d003d79fe4333e5a67aa74b004bb11c", [ null, {} @@ -577968,6 +578155,17 @@ ] ] }, + "local-network-access": { + "fetch.tentative.https.html": [ + "a01bad6a420d61e13188fda314232c6a31332623", + [ + null, + { + "testdriver": true + } + ] + ] + }, "metadata": { "audio-worklet.https.html": [ "3b768ef0b5ddd2d13361629afd011e6987cb38d0", @@ -648498,6 +648696,15 @@ } ] ], + "select-input-keyboard-behavior.tentative.html": [ + "bf3fbab9d18a4747f903d082a8c11d6ebad737aa", + [ + null, + { + "testdriver": true + } + ] + ], "select-inside-top-layer.tentative.html": [ "6d70f3aaf8d3dc23b2f5fb784c399991913dc938", [ @@ -663133,7 +663340,7 @@ }, "emulation": { "set_geolocation_override.https.html": [ - "5cbcf546423c772a98fd3725531754c366ab7b91", + "e339f39dcd89aa311e91c744669bf2cd9aadc103", [ null, { @@ -711237,7 +711444,7 @@ ] ], "innertext.tentative.html": [ - "d40b6047924834ef09137fa975cbd2d142999bcb", + "7716488f25a08ea62635fceec679d97650d1f383", [ null, { @@ -711533,7 +711740,7 @@ ] ], "text-lcp-followed-by-anim-image-softnav-lcp.tentative.html": [ - "0615b513e61319d61bcbed3540aa1a5d47289cb6", + "b34a6e81a58333c61ccedb4e25551feba4893736", [ null, { @@ -711560,7 +711767,7 @@ ] ], "visited-link.tentative.html": [ - "0bb149f00e91fc2f0033a6f763543967ef542ab2", + "0bb31aaac1540b3d2b9f6a3157bb43d96e430a58", [ null, { @@ -727920,6 +728127,34 @@ {} ] ], + "tentative": { + "integrity-policy": { + "parsing.https.html": [ + "205854419a7d58871e39a5cfb3a86ccd38cd5492", + [ + "subresource-integrity/tentative/integrity-policy/parsing.https.html?type=enforce", + { + "timeout": "long" + } + ], + [ + "subresource-integrity/tentative/integrity-policy/parsing.https.html?type=report", + { + "timeout": "long" + } + ] + ], + "script.https.html": [ + "783374db920a24ae32a3492d8cfe2edc5d8eb5d3", + [ + null, + { + "timeout": "long" + } + ] + ] + } + }, "unencoded-digest": { "tentative": { "fetch.any.js": [ @@ -834227,21 +834462,21 @@ "emulation": { "set_geolocation_override": { "contexts.py": [ - "8a0e43475da52609a362bf5f3e0853ceb2a9725f", + "068bb804e73bd06e2d901363280792d479cfb38f", [ null, {} ] ], "coordinates.py": [ - "b23354e9e42ef1bdd9d6684d11b782ce15f4eb8c", + "ea4fe643c3ecfc6e3609172706b51df17456e2e7", [ null, {} ] ], "error.py": [ - "ec905e384822b6af73e1ca68f21c93d5b6b0d6ed", + "27c23dc7811458feb7cd43c8a286c83809d9d2d0", [ null, {} @@ -834255,7 +834490,7 @@ ] ], "user_contexts.py": [ - "008dee5698de43a3371c1f7d697bb69014cf1b65", + "b3038bb59587b661e75945c5b8eeb4e943c72d9e", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/ai/translator/resources/util.js b/third_party/blink/web_tests/external/wpt/ai/translator/resources/util.js new file mode 100644 index 0000000..ad06086 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/ai/translator/resources/util.js
@@ -0,0 +1,4 @@ +async function createTranslator(options) { + await test_driver.bless(); + return await Translator.create(options); +}
diff --git a/third_party/blink/web_tests/external/wpt/ai/translator/translator-bad-input.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/translator/translator-bad-input.https.window.js similarity index 89% rename from third_party/blink/web_tests/external/wpt/ai/translator/translator-bad-input.tentative.https.window.js rename to third_party/blink/web_tests/external/wpt/ai/translator/translator-bad-input.https.window.js index 53a184bf..db8905a6 100644 --- a/third_party/blink/web_tests/external/wpt/ai/translator/translator-bad-input.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/translator/translator-bad-input.https.window.js
@@ -8,8 +8,7 @@ 'use strict'; promise_test(async t => { - await promise_rejects_js( - t, TypeError, Translator.create(/*empty options*/)); + await promise_rejects_js(t, TypeError, Translator.create(/*empty options*/)); }, 'Translator.create rejects with TypeError if no options are passed.'); promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/ai/translator/translator-translate.tentative.https.window.js b/third_party/blink/web_tests/external/wpt/ai/translator/translator.optional.https.window.js similarity index 95% rename from third_party/blink/web_tests/external/wpt/ai/translator/translator-translate.tentative.https.window.js rename to third_party/blink/web_tests/external/wpt/ai/translator/translator.optional.https.window.js index a8aad5e..96eca09d 100644 --- a/third_party/blink/web_tests/external/wpt/ai/translator/translator-translate.tentative.https.window.js +++ b/third_party/blink/web_tests/external/wpt/ai/translator/translator.optional.https.window.js
@@ -1,21 +1,16 @@ -// META: title=Translate from English to Japanese +// META: title=Translator Translate // META: global=window // META: timeout=long // META: script=../resources/util.js // META: script=../resources/language_codes.js // META: script=/resources/testdriver.js +// META: script=resources/util.js // // Setting `timeout=long` as this test may require downloading the translation // library and the language models. 'use strict'; -async function createTranslator(options) { - return await test_driver.bless('Create translator', async () => { - return await Translator.create(options); - }); -} - promise_test(async t => { const languagePair = {sourceLanguage: 'en', targetLanguage: 'ja'}; @@ -141,7 +136,7 @@ for (let i = 0; i < translatableStrings.length; i++) { assert_not_equals(translatedTranslatableString[i], translatableStrings[i]); } -}, 'Translator.translate() echos non-translatable content'); +}, 'Translator.translate() echoes non-translatable content'); promise_test(async t => { const translator =
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-variant-emoji-005-ref.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-variant-emoji-005-ref.html new file mode 100644 index 0000000..d4275b5c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-variant-emoji-005-ref.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<meta charset="UTF-8" /> +<title>CSS Fonts reference</title> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + +<style> +body { background: white; } +p { font: 16px/3 serif; } +span { color: white; font: 25px Ahem; } +span span { color: initial; font-variant-emoji: emoji; } +</style> + +<h4>Only lines 3 and 4 should show a keycap numeral:</h4> + +<p>1. text: <span>X</span></p> + +<p>2. unicode: <span>X</span></p> + +<p>3. emoji: <span>X<span>3️⃣</span>X</span></p> + +<p>4. with VS16: <span>X<span>4️⃣</span>X</span></p> + +<p>5. emoji, with VS15: <span>X</span></p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-variant-emoji-005.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-variant-emoji-005.html new file mode 100644 index 0000000..0f5c2d7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-variant-emoji-005.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset="UTF-8" /> +<title>CSS Fonts: font-variant-emoji web font test</title> +<link rel="help" href="https://www.w3.org/TR/css-fonts-4/#font-variant-emoji-prop" /> +<link rel="help" href="https://www.unicode.org/reports/tr51/tr51-25.html#Emoji_Properties_and_Data_Files" /> +<link rel="match" href="font-variant-emoji-005-ref.html"/> +<meta name="assert" content="Digit-keycap sequences render as emoji if required, in preference to using the named font"/> +<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + +<style> +body { background: white; } +p { font: 16px/3 serif; } +/* A color-emoji glyph in the span will be visible despite the white color; + * if color-emoji presentation is not used, the span will be invisible. + */ +span { color: white; font: 25px Ahem; } +</style> + +<h4>Only lines 3 and 4 should show a keycap numeral:</h4> + +<p>1. text: <span style="font-variant-emoji: text">X1⃣X</span></p> + +<p>2. unicode: <span style="font-variant-emoji: unicode">X2⃣X</span></p> + +<p>3. emoji: <span style="font-variant-emoji: emoji">X3⃣X</span></p> + +<p>4. with VS16: <span style="font-variant-emoji: normal">X4️⃣X</span></p> + +<p>5. emoji, with VS15: <span style="font-variant-emoji: emoji">X5︎⃣X</span></p>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/urls/fragment-only-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/urls/fragment-only-expected.txt deleted file mode 100644 index e79da1e..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-values/urls/fragment-only-expected.txt +++ /dev/null
@@ -1,13 +0,0 @@ -This is a testharness.js-based test. -[FAIL] empty URL: inline-unquoted - assert_equals: expected "url(\\"#foo\\")" but got "url(\\"http://web-platform.test:8001/css/css-values/urls/fragment-only.html#foo\\")" -[FAIL] empty URL: inline-quoted - assert_equals: expected "url(\\"#foo\\")" but got "url(\\"http://web-platform.test:8001/css/css-values/urls/fragment-only.html#foo\\")" -[FAIL] empty URL: external-unquoted - assert_equals: expected "url(\\"#foo\\")" but got "url(\\"http://web-platform.test:8001/css/css-values/urls/support/fragment-only-urls.css#foo\\")" -[FAIL] empty URL: external-quoted - assert_equals: expected "url(\\"#foo\\")" but got "url(\\"http://web-platform.test:8001/css/css-values/urls/support/fragment-only-urls.css#foo\\")" -[FAIL] empty URL: external-variable - assert_equals: expected "url(\\"#foo\\")" but got "url(\\"http://web-platform.test:8001/css/css-values/urls/support/fragment-only-urls.css#foo\\")" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-view-transitions/root-replace-crash.html b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/root-replace-crash.html new file mode 100644 index 0000000..165eec4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-view-transitions/root-replace-crash.html
@@ -0,0 +1,15 @@ +<html> +<head> + <script> + document.addEventListener("DOMContentLoaded", async () => { + const tt = document.createElementNS("http://www.w3.org/1999/xhtml", "tt") + tt.popover = "manual" + const viewTransition = document.startViewTransition(undefined) + await viewTransition.updateCallbackDone + for (let i = 0; i < 2; i++) { + document.replaceChild(tt, document.childNodes[(2324524876 % document.childNodes.length)]) + } + }) + </script> + <head> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/cssom-view/getBoundingClientRect-newline.html b/third_party/blink/web_tests/external/wpt/css/cssom-view/getBoundingClientRect-newline.html index 40e2918..ce82b723 100644 --- a/third_party/blink/web_tests/external/wpt/css/cssom-view/getBoundingClientRect-newline.html +++ b/third_party/blink/web_tests/external/wpt/css/cssom-view/getBoundingClientRect-newline.html
@@ -5,17 +5,14 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <style> -div { +div[contenteditable] { white-space: pre; - font-family: Ahem; - font-size: 10px; - line-height: 1; + font: 10px/1 Ahem; width: 10ch; } </style> <body> <div contenteditable></div> -</body> <script> function getBoundingClientRect(node, offset) { const range = document.createRange(); @@ -37,3 +34,4 @@ assert_less_than(rect6.y, rect7.y); }, 'Range.getBoundingClientRect() should return the first position of the next line when the collapsed range is a newline character'); </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/docs/writing-tests/testdriver.md b/third_party/blink/web_tests/external/wpt/docs/writing-tests/testdriver.md index 67757af..e0fae52 100644 --- a/third_party/blink/web_tests/external/wpt/docs/writing-tests/testdriver.md +++ b/third_party/blink/web_tests/external/wpt/docs/writing-tests/testdriver.md
@@ -313,3 +313,11 @@ .. js:autofunction:: test_driver.bidi.bluetooth.simulate_preconnected_peripheral .. js:autofunction:: test_driver.bidi.bluetooth.request_device_prompt_updated ``` + +### Emulation ### + +Emulation of browser APIs via [WebDriver BiDi Emulation](https://www.w3.org/TR/webdriver-bidi/#module-emulation). + +```eval_rst +.. js:autofunction:: test_driver.bidi.emulation.set_geolocation_override +```
diff --git a/third_party/blink/web_tests/external/wpt/dom/observable/WEB_FEATURES.yml b/third_party/blink/web_tests/external/wpt/dom/observable/WEB_FEATURES.yml new file mode 100644 index 0000000..3e872791 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/dom/observable/WEB_FEATURES.yml
@@ -0,0 +1,3 @@ +features: +- name: observable + files: "**"
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative.html new file mode 100644 index 0000000..bf3fbab9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://issues.chromium.org/issues/402429384"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<script src="/resources/testdriver-actions.js"></script> + +<style> +select, ::picker(select) { + appearance: base-select; +} +</style> + +<select> + <div id=inputwrapper></div> + <option class=one>one</option> + <option class=two>two</option> +</select> + +<script> +const select = document.querySelector('select'); +const optionOne = select.querySelector('option.one'); +const optionTwo = select.querySelector('option.two'); +const input = document.createElement('input'); +document.getElementById('inputwrapper').appendChild(input); + +function pressKey(key) { + return (new test_driver.Actions() + .keyDown(key) + .keyUp(key)) + .send(); +} +const spaceKey = '\uE00D'; +const arrowDown = '\uE015'; +const arrowUp = '\uE013'; + +promise_test(async () => { + assert_equals(getComputedStyle(select).appearance, 'base-select', + 'appearance: base-select must be supported for this test to run.'); + + select.focus(); + await pressKey(spaceKey); + assert_true(select.matches(':open'), + 'select should be open after pressing space.'); + assert_equals(document.activeElement, input, + 'input should be focused after opening select.'); + + await pressKey(arrowDown); + assert_equals(document.activeElement, optionOne, + 'first option should be focused after arrow down from input.'); + + await pressKey(arrowUp); + assert_equals(document.activeElement, input, + 'input should be focused after arrow up from first option.'); +}, 'Keyboard behavior of <input> in <select>.'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/bidi/emulation/set_geolocation_override.https.html b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/bidi/emulation/set_geolocation_override.https.html index 5cbcf54..e339f39d 100644 --- a/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/bidi/emulation/set_geolocation_override.https.html +++ b/third_party/blink/web_tests/external/wpt/infrastructure/testdriver/bidi/emulation/set_geolocation_override.https.html
@@ -13,10 +13,6 @@ descriptor: {name: "geolocation"}, state: "granted", }); - - // Ensure any previously set geolocation emulations are cleared. - await test_driver.bidi.emulation.set_geolocation_override( - {coordinates: null}); }); /** Get the current geolocation or error */ @@ -24,13 +20,13 @@ return new Promise( resolve => window.navigator.geolocation.getCurrentPosition( position => resolve(position.coords.toJSON()), - error => resolve({code: error.code, message: error.message}), + error => resolve({code: error.code}), // Fail fast if geolocation is not available. {timeout: 500} )) } - /** Asserts that relevant coordinate properties match */ + /** Asserts that coordinate or error matches the expected value */ function assert_coordinates_match(actual, expected) { for (const key in expected) { assert_equals(actual[key], expected[key], @@ -49,6 +45,11 @@ }; promise_test(async (t) => { + t.add_cleanup(async () => { + await test_driver.bidi.emulation.set_geolocation_override( + {coordinates: null}); + }); + // Get the initial geolocation (might be error). const initial_coords = await get_current_geolocation(); @@ -66,6 +67,28 @@ await test_driver.bidi.emulation.set_geolocation_override( {coordinates: null}); // Assert coordinates are set to the original value. - assert_coordinates_match(await get_current_geolocation(), initial_coords); + assert_coordinates_match(await get_current_geolocation(), + initial_coords); }, "emulate geolocation and clear override"); + + promise_test(async (t) => { + // Emulate position unavailable. + await test_driver.bidi.emulation.set_geolocation_override({ + error: {type: 'positionUnavailable'}, + }); + + // Get the geolocation after setting the override. + const error = await get_current_geolocation(); + + assert_equals(error.code, 2, + `Geolocation should be unavailable with code POSITION_UNAVAILABLE = 2`); + }, "emulate geolocation position unavailable"); + + promise_test(async (t) => { + assert_throws_js(Error, + () => test_driver.bidi.emulation.set_geolocation_override({ + error: {type: 'positionUnavailable'}, + coordinates: SOME_COORDINATES + }), "Setting both `coordinates` and `error` should fail"); + }, "cannot set `coordinates` and `error` simultaneously"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/resources/testdriver.js b/third_party/blink/web_tests/external/wpt/resources/testdriver.js index 6e8410b7..992b9e3 100644 --- a/third_party/blink/web_tests/external/wpt/resources/testdriver.js +++ b/third_party/blink/web_tests/external/wpt/resources/testdriver.js
@@ -280,8 +280,14 @@ * @param {object} params - Parameters for the command. * @param {null|object} params.coordinates - The optional * geolocation coordinates to set. Matches the - * `emulation.GeolocationCoordinates <https://w3c.github.io/webdriver-bidi/#type-emulation-GeolocationCoordinates>`_ - * value. If null or omitted, the emulation will be removed. + * `emulation.GeolocationCoordinates <https://w3c.github.io/webdriver-bidi/#commands-emulationsetgeolocationoverride>`_ + * value. If null or omitted and the `params.error` is set, the + * emulation will be removed. Mutually exclusive with + * `params.error`. + * @param {object} params.error - The optional + * geolocation error to emulate. Matches the + * `emulation.GeolocationPositionError <https://w3c.github.io/webdriver-bidi/#commands-emulationsetgeolocationoverride>`_ + * value. Mutually exclusive with `params.coordinates`. * @param {null|Array.<(Context)>} [params.contexts] The * optional contexts parameter specifies which browsing contexts * to set the geolocation override on. It should be either an
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/basic-service-worker.js b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/basic-service-worker.js index 17fccd44..59d7d8b 100644 --- a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/basic-service-worker.js +++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/basic-service-worker.js
@@ -32,6 +32,13 @@ if (swOption === 'fetch-handler') { event.respondWith(fetch(event.request)); + } else if (swOption === 'fetch-handler-synthetic') { + const finalUrl = new URL(event.request.url).searchParams.get('location'); + if (finalUrl) { + event.respondWith(Response.redirect(finalUrl)); + } else { + // Fallback to the network. + } } else if (swOption === 'fetch-handler-modify-url') { // The "Sec-Purpose: prefetch" header is dropped in fetch-handler-modify-* // cases in Step 33 of // https://fetch.spec.whatwg.org/#dom-request
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/counting-executor.py b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/counting-executor.py index cbcbc8e..3511fe49 100644 --- a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/counting-executor.py +++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/counting-executor.py
@@ -21,6 +21,11 @@ request_count["prefetch" if prefetch else "nonPrefetch"] += 1 request.server.stash.put(uuid, request_count) + if b"location" in request.GET: + response.status = 302 + response.headers.set(b"Location", request.GET[b"location"]) + return + response.content = template( request, open(os.path.join(os.path.dirname(__file__), "executor.sub.html"), "rb").read())
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https.html new file mode 100644 index 0000000..f56f6bf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https.html
@@ -0,0 +1,122 @@ +<!DOCTYPE html> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script src="/common/dispatcher/dispatcher.js"></script> +<script src="../../../resources/utils.js"></script> +<script src="../../resources/utils.sub.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> + +<meta name="variant" content="?origin=same-site&sc=in-in&sw=fetch-handler"> +<meta name="variant" content="?origin=same-site&sc=in-in&sw=fetch-handler-to-fallback"> +<meta name="variant" content="?origin=same-site&sc=in-in&sw=fetch-handler-synthetic"> +<meta name="variant" content="?origin=same-site&sc=in-in&sw=no-fetch-handler"> + +<meta name="variant" content="?origin=same-site&sc=in-out&sw=fetch-handler"> +<meta name="variant" content="?origin=same-site&sc=in-out&sw=fetch-handler-to-fallback"> +<meta name="variant" content="?origin=same-site&sc=in-out&sw=fetch-handler-synthetic"> +<meta name="variant" content="?origin=same-site&sc=in-out&sw=no-fetch-handler"> + +<meta name="variant" content="?origin=same-site&sc=out-in&sw=fetch-handler"> +<meta name="variant" content="?origin=same-site&sc=out-in&sw=fetch-handler-to-fallback"> +<meta name="variant" content="?origin=same-site&sc=out-in&sw=no-fetch-handler"> + +<script> +setup(() => assertSpeculationRulesIsSupported()); + +const originOption = new URL(location.href).searchParams.get('origin'); +const swOption = new URL(location.href).searchParams.get('sw'); + +// We use a short name `sc` to avoid long file names https://crbug.com/40469687 +const scopeOption = new URL(location.href).searchParams.get('sc'); + +promise_test(async t => { + const hostname = originOption === 'cross-site' ? '{{hosts[alt][www]}}' + : undefined; + const win = await spawnWindow(t, { protocol: 'https', hostname: hostname }); + + const finalUrl = win.getExecutorURL({ executor: 'counting-executor.py', protocol: 'https', page: 2 }); + const initialUrl = new URL('../../resources/counting-executor.py', location.href); + // Assign a different UUID to track the number of requests to server + // separately for the initialUrl and finalUrl. + initialUrl.searchParams.set('uuid', token()); + initialUrl.searchParams.set('location', finalUrl); + + const swUrl = new URL('../../resources/basic-service-worker.js?sw=' + swOption, location.href).href; + + let sw1; + if (scopeOption === 'in-in' || scopeOption === 'in-out') { + // Register a SW for `initialUrl`. + const reg = await service_worker_unregister_and_register( + t, swUrl + '&sw1', initialUrl); + sw1 = reg.installing; + await wait_for_state(t, reg.installing, 'activated'); + } + + let sw2; + if (scopeOption === 'in-in' || scopeOption === 'out-in') { + // Register a SW for `finalUrl`. + const reg = await service_worker_unregister_and_register( + t, swUrl + '&sw2', finalUrl); + sw2 = reg.installing; + await wait_for_state(t, reg.installing, 'activated'); + } + + // Start speculation rules prefetch and navigate to the URL. + await win.forceSinglePrefetch(initialUrl); + + await win.navigate(initialUrl, {expectedDestinationUrl: finalUrl}); + + const initialRequestCount = await (await fetch(initialUrl + '&check')).json(); + const finalRequestCount = await (await fetch(finalUrl + '&check')).json(); + + const headers = await win.execute_script(() => { + return requestHeaders; + }, []); + + const controllerUrl = await win.execute_script(() => { + return navigator.serviceWorker.controller ? + navigator.serviceWorker.controller.scriptURL : + undefined; + }, []); + + if (sw2) { + // The navigated page should be controlled by the ServiceWorker, + // regardless of whether prefetch is performed/used. + assert_equals(controllerUrl, swUrl + '&sw2'); + } else { + assert_equals(controllerUrl, undefined); + } + + // In any cases prefetch + redirects + ServiceWorker fails and prefetched + // results aren't served. + assert_not_prefetched(headers, "Prefetched result should not be served."); + + if (swOption === 'fetch-handler-synthetic') { + // Synthetic redirect response from ServiceWorker prevents the initial + // prefetch/non-prefetch requests to the server. + assert_equals(initialRequestCount.prefetch, 0, + 'prefetch requests to initial URL should not be sent to the server.'); + assert_equals(initialRequestCount.nonPrefetch, 0, + 'a non-prefetch requests to initial URL should not be sent to the server.'); + } else { + // Otherwise, the initial prefetch request (either with or without + // ServiceWorker interception) anyway reaches the server, and then + // re-requested as a non-prefetch request on navigation. + assert_equals(initialRequestCount.prefetch, 1, + 'prefetch requests to initial URL should be sent to the server.'); + assert_equals(initialRequestCount.nonPrefetch, 1, + 'a non-prefetch requests to initial URL should be sent to the server.'); + } + + // Prefetch requests to the URL after redirects shouldn't be sent to server + // because prefetch should fail immediately on receiving redirects. + assert_equals(finalRequestCount.prefetch, 0, + 'prefetch requests should not be sent to the server.'); + // Instead, a single non-prefetch request should be sent. + assert_equals(finalRequestCount.nonPrefetch, 1, + 'a non-prefetch request should be sent to the server.'); + +}, "Prefetch with ServiceWorker (" + swOption + ")"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/__init__.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/__init__.py index 7861734..5e1fd1a 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/__init__.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/__init__.py
@@ -1,28 +1 @@ -from webdriver.bidi.modules.script import ContextTarget - -from ... import remote_mapping_to_dict - - TEST_COORDINATES = {"latitude": 10, "longitude": 15, "accuracy": 0.5} - - -async def get_current_geolocation(bidi_session, context): - # Per geolocation spec, the geolocation coordinates are returned - # only for an active browsing context. It might be required to - # re-activate the previously active tab in the test. - await bidi_session.browsing_context.activate(context=context["context"]) - - result = await bidi_session.script.call_function( - function_declaration="""() => - new Promise( - resolve => window.navigator.geolocation.getCurrentPosition( - position => resolve(position.coords.toJSON()), - error => resolve({code: error.code}), - {timeout: 500} - )) - """, - target=ContextTarget(context["context"]), - await_promise=True, - ) - - return remote_mapping_to_dict(result["value"])
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/conftest.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/conftest.py index a90895c..5fb9451f 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/conftest.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/conftest.py
@@ -1,6 +1,35 @@ import pytest_asyncio -from ... import get_context_origin +from webdriver.bidi.modules.script import ContextTarget + +from ... import get_context_origin, remote_mapping_to_dict + + +@pytest_asyncio.fixture +async def get_current_geolocation(bidi_session, configuration): + async def get_current_geolocation(context): + # Per geolocation spec, the geolocation coordinates are returned + # only for an active browsing context. It might be required to + # re-activate the previously active tab in the test. + await bidi_session.browsing_context.activate(context=context["context"]) + + result = await bidi_session.script.call_function( + function_declaration="""(multiplier) => + new Promise( + resolve => window.navigator.geolocation.getCurrentPosition( + position => resolve(position.coords.toJSON()), + error => resolve({code: error.code}), + {timeout: 500 * multiplier} + )) + """, + arguments=[{"type": "number", "value": configuration["timeout_multiplier"]}], + target=ContextTarget(context["context"]), + await_promise=True, + ) + + return remote_mapping_to_dict(result["value"]) + + return get_current_geolocation @pytest_asyncio.fixture
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/contexts.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/contexts.py index 8a0e434..068bb80 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/contexts.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/contexts.py
@@ -2,14 +2,14 @@ from webdriver.bidi.modules.emulation import CoordinatesOptions -from . import get_current_geolocation, TEST_COORDINATES +from . import TEST_COORDINATES pytestmark = pytest.mark.asyncio async def test_contexts( - bidi_session, new_tab, top_context, url, set_geolocation_permission + bidi_session, new_tab, top_context, url, get_current_geolocation, set_geolocation_permission ): test_url = url("/common/blank.html") await bidi_session.browsing_context.navigate( @@ -24,12 +24,10 @@ ) await set_geolocation_permission(new_tab) - default_coordinates = await get_current_geolocation(bidi_session, new_tab) + default_coordinates = await get_current_geolocation(new_tab) assert default_coordinates != TEST_COORDINATES - assert ( - await get_current_geolocation(bidi_session, top_context) == default_coordinates - ) + assert await get_current_geolocation(top_context) == default_coordinates # Set geolocation override. await bidi_session.emulation.set_geolocation_override( @@ -41,24 +39,20 @@ ), ) - assert await get_current_geolocation(bidi_session, new_tab) == TEST_COORDINATES - assert ( - await get_current_geolocation(bidi_session, top_context) == default_coordinates - ) + assert await get_current_geolocation(new_tab) == TEST_COORDINATES + assert await get_current_geolocation(top_context) == default_coordinates # Reset geolocation override. await bidi_session.emulation.set_geolocation_override( contexts=[new_tab["context"]], coordinates=None ) - assert await get_current_geolocation(bidi_session, new_tab) == default_coordinates - assert ( - await get_current_geolocation(bidi_session, top_context) == default_coordinates - ) + assert await get_current_geolocation(new_tab) == default_coordinates + assert await get_current_geolocation(top_context) == default_coordinates async def test_multiple_contexts( - bidi_session, new_tab, url, set_geolocation_permission + bidi_session, new_tab, url, get_current_geolocation, set_geolocation_permission ): new_context = await bidi_session.browsing_context.create(type_hint="tab") test_url = url("/common/blank.html") @@ -74,12 +68,10 @@ ) await set_geolocation_permission(new_tab) - default_coordinates = await get_current_geolocation(bidi_session, new_tab) + default_coordinates = await get_current_geolocation(new_tab) assert default_coordinates != TEST_COORDINATES - assert ( - await get_current_geolocation(bidi_session, new_context) == default_coordinates - ) + assert await get_current_geolocation(new_context) == default_coordinates # Set geolocation override. await bidi_session.emulation.set_geolocation_override( @@ -91,8 +83,8 @@ ), ) - assert await get_current_geolocation(bidi_session, new_tab) == TEST_COORDINATES - assert await get_current_geolocation(bidi_session, new_context) == TEST_COORDINATES + assert await get_current_geolocation(new_tab) == TEST_COORDINATES + assert await get_current_geolocation(new_context) == TEST_COORDINATES # Reset geolocation override. await bidi_session.emulation.set_geolocation_override( @@ -101,7 +93,5 @@ # The new coordinates can be different from the initial ones if the position # was not available at the beginning. - assert await get_current_geolocation(bidi_session, new_tab) != TEST_COORDINATES - assert ( - await get_current_geolocation(bidi_session, new_context) != TEST_COORDINATES - ) + assert await get_current_geolocation(new_tab) != TEST_COORDINATES + assert await get_current_geolocation(new_context) != TEST_COORDINATES
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/coordinates.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/coordinates.py index b23354e..ea4fe64 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/coordinates.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/coordinates.py
@@ -4,7 +4,6 @@ from webdriver.bidi.modules.script import ContextTarget from ... import remote_mapping_to_dict -from . import get_current_geolocation pytestmark = pytest.mark.asyncio @@ -22,7 +21,12 @@ ], ) async def test_get_current_position( - bidi_session, new_tab, url, set_geolocation_permission, test_coordinates + bidi_session, + new_tab, + url, + get_current_geolocation, + set_geolocation_permission, + test_coordinates, ): test_url = url("/common/blank.html") await bidi_session.browsing_context.navigate( @@ -32,7 +36,7 @@ ) await set_geolocation_permission(new_tab) - default_coordinates = await get_current_geolocation(bidi_session, new_tab) + default_coordinates = await get_current_geolocation(new_tab) # Set default accuracy value. if "accuracy" not in test_coordinates: @@ -44,7 +48,7 @@ contexts=[new_tab["context"]], coordinates=test_coordinates ) - assert await get_current_geolocation(bidi_session, new_tab) == test_coordinates + assert await get_current_geolocation(new_tab) == test_coordinates async def test_watch_position( @@ -132,7 +136,7 @@ async def test_persists_on_reload( - bidi_session, url, new_tab, set_geolocation_permission + bidi_session, url, new_tab, get_current_geolocation, set_geolocation_permission ): test_url = url("/common/blank.html") await bidi_session.browsing_context.navigate( @@ -153,17 +157,17 @@ ), ) - assert await get_current_geolocation(bidi_session, new_tab) == test_coordinates + assert await get_current_geolocation(new_tab) == test_coordinates await bidi_session.browsing_context.reload( context=new_tab["context"], wait="complete" ) - assert await get_current_geolocation(bidi_session, new_tab) == test_coordinates + assert await get_current_geolocation(new_tab) == test_coordinates async def test_persists_on_navigation( - bidi_session, url, new_tab, set_geolocation_permission + bidi_session, url, new_tab, get_current_geolocation, set_geolocation_permission ): test_url = url("/common/blank.html") await bidi_session.browsing_context.navigate( @@ -184,7 +188,7 @@ ), ) - assert await get_current_geolocation(bidi_session, new_tab) == test_coordinates + assert await get_current_geolocation(new_tab) == test_coordinates await bidi_session.browsing_context.navigate( context=new_tab["context"], @@ -192,4 +196,24 @@ wait="complete", ) - assert await get_current_geolocation(bidi_session, new_tab) == test_coordinates + assert await get_current_geolocation(new_tab) == test_coordinates + + +async def test_reset_without_override( + bidi_session, new_tab, url, get_current_geolocation, set_geolocation_permission +): + test_url = url("/common/blank.html") + await bidi_session.browsing_context.navigate( + context=new_tab["context"], + url=test_url, + wait="complete", + ) + await set_geolocation_permission(new_tab) + + default_coordinates = await get_current_geolocation(new_tab) + + await bidi_session.emulation.set_geolocation_override( + contexts=[new_tab["context"]], coordinates=None + ) + + assert await get_current_geolocation(new_tab) == default_coordinates
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/error.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/error.py index ec905e3..27c23dc7 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/error.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/error.py
@@ -3,7 +3,6 @@ from webdriver.bidi.modules.script import ContextTarget from ... import remote_mapping_to_dict -from . import get_current_geolocation pytestmark = pytest.mark.asyncio @@ -12,7 +11,7 @@ async def test_get_current_position(bidi_session, new_tab, url, - set_geolocation_permission): + get_current_geolocation, set_geolocation_permission): test_url = url("/common/blank.html") await bidi_session.browsing_context.navigate( context=new_tab["context"], @@ -25,8 +24,7 @@ contexts=[new_tab["context"]], error=ERROR ) - assert await get_current_geolocation(bidi_session, - new_tab) == EXPECTED_ERROR + assert await get_current_geolocation(new_tab) == EXPECTED_ERROR async def test_watch_position( @@ -72,7 +70,7 @@ async def test_persists_on_reload( - bidi_session, url, new_tab, set_geolocation_permission + bidi_session, url, new_tab, get_current_geolocation, set_geolocation_permission ): test_url = url("/common/blank.html") await bidi_session.browsing_context.navigate( @@ -88,19 +86,17 @@ error=ERROR, ) - assert await get_current_geolocation(bidi_session, - new_tab) == EXPECTED_ERROR + assert await get_current_geolocation(new_tab) == EXPECTED_ERROR await bidi_session.browsing_context.reload( context=new_tab["context"], wait="complete" ) - assert await get_current_geolocation(bidi_session, - new_tab) == EXPECTED_ERROR + assert await get_current_geolocation(new_tab) == EXPECTED_ERROR async def test_persists_on_navigation( - bidi_session, url, new_tab, set_geolocation_permission + bidi_session, url, new_tab, get_current_geolocation, set_geolocation_permission ): test_url = url("/common/blank.html") await bidi_session.browsing_context.navigate( @@ -116,8 +112,7 @@ error=ERROR, ) - assert await get_current_geolocation(bidi_session, - new_tab) == EXPECTED_ERROR + assert await get_current_geolocation(new_tab) == EXPECTED_ERROR await bidi_session.browsing_context.navigate( context=new_tab["context"], @@ -125,5 +120,4 @@ wait="complete", ) - assert await get_current_geolocation(bidi_session, - new_tab) == EXPECTED_ERROR + assert await get_current_geolocation(new_tab) == EXPECTED_ERROR
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/user_contexts.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/user_contexts.py index 008dee5..b3038bb5 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/user_contexts.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/bidi/emulation/set_geolocation_override/user_contexts.py
@@ -2,14 +2,19 @@ from webdriver.bidi.modules.emulation import CoordinatesOptions -from . import get_current_geolocation, TEST_COORDINATES +from . import TEST_COORDINATES pytestmark = pytest.mark.asyncio async def test_user_contexts( - bidi_session, url, create_user_context, new_tab, set_geolocation_permission + bidi_session, + url, + create_user_context, + new_tab, + get_current_geolocation, + set_geolocation_permission, ): user_context = await create_user_context() context_in_user_context_1 = await bidi_session.browsing_context.create( @@ -29,12 +34,10 @@ await set_geolocation_permission(new_tab) await set_geolocation_permission(new_tab, user_context) - default_coordinates = await get_current_geolocation( - bidi_session, context_in_user_context_1 - ) + default_coordinates = await get_current_geolocation(context_in_user_context_1) assert default_coordinates != TEST_COORDINATES - assert await get_current_geolocation(bidi_session, new_tab) == default_coordinates + assert await get_current_geolocation(new_tab) == default_coordinates # Set geolocation override. await bidi_session.emulation.set_geolocation_override( @@ -46,11 +49,8 @@ ), ) - assert ( - await get_current_geolocation(bidi_session, context_in_user_context_1) - == TEST_COORDINATES - ) - assert await get_current_geolocation(bidi_session, new_tab) == default_coordinates + assert await get_current_geolocation(context_in_user_context_1) == TEST_COORDINATES + assert await get_current_geolocation(new_tab) == default_coordinates # Create a new context in the user context. context_in_user_context_2 = await bidi_session.browsing_context.create( @@ -62,14 +62,16 @@ wait="complete", ) - assert ( - await get_current_geolocation(bidi_session, context_in_user_context_2) - == TEST_COORDINATES - ) + assert await get_current_geolocation(context_in_user_context_2) == TEST_COORDINATES async def test_set_to_default_user_context( - bidi_session, new_tab, create_user_context, url, set_geolocation_permission + bidi_session, + new_tab, + create_user_context, + url, + get_current_geolocation, + set_geolocation_permission, ): user_context = await create_user_context() context_in_user_context_1 = await bidi_session.browsing_context.create( @@ -89,7 +91,7 @@ await set_geolocation_permission(new_tab) await set_geolocation_permission(new_tab, user_context) - default_coordinates = await get_current_geolocation(bidi_session, new_tab) + default_coordinates = await get_current_geolocation(new_tab) assert default_coordinates != TEST_COORDINATES await bidi_session.emulation.set_geolocation_override( @@ -103,10 +105,9 @@ # Make sure that the geolocation changes are only applied to the context associated with default user context. assert ( - await get_current_geolocation(bidi_session, context_in_user_context_1) - == default_coordinates + await get_current_geolocation(context_in_user_context_1) == default_coordinates ) - assert await get_current_geolocation(bidi_session, new_tab) == TEST_COORDINATES + assert await get_current_geolocation(new_tab) == TEST_COORDINATES # Create a new context in the default context. context_in_default_context_2 = await bidi_session.browsing_context.create( @@ -120,8 +121,7 @@ ) assert ( - await get_current_geolocation(bidi_session, context_in_default_context_2) - == TEST_COORDINATES + await get_current_geolocation(context_in_default_context_2) == TEST_COORDINATES ) # Reset geolocation override. @@ -131,7 +131,11 @@ async def test_set_to_multiple_user_contexts( - bidi_session, create_user_context, url, set_geolocation_permission + bidi_session, + create_user_context, + url, + get_current_geolocation, + set_geolocation_permission, ): user_context_1 = await create_user_context() context_in_user_context_1 = await bidi_session.browsing_context.create( @@ -164,18 +168,17 @@ ), ) - assert ( - await get_current_geolocation(bidi_session, context_in_user_context_1) - == TEST_COORDINATES - ) - assert ( - await get_current_geolocation(bidi_session, context_in_user_context_2) - == TEST_COORDINATES - ) + assert await get_current_geolocation(context_in_user_context_1) == TEST_COORDINATES + assert await get_current_geolocation(context_in_user_context_2) == TEST_COORDINATES async def test_set_to_user_context_and_then_to_context( - bidi_session, create_user_context, url, new_tab, set_geolocation_permission + bidi_session, + create_user_context, + url, + new_tab, + get_current_geolocation, + set_geolocation_permission, ): user_context = await create_user_context() context_in_user_context_1 = await bidi_session.browsing_context.create( @@ -195,9 +198,7 @@ await set_geolocation_permission(new_tab) await set_geolocation_permission(new_tab, user_context) - default_coordinates = await get_current_geolocation( - bidi_session, context_in_user_context_1 - ) + default_coordinates = await get_current_geolocation(context_in_user_context_1) assert default_coordinates != TEST_COORDINATES @@ -222,7 +223,7 @@ ), ) assert ( - await get_current_geolocation(bidi_session, context_in_user_context_1) + await get_current_geolocation(context_in_user_context_1) == new_geolocation_coordinates ) @@ -232,7 +233,7 @@ # Make sure that after reload the geolocation is still updated. assert ( - await get_current_geolocation(bidi_session, context_in_user_context_1) + await get_current_geolocation(context_in_user_context_1) == new_geolocation_coordinates ) @@ -246,10 +247,7 @@ wait="complete", ) # Make sure that the geolocation override for the user context is applied. - assert ( - await get_current_geolocation(bidi_session, context_in_user_context_2) - == TEST_COORDINATES - ) + assert await get_current_geolocation(context_in_user_context_2) == TEST_COORDINATES await bidi_session.emulation.set_geolocation_override( contexts=[context_in_user_context_1["context"]], @@ -258,6 +256,5 @@ # Make sure that the geolocation override was reset. assert ( - await get_current_geolocation(bidi_session, context_in_user_context_1) - == default_coordinates + await get_current_geolocation(context_in_user_context_1) == default_coordinates )
diff --git a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js index 3b59c3b..64f3776 100644 --- a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js +++ b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.js
@@ -924,6 +924,89 @@ } } }, + { + 'name': 'quantized elu', + 'graph': { + 'inputs': { + 'input': { + 'data': [ + 1.6811466217041016, 0.0479511022567749, 0.33355462551116943, + -0.1988269537687301, -0.0041167140007019, -0.0634240251779556, + ], + 'descriptor': {shape: [2, 3], dataType: 'float32'}, + 'constant': false + }, + 'inputScale': { + 'data': [0.003921568859368563], + 'descriptor': {shape: [1], dataType: 'float32'}, + 'constant': true + }, + 'inputZeroPoint': { + 'data': [0], + 'descriptor': {shape: [1], dataType: 'int8'}, + 'constant': true + }, + 'outputScale': { + 'data': [0.003921568859368563], + 'descriptor': {shape: [1], dataType: 'float32'}, + 'constant': true + }, + 'outputZeroPoint': { + 'data': [0], + 'descriptor': {shape: [1], dataType: 'int8'}, + 'constant': true + }, + }, + 'operators': [ + { + 'name': 'quantizeLinear', + 'arguments': [ + {'input': 'input'}, + {'scale': 'inputScale', 'zeroPoint': 'inputZeroPoint'} + ], + 'outputs': 'quantizedInput' + }, + { + 'name': 'dequantizeLinear', + 'arguments': [ + {'input': 'quantizedInput'}, + {'scale': 'inputScale', 'zeroPoint': 'inputZeroPoint'} + ], + 'outputs': 'dequantizedInput' + }, + { + 'name': 'elu', + 'arguments': [{'input': 'dequantizedInput'}], + 'outputs': 'eluOutput' + }, + { + 'name': 'quantizeLinear', + 'arguments': [ + {'input': 'eluOutput'}, + {'scale': 'outputScale', 'zeroPoint': 'outputZeroPoint'} + ], + 'outputs': 'quantizedeluOutput' + }, + { + 'name': 'dequantizeLinear', + 'arguments': [ + {'input': 'quantizedeluOutput'}, + {'scale': 'outputScale', 'zeroPoint': 'outputZeroPoint'} + ], + 'outputs': 'output' + } + ], + 'expectedOutputs': { + 'output': { + 'data': [ + 0.49803924560546875, 0.0470588281750679, 0.3333333432674408, + -0.18039216101169586, -0.003921568859368563, -0.062745101749897, + ], + 'descriptor': {shape: [2, 3], dataType: 'float32'} + } + } + } + }, ]; if (navigator.ml) {
diff --git a/third_party/blink/web_tests/http/tests/lcp_critical_path_predictor/prioritize_lcp_image.php b/third_party/blink/web_tests/http/tests/lcp_critical_path_predictor/prioritize_lcp_image.php index db9f592c..34b93d9 100644 --- a/third_party/blink/web_tests/http/tests/lcp_critical_path_predictor/prioritize_lcp_image.php +++ b/third_party/blink/web_tests/http/tests/lcp_critical_path_predictor/prioritize_lcp_image.php
@@ -18,19 +18,14 @@ const hint_matched_img_priority = await internals.getInitialResourcePriority(url, document); assert_equals(hint_matched_img_priority, kVeryHigh); - }, "Ensure LCPP hinted images were loaded with VeryHigh priority.") + }, "Ensure LCPP hinted images were loaded with VeryHigh priority."); promise_test(async t => { const url = new URL('/resources/square100.png', location).toString(); const hint_matched_img_priority = await internals.getInitialResourcePriority(url, document); assert_equals(hint_matched_img_priority, kMedium); - }, "Ensure non-LCPP hinted images were loaded unaffected with Medium priority.") - - promise_test(async t => { - const lcp_element = await internals.LCPPrediction(document); - assert_equals(lcp_element, "/#lcp_image"); - }, "Ensure document::RunLCPPredictedCallbacks is called with LCP element locator.") + }, "Ensure non-LCPP hinted images were loaded unaffected with Medium priority."); </script> <img src="/resources/square.png" id="lcp_image"> <img src="/resources/square100.png">
diff --git a/third_party/blink/web_tests/http/tests/lcp_critical_path_predictor/resources/common.js b/third_party/blink/web_tests/http/tests/lcp_critical_path_predictor/resources/common.js index 8fc4da50..b8a049c 100644 --- a/third_party/blink/web_tests/http/tests/lcp_critical_path_predictor/resources/common.js +++ b/third_party/blink/web_tests/http/tests/lcp_critical_path_predictor/resources/common.js
@@ -15,6 +15,7 @@ const hint = new LCPCriticalPathPredictorNavigationTimeHint(); // All fields are non-nullable. hint.lcpElementLocators = []; + hint.lcpElementLocatorsAll = []; hint.lcpInfluencerScripts = params.lcpInfluencerScripts || []; hint.fetchedFonts = params.fetchedFonts || []; hint.preconnectOrigins = params.preconnectOrigins || []; @@ -36,6 +37,11 @@ hint.lcpElementLocators.push(await getLCPBytes(proto)); } + const lcp_locator_protos_all = params.lcp_locator_protos_all || []; + for (let proto of lcp_locator_protos_all) { + hint.lcpElementLocatorsAll.push(await getLCPBytes(proto)); + } + const web_test_control_host_remote = new NonAssociatedWebTestControlHostRemote(); web_test_control_host_remote.$.bindNewPipeAndPassReceiver().bindInBrowser(
diff --git a/third_party/blink/web_tests/http/tests/lcpp_timing_predictor/timing_predictor_fallback_delayed_lcp.php b/third_party/blink/web_tests/http/tests/lcpp_timing_predictor/timing_predictor_fallback_delayed_lcp.php index b5873e8..49e82ac 100644 --- a/third_party/blink/web_tests/http/tests/lcpp_timing_predictor/timing_predictor_fallback_delayed_lcp.php +++ b/third_party/blink/web_tests/http/tests/lcpp_timing_predictor/timing_predictor_fallback_delayed_lcp.php
@@ -2,7 +2,8 @@ <script src="/priorities/resources/common.js"></script> <script type=module> import {setupLCPTest} from "../lcp_critical_path_predictor/resources/common.js"; -await setupLCPTest(["lcp_image_id.pb"]); +await setupLCPTest({ + lcp_locator_protos_all :["lcp_image_id.pb"]}); </script> <?php // Do not output the HTML below this PHP block until the test is reloaded with
diff --git a/third_party/blink/web_tests/http/tests/lcpp_timing_predictor/timing_predictor_hit_secondary.php b/third_party/blink/web_tests/http/tests/lcpp_timing_predictor/timing_predictor_hit_secondary.php index 4a7b35e..2c03112a 100644 --- a/third_party/blink/web_tests/http/tests/lcpp_timing_predictor/timing_predictor_hit_secondary.php +++ b/third_party/blink/web_tests/http/tests/lcpp_timing_predictor/timing_predictor_hit_secondary.php
@@ -2,7 +2,8 @@ <script src="/priorities/resources/common.js"></script> <script type=module> import {setupLCPTest} from "../lcp_critical_path_predictor/resources/common.js"; -await setupLCPTest(["lcp_image_id.pb", "lcp_image_id_b.pb"]); +await setupLCPTest({ + lcp_locator_protos_all :["lcp_image_id.pb", "lcp_image_id_b.pb"]}); </script> <?php // Do not output the HTML below this PHP block until the test is reloaded with
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/foldable-apis-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/foldable-apis-origin-trial-interfaces.html deleted file mode 100644 index 2bf18d6..0000000 --- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/foldable-apis-origin-trial-interfaces.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<!-- Generate token with the command: -generate_token.py http://127.0.0.1:8000 FoldableAPIs --expire-timestamp=2000000000 --- --> -<meta http-equiv="origin-trial" content="AwbXTS8rkMQ7E3eYhkhRbmpyRf7dkXHwlUm2DR9yt+a/4UrtCvY5QVthdGlpXnDWi/VlABqvrgXEFdASIzs2uQEAAABUeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiRm9sZGFibGVBUElzIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9" /> -<title>Foldable APIs - interfaces exposed by origin trial</title> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> -<script src="../../resources/origin-trials-helper.js"></script> -<script> -test(t => { - OriginTrialsHelper.check_properties_exist(this, - { - 'Navigator': ['devicePosture'], - 'DevicePosture': ['type'], - }, - ); - OriginTrialsHelper.check_properties_exist(this, - { - 'Viewport': ['segments'], - }, - ); -}, "Foldables APIs related interfaces in Origin-Trial enabled document."); - -</script>
diff --git a/third_party/blink/web_tests/platform/android/external/wpt/serial/idlharness.https.any-expected.txt b/third_party/blink/web_tests/platform/android/external/wpt/serial/idlharness.https.any-expected.txt index a03b903b..bf166f0d 100644 --- a/third_party/blink/web_tests/platform/android/external/wpt/serial/idlharness.https.any-expected.txt +++ b/third_party/blink/web_tests/platform/android/external/wpt/serial/idlharness.https.any-expected.txt
@@ -1,75 +1,5 @@ This is a testharness.js-based test. -Found 36 FAIL, 0 TIMEOUT, 0 NOTRUN. -[FAIL] Serial interface: existence and properties of interface object - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface object length - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface object name - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: existence and properties of interface prototype object - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: existence and properties of interface prototype object's "constructor" property - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: existence and properties of interface prototype object's @@unscopables property - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: attribute onconnect - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: attribute ondisconnect - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: operation getPorts() - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: operation requestPort(optional SerialPortRequestOptions) - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial must be primary interface of navigator.serial - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Stringification of navigator.serial - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: navigator.serial must inherit property "onconnect" with the proper type - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: navigator.serial must inherit property "ondisconnect" with the proper type - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: navigator.serial must inherit property "getPorts()" with the proper type - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: navigator.serial must inherit property "requestPort(optional SerialPortRequestOptions)" with the proper type - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: calling requestPort(optional SerialPortRequestOptions) on navigator.serial with too few arguments must throw TypeError - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] SerialPort interface: existence and properties of interface object - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface object length - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface object name - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: existence and properties of interface prototype object - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: existence and properties of interface prototype object's "constructor" property - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: existence and properties of interface prototype object's @@unscopables property - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: attribute onconnect - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: attribute ondisconnect - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing +Found 1 FAIL, 0 TIMEOUT, 0 NOTRUN. [FAIL] SerialPort interface: attribute connected - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: attribute readable - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: attribute writable - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation getInfo() - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation open(SerialOptions) - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation setSignals(optional SerialOutputSignals) - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation getSignals() - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation close() - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation forget() - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] Navigator interface: attribute serial - assert_true: The prototype object must have a property "serial" expected true got false -[FAIL] Navigator interface: navigator must inherit property "serial" with the proper type - assert_inherits: property "serial" not found in prototype chain + assert_true: The prototype object must have a property "connected" expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/android/external/wpt/serial/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/platform/android/external/wpt/serial/idlharness.https.any.worker-expected.txt index eb943727..bf166f0d 100644 --- a/third_party/blink/web_tests/platform/android/external/wpt/serial/idlharness.https.any.worker-expected.txt +++ b/third_party/blink/web_tests/platform/android/external/wpt/serial/idlharness.https.any.worker-expected.txt
@@ -1,73 +1,5 @@ This is a testharness.js-based test. -Found 35 FAIL, 0 TIMEOUT, 0 NOTRUN. -[FAIL] Serial interface: existence and properties of interface object - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface object length - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface object name - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: existence and properties of interface prototype object - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: existence and properties of interface prototype object's "constructor" property - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: existence and properties of interface prototype object's @@unscopables property - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: attribute onconnect - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: attribute ondisconnect - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: operation getPorts() - assert_own_property: self does not have own property "Serial" expected property "Serial" missing -[FAIL] Serial interface: member requestPort - Cannot use 'in' operator to search for 'requestPort' in undefined -[FAIL] Serial must be primary interface of navigator.serial - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Stringification of navigator.serial - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: navigator.serial must inherit property "onconnect" with the proper type - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: navigator.serial must inherit property "ondisconnect" with the proper type - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: navigator.serial must inherit property "getPorts()" with the proper type - assert_equals: wrong typeof object expected "object" but got "undefined" -[FAIL] Serial interface: navigator.serial must not have property "requestPort" - Cannot use 'in' operator to search for 'requestPort' in undefined -[FAIL] SerialPort interface: existence and properties of interface object - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface object length - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface object name - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: existence and properties of interface prototype object - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: existence and properties of interface prototype object's "constructor" property - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: existence and properties of interface prototype object's @@unscopables property - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: attribute onconnect - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: attribute ondisconnect - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing +Found 1 FAIL, 0 TIMEOUT, 0 NOTRUN. [FAIL] SerialPort interface: attribute connected - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: attribute readable - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: attribute writable - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation getInfo() - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation open(SerialOptions) - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation setSignals(optional SerialOutputSignals) - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation getSignals() - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation close() - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] SerialPort interface: operation forget() - assert_own_property: self does not have own property "SerialPort" expected property "SerialPort" missing -[FAIL] WorkerNavigator interface: attribute serial - assert_true: The prototype object must have a property "serial" expected true got false -[FAIL] WorkerNavigator interface: navigator must inherit property "serial" with the proper type - assert_inherits: property "serial" not found in prototype chain + assert_true: The prototype object must have a property "connected" expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/mac-mac11/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice-expected.txt b/third_party/blink/web_tests/platform/mac-mac11/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice-expected.txt deleted file mode 100644 index 5b37deb..0000000 --- a/third_party/blink/web_tests/platform/mac-mac11/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice-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/virtual/customizable-select-disabled/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt b/third_party/blink/web_tests/virtual/customizable-select-disabled/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt new file mode 100644 index 0000000..3fde5cc --- /dev/null +++ b/third_party/blink/web_tests/virtual/customizable-select-disabled/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: Cannot read properties of null (reading 'appendChild') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=fetch-handler-expected.txt b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=fetch-handler-expected.txt new file mode 100644 index 0000000..042227b9 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=fetch-handler-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Prefetch with ServiceWorker (fetch-handler) + assert_equals: prefetch requests to initial URL should be sent to the server. expected 1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=fetch-handler-to-fallback-expected.txt b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=fetch-handler-to-fallback-expected.txt new file mode 100644 index 0000000..6583f56 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=fetch-handler-to-fallback-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Prefetch with ServiceWorker (fetch-handler-to-fallback) + assert_equals: prefetch requests to initial URL should be sent to the server. expected 1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=no-fetch-handler-expected.txt b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=no-fetch-handler-expected.txt new file mode 100644 index 0000000..7c599b4 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-in_sw=no-fetch-handler-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Prefetch with ServiceWorker (no-fetch-handler) + assert_equals: prefetch requests to initial URL should be sent to the server. expected 1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=fetch-handler-expected.txt b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=fetch-handler-expected.txt new file mode 100644 index 0000000..042227b9 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=fetch-handler-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Prefetch with ServiceWorker (fetch-handler) + assert_equals: prefetch requests to initial URL should be sent to the server. expected 1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=fetch-handler-to-fallback-expected.txt b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=fetch-handler-to-fallback-expected.txt new file mode 100644 index 0000000..6583f56 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=fetch-handler-to-fallback-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Prefetch with ServiceWorker (fetch-handler-to-fallback) + assert_equals: prefetch requests to initial URL should be sent to the server. expected 1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=no-fetch-handler-expected.txt b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=no-fetch-handler-expected.txt new file mode 100644 index 0000000..7c599b4 --- /dev/null +++ b/third_party/blink/web_tests/virtual/prefetch/external/wpt/speculation-rules/prefetch/tentative/service-worker/redirect.sub.https_origin=same-site_sc=in-out_sw=no-fetch-handler-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Prefetch with ServiceWorker (no-fetch-handler) + assert_equals: prefetch requests to initial URL should be sent to the server. expected 1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt b/third_party/blink/web_tests/virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt new file mode 100644 index 0000000..3fde5cc --- /dev/null +++ b/third_party/blink/web_tests/virtual/select-parser-relaxation-opt-out/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +Harness Error. harness_status.status = 1 , harness_status.message = Uncaught TypeError: Cannot read properties of null (reading 'appendChild') +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/select-parser-relaxation/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt b/third_party/blink/web_tests/virtual/select-parser-relaxation/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt new file mode 100644 index 0000000..e3f13fc --- /dev/null +++ b/third_party/blink/web_tests/virtual/select-parser-relaxation/external/wpt/html/semantics/forms/the-select-element/customizable-select/select-input-keyboard-behavior.tentative-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] Keyboard behavior of <input> in <select>. + assert_equals: appearance: base-select must be supported for this test to run. expected "base-select" but got "auto" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt index 71375285..78be227 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
@@ -134,6 +134,7 @@ PASS window.cached_styleMedia.type is '' PASS window.cached_toolbar.visible is false PASS window.cached_trustedTypes.defaultPolicy is null +PASS window.cached_viewport.segments is null PASS window.cached_visualViewport.height is 0 PASS window.cached_visualViewport.offsetLeft is 0 PASS window.cached_visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt index ad60be25..e616044d 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
@@ -134,6 +134,7 @@ PASS window.cached_styleMedia.type is '' PASS window.cached_toolbar.visible is false PASS window.cached_trustedTypes.defaultPolicy is null +PASS window.cached_viewport.segments is null PASS window.cached_visualViewport.height is 0 PASS window.cached_visualViewport.offsetLeft is 0 PASS window.cached_visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt index 8d77c5c..a2791361 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
@@ -134,6 +134,7 @@ PASS window.cached_styleMedia.type is '' PASS window.cached_toolbar.visible is false PASS window.cached_trustedTypes.defaultPolicy is null +PASS window.cached_viewport.segments is null PASS window.cached_visualViewport.height is 0 PASS window.cached_visualViewport.offsetLeft is 0 PASS window.cached_visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt index ad21b7a2..9dd9a87 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -284,6 +284,7 @@ PASS oldChildWindow.styleMedia.type is newChildWindow.styleMedia.type PASS oldChildWindow.toolbar.visible is newChildWindow.toolbar.visible PASS oldChildWindow.trustedTypes.defaultPolicy is newChildWindow.trustedTypes.defaultPolicy +PASS oldChildWindow.viewport.segments is newChildWindow.viewport.segments PASS oldChildWindow.visualViewport.height is newChildWindow.visualViewport.height PASS oldChildWindow.visualViewport.offsetLeft is newChildWindow.visualViewport.offsetLeft PASS oldChildWindow.visualViewport.offsetTop is newChildWindow.visualViewport.offsetTop
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt index 81eac550..3169310 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-and-gced-expected.txt
@@ -215,6 +215,7 @@ PASS childWindow.styleMedia.type is '' PASS childWindow.toolbar.visible is false PASS childWindow.trustedTypes.defaultPolicy is null +PASS childWindow.viewport.segments is null PASS childWindow.visualViewport.height is 0 PASS childWindow.visualViewport.offsetLeft is 0 PASS childWindow.visualViewport.offsetTop is 0
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt index 518adb2..484ae5fd 100644 --- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-removed-expected.txt
@@ -215,6 +215,7 @@ PASS childWindow.styleMedia.type is '' PASS childWindow.toolbar.visible is false PASS childWindow.trustedTypes.defaultPolicy is null +PASS childWindow.viewport.segments is null PASS childWindow.visualViewport.height is 0 PASS childWindow.visualViewport.offsetLeft is 0 PASS childWindow.visualViewport.offsetTop is 0
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 62ae0652..e9cccf5 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
@@ -5229,6 +5229,14 @@ getter isComposing method constructor method getTargetRanges +interface IntegrityViolationReportBody : ReportBody + attribute @@toStringTag + getter blockedURL + getter destination + getter documentURL + getter reportOnly + method constructor + method toJSON interface IntersectionObserver attribute @@toStringTag getter delay @@ -9702,6 +9710,10 @@ method has method keys method values +interface Viewport + attribute @@toStringTag + getter segments + method constructor interface VirtualKeyboard : EventTarget attribute @@toStringTag getter boundingRect @@ -12132,6 +12144,7 @@ getter toolbar getter top getter trustedTypes + getter viewport getter visualViewport getter window method NodeFilter @@ -12346,6 +12359,7 @@ setter status setter statusbar setter toolbar + setter viewport setter visualViewport PASS successfullyParsed is true
diff --git a/third_party/blink/web_tests/wpt_internal/webxr/resources/xr-internal-device-mocking.js b/third_party/blink/web_tests/wpt_internal/webxr/resources/xr-internal-device-mocking.js index 78a155f..3e6a528 100644 --- a/third_party/blink/web_tests/wpt_internal/webxr/resources/xr-internal-device-mocking.js +++ b/third_party/blink/web_tests/wpt_internal/webxr/resources/xr-internal-device-mocking.js
@@ -49,12 +49,13 @@ reflectionProbe: { cubeMap: { widthAndHeight: 16, - positiveX: new Array(16 * 16).fill({ red: 0, green: 0, blue: 0, alpha: 0 }), - negativeX: new Array(16 * 16).fill({ red: 0, green: 0, blue: 0, alpha: 0 }), - positiveY: new Array(16 * 16).fill({ red: 0, green: 0, blue: 0, alpha: 0 }), - negativeY: new Array(16 * 16).fill({ red: 0, green: 0, blue: 0, alpha: 0 }), - positiveZ: new Array(16 * 16).fill({ red: 0, green: 0, blue: 0, alpha: 0 }), - negativeZ: new Array(16 * 16).fill({ red: 0, green: 0, blue: 0, alpha: 0 }), + // Arrays should be widthAndHeight^2 * 4 channels per pixel (r, g, b, a). + positiveX: new Array(16 * 16 * 4).fill(0), + negativeX: new Array(16 * 16 * 4).fill(0), + positiveY: new Array(16 * 16 * 4).fill(0), + negativeY: new Array(16 * 16 * 4).fill(0), + positiveZ: new Array(16 * 16 * 4).fill(0), + negativeZ: new Array(16 * 16 * 4).fill(0), }, }, };
diff --git a/third_party/catapult b/third_party/catapult index 4a83985..52ad7cf 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit 4a839855c5e79d91689784e2c7284f3f6288123b +Subproject commit 52ad7cf544050f01f47c070716b9dae8eb9fab2b
diff --git a/third_party/crashpad/crashpad/test/ios/crash_type_xctest.mm b/third_party/crashpad/crashpad/test/ios/crash_type_xctest.mm index 1c92fb6..b6d1bff 100644 --- a/third_party/crashpad/crashpad/test/ios/crash_type_xctest.mm +++ b/third_party/crashpad/crashpad/test/ios/crash_type_xctest.mm
@@ -356,7 +356,8 @@ } #endif -- (void)testCrashWithAnnotations { +// TODO(crbug.com/416140624): The test is flaky. Enabled the test. +- (void)DISABLED_testCrashWithAnnotations { #if TARGET_OS_SIMULATOR // This test will fail on <iOS17 simulators when running on macOS >=14.3 or // <iOS18 simulators when running on macOS >=15.4 due to a bug in Simulator.
diff --git a/third_party/crossbench b/third_party/crossbench index 6f0c318..47e5e3d 160000 --- a/third_party/crossbench +++ b/third_party/crossbench
@@ -1 +1 @@ -Subproject commit 6f0c3181a39f6fdfbaea35689d8126e0361da071 +Subproject commit 47e5e3d994ddcc2319cec110ce670ccc1baa3223
diff --git a/third_party/dawn b/third_party/dawn index 0f24b33..968646ae 160000 --- a/third_party/dawn +++ b/third_party/dawn
@@ -1 +1 @@ -Subproject commit 0f24b334d63efffa544d1c2fc6d779576a3aa5e9 +Subproject commit 968646ae6a99b1751d5a7a4298e3bf6976123326
diff --git a/third_party/depot_tools b/third_party/depot_tools index 30d9438..18580cf 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit 30d9438e7baf0c045f973de2f517b51554d14d7d +Subproject commit 18580cf9c407a3c23aa072b9d745832516de699e
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 682af1f..28fbee1 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 682af1f84e33247088b8ca38e189f734ff9923ef +Subproject commit 28fbee169c8a26c6c2ed2ec2550465fe3d697a34
diff --git a/third_party/libc++/src b/third_party/libc++/src index a01c02c..a9cc573 160000 --- a/third_party/libc++/src +++ b/third_party/libc++/src
@@ -1 +1 @@ -Subproject commit a01c02c9d4acbdae3b7e8a2f3ee58579a9c29f96 +Subproject commit a9cc573e7c591795d11b72d8323ba0e573b55bd6
diff --git a/third_party/libxslt/chromium/change-atype-extra.patch b/third_party/libxslt/chromium/change-atype-extra.patch new file mode 100644 index 0000000..9e2f666 --- /dev/null +++ b/third_party/libxslt/chromium/change-atype-extra.patch
@@ -0,0 +1,110 @@ +diff --git a/third_party/libxslt/src/libxslt/transform.c b/third_party/libxslt/src/libxslt/transform.c +index 54ef821b5016f..1ac2471d6441b 100644 +--- a/third_party/libxslt/src/libxslt/transform.c ++++ b/third_party/libxslt/src/libxslt/transform.c +@@ -5772,7 +5772,8 @@ xsltCleanupSourceDoc(xmlDocPtr doc) { + xmlAttrPtr prop = cur->properties; + + while (prop) { +- prop->atype &= ~(XSLT_SOURCE_NODE_MASK << 27); ++ prop->extra &= ++ ~(XSLT_SOURCE_NODE_MASK << XSLT_SOURCE_NODE_SHIFT_32); + prop->psvi = NULL; + prop = prop->next; + } +diff --git a/third_party/libxslt/src/libxslt/xsltutils.c b/third_party/libxslt/src/libxslt/xsltutils.c +index a20da96182289..0155e7fc5a89f 100644 +--- a/third_party/libxslt/src/libxslt/xsltutils.c ++++ b/third_party/libxslt/src/libxslt/xsltutils.c +@@ -1920,26 +1920,26 @@ xsltSaveResultToString(xmlChar **doc_txt_ptr, int * doc_txt_len, + int + xsltGetSourceNodeFlags(xmlNodePtr node) { + /* +- * Squeeze the bit flags into the upper bits of ++ * Squeeze the bit flags into the upper 4 bits of + * +- * - 'int properties' member in struct _xmlDoc +- * - 'xmlAttributeType atype' member in struct _xmlAttr ++ * - 'unsigned int extra' member in struct _xmlDoc ++ * - 'unsigned int extra' member in struct _xmlAttr + * - 'unsigned short extra' member in struct _xmlNode + */ + switch (node->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +- return ((xmlDocPtr) node)->properties >> 27; ++ return ((xmlDocPtr) node)->extra >> XSLT_SOURCE_NODE_SHIFT_32; + + case XML_ATTRIBUTE_NODE: +- return ((xmlAttrPtr) node)->atype >> 27; ++ return ((xmlAttrPtr) node)->extra >> XSLT_SOURCE_NODE_SHIFT_32; + + case XML_ELEMENT_NODE: + case XML_TEXT_NODE: + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: +- return node->extra >> 12; ++ return node->extra >> XSLT_SOURCE_NODE_SHIFT_32; + + default: + return 0; +@@ -1964,11 +1964,11 @@ xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node, + switch (node->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +- ((xmlDocPtr) node)->properties |= flags << 27; ++ ((xmlDocPtr) node)->extra |= (flags << XSLT_SOURCE_NODE_SHIFT_32); + return 0; + + case XML_ATTRIBUTE_NODE: +- ((xmlAttrPtr) node)->atype |= flags << 27; ++ ((xmlAttrPtr) node)->extra |= (flags << XSLT_SOURCE_NODE_SHIFT_32); + return 0; + + case XML_ELEMENT_NODE: +@@ -1976,7 +1976,7 @@ xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node, + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: +- node->extra |= flags << 12; ++ node->extra |= (flags << XSLT_SOURCE_NODE_SHIFT_16); + return 0; + + default: +@@ -1998,11 +1998,11 @@ xsltClearSourceNodeFlags(xmlNodePtr node, int flags) { + switch (node->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: +- ((xmlDocPtr) node)->properties &= ~(flags << 27); ++ ((xmlDocPtr) node)->extra &= ~(flags << XSLT_SOURCE_NODE_SHIFT_32); + return 0; + + case XML_ATTRIBUTE_NODE: +- ((xmlAttrPtr) node)->atype &= ~(flags << 27); ++ ((xmlAttrPtr) node)->extra &= ~(flags << XSLT_SOURCE_NODE_SHIFT_32); + return 0; + + case XML_ELEMENT_NODE: +@@ -2010,7 +2010,7 @@ xsltClearSourceNodeFlags(xmlNodePtr node, int flags) { + case XML_CDATA_SECTION_NODE: + case XML_PI_NODE: + case XML_COMMENT_NODE: +- node->extra &= ~(flags << 12); ++ node->extra &= ~(flags << XSLT_SOURCE_NODE_SHIFT_16); + return 0; + + default: +diff --git a/third_party/libxslt/src/libxslt/xsltutils.h b/third_party/libxslt/src/libxslt/xsltutils.h +index 2514774b3f11a..d15d22726afaa 100644 +--- a/third_party/libxslt/src/libxslt/xsltutils.h ++++ b/third_party/libxslt/src/libxslt/xsltutils.h +@@ -261,6 +261,8 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL + #define XSLT_SOURCE_NODE_MASK 15u + #define XSLT_SOURCE_NODE_HAS_KEY 1u + #define XSLT_SOURCE_NODE_HAS_ID 2u ++#define XSLT_SOURCE_NODE_SHIFT_16 12u ++#define XSLT_SOURCE_NODE_SHIFT_32 28u + int + xsltGetSourceNodeFlags(xmlNodePtr node); + int
diff --git a/third_party/libxslt/chromium/change-id.patch b/third_party/libxslt/chromium/change-id.patch new file mode 100644 index 0000000..b151abb --- /dev/null +++ b/third_party/libxslt/chromium/change-id.patch
@@ -0,0 +1,114 @@ +diff --git a/third_party/libxslt/src/libxslt/functions.c b/third_party/libxslt/src/libxslt/functions.c +index 72a58dc4d6592..309af458c22f7 100644 +--- a/third_party/libxslt/src/libxslt/functions.c ++++ b/third_party/libxslt/src/libxslt/functions.c +@@ -760,7 +760,7 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){ + } + + if (xsltGetSourceNodeFlags(cur) & XSLT_SOURCE_NODE_HAS_ID) { +- id = (unsigned long) (size_t) *psviPtr; ++ id = (unsigned long) xsltGetSourceNodeValue(cur); + } else { + if (cur->type == XML_TEXT_NODE && cur->line == USHRT_MAX) { + /* Text nodes store big line numbers in psvi. */ +@@ -772,7 +772,7 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){ + goto out; + } + +- if (tctxt->currentId == ULONG_MAX) { ++ if (tctxt->currentId == XSLT_SOURCE_NODE_VALUE_MAX) { + xsltTransformError(tctxt, NULL, NULL, + "generate-id(): id overflow\n"); + ctxt->error = XPATH_MEMORY_ERROR; +@@ -780,7 +780,7 @@ xsltGenerateIdFunction(xmlXPathParserContextPtr ctxt, int nargs){ + } + + id = ++tctxt->currentId; +- *psviPtr = (void *) (size_t) id; ++ xsltSetSourceNodeValue(cur, id); + xsltSetSourceNodeFlags(tctxt, cur, XSLT_SOURCE_NODE_HAS_ID); + } + +diff --git a/third_party/libxslt/src/libxslt/xsltutils.c b/third_party/libxslt/src/libxslt/xsltutils.c +index 0155e7fc5a89f..aec8be4ad077c 100644 +--- a/third_party/libxslt/src/libxslt/xsltutils.c ++++ b/third_party/libxslt/src/libxslt/xsltutils.c +@@ -2018,6 +2018,54 @@ xsltClearSourceNodeFlags(xmlNodePtr node, int flags) { + } + } + ++/** ++ * xsltGetSourceNodeValue: ++ * @node: Node from source document ++ * ++ * Returns the associated 28 bit unsigned value for a source node, ++ * or 0 if node does not have an associated value. ++ */ ++int ++xsltGetSourceNodeValue(xmlNodePtr node) { ++ switch (node->type) { ++ case XML_DOCUMENT_NODE: ++ case XML_HTML_DOCUMENT_NODE: ++ return (((xmlDocPtr) node)->extra & XSLT_SOURCE_NODE_VALUE_MASK); ++ ++ case XML_ATTRIBUTE_NODE: ++ return (((xmlAttrPtr) node)->extra & XSLT_SOURCE_NODE_VALUE_MASK); ++ ++ default: ++ return 0; ++ } ++} ++ ++/** ++ * xsltSetSourceNodeValue: ++ * @node: Node from source document ++ * @value: 28 bit unsigned value to associate with the node. ++ * ++ * Returns 0 on success, -1 on error. ++ */ ++int ++xsltSetSourceNodeValue(xmlNodePtr node, int value) { ++ switch (node->type) { ++ case XML_DOCUMENT_NODE: ++ case XML_HTML_DOCUMENT_NODE: ++ ((xmlDocPtr) node)->extra &= ~XSLT_SOURCE_NODE_VALUE_MASK; ++ ((xmlDocPtr) node)->extra |= (value & XSLT_SOURCE_NODE_VALUE_MASK); ++ return 0; ++ ++ case XML_ATTRIBUTE_NODE: ++ ((xmlAttrPtr) node)->extra &= ~XSLT_SOURCE_NODE_VALUE_MASK; ++ ((xmlAttrPtr) node)->extra |= (value & XSLT_SOURCE_NODE_VALUE_MASK); ++ return 0; ++ ++ default: ++ return -1; ++ } ++} ++ + /** + * xsltGetPSVIPtr: + * @cur: Node +diff --git a/third_party/libxslt/src/libxslt/xsltutils.h b/third_party/libxslt/src/libxslt/xsltutils.h +index d15d22726afaa..1e753eebadd98 100644 +--- a/third_party/libxslt/src/libxslt/xsltutils.h ++++ b/third_party/libxslt/src/libxslt/xsltutils.h +@@ -263,6 +263,8 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL + #define XSLT_SOURCE_NODE_HAS_ID 2u + #define XSLT_SOURCE_NODE_SHIFT_16 12u + #define XSLT_SOURCE_NODE_SHIFT_32 28u ++#define XSLT_SOURCE_NODE_VALUE_MASK ((1 << XSLT_SOURCE_NODE_SHIFT_32) - 1) ++#define XSLT_SOURCE_NODE_VALUE_MAX XSLT_SOURCE_NODE_VALUE_MASK + int + xsltGetSourceNodeFlags(xmlNodePtr node); + int +@@ -270,6 +272,10 @@ xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node, + int flags); + int + xsltClearSourceNodeFlags(xmlNodePtr node, int flags); ++int ++xsltSetSourceNodeValue(xmlNodePtr node, int value); ++int ++xsltGetSourceNodeValue(xmlNodePtr node); + void ** + xsltGetPSVIPtr(xmlNodePtr cur); + /** DOC_ENABLE */
diff --git a/third_party/libxslt/src/libxslt/functions.c b/third_party/libxslt/src/libxslt/functions.c index 72a58dc..309af45 100644 --- a/third_party/libxslt/src/libxslt/functions.c +++ b/third_party/libxslt/src/libxslt/functions.c
@@ -760,7 +760,7 @@ } if (xsltGetSourceNodeFlags(cur) & XSLT_SOURCE_NODE_HAS_ID) { - id = (unsigned long) (size_t) *psviPtr; + id = (unsigned long) xsltGetSourceNodeValue(cur); } else { if (cur->type == XML_TEXT_NODE && cur->line == USHRT_MAX) { /* Text nodes store big line numbers in psvi. */ @@ -772,7 +772,7 @@ goto out; } - if (tctxt->currentId == ULONG_MAX) { + if (tctxt->currentId == XSLT_SOURCE_NODE_VALUE_MAX) { xsltTransformError(tctxt, NULL, NULL, "generate-id(): id overflow\n"); ctxt->error = XPATH_MEMORY_ERROR; @@ -780,7 +780,7 @@ } id = ++tctxt->currentId; - *psviPtr = (void *) (size_t) id; + xsltSetSourceNodeValue(cur, id); xsltSetSourceNodeFlags(tctxt, cur, XSLT_SOURCE_NODE_HAS_ID); }
diff --git a/third_party/libxslt/src/libxslt/transform.c b/third_party/libxslt/src/libxslt/transform.c index 54ef821..1ac2471 100644 --- a/third_party/libxslt/src/libxslt/transform.c +++ b/third_party/libxslt/src/libxslt/transform.c
@@ -5772,7 +5772,8 @@ xmlAttrPtr prop = cur->properties; while (prop) { - prop->atype &= ~(XSLT_SOURCE_NODE_MASK << 27); + prop->extra &= + ~(XSLT_SOURCE_NODE_MASK << XSLT_SOURCE_NODE_SHIFT_32); prop->psvi = NULL; prop = prop->next; }
diff --git a/third_party/libxslt/src/libxslt/xsltutils.c b/third_party/libxslt/src/libxslt/xsltutils.c index a20da96..aec8be4a 100644 --- a/third_party/libxslt/src/libxslt/xsltutils.c +++ b/third_party/libxslt/src/libxslt/xsltutils.c
@@ -1920,26 +1920,26 @@ int xsltGetSourceNodeFlags(xmlNodePtr node) { /* - * Squeeze the bit flags into the upper bits of + * Squeeze the bit flags into the upper 4 bits of * - * - 'int properties' member in struct _xmlDoc - * - 'xmlAttributeType atype' member in struct _xmlAttr + * - 'unsigned int extra' member in struct _xmlDoc + * - 'unsigned int extra' member in struct _xmlAttr * - 'unsigned short extra' member in struct _xmlNode */ switch (node->type) { case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: - return ((xmlDocPtr) node)->properties >> 27; + return ((xmlDocPtr) node)->extra >> XSLT_SOURCE_NODE_SHIFT_32; case XML_ATTRIBUTE_NODE: - return ((xmlAttrPtr) node)->atype >> 27; + return ((xmlAttrPtr) node)->extra >> XSLT_SOURCE_NODE_SHIFT_32; case XML_ELEMENT_NODE: case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: - return node->extra >> 12; + return node->extra >> XSLT_SOURCE_NODE_SHIFT_32; default: return 0; @@ -1964,11 +1964,11 @@ switch (node->type) { case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: - ((xmlDocPtr) node)->properties |= flags << 27; + ((xmlDocPtr) node)->extra |= (flags << XSLT_SOURCE_NODE_SHIFT_32); return 0; case XML_ATTRIBUTE_NODE: - ((xmlAttrPtr) node)->atype |= flags << 27; + ((xmlAttrPtr) node)->extra |= (flags << XSLT_SOURCE_NODE_SHIFT_32); return 0; case XML_ELEMENT_NODE: @@ -1976,7 +1976,7 @@ case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: - node->extra |= flags << 12; + node->extra |= (flags << XSLT_SOURCE_NODE_SHIFT_16); return 0; default: @@ -1998,11 +1998,11 @@ switch (node->type) { case XML_DOCUMENT_NODE: case XML_HTML_DOCUMENT_NODE: - ((xmlDocPtr) node)->properties &= ~(flags << 27); + ((xmlDocPtr) node)->extra &= ~(flags << XSLT_SOURCE_NODE_SHIFT_32); return 0; case XML_ATTRIBUTE_NODE: - ((xmlAttrPtr) node)->atype &= ~(flags << 27); + ((xmlAttrPtr) node)->extra &= ~(flags << XSLT_SOURCE_NODE_SHIFT_32); return 0; case XML_ELEMENT_NODE: @@ -2010,7 +2010,55 @@ case XML_CDATA_SECTION_NODE: case XML_PI_NODE: case XML_COMMENT_NODE: - node->extra &= ~(flags << 12); + node->extra &= ~(flags << XSLT_SOURCE_NODE_SHIFT_16); + return 0; + + default: + return -1; + } +} + +/** + * xsltGetSourceNodeValue: + * @node: Node from source document + * + * Returns the associated 28 bit unsigned value for a source node, + * or 0 if node does not have an associated value. + */ +int +xsltGetSourceNodeValue(xmlNodePtr node) { + switch (node->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + return (((xmlDocPtr) node)->extra & XSLT_SOURCE_NODE_VALUE_MASK); + + case XML_ATTRIBUTE_NODE: + return (((xmlAttrPtr) node)->extra & XSLT_SOURCE_NODE_VALUE_MASK); + + default: + return 0; + } +} + +/** + * xsltSetSourceNodeValue: + * @node: Node from source document + * @value: 28 bit unsigned value to associate with the node. + * + * Returns 0 on success, -1 on error. + */ +int +xsltSetSourceNodeValue(xmlNodePtr node, int value) { + switch (node->type) { + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + ((xmlDocPtr) node)->extra &= ~XSLT_SOURCE_NODE_VALUE_MASK; + ((xmlDocPtr) node)->extra |= (value & XSLT_SOURCE_NODE_VALUE_MASK); + return 0; + + case XML_ATTRIBUTE_NODE: + ((xmlAttrPtr) node)->extra &= ~XSLT_SOURCE_NODE_VALUE_MASK; + ((xmlAttrPtr) node)->extra |= (value & XSLT_SOURCE_NODE_VALUE_MASK); return 0; default:
diff --git a/third_party/libxslt/src/libxslt/xsltutils.h b/third_party/libxslt/src/libxslt/xsltutils.h index 2514774..1e753ee 100644 --- a/third_party/libxslt/src/libxslt/xsltutils.h +++ b/third_party/libxslt/src/libxslt/xsltutils.h
@@ -261,6 +261,10 @@ #define XSLT_SOURCE_NODE_MASK 15u #define XSLT_SOURCE_NODE_HAS_KEY 1u #define XSLT_SOURCE_NODE_HAS_ID 2u +#define XSLT_SOURCE_NODE_SHIFT_16 12u +#define XSLT_SOURCE_NODE_SHIFT_32 28u +#define XSLT_SOURCE_NODE_VALUE_MASK ((1 << XSLT_SOURCE_NODE_SHIFT_32) - 1) +#define XSLT_SOURCE_NODE_VALUE_MAX XSLT_SOURCE_NODE_VALUE_MASK int xsltGetSourceNodeFlags(xmlNodePtr node); int @@ -268,6 +272,10 @@ int flags); int xsltClearSourceNodeFlags(xmlNodePtr node, int flags); +int +xsltSetSourceNodeValue(xmlNodePtr node, int value); +int +xsltGetSourceNodeValue(xmlNodePtr node); void ** xsltGetPSVIPtr(xmlNodePtr cur); /** DOC_ENABLE */
diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src index c8248a0..d7bdad4 160000 --- a/third_party/llvm-libc/src +++ b/third_party/llvm-libc/src
@@ -1 +1 @@ -Subproject commit c8248a038fe70b7495d1d52fde500cf2dd6fae82 +Subproject commit d7bdad4ef86b827a96469b1dfdfcfa1218930e59
diff --git a/third_party/omnibox_proto/README.chromium b/third_party/omnibox_proto/README.chromium index 581050f..ad576226 100644 --- a/third_party/omnibox_proto/README.chromium +++ b/third_party/omnibox_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Omnibox Protos Short Name: omnibox_proto URL: This is the canonical public repository -Version: 738839352 -Date: 2025-03-20 +Version: 755469696 +Date: 2025-05-06 License: BSD-3-Clause License File: LICENSE Shipped: yes
diff --git a/third_party/omnibox_proto/answer_type.proto b/third_party/omnibox_proto/answer_type.proto index b9ce998..9322ae0 100644 --- a/third_party/omnibox_proto/answer_type.proto +++ b/third_party/omnibox_proto/answer_type.proto
@@ -20,10 +20,10 @@ ANSWER_TYPE_SUNRISE_SUNSET = 6; ANSWER_TYPE_TRANSLATION = 7; ANSWER_TYPE_WEATHER = 8; - ANSWER_TYPE_WHEN_IS = 9; + ANSWER_TYPE_WHEN_IS = 9 [deprecated = true]; ANSWER_TYPE_CURRENCY = 10; ANSWER_TYPE_LOCAL_TIME = 11; - ANSWER_TYPE_PLAY_INSTALL = 12; - ANSWER_TYPE_WEB_ANSWER = 14; + ANSWER_TYPE_PLAY_INSTALL = 12 [deprecated = true]; + ANSWER_TYPE_WEB_ANSWER = 14 [deprecated = true]; reserved 4, 13; }
diff --git a/third_party/omnibox_proto/groups.proto b/third_party/omnibox_proto/groups.proto index fd18521..f90ff3f 100644 --- a/third_party/omnibox_proto/groups.proto +++ b/third_party/omnibox_proto/groups.proto
@@ -73,6 +73,7 @@ GROUP_VISITED_DOC_RELATED = 10005; GROUP_MULTIMODAL = 10006; GROUP_CONTEXTUAL_SEARCH = 10007; + GROUP_CONTEXTUAL_SEARCH_ACTION = 10008; GROUP_POLARIS_RESERVED_MAX = 19999; // Mobile-specific auxiliary suggestions.
diff --git a/third_party/skia b/third_party/skia index 32591be..c8f54c1 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit 32591be9cd3bea8c9e1ad39c64bc8230a4c4d499 +Subproject commit c8f54c1bc565b8a7eced0a77088b228efdc70c2c
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn index 79df6e8..4bcbc2c 100644 --- a/third_party/wayland-protocols/BUILD.gn +++ b/third_party/wayland-protocols/BUILD.gn
@@ -171,10 +171,6 @@ sources = [ "unstable/ui-controls/ui-controls-unstable-v1.xml" ] } -wayland_protocol("test_controller_protocol") { - sources = [ "unstable/test-controller/test-controller-unstable-v1.xml" ] -} - wayland_protocol("viewporter_protocol") { sources = [ "src/stable/viewporter/viewporter.xml" ] }
diff --git a/third_party/wayland-protocols/unstable/test-controller/OWNERS b/third_party/wayland-protocols/unstable/test-controller/OWNERS deleted file mode 100644 index 6cb9cdc..0000000 --- a/third_party/wayland-protocols/unstable/test-controller/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -aycyang@chromium.org
diff --git a/third_party/wayland-protocols/unstable/test-controller/README b/third_party/wayland-protocols/unstable/test-controller/README deleted file mode 100644 index 690d497..0000000 --- a/third_party/wayland-protocols/unstable/test-controller/README +++ /dev/null
@@ -1,4 +0,0 @@ -APIs used in tests. - -Maintainers: -Alex Yang <aycyang@chromium.org>
diff --git a/third_party/wayland-protocols/unstable/test-controller/test-controller-unstable-v1.xml b/third_party/wayland-protocols/unstable/test-controller/test-controller-unstable-v1.xml deleted file mode 100644 index 84d31f2..0000000 --- a/third_party/wayland-protocols/unstable/test-controller/test-controller-unstable-v1.xml +++ /dev/null
@@ -1,45 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<protocol name="test_controller_unstable_v1"> - <copyright> - Copyright 2024 The Chromium Authors. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - </copyright> - - <interface name="zcr_test_controller_v1" version="1"> - <description summary="APIs for tests"> - Contains APIs intended for use in integration tests. - </description> - <request name="mock_event_tick_clock_start" since="1"> - <description summary="initialize a test-controlled event tick clock"> - Replace the compositor's real-time event tick clock with a - client-controlled event tick clock. Useful for tighter control of input - event timing. - </description> - </request> - <request name="mock_event_tick_clock_advance" since="1"> - <arg name="milliseconds" type="uint"/> - <description summary="advance the mock event tick clock"> - Advance the client-controlled event tick clock by the given number of - milliseconds. - </description> - </request> - </interface> -</protocol>
diff --git a/third_party/webrtc b/third_party/webrtc index 626c9f1..d69d080 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit 626c9f19118aac2e0faf45db73e9101d4502190c +Subproject commit d69d0808c37b4ea338e59a58837ef180023316a6
diff --git a/tools/cast3p/runtime.version b/tools/cast3p/runtime.version index eb8be83..3f73c7226 100644 --- a/tools/cast3p/runtime.version +++ b/tools/cast3p/runtime.version
@@ -1 +1 @@ -476819 +477659
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index f274064..e30c768f 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -39,7 +39,7 @@ # These fields are written by //tools/clang/scripts/upload_revision.py, and # should not be changed manually. # They are also read by build/config/compiler/BUILD.gn. -CLANG_REVISION = 'llvmorg-21-init-10502-gb2e2ae87' +CLANG_REVISION = 'llvmorg-21-init-10851-gcd6c4b61' CLANG_SUB_REVISION = 1 PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/tools/cygprofile/generate_orderfile.pydeps b/tools/cygprofile/generate_orderfile.pydeps index 08b16e8..7555de0 100644 --- a/tools/cygprofile/generate_orderfile.pydeps +++ b/tools/cygprofile/generate_orderfile.pydeps
@@ -54,6 +54,7 @@ //third_party/catapult/devil/devil/devil_env.py //third_party/catapult/devil/devil/utils/__init__.py //third_party/catapult/devil/devil/utils/cmd_helper.py +//third_party/catapult/devil/devil/utils/host_utils.py //third_party/catapult/devil/devil/utils/lazy/__init__.py //third_party/catapult/devil/devil/utils/lazy/weak_constant.py //third_party/catapult/devil/devil/utils/logging_common.py
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 9560ec11..76e40bed 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -12434,6 +12434,22 @@ </description> </action> +<action name="Glic.Settings.ClosedCaptions.Disabled"> + <owner>sanaakbani@google.com</owner> + <owner>iwells@chromium.org</owner> + <description> + Logged if the user disables closed captions in glic settings. + </description> +</action> + +<action name="Glic.Settings.ClosedCaptions.Enabled"> + <owner>sanaakbani@google.com</owner> + <owner>iwells@chromium.org</owner> + <description> + Logged if the user enables closed captions in glic settings. + </description> +</action> + <action name="Glic.Settings.Geolocation.Disabled"> <owner>tommasin@chromium.org</owner> <owner>erikchen@chromium.org</owner>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index f805f67..5335630 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -11329,6 +11329,7 @@ <int value="-1169571217" label="SharingDesktopScreenshotsEdit:disabled"/> <int value="-1168910727" label="enable-experimental-accessibility-language-detection-dynamic"/> + <int value="-1168836114" label="AndroidTabDeclutterAutoDelete:enabled"/> <int value="-1168123287" label="WebRTC-FrameBuffer3:disabled"/> <int value="-1167992523" label="DesktopPWAsCustomTabUI:disabled"/> <int value="-1167716837" @@ -14661,6 +14662,7 @@ <int value="110888614" label="ReduceDisplayNotifications:enabled"/> <int value="112126033" label="ClearInstanceInfoWhenClosedIntentionally:disabled"/> + <int value="112131756" label="AndroidSmsOtpFilling:disabled"/> <int value="112140177" label="DesktopPWAsUnifiedInstall:disabled"/> <int value="113142558" label="TrackingProtectionOnboardingRollback:enabled"/> <int value="114318184" label="AccessibilityFlashScreenFeature:disabled"/> @@ -14669,6 +14671,7 @@ <int value="114657517" label="SecurePaymentConfirmationDebug:disabled"/> <int value="114748684" label="AlmanacGameMigration:disabled"/> <int value="114948617" label="SurfacePolish:enabled"/> + <int value="115449720" label="AndroidTabDeclutterAutoDelete:disabled"/> <int value="115834091" label="TrackByDefaultOnMobile:enabled"/> <int value="115852043" label="PageInfoAboutThisSiteKeepSidePanelOnSameTabNavs:enabled"/> @@ -14920,6 +14923,7 @@ <int value="212194994" label="PerAppLanguage:enabled"/> <int value="212245695" label="PowerBookmarksSidePanel:disabled"/> <int value="212361556" label="ComposeProactiveNudge:disabled"/> + <int value="212459881" label="AndroidSmsOtpFilling:enabled"/> <int value="212489101" label="AutofillAssistantChromeEntry:enabled"/> <int value="212959824" label="SafetyHubWeakAndReusedPasswords:disabled"/> <int value="212977039" label="MediaFoundationD3D11VideoCapture:disabled"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml index a3f4e38..abf5b3b9 100644 --- a/tools/metrics/histograms/metadata/accessibility/histograms.xml +++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -3270,15 +3270,6 @@ </token> </histogram> -<histogram name="Accessibility.ScreenAI.OCR.ImageSize10M" units="count" - expires_after="2025-08-24"> - <owner>rhalavati@chromium.org</owner> - <owner>chrome-a11y-core@google.com</owner> - <summary> - Records the number of pixels in the passed image to OCR request. - </summary> -</histogram> - <histogram name="Accessibility.ScreenAI.OCR.Latency.{DownsampleStatus}" units="ms" expires_after="2026-04-01"> <owner>rhalavati@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/android/enums.xml b/tools/metrics/histograms/metadata/android/enums.xml index a113b188..5a46dc1 100644 --- a/tools/metrics/histograms/metadata/android/enums.xml +++ b/tools/metrics/histograms/metadata/android/enums.xml
@@ -958,11 +958,12 @@ <int value="4" label="START_STICKY"/> </enum> -<enum name="DragDropTabResult"> +<enum name="DragDropResult"> <summary> SUCCESS is recorded during ACTION_DRAG_ENDED. The rest enums are all for failed drops, which are recorded in ACTION_DROP. Also see - Android.DragDrop.Tab.FromStrip.Result + Android.DragDrop.Tab.FromStrip.Result and + Android.DragDrop.TabGroup.FromStrip.Result. </summary> <int value="0" label="SUCCESS"/> <int value="1" label="IGNORED_TOOLBAR"/> @@ -971,10 +972,13 @@ <int value="4" label="IGNORED_SAME_INSTANCE"/> <int value="5" label="ERROR_TAB_NOT_FOUND"/> <int value="6" label="IGNORED_MAX_INSTANCES"/> + <int value="7" label="IGNORED_MHTML_TAB"/> </enum> <enum name="DragDropType"> - <summary>See Android.DragDrop.Tab.Type</summary> + <summary> + See Android.DragDrop.Tab.Type and Android.DragDrop.TabGroup.Type + </summary> <int value="0" label="TAB_STRIP_TO_TAB_STRIP"/> <int value="1" label="TAB_STRIP_TO_CONTENT"/> <int value="2" label="TAB_STRIP_TO_NEW_INSTANCE"/>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index 5bfc066..20c4665e 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -304,6 +304,11 @@ <variant name="Unset" summary="pre-warmed tabs without creation reason"/> </variants> +<variants name="TabObjectType"> + <variant name=".Tab" summary="tab"/> + <variant name=".TabGroup" summary="tab group"/> +</variants> + <variants name="TaskType"> <variant name="AuxiliarySearchDonate" summary="AuxiliarySearchDonate"/> <variant name="BackgroundSyncOneShot" summary="BackgroundSyncOneShot"/> @@ -1750,99 +1755,16 @@ </summary> </histogram> -<histogram name="Android.DragDrop.Tab.Duration.WithinDestStrip" units="ms" - expires_after="2025-09-07"> - <owner>shuyng@google.com</owner> - <owner>clank-large-form-factors@google.com</owner> - <summary> - During tab drag and drop, record duration when the drag is within the - destination strip, which is the time difference from the first time entering - the destination strip to the last time leaving or dropping into the - destination strip. Recorded when a tab drag and drop is finished. - </summary> -</histogram> - -<histogram name="Android.DragDrop.Tab.FromStrip.Result" - enum="DragDropTabResult" expires_after="2025-09-07"> - <owner>shuyng@google.com</owner> - <owner>clank-large-form-factors@google.com</owner> - <summary> - Records the tab drag and drop results, including successful drops and failed - drops with varied reasons. For failed drops, it is recorded during - ACTION_DROP. For successful drops, it is recored during ACTION_DRAG_ENDED. - Note that the successful drops count can be recorded more often than - Android.DragDrop.Tab.Type, such as reorder within strip or tabs being - consumed as text by EditText in native pages. - </summary> -</histogram> - -<histogram name="Android.DragDrop.Tab.FromStrip.Result.DesktopWindow" - enum="DragDropTabResult" expires_after="2025-11-04"> - <owner>aishwaryarj@google.com</owner> - <owner>clank-large-form-factors@google.com</owner> - <summary> - Records the tab drag and drop results in desktop windowing mode, including - successful drops and failed drops with varied reasons. For failed drops, it - is recorded during ACTION_DROP. For successful drops, it is recored during - ACTION_DRAG_ENDED. Note that the successful drops count can be recorded more - often than Android.DragDrop.Tab.Type.DesktopWindow, such as reorder within - strip or tabs being consumed as text by EditText in native pages. - </summary> -</histogram> - -<histogram name="Android.DragDrop.Tab.MaxInstanceFailureCount" units="failures" - expires_after="2025-09-28"> +<histogram name="Android.DragDrop.TabOrGroup.MaxInstanceFailureCount" + units="failures" expires_after="2026-05-05"> <owner>aishwaryarj@google.com</owner> <owner>wenyufu@chromium.org</owner> <owner>clank-large-form-factors@google.com</owner> <summary> - The number of times tab tearing failed for a user, because the maximum - number of Chrome instances were open, in a 24-hour period. Recorded when the - max-instance toast is shown when a dragged tab drop is unhandled at the max - instance limit. - </summary> -</histogram> - -<histogram name="Android.DragDrop.Tab.ReorderStripWithDragDrop" enum="Boolean" - expires_after="2025-09-28"> - <owner>shuyng@google.com</owner> - <owner>clank-large-form-factors@google.com</owner> - <summary> - Records tab drops into source strip with or without leaving the strip. True - means the tab drag has left the source strip; while false means it does not. - Recorded when tab is dropped into source strip. Used to determine the amount - of accidental tab drag out of the strip. - </summary> -</histogram> - -<histogram name="Android.DragDrop.Tab.SourceWindowClosed" enum="Boolean" - expires_after="2025-09-14"> - <owner>aishwaryarj@google.com</owner> - <owner>wenyufu@chromium.org</owner> - <owner>clank-large-form-factors@google.com</owner> - <summary> - Records true when a tab drag/drop results in closing the source Chrome - window because it was the last tab in the window, false when the drop does - not close the source window. Only recorded when tab drag/drop is handled. - </summary> -</histogram> - -<histogram name="Android.DragDrop.Tab.Type" enum="DragDropType" - expires_after="2025-09-07"> - <owner>shuyng@google.com</owner> - <owner>clank-large-form-factors@google.com</owner> - <summary> - Records the drag source and drop target when a tab is dropped successfully. - </summary> -</histogram> - -<histogram name="Android.DragDrop.Tab.Type.DesktopWindow" enum="DragDropType" - expires_after="2025-11-04"> - <owner>aishwaryarj@google.com</owner> - <owner>clank-large-form-factors@google.com</owner> - <summary> - Records the drag source and drop target when a tab is dropped successfully - in desktop windowing mode. + The number of times tab or group tearing failed for a user, because the + maximum number of Chrome instances were open, in a 24-hour period. Recorded + when the max-instance toast is shown when a dragged tab or group drop is + unhandled at the max instance limit. </summary> </histogram> @@ -1858,6 +1780,109 @@ </summary> </histogram> +<histogram name="Android.DragDrop{TabObjectType}.Duration.WithinDestStrip" + units="ms" expires_after="2026-05-05"> + <owner>shuyng@google.com</owner> + <owner>zheliooo@google.com</owner> + <owner>clank-large-form-factors@google.com</owner> + <summary> + During {TabObjectType} drag and drop, record duration when the drag is + within the destination strip, which is the time difference from the first + time entering the destination strip to the last time leaving or dropping + into the destination strip. Recorded when a {TabObjectType} drag and drop is + finished. + </summary> + <token key="TabObjectType" variants="TabObjectType"/> +</histogram> + +<histogram name="Android.DragDrop{TabObjectType}.FromStrip.Result" + enum="DragDropResult" expires_after="2026-05-05"> + <owner>shuyng@google.com</owner> + <owner>zheliooo@google.com</owner> + <owner>clank-large-form-factors@google.com</owner> + <summary> + Records the {TabObjectType} drag and drop results, including successful + drops and failed drops with varied reasons. For failed drops, it is recorded + during ACTION_DROP. For successful drops, it is recorded during + ACTION_DRAG_ENDED. Note that the successful drops count can be recorded more + often than Android.DragDrop.Tab.Type or Android.DragDrop.TabGroup.Type such + as reorder within strip or tabs being consumed as text by EditText in native + pages. + </summary> + <token key="TabObjectType" variants="TabObjectType"/> +</histogram> + +<histogram + name="Android.DragDrop{TabObjectType}.FromStrip.Result.DesktopWindow" + enum="DragDropResult" expires_after="2026-05-05"> + <owner>aishwaryarj@google.com</owner> + <owner>zheliooo@google.com</owner> + <owner>clank-large-form-factors@google.com</owner> + <summary> + Records the {TabObjectType} drag and drop results in desktop windowing mode, + including successful drops and failed drops with varied reasons. For failed + drops, it is recorded during ACTION_DROP. For successful drops, it is + recored during ACTION_DRAG_ENDED. Note that the successful drops count can + be recorded more often than Android.DragDrop.Tab.Type.DesktopWindow or + Android.DragDrop.TabGroup.Type.DesktopWindow, such as reorder within strip + or tabs being consumed as text by EditText in native pages. + </summary> + <token key="TabObjectType" variants="TabObjectType"/> +</histogram> + +<histogram name="Android.DragDrop{TabObjectType}.ReorderStripWithDragDrop" + enum="Boolean" expires_after="2026-05-05"> + <owner>shuyng@google.com</owner> + <owner>zheliooo@google.com</owner> + <owner>clank-large-form-factors@google.com</owner> + <summary> + Records {TabObjectType} drops into source strip with or without leaving the + strip. True means the drag has left the source strip; while false means it + does not. Recorded when drop into source strip. Used to determine the amount + of accidental drag out of the strip. + </summary> + <token key="TabObjectType" variants="TabObjectType"/> +</histogram> + +<histogram name="Android.DragDrop{TabObjectType}.SourceWindowClosed" + enum="Boolean" expires_after="2026-05-05"> + <owner>aishwaryarj@google.com</owner> + <owner>wenyufu@chromium.org</owner> + <owner>zheliooo@google.com</owner> + <owner>clank-large-form-factors@google.com</owner> + <summary> + Records true when a {TabObjectType} drag/drop results in closing the source + Chrome window because it was the last {TabObjectType} in the window, false + when the drop does not close the source window. Only recorded when drag/drop + is handled. + </summary> + <token key="TabObjectType" variants="TabObjectType"/> +</histogram> + +<histogram name="Android.DragDrop{TabObjectType}.Type" enum="DragDropType" + expires_after="2026-05-05"> + <owner>shuyng@google.com</owner> + <owner>zheliooo@google.com</owner> + <owner>clank-large-form-factors@google.com</owner> + <summary> + Records the drag source and drop target when a {TabObjectType} is dropped + successfully. + </summary> + <token key="TabObjectType" variants="TabObjectType"/> +</histogram> + +<histogram name="Android.DragDrop{TabObjectType}.Type.DesktopWindow" + enum="DragDropType" expires_after="2026-05-05"> + <owner>aishwaryarj@google.com</owner> + <owner>zheliooo@google.com</owner> + <owner>clank-large-form-factors@google.com</owner> + <summary> + Records the drag source and drop target when a {TabObjectType} is dropped + successfully in desktop windowing mode. + </summary> + <token key="TabObjectType" variants="TabObjectType"/> +</histogram> + <histogram name="Android.DynamicColors.IsAvailable" enum="Boolean" expires_after="2024-06-30"> <owner>skym@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/apps/enums.xml b/tools/metrics/histograms/metadata/apps/enums.xml index 7cd65d8..1b3b604e 100644 --- a/tools/metrics/histograms/metadata/apps/enums.xml +++ b/tools/metrics/histograms/metadata/apps/enums.xml
@@ -390,6 +390,23 @@ label="(Obsolete) Web apps opened in Standalone browser tabs"/> </enum> +<enum name="ChromeAppDeprecationLaunchOutcome"> + <int value="0" label="UserInstalled AllowedByFlag"/> + <int value="1" label="UserInstalled AllowedByAllowlist"/> + <int value="2" label="UserInstalled Blocked"/> + <int value="3" label="KioskMode AllowedByFlag"/> + <int value="4" label="KioskMode AllowedByAllowlist"/> + <int value="5" label="KioskMode AllowedByAdminPolicy"/> + <int value="6" label="KioskMode Blocked"/> + <int value="7" label="Managed AllowedByFlag"/> + <int value="8" label="Managed AllowedByAllowlist"/> + <int value="9" label="Managed AllowedByAdminPolicy"/> + <int value="10" label="Managed Blocked"/> + <int value="11" label="Not Chrome App Allowed"/> + <int value="12" label="Default Allowed"/> + <int value="13" label="Default Blocked"/> +</enum> + <enum name="ChromeOSUICommands"> <!-- Please put in checks to ensure Command IDs are stable before adding them to this enum. -->
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml index ccfa1d7..b605c96e8 100644 --- a/tools/metrics/histograms/metadata/apps/histograms.xml +++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -346,6 +346,16 @@ </summary> </histogram> +<histogram name="Apps.AppLaunch.ChromeAppsDeprecationCheck" + enum="ChromeAppDeprecationLaunchOutcome" expires_after="2026-05-01"> + <owner>giovax@google.com</owner> + <owner>src/apps/DEPRECATION_OWNERS</owner> + <summary> + The outcome of the deprecation checks performed during the launch of a + Chrome App. + </summary> +</histogram> + <histogram name="Apps.AppLaunchPerAppType" enum="AppType" expires_after="2025-09-14"> <owner>ovn@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index a5cf1a2..9214d9af 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -6648,6 +6648,18 @@ </summary> </histogram> +<histogram name="Autofill.TouchToFill.LoyaltyCard.TriggerOutcome" + enum="TouchToFill.PaymentMethod.TriggerOutcome" expires_after="2025-12-31"> + <owner>tchudakov@google.com</owner> + <owner>jsaul@google.com</owner> + <owner>payments-autofill-team@google.com</owner> + <summary> + Records the outcome of the attempt to trigger Touch To Fill for loyalty + cards. It is recorded only when the form is parsed as a loyalty card by + Autofill on Chrome Android and the user clicks on the form field. + </summary> +</histogram> + <histogram name="Autofill.TransliterationDuration" units="ms" expires_after="2025-11-01"> <owner>sygiet@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/blink/enums.xml b/tools/metrics/histograms/metadata/blink/enums.xml index 02d3134e..59a462d 100644 --- a/tools/metrics/histograms/metadata/blink/enums.xml +++ b/tools/metrics/histograms/metadata/blink/enums.xml
@@ -8197,6 +8197,7 @@ <int value="332" label="WindowManagement"/> <int value="333" label="Requestclose"/> <int value="334" label="DRAFT_Uint8ArrayToFromBase64AndHex"/> + <int value="335" label="LineBreak"/> </enum> <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom:WebDXFeature) -->
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml index 930e5cb6..687d647 100644 --- a/tools/metrics/histograms/metadata/omnibox/histograms.xml +++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -2019,6 +2019,20 @@ </token> </histogram> +<histogram name="Omnibox.SearchPrefetch.DuplicateSearchTermsAge" units="ms" + expires_after="2025-09-14"> + <owner>lingqi@chromium.org</owner> + <owner>nhiroki@chromium.org</owner> + <owner>chrome-prerendering@google.com</owner> + <summary> + Measures the duration between when the search terms are visited and when the + same search terms are visited again. + + Recorded at SearchPrefetchService::RecordInterceptionMetrics when the same + search terms are visited again. + </summary> +</histogram> + <histogram name="Omnibox.SearchPrefetch.SearchWhatYouTypedWasAlsoSuggested.{HistoryOrSuggest}" enum="Boolean" expires_after="2023-05-02">
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml index a9d3b5eb..0723f80a 100644 --- a/tools/metrics/histograms/metadata/sync/histograms.xml +++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -1617,10 +1617,8 @@ </histogram> <histogram name="Sync.PassphraseType5" enum="PassphraseTypeForMetrics" - expires_after="2025-06-17"> -<!-- Note: This histogram should (once it's verified to work correctly) replace - Sync.PassphraseType4 for the purpose of UMA filtering, and then become - expires-never. --> + expires_after="never"> +<!-- expires-never: important for UMA filtering. --> <owner>treib@chromium.org</owner> <owner>src/components/sync/OWNERS</owner>
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py index 1be69fc..b058d2b 100644 --- a/tools/perf/core/bot_platforms.py +++ b/tools/perf/core/bot_platforms.py
@@ -380,14 +380,14 @@ def _crossbench_speedometer2(estimated_runtime=60, arguments=None): """Alias for the latest Speedometer 2.X version.""" - return CrossbenchConfig('speedometer2.1.crossbench', - 'speedometer_2.1', + return CrossbenchConfig('speedometer2.crossbench', + 'speedometer_2', estimated_runtime=estimated_runtime, arguments=arguments) def _crossbench_speedometer3_0(estimated_runtime=60, arguments=None): - return CrossbenchConfig('speedometer3.crossbench', + return CrossbenchConfig('speedometer3.0.crossbench', 'speedometer_3.0', estimated_runtime=estimated_runtime, arguments=arguments) @@ -403,7 +403,7 @@ def _crossbench_speedometer3(estimated_runtime=60, arguments=None): """Alias for the latest Speedometer 3.X version.""" return CrossbenchConfig('speedometer3.crossbench', - 'speedometer_3.0', + 'speedometer_3', estimated_runtime=estimated_runtime, arguments=arguments) @@ -498,20 +498,17 @@ _CROSSBENCH_JETSTREAM_SPEEDOMETER = frozenset([ _crossbench_jetstream2(), - _crossbench_speedometer3_0(), - _crossbench_speedometer3_1(), + _crossbench_speedometer3(), ]) _CROSSBENCH_MOTIONMARK_SPEEDOMETER = frozenset([ _crossbench_motionmark1_3(), - _crossbench_speedometer3_0(), - _crossbench_speedometer3_1(), + _crossbench_speedometer3(), ]) _CROSSBENCH_BENCHMARKS_ALL = frozenset([ _crossbench_speedometer2(), - _crossbench_speedometer3_0(), - _crossbench_speedometer3_1(), + _crossbench_speedometer3(), _crossbench_motionmark1_3(), _crossbench_jetstream2(), ]) @@ -520,7 +517,7 @@ # Android. _CROSSBENCH_ANDROID = frozenset([ _crossbench_speedometer3_0(arguments=['--fileserver']), - _crossbench_speedometer3_1(arguments=['--fileserver']), + _crossbench_speedometer3(arguments=['--fileserver']), _crossbench_loadline_phone(arguments=[ '--cool-down-threshold=moderate', '--no-splash', @@ -532,7 +529,7 @@ _CROSSBENCH_PIXEL9 = frozenset([ # _crossbench_jetstream2(arguments=['--fileserver', '--debug']), _crossbench_motionmark1_3(arguments=['--fileserver', '--debug']), - _crossbench_speedometer3_1(arguments=['--fileserver', '--debug']), + _crossbench_speedometer3(arguments=['--fileserver', '--debug']), _crossbench_loadline_phone(arguments=[ '--cool-down-threshold=moderate', '--no-splash', @@ -541,7 +538,7 @@ ]) _CROSSBENCH_ANDROID_BYRA = frozenset([ - _crossbench_speedometer3_1(arguments=['--fileserver', '--debug']), + _crossbench_speedometer3(arguments=['--fileserver', '--debug']), ]) _CROSSBENCH_TANGOR = frozenset([
diff --git a/tools/perf/core/shard_maps/android-byra-perf_map.json b/tools/perf/core/shard_maps/android-byra-perf_map.json index 94eba60..4f4d6a6e 100644 --- a/tools/perf/core/shard_maps/android-byra-perf_map.json +++ b/tools/perf/core/shard_maps/android-byra-perf_map.json
@@ -63,8 +63,8 @@ } }, "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "speedometer_3": { + "display_name": "speedometer3.crossbench", "arguments": [ "--fileserver", "--debug"
diff --git a/tools/perf/core/shard_maps/android-pixel-fold-perf_map.json b/tools/perf/core/shard_maps/android-pixel-fold-perf_map.json index 918edaf..194f3e9f 100644 --- a/tools/perf/core/shard_maps/android-pixel-fold-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel-fold-perf_map.json
@@ -50,7 +50,7 @@ "abridged": false }, "blink_perf.shadow_dom": { - "end": 8, + "end": 6, "abridged": false } } @@ -58,7 +58,7 @@ "3": { "benchmarks": { "blink_perf.shadow_dom": { - "begin": 8, + "begin": 6, "abridged": false }, "blink_perf.webaudio": { @@ -92,7 +92,7 @@ "abridged": false }, "rasterize_and_record_micro.top_25": { - "end": 4, + "end": 3, "abridged": false } }, @@ -108,7 +108,7 @@ "4": { "benchmarks": { "rasterize_and_record_micro.top_25": { - "begin": 4, + "begin": 3, "abridged": false }, "rendering.mobile": { @@ -248,16 +248,16 @@ } }, "extra_infos": { - "num_stories": 1109, + "num_stories": 1110, "predicted_min_shard_time": 1781.0, "predicted_min_shard_index": 10, "predicted_max_shard_time": 1832.0, "predicted_max_shard_index": 12, "shard #0": 1809.0, - "shard #1": 1812.0, - "shard #2": 1814.0, - "shard #3": 1807.0, - "shard #4": 1799.0, + "shard #1": 1811.0, + "shard #2": 1809.0, + "shard #3": 1810.0, + "shard #4": 1812.0, "shard #5": 1816.0, "shard #6": 1818.0, "shard #7": 1821.0,
diff --git a/tools/perf/core/shard_maps/android-pixel-tangor-perf_map.json b/tools/perf/core/shard_maps/android-pixel-tangor-perf_map.json index d1a1582..82d3ee3 100644 --- a/tools/perf/core/shard_maps/android-pixel-tangor-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel-tangor-perf_map.json
@@ -194,13 +194,13 @@ } }, "extra_infos": { - "num_stories": 1109, + "num_stories": 1111, "predicted_min_shard_time": 3797.0, "predicted_min_shard_index": 7, - "predicted_max_shard_time": 5608.0, + "predicted_max_shard_time": 5620.0, "predicted_max_shard_index": 1, - "shard #0": 4097.0, - "shard #1": 5608.0, + "shard #0": 4105.0, + "shard #1": 5620.0, "shard #2": 3860.0, "shard #3": 3837.0, "shard #4": 3826.0,
diff --git a/tools/perf/core/shard_maps/android-pixel4-perf_map.json b/tools/perf/core/shard_maps/android-pixel4-perf_map.json index 041a2b5..b7fb420a 100644 --- a/tools/perf/core/shard_maps/android-pixel4-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel4-perf_map.json
@@ -44,7 +44,7 @@ "abridged": false }, "blink_perf.bindings": { - "end": 28, + "end": 29, "abridged": false }, "jetstream2": { @@ -61,11 +61,11 @@ "3": { "benchmarks": { "blink_perf.bindings": { - "begin": 28, + "begin": 29, "abridged": false }, "blink_perf.css": { - "end": 25, + "end": 26, "abridged": false }, "jetstream2": { @@ -82,7 +82,7 @@ "4": { "benchmarks": { "blink_perf.css": { - "begin": 25, + "begin": 26, "abridged": false }, "jetstream2": { @@ -123,7 +123,7 @@ "abridged": false }, "blink_perf.layout": { - "end": 33, + "end": 34, "abridged": false }, "speedometer2": { @@ -137,8 +137,8 @@ "7": { "benchmarks": { "blink_perf.layout": { - "begin": 33, - "end": 90, + "begin": 34, + "end": 91, "abridged": false }, "speedometer2": { @@ -152,7 +152,7 @@ "8": { "benchmarks": { "blink_perf.layout": { - "begin": 90, + "begin": 91, "abridged": false }, "blink_perf.owp_storage": { @@ -635,18 +635,18 @@ } }, "extra_infos": { - "num_stories": 1147, + "num_stories": 1149, "predicted_min_shard_time": 687.0, "predicted_min_shard_index": 27, "predicted_max_shard_time": 1158.0, "predicted_max_shard_index": 43, "shard #0": 753.0, "shard #1": 780.0, - "shard #2": 776.0, - "shard #3": 782.0, - "shard #4": 777.0, + "shard #2": 784.0, + "shard #3": 780.0, + "shard #4": 781.0, "shard #5": 785.0, - "shard #6": 775.0, + "shard #6": 785.0, "shard #7": 782.0, "shard #8": 779.0, "shard #9": 787.0,
diff --git a/tools/perf/core/shard_maps/android-pixel4_webview-perf-pgo_map.json b/tools/perf/core/shard_maps/android-pixel4_webview-perf-pgo_map.json index f1550e2..98c4fb4a 100644 --- a/tools/perf/core/shard_maps/android-pixel4_webview-perf-pgo_map.json +++ b/tools/perf/core/shard_maps/android-pixel4_webview-perf-pgo_map.json
@@ -26,7 +26,7 @@ "abridged": false }, "blink_perf.css": { - "end": 70, + "end": 71, "abridged": false }, "speedometer2": { @@ -40,7 +40,7 @@ "2": { "benchmarks": { "blink_perf.css": { - "begin": 70, + "begin": 71, "abridged": false }, "blink_perf.dom": { @@ -53,7 +53,7 @@ "abridged": false }, "blink_perf.layout": { - "end": 23, + "end": 24, "abridged": false }, "speedometer2": { @@ -67,8 +67,8 @@ "3": { "benchmarks": { "blink_perf.layout": { - "begin": 23, - "end": 101, + "begin": 24, + "end": 102, "abridged": false }, "speedometer2": { @@ -82,7 +82,7 @@ "4": { "benchmarks": { "blink_perf.layout": { - "begin": 101, + "begin": 102, "abridged": false }, "blink_perf.owp_storage": { @@ -384,14 +384,14 @@ } }, "extra_infos": { - "num_stories": 1110, + "num_stories": 1112, "predicted_min_shard_time": 2668.0, "predicted_min_shard_index": 19, "predicted_max_shard_time": 3149.0, "predicted_max_shard_index": 18, "shard #0": 2912.0, - "shard #1": 2894.0, - "shard #2": 2906.0, + "shard #1": 2904.0, + "shard #2": 2916.0, "shard #3": 2897.0, "shard #4": 2894.0, "shard #5": 2906.0,
diff --git a/tools/perf/core/shard_maps/android-pixel4_webview-perf_map.json b/tools/perf/core/shard_maps/android-pixel4_webview-perf_map.json index b7e15ef..c185bf9 100644 --- a/tools/perf/core/shard_maps/android-pixel4_webview-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel4_webview-perf_map.json
@@ -107,7 +107,7 @@ "abridged": false }, "blink_perf.shadow_dom": { - "end": 30, + "end": 29, "abridged": false }, "speedometer2": { @@ -121,7 +121,7 @@ "6": { "benchmarks": { "blink_perf.shadow_dom": { - "begin": 30, + "begin": 29, "abridged": false }, "blink_perf.webaudio": { @@ -152,7 +152,7 @@ "abridged": false }, "rendering.mobile": { - "end": 2, + "end": 1, "abridged": false }, "speedometer2": { @@ -166,8 +166,8 @@ "7": { "benchmarks": { "rendering.mobile": { - "begin": 2, - "end": 58, + "begin": 1, + "end": 57, "abridged": false }, "speedometer2": { @@ -181,8 +181,8 @@ "8": { "benchmarks": { "rendering.mobile": { - "begin": 58, - "end": 114, + "begin": 57, + "end": 113, "abridged": false }, "speedometer2": { @@ -196,8 +196,8 @@ "9": { "benchmarks": { "rendering.mobile": { - "begin": 114, - "end": 160, + "begin": 113, + "end": 159, "abridged": false }, "speedometer2": { @@ -211,8 +211,8 @@ "10": { "benchmarks": { "rendering.mobile": { - "begin": 160, - "end": 200, + "begin": 159, + "end": 199, "abridged": false }, "speedometer2": { @@ -226,8 +226,8 @@ "11": { "benchmarks": { "rendering.mobile": { - "begin": 200, - "end": 250, + "begin": 199, + "end": 249, "abridged": false }, "speedometer2": { @@ -241,8 +241,8 @@ "12": { "benchmarks": { "rendering.mobile": { - "begin": 250, - "end": 320, + "begin": 249, + "end": 319, "abridged": false }, "speedometer2": { @@ -256,8 +256,8 @@ "13": { "benchmarks": { "rendering.mobile": { - "begin": 320, - "end": 357, + "begin": 319, + "end": 356, "abridged": false }, "speedometer2": { @@ -271,7 +271,7 @@ "14": { "benchmarks": { "rendering.mobile": { - "begin": 357, + "begin": 356, "abridged": false }, "rendering.mobile.notracing": { @@ -280,9 +280,6 @@ "speedometer": { "abridged": false }, - "speedometer-future": { - "abridged": false - }, "speedometer2": { "abridged": false }, @@ -293,6 +290,9 @@ }, "15": { "benchmarks": { + "speedometer-future": { + "abridged": false + }, "speedometer2": { "abridged": false }, @@ -309,7 +309,7 @@ "abridged": false }, "system_health.common_mobile": { - "end": 39, + "end": 38, "abridged": false } } @@ -317,7 +317,7 @@ "16": { "benchmarks": { "system_health.common_mobile": { - "begin": 39, + "begin": 38, "abridged": false }, "system_health.memory_mobile": { @@ -416,28 +416,28 @@ } }, "extra_infos": { - "num_stories": 1110, + "num_stories": 1112, "predicted_min_shard_time": 2024.0, "predicted_min_shard_index": 21, "predicted_max_shard_time": 2204.0, "predicted_max_shard_index": 17, "shard #0": 2108.0, "shard #1": 2113.0, - "shard #2": 2112.0, - "shard #3": 2117.0, - "shard #4": 2115.0, - "shard #5": 2099.0, - "shard #6": 2124.0, - "shard #7": 2107.0, - "shard #8": 2109.0, - "shard #9": 2105.0, - "shard #10": 2106.0, - "shard #11": 2092.0, - "shard #12": 2122.0, - "shard #13": 2093.0, - "shard #14": 2099.0, - "shard #15": 2112.0, - "shard #16": 2082.0, + "shard #2": 2122.0, + "shard #3": 2103.0, + "shard #4": 2114.0, + "shard #5": 2105.0, + "shard #6": 2105.0, + "shard #7": 2095.0, + "shard #8": 2125.0, + "shard #9": 2087.0, + "shard #10": 2114.0, + "shard #11": 2103.0, + "shard #12": 2109.0, + "shard #13": 2091.0, + "shard #14": 2114.0, + "shard #15": 2098.0, + "shard #16": 2129.0, "shard #17": 2204.0, "shard #18": 2099.0, "shard #19": 2126.0,
diff --git a/tools/perf/core/shard_maps/android-pixel6-perf-pgo_map.json b/tools/perf/core/shard_maps/android-pixel6-perf-pgo_map.json index 059820b..555a0e333 100644 --- a/tools/perf/core/shard_maps/android-pixel6-perf-pgo_map.json +++ b/tools/perf/core/shard_maps/android-pixel6-perf-pgo_map.json
@@ -145,13 +145,13 @@ } }, "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "speedometer_3.0": { + "display_name": "speedometer3.0.crossbench", "arguments": [ "--fileserver" ] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [ "--fileserver"
diff --git a/tools/perf/core/shard_maps/android-pixel6-perf_map.json b/tools/perf/core/shard_maps/android-pixel6-perf_map.json index b263de35..2de1f36 100644 --- a/tools/perf/core/shard_maps/android-pixel6-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel6-perf_map.json
@@ -266,13 +266,13 @@ } }, "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "speedometer_3.0": { + "display_name": "speedometer3.0.crossbench", "arguments": [ "--fileserver" ] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [ "--fileserver"
diff --git a/tools/perf/core/shard_maps/android-pixel6-pro-perf_map.json b/tools/perf/core/shard_maps/android-pixel6-pro-perf_map.json index 141a01b1..23138db 100644 --- a/tools/perf/core/shard_maps/android-pixel6-pro-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel6-pro-perf_map.json
@@ -213,13 +213,13 @@ } }, "extra_infos": { - "num_stories": 1108, + "num_stories": 1110, "predicted_min_shard_time": 3155.0, "predicted_min_shard_index": 6, "predicted_max_shard_time": 3258.0, "predicted_max_shard_index": 7, - "shard #0": 3209.0, - "shard #1": 3217.0, + "shard #0": 3219.0, + "shard #1": 3227.0, "shard #2": 3210.0, "shard #3": 3216.0, "shard #4": 3195.0,
diff --git a/tools/perf/core/shard_maps/android-pixel9-perf_map.json b/tools/perf/core/shard_maps/android-pixel9-perf_map.json index 839d753..baa5795b 100644 --- a/tools/perf/core/shard_maps/android-pixel9-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel9-perf_map.json
@@ -41,8 +41,8 @@ }, "3": { "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "speedometer_3": { + "display_name": "speedometer3.crossbench", "arguments": [ "--fileserver", "--debug"
diff --git a/tools/perf/core/shard_maps/android-pixel9-pro-perf_map.json b/tools/perf/core/shard_maps/android-pixel9-pro-perf_map.json index 839d753..baa5795b 100644 --- a/tools/perf/core/shard_maps/android-pixel9-pro-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel9-pro-perf_map.json
@@ -41,8 +41,8 @@ }, "3": { "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "speedometer_3": { + "display_name": "speedometer3.crossbench", "arguments": [ "--fileserver", "--debug"
diff --git a/tools/perf/core/shard_maps/android-pixel9-pro-xl-perf_map.json b/tools/perf/core/shard_maps/android-pixel9-pro-xl-perf_map.json index 839d753..baa5795b 100644 --- a/tools/perf/core/shard_maps/android-pixel9-pro-xl-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel9-pro-xl-perf_map.json
@@ -41,8 +41,8 @@ }, "3": { "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "speedometer_3": { + "display_name": "speedometer3.crossbench", "arguments": [ "--fileserver", "--debug"
diff --git a/tools/perf/core/shard_maps/linux-perf-calibration_map.json b/tools/perf/core/shard_maps/linux-perf-calibration_map.json index 6ee588eb..2793ee6 100644 --- a/tools/perf/core/shard_maps/linux-perf-calibration_map.json +++ b/tools/perf/core/shard_maps/linux-perf-calibration_map.json
@@ -8,7 +8,7 @@ "abridged": false }, "blink_perf.accessibility": { - "end": 14, + "end": 15, "abridged": false }, "jetstream2": { @@ -37,11 +37,11 @@ "abridged": false }, "blink_perf.accessibility": { - "begin": 14, + "begin": 15, "abridged": false }, "blink_perf.bindings": { - "end": 30, + "end": 31, "abridged": false }, "jetstream2": { @@ -61,11 +61,11 @@ "abridged": false }, "blink_perf.bindings": { - "begin": 30, + "begin": 31, "abridged": false }, "blink_perf.css": { - "end": 17, + "end": 19, "abridged": false }, "jetstream2": { @@ -85,8 +85,8 @@ "abridged": false }, "blink_perf.css": { - "begin": 17, - "end": 58, + "begin": 19, + "end": 60, "abridged": false }, "jetstream2": { @@ -106,14 +106,14 @@ "abridged": false }, "blink_perf.css": { - "begin": 58, + "begin": 60, "abridged": false }, "blink_perf.dom": { "abridged": false }, "blink_perf.events": { - "end": 1, + "end": 2, "abridged": false }, "jetstream2": { @@ -133,14 +133,14 @@ "abridged": false }, "blink_perf.events": { - "begin": 1, + "begin": 2, "abridged": false }, "blink_perf.image_decoder": { "abridged": false }, "blink_perf.layout": { - "end": 26, + "end": 27, "abridged": false }, "jetstream2": { @@ -160,8 +160,8 @@ "abridged": false }, "blink_perf.layout": { - "begin": 26, - "end": 66, + "begin": 27, + "end": 67, "abridged": false }, "jetstream2": { @@ -181,8 +181,8 @@ "abridged": false }, "blink_perf.layout": { - "begin": 66, - "end": 107, + "begin": 67, + "end": 108, "abridged": false }, "jetstream2": { @@ -202,7 +202,7 @@ "abridged": false }, "blink_perf.layout": { - "begin": 107, + "begin": 108, "abridged": false }, "blink_perf.owp_storage": { @@ -662,14 +662,14 @@ } }, "extra_infos": { - "num_stories": 2275, + "num_stories": 2277, "predicted_min_shard_time": 785.0, "predicted_min_shard_index": 26, "predicted_max_shard_time": 900.0, "predicted_max_shard_index": 25, - "shard #0": 820.0, + "shard #0": 830.0, "shard #1": 830, - "shard #2": 820, + "shard #2": 830, "shard #3": 830, "shard #4": 820, "shard #5": 830,
diff --git a/tools/perf/core/shard_maps/linux-perf-fyi_map.json b/tools/perf/core/shard_maps/linux-perf-fyi_map.json index 7011acc..eafaa3e6 100644 --- a/tools/perf/core/shard_maps/linux-perf-fyi_map.json +++ b/tools/perf/core/shard_maps/linux-perf-fyi_map.json
@@ -12,14 +12,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -43,14 +39,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -74,14 +66,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -90,11 +78,9 @@ "display_name": "motionmark1.3.crossbench", "arguments": [] }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", - "arguments": [ - "--fileserver" - ] + "speedometer_2": { + "display_name": "speedometer2.crossbench", + "arguments": [] } } }, @@ -111,14 +97,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -130,14 +112,14 @@ } }, "extra_infos": { - "num_stories": 29, - "predicted_min_shard_time": 787.0, + "num_stories": 25, + "predicted_min_shard_time": 727.0, "predicted_min_shard_index": 0, - "predicted_max_shard_time": 847.0, + "predicted_max_shard_time": 787.0, "predicted_max_shard_index": 2, - "shard #0": 787.0, - "shard #1": 787.0, - "shard #2": 847.0, - "shard #3": 787.0 + "shard #0": 727.0, + "shard #1": 727.0, + "shard #2": 787.0, + "shard #3": 727.0 } }
diff --git a/tools/perf/core/shard_maps/linux-r350-perf_map.json b/tools/perf/core/shard_maps/linux-r350-perf_map.json index cf41f48..1c7a651 100644 --- a/tools/perf/core/shard_maps/linux-r350-perf_map.json +++ b/tools/perf/core/shard_maps/linux-r350-perf_map.json
@@ -33,14 +33,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -58,14 +54,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -136,14 +128,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -186,14 +174,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -204,7 +188,7 @@ "benchmarks": { "blink_perf.accessibility": { "begin": 7, - "end": 9, + "end": 10, "abridged": false }, "jetstream2": { @@ -236,14 +220,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -253,8 +233,8 @@ "5": { "benchmarks": { "blink_perf.accessibility": { - "begin": 9, - "end": 22, + "begin": 10, + "end": 24, "abridged": false }, "speedometer": { @@ -280,14 +260,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -297,11 +273,14 @@ "6": { "benchmarks": { "blink_perf.accessibility": { - "begin": 22, + "begin": 24, "abridged": false }, "blink_perf.bindings": { - "end": 41, + "abridged": false + }, + "blink_perf.css": { + "end": 4, "abridged": false }, "speedometer": { @@ -327,14 +306,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -343,12 +318,9 @@ }, "7": { "benchmarks": { - "blink_perf.bindings": { - "begin": 41, - "abridged": false - }, "blink_perf.css": { - "end": 50, + "begin": 4, + "end": 67, "abridged": false }, "speedometer": { @@ -374,14 +346,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -391,11 +359,11 @@ "8": { "benchmarks": { "blink_perf.css": { - "begin": 50, + "begin": 67, "abridged": false }, "blink_perf.dom": { - "end": 3, + "end": 4, "abridged": false }, "speedometer": { @@ -421,14 +389,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -438,8 +402,14 @@ "9": { "benchmarks": { "blink_perf.dom": { - "begin": 3, - "end": 13, + "begin": 4, + "abridged": false + }, + "blink_perf.events": { + "abridged": false + }, + "blink_perf.image_decoder": { + "end": 1, "abridged": false }, "speedometer": { @@ -465,14 +435,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -481,17 +447,141 @@ }, "10": { "benchmarks": { - "blink_perf.dom": { - "begin": 13, - "abridged": false - }, - "blink_perf.events": { - "abridged": false - }, "blink_perf.image_decoder": { + "begin": 1, "abridged": false }, "blink_perf.layout": { + "end": 42, + "abridged": false + }, + "speedometer": { + "abridged": false + }, + "speedometer2-minorms": { + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer2-predictable": { + "abridged": false + }, + "speedometer3": { + "abridged": false + }, + "speedometer3-minorms": { + "abridged": false + }, + "speedometer3-predictable": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3": { + "display_name": "speedometer3.crossbench", + "arguments": [] + }, + "jetstream_2.2": { + "display_name": "jetstream2.crossbench", + "arguments": [] + } + } + }, + "11": { + "benchmarks": { + "blink_perf.layout": { + "begin": 42, + "end": 95, + "abridged": false + }, + "speedometer": { + "abridged": false + }, + "speedometer2-minorms": { + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer2-predictable": { + "abridged": false + }, + "speedometer3": { + "abridged": false + }, + "speedometer3-minorms": { + "abridged": false + }, + "speedometer3-predictable": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3": { + "display_name": "speedometer3.crossbench", + "arguments": [] + }, + "jetstream_2.2": { + "display_name": "jetstream2.crossbench", + "arguments": [] + } + } + }, + "12": { + "benchmarks": { + "blink_perf.layout": { + "begin": 95, + "abridged": false + }, + "blink_perf.owp_storage": { + "abridged": false + }, + "blink_perf.paint": { + "abridged": false + }, + "speedometer": { + "abridged": false + }, + "speedometer2-minorms": { + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer2-predictable": { + "abridged": false + }, + "speedometer3": { + "abridged": false + }, + "speedometer3-minorms": { + "abridged": false + }, + "speedometer3-predictable": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3": { + "display_name": "speedometer3.crossbench", + "arguments": [] + }, + "jetstream_2.2": { + "display_name": "jetstream2.crossbench", + "arguments": [] + } + } + }, + "13": { + "benchmarks": { + "blink_perf.parser": { + "abridged": false + }, + "blink_perf.shadow_dom": { + "abridged": false + }, + "blink_perf.svg": { "end": 14, "abridged": false }, @@ -518,155 +608,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "jetstream_2.2": { - "display_name": "jetstream2.crossbench", - "arguments": [] - } - } - }, - "11": { - "benchmarks": { - "blink_perf.layout": { - "begin": 14, - "end": 63, - "abridged": false - }, - "speedometer": { - "abridged": false - }, - "speedometer2-minorms": { - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer2-predictable": { - "abridged": false - }, - "speedometer3": { - "abridged": false - }, - "speedometer3-minorms": { - "abridged": false - }, - "speedometer3-predictable": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "jetstream_2.2": { - "display_name": "jetstream2.crossbench", - "arguments": [] - } - } - }, - "12": { - "benchmarks": { - "blink_perf.layout": { - "begin": 63, - "end": 106, - "abridged": false - }, - "speedometer": { - "abridged": false - }, - "speedometer2-minorms": { - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer2-predictable": { - "abridged": false - }, - "speedometer3": { - "abridged": false - }, - "speedometer3-minorms": { - "abridged": false - }, - "speedometer3-predictable": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "jetstream_2.2": { - "display_name": "jetstream2.crossbench", - "arguments": [] - } - } - }, - "13": { - "benchmarks": { - "blink_perf.layout": { - "begin": 106, - "abridged": false - }, - "blink_perf.owp_storage": { - "abridged": false - }, - "blink_perf.paint": { - "abridged": false - }, - "blink_perf.parser": { - "end": 9, - "abridged": false - }, - "speedometer": { - "abridged": false - }, - "speedometer2-minorms": { - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer2-predictable": { - "abridged": false - }, - "speedometer3": { - "abridged": false - }, - "speedometer3-minorms": { - "abridged": false - }, - "speedometer3-predictable": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -675,55 +620,10 @@ }, "14": { "benchmarks": { - "blink_perf.parser": { - "begin": 9, - "abridged": false - }, - "blink_perf.shadow_dom": { - "abridged": false - }, "blink_perf.svg": { + "begin": 14, "abridged": false }, - "speedometer": { - "abridged": false - }, - "speedometer2-minorms": { - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer2-predictable": { - "abridged": false - }, - "speedometer3": { - "abridged": false - }, - "speedometer3-minorms": { - "abridged": false - }, - "speedometer3-predictable": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "jetstream_2.2": { - "display_name": "jetstream2.crossbench", - "arguments": [] - } - } - }, - "15": { - "benchmarks": { "blink_perf.webaudio": { "abridged": false }, @@ -763,21 +663,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] } } }, - "16": { + "15": { "benchmarks": { "desktop_ui": { "begin": 1, @@ -807,21 +703,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] } } }, - "17": { + "16": { "benchmarks": { "desktop_ui": { "begin": 5, @@ -851,21 +743,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] } } }, - "18": { + "17": { "benchmarks": { "desktop_ui": { "begin": 7, @@ -877,6 +765,9 @@ "dummy_benchmark.stable_benchmark_1": { "abridged": false }, + "jetstream2": { + "abridged": false + }, "speedometer": { "abridged": false }, @@ -900,30 +791,23 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] } } }, - "19": { + "18": { "benchmarks": { - "jetstream2": { - "abridged": false - }, "jetstream2-minorms": { "abridged": false }, "media.desktop": { - "end": 6, + "end": 8, "abridged": false }, "speedometer": { @@ -954,12 +838,48 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "jetstream_2.2": { + "display_name": "jetstream2.crossbench", + "arguments": [] + } + } + }, + "19": { + "benchmarks": { + "media.desktop": { + "begin": 8, + "end": 12, + "abridged": false + }, + "speedometer": { + "abridged": false + }, + "speedometer2-minorms": { + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer2-predictable": { + "abridged": false + }, + "speedometer3": { + "abridged": false + }, + "speedometer3-minorms": { + "abridged": false + }, + "speedometer3-predictable": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3": { + "display_name": "speedometer3.crossbench", "arguments": [] }, "jetstream_2.2": { @@ -971,22 +891,24 @@ "20": { "benchmarks": { "media.desktop": { - "begin": 6, + "begin": 12, "abridged": false }, "memory.desktop": { - "end": 4, "abridged": false } } }, "21": { "benchmarks": { - "memory.desktop": { - "begin": 4, + "octane": { "abridged": false }, - "octane": { + "octane-minorms": { + "abridged": false + }, + "power.desktop": { + "end": 9, "abridged": false } }, @@ -999,10 +921,8 @@ }, "22": { "benchmarks": { - "octane-minorms": { - "abridged": false - }, "power.desktop": { + "begin": 9, "abridged": false }, "rasterize_and_record_micro.top_25": { @@ -1019,11 +939,7 @@ }, "speedometer2-future": { "abridged": false - } - } - }, - "23": { - "benchmarks": { + }, "speedometer2-minorms": { "abridged": false }, @@ -1043,22 +959,31 @@ "abridged": false }, "system_health.memory_desktop": { - "end": 20, + "end": 1, "abridged": false } }, "crossbench": { - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] } } }, + "23": { + "benchmarks": { + "system_health.memory_desktop": { + "begin": 1, + "end": 23, + "abridged": false + } + } + }, "24": { "benchmarks": { "system_health.memory_desktop": { - "begin": 20, - "end": 38, + "begin": 23, + "end": 43, "abridged": false } } @@ -1066,8 +991,8 @@ "25": { "benchmarks": { "system_health.memory_desktop": { - "begin": 38, - "end": 62, + "begin": 43, + "end": 65, "abridged": false } } @@ -1075,8 +1000,8 @@ "26": { "benchmarks": { "system_health.memory_desktop": { - "begin": 62, - "end": 74, + "begin": 65, + "end": 76, "abridged": false } } @@ -1084,7 +1009,11 @@ "27": { "benchmarks": { "system_health.memory_desktop": { - "begin": 74, + "begin": 76, + "abridged": false + }, + "v8.browsing_desktop": { + "end": 2, "abridged": false } }, @@ -1094,20 +1023,19 @@ "--use-chrome-perf-format" ], "path": "tint_benchmark" + }, + "tracing_perftests": { + "path": "tracing_perftests" } } }, "28": { "benchmarks": { "v8.browsing_desktop": { + "begin": 2, "end": 28, "abridged": false } - }, - "executables": { - "tracing_perftests": { - "path": "tracing_perftests" - } } }, "29": { @@ -1128,40 +1056,40 @@ } }, "extra_infos": { - "num_stories": 938, - "predicted_min_shard_time": 701.0, + "num_stories": 920, + "predicted_min_shard_time": 641.0, "predicted_min_shard_index": 0, "predicted_max_shard_time": 1086.0, "predicted_max_shard_index": 29, - "shard #0": 701.0, - "shard #1": 862.0, - "shard #2": 788.0, - "shard #3": 770.0, - "shard #4": 787.0, - "shard #5": 782.0, - "shard #6": 779.0, - "shard #7": 777.0, - "shard #8": 818.0, - "shard #9": 772.0, - "shard #10": 774.0, - "shard #11": 770.0, - "shard #12": 776.0, - "shard #13": 776.0, - "shard #14": 770.0, - "shard #15": 767.0, - "shard #16": 756.0, - "shard #17": 794.0, - "shard #18": 749.0, - "shard #19": 780.0, - "shard #20": 755.0, - "shard #21": 776.0, - "shard #22": 797.0, - "shard #23": 786.0, - "shard #24": 783.0, - "shard #25": 789.0, - "shard #26": 777.0, - "shard #27": 813.0, - "shard #28": 783.0, + "shard #0": 641.0, + "shard #1": 802.0, + "shard #2": 728.0, + "shard #3": 710.0, + "shard #4": 747.0, + "shard #5": 740.0, + "shard #6": 742.0, + "shard #7": 746.0, + "shard #8": 776.0, + "shard #9": 741.0, + "shard #10": 738.0, + "shard #11": 737.0, + "shard #12": 736.0, + "shard #13": 739.0, + "shard #14": 739.0, + "shard #15": 696.0, + "shard #16": 734.0, + "shard #17": 756.0, + "shard #18": 739.0, + "shard #19": 770.0, + "shard #20": 746.0, + "shard #21": 750.0, + "shard #22": 755.0, + "shard #23": 654.0, + "shard #24": 747.0, + "shard #25": 753.0, + "shard #26": 783.0, + "shard #27": 747.0, + "shard #28": 735.0, "shard #29": 1086.0 } }
diff --git a/tools/perf/core/shard_maps/mac-intel-perf_map.json b/tools/perf/core/shard_maps/mac-intel-perf_map.json index 8d85013..6cf3f2a 100644 --- a/tools/perf/core/shard_maps/mac-intel-perf_map.json +++ b/tools/perf/core/shard_maps/mac-intel-perf_map.json
@@ -5,7 +5,7 @@ "abridged": false }, "blink_perf.accessibility": { - "end": 2, + "end": 3, "abridged": false }, "jetstream2": { @@ -32,21 +32,17 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "1": { "benchmarks": { "blink_perf.accessibility": { - "begin": 2, - "end": 15, + "begin": 3, + "end": 16, "abridged": false }, "jetstream2": { @@ -64,24 +60,20 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "2": { "benchmarks": { "blink_perf.accessibility": { - "begin": 15, + "begin": 16, "abridged": false }, "blink_perf.bindings": { - "end": 36, + "end": 42, "abridged": false }, "jetstream2": { @@ -99,24 +91,20 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "3": { "benchmarks": { "blink_perf.bindings": { - "begin": 36, + "begin": 42, "abridged": false }, "blink_perf.css": { - "end": 66, + "end": 74, "abridged": false }, "jetstream2": { @@ -134,24 +122,20 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "4": { "benchmarks": { "blink_perf.css": { - "begin": 66, + "begin": 74, "abridged": false }, "blink_perf.dom": { - "end": 4, + "end": 6, "abridged": false }, "jetstream2": { @@ -169,20 +153,16 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "5": { "benchmarks": { "blink_perf.dom": { - "begin": 4, + "begin": 6, "abridged": false }, "blink_perf.events": { @@ -192,7 +172,7 @@ "abridged": false }, "blink_perf.layout": { - "end": 46, + "end": 54, "abridged": false }, "speedometer2": { @@ -203,27 +183,26 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "6": { "benchmarks": { "blink_perf.layout": { - "begin": 46, + "begin": 54, "abridged": false }, "blink_perf.owp_storage": { "abridged": false }, "blink_perf.parser": { - "end": 29, + "abridged": false + }, + "blink_perf.shadow_dom": { + "end": 15, "abridged": false }, "speedometer2": { @@ -234,23 +213,16 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "7": { "benchmarks": { - "blink_perf.parser": { - "begin": 29, - "abridged": false - }, "blink_perf.shadow_dom": { + "begin": 15, "abridged": false }, "blink_perf.webaudio": { @@ -288,13 +260,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -313,7 +281,7 @@ "abridged": false }, "media.desktop": { - "end": 10, + "end": 11, "abridged": false }, "speedometer2": { @@ -329,24 +297,20 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "9": { "benchmarks": { "media.desktop": { - "begin": 10, + "begin": 11, "abridged": false }, "memory.desktop": { - "end": 3, + "end": 5, "abridged": false }, "speedometer2": { @@ -357,20 +321,16 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "10": { "benchmarks": { "memory.desktop": { - "begin": 3, + "begin": 5, "abridged": false }, "speedometer2": { @@ -381,12 +341,12 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "motionmark_1.3": { + "display_name": "motionmark1.3.crossbench", "arguments": [] } } @@ -397,7 +357,10 @@ "abridged": false }, "power.desktop": { - "end": 8, + "abridged": false + }, + "rasterize_and_record_micro.top_25": { + "end": 9, "abridged": false }, "speedometer2": { @@ -408,52 +371,21 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "motionmark_1.3": { - "display_name": "motionmark1.3.crossbench", - "arguments": [] } } }, "12": { "benchmarks": { - "power.desktop": { - "begin": 8, - "abridged": false - }, "rasterize_and_record_micro.top_25": { + "begin": 9, "abridged": false }, "rendering.desktop.notracing": { "abridged": false }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - } - } - }, - "13": { - "benchmarks": { "speedometer": { "abridged": false }, @@ -473,21 +405,38 @@ "abridged": false }, "system_health.common_desktop": { - "end": 27, + "end": 8, "abridged": false } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] + } + } + }, + "13": { + "benchmarks": { + "system_health.common_desktop": { + "begin": 8, + "end": 46, + "abridged": false }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer2": { + "abridged": false + }, + "speedometer3": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3": { + "display_name": "speedometer3.crossbench", "arguments": [] } } @@ -495,8 +444,8 @@ "14": { "benchmarks": { "system_health.common_desktop": { - "begin": 27, - "end": 69, + "begin": 46, + "end": 75, "abridged": false }, "speedometer2": { @@ -507,24 +456,20 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "15": { "benchmarks": { "system_health.common_desktop": { - "begin": 69, + "begin": 75, "abridged": false }, "system_health.memory_desktop": { - "end": 2, + "end": 10, "abridged": false }, "speedometer2": { @@ -535,21 +480,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "16": { "benchmarks": { "system_health.memory_desktop": { - "begin": 2, - "end": 17, + "begin": 10, + "end": 23, "abridged": false }, "speedometer2": { @@ -560,21 +501,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "17": { "benchmarks": { "system_health.memory_desktop": { - "begin": 17, - "end": 27, + "begin": 23, + "end": 35, "abridged": false }, "speedometer2": { @@ -585,21 +522,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "18": { "benchmarks": { "system_health.memory_desktop": { - "begin": 27, - "end": 44, + "begin": 35, + "end": 49, "abridged": false }, "speedometer2": { @@ -610,21 +543,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "19": { "benchmarks": { "system_health.memory_desktop": { - "begin": 44, - "end": 57, + "begin": 49, + "end": 62, "abridged": false }, "speedometer2": { @@ -635,21 +564,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "20": { "benchmarks": { "system_health.memory_desktop": { - "begin": 57, - "end": 73, + "begin": 62, + "end": 74, "abridged": false } } @@ -657,18 +582,7 @@ "21": { "benchmarks": { "system_health.memory_desktop": { - "begin": 73, - "abridged": false - } - } - }, - "22": { - "benchmarks": { - "v8.browsing_desktop": { - "abridged": false - }, - "v8.browsing_desktop-future": { - "end": 1, + "begin": 74, "abridged": false } }, @@ -681,10 +595,21 @@ } } }, + "22": { + "benchmarks": { + "v8.browsing_desktop": { + "abridged": false + }, + "v8.browsing_desktop-future": { + "end": 5, + "abridged": false + } + } + }, "23": { "benchmarks": { "v8.browsing_desktop-future": { - "begin": 1, + "begin": 5, "abridged": false }, "wasmpspdfkit": { @@ -704,34 +629,34 @@ } }, "extra_infos": { - "num_stories": 860, - "predicted_min_shard_time": 792.0, - "predicted_min_shard_index": 10, - "predicted_max_shard_time": 1077.0, + "num_stories": 842, + "predicted_min_shard_time": 836.0, + "predicted_min_shard_index": 17, + "predicted_max_shard_time": 965.0, "predicted_max_shard_index": 7, - "shard #0": 929.0, - "shard #1": 938.0, - "shard #2": 926.0, - "shard #3": 942.0, - "shard #4": 924.0, - "shard #5": 919.0, - "shard #6": 933.0, - "shard #7": 1077.0, - "shard #8": 868.0, - "shard #9": 911.0, - "shard #10": 792.0, - "shard #11": 929.0, - "shard #12": 965.0, - "shard #13": 940.0, - "shard #14": 904.0, - "shard #15": 906.0, - "shard #16": 953.0, - "shard #17": 914.0, - "shard #18": 965.0, - "shard #19": 938.0, - "shard #20": 981.0, - "shard #21": 933.0, - "shard #22": 899.0, - "shard #23": 1013.0 + "shard #0": 891.0, + "shard #1": 878.0, + "shard #2": 882.0, + "shard #3": 888.0, + "shard #4": 864.0, + "shard #5": 880.0, + "shard #6": 880.0, + "shard #7": 965.0, + "shard #8": 941.0, + "shard #9": 888.0, + "shard #10": 922.0, + "shard #11": 866.0, + "shard #12": 870.0, + "shard #13": 867.0, + "shard #14": 863.0, + "shard #15": 893.0, + "shard #16": 860.0, + "shard #17": 836.0, + "shard #18": 857.0, + "shard #19": 875.0, + "shard #20": 891.0, + "shard #21": 930.0, + "shard #22": 836.0, + "shard #23": 896.0 } }
diff --git a/tools/perf/core/shard_maps/mac-laptop_low_end-perf_map.json b/tools/perf/core/shard_maps/mac-laptop_low_end-perf_map.json index b70bd2b..34d1193 100644 --- a/tools/perf/core/shard_maps/mac-laptop_low_end-perf_map.json +++ b/tools/perf/core/shard_maps/mac-laptop_low_end-perf_map.json
@@ -8,7 +8,7 @@ "abridged": false }, "blink_perf.bindings": { - "end": 39, + "end": 51, "abridged": false } } @@ -16,7 +16,7 @@ "1": { "benchmarks": { "blink_perf.bindings": { - "begin": 39, + "begin": 51, "abridged": false }, "blink_perf.css": { @@ -26,39 +26,34 @@ "abridged": false }, "blink_perf.dom": { - "end": 11, + "abridged": false + }, + "blink_perf.events": { "abridged": false } } }, "2": { "benchmarks": { - "blink_perf.dom": { - "begin": 11, - "abridged": false - }, - "blink_perf.events": { - "abridged": false - }, "blink_perf.image_decoder": { "abridged": false }, "blink_perf.layout": { - "end": 105, - "abridged": false - } - } - }, - "3": { - "benchmarks": { - "blink_perf.layout": { - "begin": 105, "abridged": false }, "blink_perf.owp_storage": { "abridged": false }, "blink_perf.parser": { + "end": 21, + "abridged": false + } + } + }, + "3": { + "benchmarks": { + "blink_perf.parser": { + "begin": 21, "abridged": false }, "blink_perf.shadow_dom": { @@ -83,15 +78,6 @@ "abridged": false }, "desktop_ui": { - "end": 5, - "abridged": false - } - } - }, - "4": { - "benchmarks": { - "desktop_ui": { - "begin": 5, "abridged": false }, "dummy_benchmark.noisy_benchmark_1": { @@ -101,10 +87,7 @@ "abridged": false }, "media.desktop": { - "abridged": false - }, - "memory.desktop": { - "end": 1, + "end": 4, "abridged": false } }, @@ -114,14 +97,30 @@ } } }, + "4": { + "benchmarks": { + "media.desktop": { + "begin": 4, + "abridged": false + }, + "memory.desktop": { + "end": 5, + "abridged": false + } + } + }, "5": { "benchmarks": { "memory.desktop": { - "begin": 1, + "begin": 5, "abridged": false }, "octane": { "abridged": false + }, + "power.desktop": { + "end": 9, + "abridged": false } }, "crossbench": { @@ -134,13 +133,14 @@ "6": { "benchmarks": { "power.desktop": { + "begin": 9, "abridged": false }, "rasterize_and_record_micro.top_25": { "abridged": false }, "rendering.desktop": { - "end": 14, + "end": 27, "abridged": false } } @@ -148,8 +148,8 @@ "7": { "benchmarks": { "rendering.desktop": { - "begin": 14, - "end": 64, + "begin": 27, + "end": 74, "abridged": false } } @@ -157,8 +157,8 @@ "8": { "benchmarks": { "rendering.desktop": { - "begin": 64, - "end": 112, + "begin": 74, + "end": 120, "abridged": false } } @@ -166,8 +166,8 @@ "9": { "benchmarks": { "rendering.desktop": { - "begin": 112, - "end": 158, + "begin": 120, + "end": 162, "abridged": false } } @@ -175,8 +175,8 @@ "10": { "benchmarks": { "rendering.desktop": { - "begin": 158, - "end": 207, + "begin": 162, + "end": 208, "abridged": false } } @@ -184,8 +184,8 @@ "11": { "benchmarks": { "rendering.desktop": { - "begin": 207, - "end": 251, + "begin": 208, + "end": 253, "abridged": false } } @@ -193,8 +193,8 @@ "12": { "benchmarks": { "rendering.desktop": { - "begin": 251, - "end": 283, + "begin": 253, + "end": 284, "abridged": false } } @@ -202,7 +202,7 @@ "13": { "benchmarks": { "rendering.desktop": { - "begin": 283, + "begin": 284, "end": 330, "abridged": false } @@ -236,7 +236,7 @@ "abridged": false }, "system_health.common_desktop": { - "end": 2, + "end": 5, "abridged": false } }, @@ -250,7 +250,7 @@ "15": { "benchmarks": { "system_health.common_desktop": { - "begin": 2, + "begin": 5, "end": 56, "abridged": false } @@ -281,7 +281,7 @@ "benchmarks": { "system_health.memory_desktop": { "begin": 24, - "end": 47, + "end": 46, "abridged": false } } @@ -289,8 +289,8 @@ "19": { "benchmarks": { "system_health.memory_desktop": { - "begin": 47, - "end": 70, + "begin": 46, + "end": 69, "abridged": false } } @@ -298,18 +298,23 @@ "20": { "benchmarks": { "system_health.memory_desktop": { - "begin": 70, + "begin": 69, + "end": 78, "abridged": false } } }, "21": { "benchmarks": { + "system_health.memory_desktop": { + "begin": 78, + "abridged": false + }, "v8.browsing_desktop": { "abridged": false }, "v8.browsing_desktop-future": { - "end": 9, + "end": 4, "abridged": false } } @@ -317,7 +322,7 @@ "22": { "benchmarks": { "v8.browsing_desktop-future": { - "begin": 9, + "begin": 4, "abridged": false }, "wasmpspdfkit": { @@ -329,33 +334,33 @@ } }, "extra_infos": { - "num_stories": 1125, - "predicted_min_shard_time": 1221.0, - "predicted_min_shard_index": 21, - "predicted_max_shard_time": 1401.0, - "predicted_max_shard_index": 19, - "shard #0": 1283.0, - "shard #1": 1264.0, - "shard #2": 1286.0, - "shard #3": 1280.0, - "shard #4": 1283.0, - "shard #5": 1291.0, - "shard #6": 1281.0, - "shard #7": 1278.0, - "shard #8": 1286.0, - "shard #9": 1291.0, - "shard #10": 1275.0, - "shard #11": 1299.0, - "shard #12": 1291.0, - "shard #13": 1273.0, - "shard #14": 1283.0, - "shard #15": 1275.0, - "shard #16": 1249.0, - "shard #17": 1287.0, - "shard #18": 1257.0, - "shard #19": 1401.0, - "shard #20": 1299.0, - "shard #21": 1221.0, - "shard #22": 1231.0 + "num_stories": 1123, + "predicted_min_shard_time": 1388.0, + "predicted_min_shard_index": 8, + "predicted_max_shard_time": 1470.0, + "predicted_max_shard_index": 18, + "shard #0": 1420.0, + "shard #1": 1418.0, + "shard #2": 1428.0, + "shard #3": 1420.0, + "shard #4": 1446.0, + "shard #5": 1419.0, + "shard #6": 1437.0, + "shard #7": 1413.0, + "shard #8": 1388.0, + "shard #9": 1407.0, + "shard #10": 1412.0, + "shard #11": 1452.0, + "shard #12": 1430.0, + "shard #13": 1427.0, + "shard #14": 1426.0, + "shard #15": 1424.0, + "shard #16": 1399.0, + "shard #17": 1416.0, + "shard #18": 1470.0, + "shard #19": 1440.0, + "shard #20": 1452.0, + "shard #21": 1404.0, + "shard #22": 1434.0 } -} \ No newline at end of file +}
diff --git a/tools/perf/core/shard_maps/mac-m1-pro-perf_map.json b/tools/perf/core/shard_maps/mac-m1-pro-perf_map.json index 5453dc7..7cb1845 100644 --- a/tools/perf/core/shard_maps/mac-m1-pro-perf_map.json +++ b/tools/perf/core/shard_maps/mac-m1-pro-perf_map.json
@@ -9,14 +9,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -30,14 +26,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -54,13 +46,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -74,29 +62,25 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] } } }, "extra_infos": { - "num_stories": 18, - "predicted_min_shard_time": 233.0, + "num_stories": 14, + "predicted_min_shard_time": 173.0, "predicted_min_shard_index": 3, - "predicted_max_shard_time": 509.0, + "predicted_max_shard_time": 449.0, "predicted_max_shard_index": 1, - "shard #0": 390.0, - "shard #1": 509.0, - "shard #2": 476.0, - "shard #3": 233.0 + "shard #0": 330.0, + "shard #1": 449.0, + "shard #2": 416.0, + "shard #3": 173.0 } }
diff --git a/tools/perf/core/shard_maps/mac-m1_mini_2020-perf-pgo_map.json b/tools/perf/core/shard_maps/mac-m1_mini_2020-perf-pgo_map.json index 5adf18a6..3ea90e3 100644 --- a/tools/perf/core/shard_maps/mac-m1_mini_2020-perf-pgo_map.json +++ b/tools/perf/core/shard_maps/mac-m1_mini_2020-perf-pgo_map.json
@@ -22,13 +22,9 @@ }, "1": { "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } }, "benchmarks": { @@ -68,13 +64,9 @@ }, "3": { "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } }, "benchmarks": { @@ -96,10 +88,6 @@ "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] - }, - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] } }, "benchmarks": { @@ -118,8 +106,8 @@ }, "5": { "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "speedometer_3": { + "display_name": "speedometer3.crossbench", "arguments": [] } }, @@ -156,36 +144,32 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] } } }, "extra_infos": { - "num_stories": 33, + "num_stories": 29, "predicted_min_shard_time": 1182.0, "predicted_min_shard_index": 5, - "predicted_max_shard_time": 2191.0, + "predicted_max_shard_time": 2131.0, "predicted_max_shard_index": 6, "shard #0": 1327.0, - "shard #1": 1267.0, + "shard #1": 1207.0, "shard #2": 1327.0, - "shard #3": 1267.0, - "shard #4": 1387.0, + "shard #3": 1207.0, + "shard #4": 1327.0, "shard #5": 1182.0, - "shard #6": 2191.0 + "shard #6": 2131.0 } }
diff --git a/tools/perf/core/shard_maps/mac-m1_mini_2020-perf_map.json b/tools/perf/core/shard_maps/mac-m1_mini_2020-perf_map.json index dbb7e9b..b900be8 100644 --- a/tools/perf/core/shard_maps/mac-m1_mini_2020-perf_map.json +++ b/tools/perf/core/shard_maps/mac-m1_mini_2020-perf_map.json
@@ -32,13 +32,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -48,7 +44,7 @@ "abridged": false }, "blink_perf.accessibility": { - "end": 8, + "end": 7, "abridged": false }, "jetstream2": { @@ -122,27 +118,20 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "3": { "benchmarks": { "blink_perf.accessibility": { - "begin": 8, + "begin": 7, "abridged": false }, "blink_perf.bindings": { - "abridged": false - }, - "blink_perf.css": { - "end": 32, + "end": 48, "abridged": false }, "jetstream2": { @@ -207,30 +196,23 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "5": { "benchmarks": { + "blink_perf.bindings": { + "begin": 48, + "abridged": false + }, "blink_perf.css": { - "begin": 32, "abridged": false }, "blink_perf.dom": { - "abridged": false - }, - "blink_perf.events": { - "abridged": false - }, - "blink_perf.image_decoder": { - "end": 9, + "end": 13, "abridged": false }, "jetstream2": { @@ -265,12 +247,18 @@ "abridged": false, "pageset_repeat": 2 }, + "blink_perf.dom": { + "begin": 13, + "abridged": false + }, + "blink_perf.events": { + "abridged": false + }, "blink_perf.image_decoder": { - "begin": 9, "abridged": false }, "blink_perf.layout": { - "end": 85, + "end": 51, "abridged": false }, "speedometer2": { @@ -293,14 +281,10 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -314,17 +298,14 @@ "pageset_repeat": 2 }, "blink_perf.layout": { - "begin": 85, + "begin": 51, "abridged": false }, "blink_perf.owp_storage": { "abridged": false }, "blink_perf.parser": { - "abridged": false - }, - "blink_perf.shadow_dom": { - "end": 19, + "end": 12, "abridged": false }, "speedometer2": { @@ -347,14 +328,10 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -367,8 +344,11 @@ "abridged": false, "pageset_repeat": 2 }, + "blink_perf.parser": { + "begin": 12, + "abridged": false + }, "blink_perf.shadow_dom": { - "begin": 19, "abridged": false }, "blink_perf.webaudio": { @@ -389,10 +369,6 @@ "blink_perf.webgpu_fast_call": { "abridged": false }, - "desktop_ui": { - "end": 8, - "abridged": false - }, "speedometer2": { "abridged": false, "pageset_repeat": 2 @@ -418,14 +394,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -439,7 +411,6 @@ "pageset_repeat": 2 }, "desktop_ui": { - "begin": 8, "abridged": false }, "dummy_benchmark.noisy_benchmark_1": { @@ -468,14 +439,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -492,7 +459,7 @@ "abridged": false }, "media.desktop": { - "end": 13, + "end": 14, "abridged": false }, "speedometer2": { @@ -511,14 +478,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -532,7 +495,7 @@ "pageset_repeat": 2 }, "media.desktop": { - "begin": 13, + "begin": 14, "abridged": false }, "memory.desktop": { @@ -555,14 +518,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -602,14 +561,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -630,7 +585,7 @@ "abridged": false }, "rendering.desktop": { - "end": 11, + "end": 12, "abridged": false }, "speedometer2": { @@ -649,14 +604,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -670,8 +621,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 11, - "end": 43, + "begin": 12, + "end": 45, "abridged": false }, "speedometer2": { @@ -690,14 +641,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -711,8 +658,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 43, - "end": 76, + "begin": 45, + "end": 79, "abridged": false }, "speedometer2": { @@ -731,14 +678,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -752,8 +695,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 76, - "end": 110, + "begin": 79, + "end": 115, "abridged": false }, "speedometer2": { @@ -772,14 +715,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -793,8 +732,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 110, - "end": 143, + "begin": 115, + "end": 148, "abridged": false }, "speedometer2": { @@ -813,14 +752,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -834,8 +769,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 143, - "end": 171, + "begin": 148, + "end": 176, "abridged": false }, "speedometer2": { @@ -854,14 +789,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -875,8 +806,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 171, - "end": 202, + "begin": 176, + "end": 204, "abridged": false }, "speedometer2": { @@ -895,14 +826,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -916,8 +843,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 202, - "end": 220, + "begin": 204, + "end": 225, "abridged": false }, "speedometer3": { @@ -929,14 +856,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -950,8 +873,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 220, - "end": 257, + "begin": 225, + "end": 263, "abridged": false }, "speedometer3": { @@ -963,14 +886,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -984,8 +903,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 257, - "end": 281, + "begin": 263, + "end": 292, "abridged": false }, "speedometer3": { @@ -997,14 +916,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -1014,7 +929,7 @@ "23": { "benchmarks": { "rendering.desktop": { - "begin": 281, + "begin": 292, "abridged": false }, "speedometer": { @@ -1044,13 +959,13 @@ "abridged": false }, "system_health.common_desktop": { - "end": 19, + "end": 24, "abridged": false } }, "crossbench": { - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] } } @@ -1058,11 +973,11 @@ "24": { "benchmarks": { "system_health.common_desktop": { - "begin": 19, + "begin": 24, "abridged": false }, "system_health.memory_desktop": { - "end": 9, + "end": 10, "abridged": false }, "speedometer3": { @@ -1077,8 +992,8 @@ "25": { "benchmarks": { "system_health.memory_desktop": { - "begin": 9, - "end": 41, + "begin": 10, + "end": 44, "abridged": false }, "speedometer3": { @@ -1093,8 +1008,8 @@ "26": { "benchmarks": { "system_health.memory_desktop": { - "begin": 41, - "end": 73, + "begin": 44, + "end": 74, "abridged": false }, "speedometer3": { @@ -1109,7 +1024,7 @@ "27": { "benchmarks": { "system_health.memory_desktop": { - "begin": 73, + "begin": 74, "abridged": false }, "v8.browsing_desktop": { @@ -1148,38 +1063,38 @@ } }, "extra_infos": { - "num_stories": 1308, - "predicted_min_shard_time": 1888.0, + "num_stories": 1290, + "predicted_min_shard_time": 1828.0, "predicted_min_shard_index": 0, - "predicted_max_shard_time": 2871.0, + "predicted_max_shard_time": 2700.0, "predicted_max_shard_index": 27, - "shard #0": 1888.0, - "shard #1": 2031.0, - "shard #2": 1888.0, - "shard #3": 2018.0, - "shard #4": 1888.0, - "shard #5": 2022.0, - "shard #6": 2025.0, - "shard #7": 2020.0, - "shard #8": 2029.0, - "shard #9": 2247.0, - "shard #10": 2014.0, - "shard #11": 2042.0, - "shard #12": 2027.0, - "shard #13": 2008.0, - "shard #14": 2003.0, - "shard #15": 2012.0, - "shard #16": 2005.0, - "shard #17": 2016.0, - "shard #18": 2017.0, - "shard #19": 2003.0, - "shard #20": 2003.0, - "shard #21": 2004.0, - "shard #22": 2006.0, - "shard #23": 1996.0, - "shard #24": 1947.0, - "shard #25": 2055.0, - "shard #26": 1941.0, - "shard #27": 2871.0 + "shard #0": 1828.0, + "shard #1": 1933.0, + "shard #2": 1828.0, + "shard #3": 1980.0, + "shard #4": 1828.0, + "shard #5": 1985.0, + "shard #6": 1987.0, + "shard #7": 1984.0, + "shard #8": 2076.0, + "shard #9": 2227.0, + "shard #10": 1965.0, + "shard #11": 1971.0, + "shard #12": 1967.0, + "shard #13": 1970.0, + "shard #14": 1961.0, + "shard #15": 1969.0, + "shard #16": 1965.0, + "shard #17": 1973.0, + "shard #18": 1963.0, + "shard #19": 1948.0, + "shard #20": 1973.0, + "shard #21": 1972.0, + "shard #22": 1965.0, + "shard #23": 1975.0, + "shard #24": 1966.0, + "shard #25": 1980.0, + "shard #26": 2007.0, + "shard #27": 2700.0 } }
diff --git a/tools/perf/core/shard_maps/mac-m2-pro-perf_map.json b/tools/perf/core/shard_maps/mac-m2-pro-perf_map.json index a8236b7..8bf1ea6 100644 --- a/tools/perf/core/shard_maps/mac-m2-pro-perf_map.json +++ b/tools/perf/core/shard_maps/mac-m2-pro-perf_map.json
@@ -32,7 +32,7 @@ "abridged": false }, "blink_perf.layout": { - "end": 78, + "end": 73, "abridged": false } } @@ -40,7 +40,7 @@ "2": { "benchmarks": { "blink_perf.layout": { - "begin": 78, + "begin": 73, "abridged": false }, "blink_perf.owp_storage": { @@ -93,7 +93,7 @@ "abridged": false }, "memory.desktop": { - "end": 3, + "end": 2, "abridged": false } }, @@ -107,14 +107,14 @@ "4": { "benchmarks": { "memory.desktop": { - "begin": 3, + "begin": 2, "abridged": false }, "octane": { "abridged": false }, "power.desktop": { - "end": 4, + "end": 2, "abridged": false } }, @@ -128,14 +128,14 @@ "5": { "benchmarks": { "power.desktop": { - "begin": 4, + "begin": 2, "abridged": false }, "rasterize_and_record_micro.top_25": { "abridged": false }, "rendering.desktop": { - "end": 27, + "end": 23, "abridged": false } } @@ -143,8 +143,8 @@ "6": { "benchmarks": { "rendering.desktop": { - "begin": 27, - "end": 88, + "begin": 23, + "end": 83, "abridged": false } } @@ -152,8 +152,8 @@ "7": { "benchmarks": { "rendering.desktop": { - "begin": 88, - "end": 149, + "begin": 83, + "end": 144, "abridged": false } } @@ -161,8 +161,8 @@ "8": { "benchmarks": { "rendering.desktop": { - "begin": 149, - "end": 203, + "begin": 144, + "end": 199, "abridged": false } } @@ -170,8 +170,8 @@ "9": { "benchmarks": { "rendering.desktop": { - "begin": 203, - "end": 249, + "begin": 199, + "end": 244, "abridged": false } } @@ -179,8 +179,8 @@ "10": { "benchmarks": { "rendering.desktop": { - "begin": 249, - "end": 295, + "begin": 244, + "end": 291, "abridged": false } } @@ -188,8 +188,8 @@ "11": { "benchmarks": { "rendering.desktop": { - "begin": 295, - "end": 348, + "begin": 291, + "end": 345, "abridged": false } } @@ -197,7 +197,7 @@ "12": { "benchmarks": { "rendering.desktop": { - "begin": 348, + "begin": 345, "abridged": false }, "rendering.desktop.notracing": { @@ -228,20 +228,16 @@ "abridged": false }, "system_health.common_desktop": { - "end": 21, + "end": 20, "abridged": false } }, "crossbench": { - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] } @@ -250,8 +246,8 @@ "13": { "benchmarks": { "system_health.common_desktop": { - "begin": 21, - "end": 73, + "begin": 20, + "end": 72, "abridged": false } } @@ -259,11 +255,11 @@ "14": { "benchmarks": { "system_health.common_desktop": { - "begin": 73, + "begin": 72, "abridged": false }, "system_health.memory_desktop": { - "end": 17, + "end": 16, "abridged": false } } @@ -271,8 +267,8 @@ "15": { "benchmarks": { "system_health.memory_desktop": { - "begin": 17, - "end": 37, + "begin": 16, + "end": 36, "abridged": false } } @@ -280,8 +276,8 @@ "16": { "benchmarks": { "system_health.memory_desktop": { - "begin": 37, - "end": 59, + "begin": 36, + "end": 58, "abridged": false } } @@ -289,7 +285,7 @@ "17": { "benchmarks": { "system_health.memory_desktop": { - "begin": 59, + "begin": 58, "end": 76, "abridged": false } @@ -325,29 +321,29 @@ } }, "extra_infos": { - "num_stories": 1123, - "predicted_min_shard_time": 1070.0, - "predicted_min_shard_index": 18, - "predicted_max_shard_time": 1144.0, - "predicted_max_shard_index": 3, + "num_stories": 1124, + "predicted_min_shard_time": 1059.0, + "predicted_min_shard_index": 3, + "predicted_max_shard_time": 1164.0, + "predicted_max_shard_index": 17, "shard #0": 1103.0, - "shard #1": 1103.0, - "shard #2": 1101.0, - "shard #3": 1144.0, - "shard #4": 1089.0, - "shard #5": 1107.0, - "shard #6": 1108.0, - "shard #7": 1104.0, - "shard #8": 1092.0, - "shard #9": 1101.0, - "shard #10": 1109.0, - "shard #11": 1109.0, - "shard #12": 1118.0, - "shard #13": 1108.0, - "shard #14": 1136.0, - "shard #15": 1089.0, + "shard #1": 1106.0, + "shard #2": 1118.0, + "shard #3": 1059.0, + "shard #4": 1094.0, + "shard #5": 1105.0, + "shard #6": 1099.0, + "shard #7": 1112.0, + "shard #8": 1102.0, + "shard #9": 1104.0, + "shard #10": 1103.0, + "shard #11": 1087.0, + "shard #12": 1122.0, + "shard #13": 1098.0, + "shard #14": 1090.0, + "shard #15": 1128.0, "shard #16": 1107.0, - "shard #17": 1113.0, + "shard #17": 1164.0, "shard #18": 1070.0, "shard #19": 1072.0 }
diff --git a/tools/perf/core/shard_maps/mac-m3-pro-perf_map.json b/tools/perf/core/shard_maps/mac-m3-pro-perf_map.json index ebb5b31f..d5f6cfa2 100644 --- a/tools/perf/core/shard_maps/mac-m3-pro-perf_map.json +++ b/tools/perf/core/shard_maps/mac-m3-pro-perf_map.json
@@ -1,10 +1,6 @@ { "0": { "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] @@ -14,19 +10,6 @@ }, "1": { "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - } - }, - "benchmarks": {} - }, - "2": { - "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -34,17 +17,18 @@ }, "benchmarks": {} }, + "2": { + "crossbench": { + "speedometer_2": { + "display_name": "speedometer2.crossbench", + "arguments": [] + } + }, + "benchmarks": {} + }, "3": { "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", - "arguments": [] - }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] } @@ -52,14 +36,14 @@ "benchmarks": {} }, "extra_infos": { - "num_stories": 8, + "num_stories": 4, "predicted_min_shard_time": 60, - "predicted_min_shard_index": 1, - "predicted_max_shard_time": 420, - "predicted_max_shard_index": 2, - "shard #0": 240, - "shard #1": 60, - "shard #2": 420, - "shard #3": 180 + "predicted_min_shard_index": 2, + "predicted_max_shard_time": 360, + "predicted_max_shard_index": 1, + "shard #0": 180, + "shard #1": 360, + "shard #2": 60, + "shard #3": 60 } }
diff --git a/tools/perf/core/shard_maps/win-10-perf_map.json b/tools/perf/core/shard_maps/win-10-perf_map.json index f01930a..3fa2e07 100644 --- a/tools/perf/core/shard_maps/win-10-perf_map.json +++ b/tools/perf/core/shard_maps/win-10-perf_map.json
@@ -8,7 +8,7 @@ "abridged": false }, "blink_perf.bindings": { - "end": 10, + "end": 11, "abridged": false }, "jetstream2": { @@ -48,20 +48,16 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "1": { "benchmarks": { "blink_perf.bindings": { - "begin": 10, + "begin": 11, "abridged": false }, "blink_perf.css": { @@ -99,13 +95,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -122,7 +114,7 @@ "abridged": false }, "blink_perf.layout": { - "end": 85, + "end": 86, "abridged": false }, "jetstream2": { @@ -153,20 +145,16 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "3": { "benchmarks": { "blink_perf.layout": { - "begin": 85, + "begin": 86, "abridged": false }, "blink_perf.owp_storage": { @@ -207,13 +195,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -284,13 +268,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -336,13 +316,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -380,14 +356,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -428,13 +400,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -466,13 +434,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -504,13 +468,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -529,13 +489,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -572,16 +528,12 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] } } @@ -601,13 +553,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -629,13 +577,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -654,13 +598,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -679,13 +619,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -707,13 +643,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -748,39 +680,35 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "extra_infos": { - "num_stories": 1227, - "predicted_min_shard_time": 2166.0, + "num_stories": 1211, + "predicted_min_shard_time": 2106.0, "predicted_min_shard_index": 13, - "predicted_max_shard_time": 2448.0, + "predicted_max_shard_time": 2388.0, "predicted_max_shard_index": 17, - "shard #0": 2243.0, - "shard #1": 2266.0, - "shard #2": 2243.0, - "shard #3": 2254.0, - "shard #4": 2308.0, - "shard #5": 2286.0, - "shard #6": 2222.0, - "shard #7": 2230.0, - "shard #8": 2247.0, - "shard #9": 2253.0, - "shard #10": 2264.0, - "shard #11": 2223.0, - "shard #12": 2207.0, - "shard #13": 2166.0, - "shard #14": 2250.0, - "shard #15": 2283.0, - "shard #16": 2267.0, - "shard #17": 2448.0 + "shard #0": 2193.0, + "shard #1": 2206.0, + "shard #2": 2193.0, + "shard #3": 2194.0, + "shard #4": 2248.0, + "shard #5": 2226.0, + "shard #6": 2162.0, + "shard #7": 2170.0, + "shard #8": 2187.0, + "shard #9": 2193.0, + "shard #10": 2204.0, + "shard #11": 2163.0, + "shard #12": 2147.0, + "shard #13": 2106.0, + "shard #14": 2190.0, + "shard #15": 2223.0, + "shard #16": 2207.0, + "shard #17": 2388.0 } }
diff --git a/tools/perf/core/shard_maps/win-10_amd_laptop-perf_map.json b/tools/perf/core/shard_maps/win-10_amd_laptop-perf_map.json index 92d3ba2..3018299 100644 --- a/tools/perf/core/shard_maps/win-10_amd_laptop-perf_map.json +++ b/tools/perf/core/shard_maps/win-10_amd_laptop-perf_map.json
@@ -7,20 +7,19 @@ } }, "1": { - "benchmarks": { - "octane": { - "abridged": false - } - }, "crossbench": { "jetstream_2.2": { "display_name": "jetstream2.crossbench", "arguments": [] } - } + }, + "benchmarks": {} }, "2": { "benchmarks": { + "octane": { + "abridged": false + }, "speedometer2": { "abridged": false }, @@ -29,24 +28,20 @@ } }, "crossbench": { - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] } } }, "extra_infos": { - "num_stories": 7, + "num_stories": 6, "predicted_min_shard_time": 75.0, "predicted_min_shard_index": 0, - "predicted_max_shard_time": 217.0, + "predicted_max_shard_time": 180, "predicted_max_shard_index": 1, "shard #0": 75.0, - "shard #1": 217.0, - "shard #2": 185.0 + "shard #1": 180, + "shard #2": 162.0 } }
diff --git a/tools/perf/core/shard_maps/win-10_laptop_low_end-perf_map.json b/tools/perf/core/shard_maps/win-10_laptop_low_end-perf_map.json index 5ee939c..c7d2f8b 100644 --- a/tools/perf/core/shard_maps/win-10_laptop_low_end-perf_map.json +++ b/tools/perf/core/shard_maps/win-10_laptop_low_end-perf_map.json
@@ -23,13 +23,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -55,13 +51,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -87,13 +79,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -101,7 +89,7 @@ "benchmarks": { "blink_perf.accessibility": { "begin": 8, - "end": 21, + "end": 22, "abridged": false }, "jetstream2": { @@ -119,24 +107,20 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "4": { "benchmarks": { "blink_perf.accessibility": { - "begin": 21, + "begin": 22, "abridged": false }, "blink_perf.bindings": { - "end": 45, + "end": 50, "abridged": false }, "jetstream2": { @@ -154,25 +138,25 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "5": { "benchmarks": { "blink_perf.bindings": { - "begin": 45, + "begin": 50, "abridged": false }, "blink_perf.css": { "abridged": false }, + "blink_perf.dom": { + "end": 2, + "abridged": false + }, "speedometer2": { "abridged": false }, @@ -181,20 +165,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "6": { "benchmarks": { "blink_perf.dom": { - "end": 11, + "begin": 2, + "end": 12, "abridged": false }, "speedometer2": { @@ -205,20 +186,16 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "7": { "benchmarks": { "blink_perf.dom": { - "begin": 11, + "begin": 12, "abridged": false }, "blink_perf.events": { @@ -228,7 +205,7 @@ "abridged": false }, "blink_perf.layout": { - "end": 42, + "end": 50, "abridged": false }, "speedometer2": { @@ -239,25 +216,25 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "8": { "benchmarks": { "blink_perf.layout": { - "begin": 42, + "begin": 50, "abridged": false }, "blink_perf.owp_storage": { "abridged": false }, + "blink_perf.parser": { + "end": 7, + "abridged": false + }, "speedometer2": { "abridged": false }, @@ -266,26 +243,23 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "9": { "benchmarks": { "blink_perf.parser": { + "begin": 7, "abridged": false }, "blink_perf.shadow_dom": { "abridged": false }, "blink_perf.webaudio": { - "end": 6, + "end": 7, "abridged": false }, "speedometer2": { @@ -296,20 +270,16 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "10": { "benchmarks": { "blink_perf.webaudio": { - "begin": 6, + "begin": 7, "abridged": false }, "blink_perf.webcodecs": { @@ -336,6 +306,9 @@ "dummy_benchmark.stable_benchmark_1": { "abridged": false }, + "jetstream2": { + "abridged": false + }, "speedometer2": { "abridged": false }, @@ -344,108 +317,18 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "11": { "benchmarks": { - "jetstream2": { - "abridged": false - }, "media.desktop": { - "end": 20, - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - } - } - }, - "12": { - "benchmarks": { - "media.desktop": { - "begin": 20, "abridged": false }, "memory.desktop": { - "end": 6, - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - } - } - }, - "13": { - "benchmarks": { - "memory.desktop": { - "begin": 6, - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "motionmark_1.3": { - "display_name": "motionmark1.3.crossbench", - "arguments": [] - } - } - }, - "14": { - "benchmarks": { - "octane": { - "abridged": false - }, - "power.desktop": { - "abridged": false - }, - "rasterize_and_record_micro.top_25": { "end": 1, "abridged": false }, @@ -457,12 +340,84 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { + "display_name": "speedometer3.crossbench", + "arguments": [] + } + } + }, + "12": { + "benchmarks": { + "memory.desktop": { + "begin": 1, + "end": 8, + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer3": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3": { + "display_name": "speedometer3.crossbench", + "arguments": [] + } + } + }, + "13": { + "benchmarks": { + "memory.desktop": { + "begin": 8, + "abridged": false + }, + "octane": { + "abridged": false + }, + "power.desktop": { + "end": 4, + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer3": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", + "motionmark_1.3": { + "display_name": "motionmark1.3.crossbench", + "arguments": [] + } + } + }, + "14": { + "benchmarks": { + "power.desktop": { + "begin": 4, + "abridged": false + }, + "rasterize_and_record_micro.top_25": { + "end": 21, + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer3": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3": { + "display_name": "speedometer3.crossbench", "arguments": [] } } @@ -470,11 +425,11 @@ "15": { "benchmarks": { "rasterize_and_record_micro.top_25": { - "begin": 1, + "begin": 21, "abridged": false }, "rendering.desktop": { - "end": 14, + "end": 22, "abridged": false }, "speedometer2": { @@ -485,21 +440,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "16": { "benchmarks": { "rendering.desktop": { - "begin": 14, - "end": 38, + "begin": 22, + "end": 49, "abridged": false }, "speedometer2": { @@ -510,21 +461,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "17": { "benchmarks": { "rendering.desktop": { - "begin": 38, - "end": 64, + "begin": 49, + "end": 76, "abridged": false }, "speedometer2": { @@ -535,21 +482,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "18": { "benchmarks": { "rendering.desktop": { - "begin": 64, - "end": 90, + "begin": 76, + "end": 103, "abridged": false }, "speedometer2": { @@ -560,21 +503,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "19": { "benchmarks": { "rendering.desktop": { - "begin": 90, - "end": 116, + "begin": 103, + "end": 130, "abridged": false }, "speedometer2": { @@ -585,21 +524,17 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "20": { "benchmarks": { "rendering.desktop": { - "begin": 116, - "end": 151, + "begin": 130, + "end": 160, "abridged": false } } @@ -607,8 +542,8 @@ "21": { "benchmarks": { "rendering.desktop": { - "begin": 151, - "end": 178, + "begin": 160, + "end": 190, "abridged": false } } @@ -616,8 +551,8 @@ "22": { "benchmarks": { "rendering.desktop": { - "begin": 178, - "end": 212, + "begin": 190, + "end": 222, "abridged": false } } @@ -625,8 +560,8 @@ "23": { "benchmarks": { "rendering.desktop": { - "begin": 212, - "end": 245, + "begin": 222, + "end": 252, "abridged": false } } @@ -634,8 +569,8 @@ "24": { "benchmarks": { "rendering.desktop": { - "begin": 245, - "end": 267, + "begin": 252, + "end": 274, "abridged": false } } @@ -643,8 +578,8 @@ "25": { "benchmarks": { "rendering.desktop": { - "begin": 267, - "end": 291, + "begin": 274, + "end": 299, "abridged": false } } @@ -652,8 +587,8 @@ "26": { "benchmarks": { "rendering.desktop": { - "begin": 291, - "end": 319, + "begin": 299, + "end": 328, "abridged": false } } @@ -661,16 +596,12 @@ "27": { "benchmarks": { "rendering.desktop": { - "begin": 319, + "begin": 328, "abridged": false }, "rendering.desktop.notracing": { "abridged": false - } - } - }, - "28": { - "benchmarks": { + }, "speedometer": { "abridged": false }, @@ -682,7 +613,11 @@ }, "speedometer2-future": { "abridged": false - }, + } + } + }, + "28": { + "benchmarks": { "speedometer3": { "abridged": false }, @@ -690,13 +625,13 @@ "abridged": false }, "system_health.common_desktop": { - "end": 18, + "end": 24, "abridged": false } }, "crossbench": { - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] } } @@ -704,8 +639,8 @@ "29": { "benchmarks": { "system_health.common_desktop": { - "begin": 18, - "end": 53, + "begin": 24, + "end": 59, "abridged": false } } @@ -713,20 +648,20 @@ "30": { "benchmarks": { "system_health.common_desktop": { - "begin": 53, - "end": 79, + "begin": 59, + "abridged": false + }, + "system_health.memory_desktop": { + "end": 1, "abridged": false } } }, "31": { "benchmarks": { - "system_health.common_desktop": { - "begin": 79, - "abridged": false - }, "system_health.memory_desktop": { - "end": 16, + "begin": 1, + "end": 18, "abridged": false } } @@ -734,8 +669,8 @@ "32": { "benchmarks": { "system_health.memory_desktop": { - "begin": 16, - "end": 27, + "begin": 18, + "end": 30, "abridged": false } } @@ -743,8 +678,8 @@ "33": { "benchmarks": { "system_health.memory_desktop": { - "begin": 27, - "end": 44, + "begin": 30, + "end": 48, "abridged": false } } @@ -752,8 +687,8 @@ "34": { "benchmarks": { "system_health.memory_desktop": { - "begin": 44, - "end": 59, + "begin": 48, + "end": 62, "abridged": false } } @@ -761,8 +696,8 @@ "35": { "benchmarks": { "system_health.memory_desktop": { - "begin": 59, - "end": 66, + "begin": 62, + "end": 67, "abridged": false } } @@ -770,8 +705,8 @@ "36": { "benchmarks": { "system_health.memory_desktop": { - "begin": 66, - "end": 72, + "begin": 67, + "end": 75, "abridged": false } } @@ -779,11 +714,11 @@ "37": { "benchmarks": { "system_health.memory_desktop": { - "begin": 72, + "begin": 75, "abridged": false }, "v8.browsing_desktop": { - "end": 7, + "end": 15, "abridged": false } } @@ -791,20 +726,20 @@ "38": { "benchmarks": { "v8.browsing_desktop": { - "begin": 7, - "end": 28, + "begin": 15, + "abridged": false + }, + "v8.browsing_desktop-future": { + "end": 6, "abridged": false } } }, "39": { "benchmarks": { - "v8.browsing_desktop": { - "begin": 28, - "abridged": false - }, "v8.browsing_desktop-future": { - "end": 25, + "begin": 6, + "end": 27, "abridged": false } } @@ -812,11 +747,11 @@ "40": { "benchmarks": { "v8.browsing_desktop-future": { - "begin": 25, + "begin": 27, "abridged": false }, "v8.runtime_stats.top_25": { - "end": 17, + "end": 20, "abridged": false } } @@ -824,8 +759,8 @@ "41": { "benchmarks": { "v8.runtime_stats.top_25": { - "begin": 17, - "end": 46, + "begin": 20, + "end": 48, "abridged": false } } @@ -833,8 +768,8 @@ "42": { "benchmarks": { "v8.runtime_stats.top_25": { - "begin": 46, - "end": 74, + "begin": 48, + "end": 75, "abridged": false } } @@ -842,7 +777,7 @@ "43": { "benchmarks": { "v8.runtime_stats.top_25": { - "begin": 74, + "begin": 75, "end": 92, "abridged": false } @@ -863,55 +798,55 @@ } }, "extra_infos": { - "num_stories": 1335, - "predicted_min_shard_time": 1086.0, - "predicted_min_shard_index": 35, - "predicted_max_shard_time": 1826.0, + "num_stories": 1315, + "predicted_min_shard_time": 1111.0, + "predicted_min_shard_index": 0, + "predicted_max_shard_time": 1766.0, "predicted_max_shard_index": 1, - "shard #0": 1171.0, - "shard #1": 1826.0, - "shard #2": 1622.0, - "shard #3": 1295.0, - "shard #4": 1304.0, - "shard #5": 1314.0, - "shard #6": 1318.0, - "shard #7": 1306.0, - "shard #8": 1325.0, - "shard #9": 1345.0, - "shard #10": 1273.0, - "shard #11": 1307.0, - "shard #12": 1374.0, - "shard #13": 1343.0, - "shard #14": 1303.0, - "shard #15": 1317.0, - "shard #16": 1299.0, - "shard #17": 1289.0, - "shard #18": 1295.0, - "shard #19": 1317.0, - "shard #20": 1295.0, - "shard #21": 1285.0, - "shard #22": 1292.0, - "shard #23": 1323.0, - "shard #24": 1273.0, - "shard #25": 1310.0, - "shard #26": 1284.0, - "shard #27": 1405.0, - "shard #28": 1317.0, - "shard #29": 1306.0, - "shard #30": 1264.0, - "shard #31": 1269.0, - "shard #32": 1302.0, - "shard #33": 1263.0, + "shard #0": 1111.0, + "shard #1": 1766.0, + "shard #2": 1562.0, + "shard #3": 1265.0, + "shard #4": 1281.0, + "shard #5": 1220.0, + "shard #6": 1282.0, + "shard #7": 1279.0, + "shard #8": 1277.0, + "shard #9": 1274.0, + "shard #10": 1356.0, + "shard #11": 1294.0, + "shard #12": 1358.0, + "shard #13": 1254.0, + "shard #14": 1278.0, + "shard #15": 1278.0, + "shard #16": 1298.0, + "shard #17": 1267.0, + "shard #18": 1259.0, + "shard #19": 1267.0, + "shard #20": 1264.0, + "shard #21": 1292.0, + "shard #22": 1263.0, + "shard #23": 1300.0, + "shard #24": 1272.0, + "shard #25": 1276.0, + "shard #26": 1282.0, + "shard #27": 1312.0, + "shard #28": 1319.0, + "shard #29": 1259.0, + "shard #30": 1209.0, + "shard #31": 1335.0, + "shard #32": 1293.0, + "shard #33": 1308.0, "shard #34": 1314.0, - "shard #35": 1086.0, - "shard #36": 1350.0, - "shard #37": 1311.0, - "shard #38": 1278.0, - "shard #39": 1350.0, - "shard #40": 1313.0, - "shard #41": 1302.0, - "shard #42": 1348.0, - "shard #43": 1322.0, + "shard #35": 1305.0, + "shard #36": 1233.0, + "shard #37": 1266.0, + "shard #38": 1264.0, + "shard #39": 1221.0, + "shard #40": 1258.0, + "shard #41": 1266.0, + "shard #42": 1297.0, + "shard #43": 1271.0, "shard #44": 1739.0 } }
diff --git a/tools/perf/core/shard_maps/win-11-perf_map.json b/tools/perf/core/shard_maps/win-11-perf_map.json index eb1fd71..1f2ce49 100644 --- a/tools/perf/core/shard_maps/win-11-perf_map.json +++ b/tools/perf/core/shard_maps/win-11-perf_map.json
@@ -32,13 +32,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -63,13 +59,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -100,13 +92,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -138,13 +126,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -173,13 +157,9 @@ "display_name": "jetstream2.crossbench", "arguments": [] }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -232,13 +212,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -265,13 +241,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -302,13 +274,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -329,13 +297,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -356,14 +320,10 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, "motionmark_1.3": { "display_name": "motionmark1.3.crossbench", "arguments": [] @@ -403,16 +363,12 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] } } @@ -432,13 +388,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -457,13 +409,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -482,13 +430,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -507,13 +451,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -532,13 +472,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -557,13 +493,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -593,13 +525,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -621,13 +549,9 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, @@ -659,41 +583,37 @@ } }, "crossbench": { - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] - }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] } } }, "extra_infos": { - "num_stories": 781, - "predicted_min_shard_time": 899.0, + "num_stories": 761, + "predicted_min_shard_time": 839.0, "predicted_min_shard_index": 16, - "predicted_max_shard_time": 1127.0, + "predicted_max_shard_time": 1067.0, "predicted_max_shard_index": 14, - "shard #0": 1078.0, - "shard #1": 1027.0, - "shard #2": 1004.0, - "shard #3": 1023.0, - "shard #4": 1028.0, - "shard #5": 969.0, - "shard #6": 1029.0, - "shard #7": 1025.0, - "shard #8": 1102.0, - "shard #9": 1038.0, - "shard #10": 1021.0, - "shard #11": 1010.0, - "shard #12": 1037.0, - "shard #13": 1043.0, - "shard #14": 1127.0, - "shard #15": 950.0, - "shard #16": 899.0, - "shard #17": 1035.0, - "shard #18": 1038.0, - "shard #19": 1114.0 + "shard #0": 1018.0, + "shard #1": 967.0, + "shard #2": 944.0, + "shard #3": 963.0, + "shard #4": 968.0, + "shard #5": 909.0, + "shard #6": 969.0, + "shard #7": 965.0, + "shard #8": 1042.0, + "shard #9": 978.0, + "shard #10": 961.0, + "shard #11": 950.0, + "shard #12": 977.0, + "shard #13": 983.0, + "shard #14": 1067.0, + "shard #15": 890.0, + "shard #16": 839.0, + "shard #17": 975.0, + "shard #18": 978.0, + "shard #19": 1054.0 } }
diff --git a/tools/perf/core/shard_maps/win-11_laptop_low_end-perf_map.json b/tools/perf/core/shard_maps/win-11_laptop_low_end-perf_map.json index 9e1fa59..97eaa77b 100644 --- a/tools/perf/core/shard_maps/win-11_laptop_low_end-perf_map.json +++ b/tools/perf/core/shard_maps/win-11_laptop_low_end-perf_map.json
@@ -23,7 +23,7 @@ "abridged": false }, "system_health.common_desktop": { - "end": 11, + "end": 14, "abridged": false } }, @@ -36,15 +36,11 @@ "display_name": "motionmark1.3.crossbench", "arguments": [] }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] } @@ -53,7 +49,7 @@ "1": { "benchmarks": { "system_health.common_desktop": { - "begin": 11, + "begin": 14, "abridged": false }, "v8.browsing_desktop": { @@ -62,12 +58,12 @@ } }, "extra_infos": { - "num_stories": 178, - "predicted_min_shard_time": 2787.0, + "num_stories": 177, + "predicted_min_shard_time": 2775.0, "predicted_min_shard_index": 1, - "predicted_max_shard_time": 2827.0, + "predicted_max_shard_time": 2779.0, "predicted_max_shard_index": 0, - "shard #0": 2827.0, - "shard #1": 2787.0 + "shard #0": 2779.0, + "shard #1": 2775.0 } }
diff --git a/tools/perf/core/shard_maps/win-arm64-snapdragon-elite-perf_map.json b/tools/perf/core/shard_maps/win-arm64-snapdragon-elite-perf_map.json index 41c3e42b..01f8b4d 100644 --- a/tools/perf/core/shard_maps/win-arm64-snapdragon-elite-perf_map.json +++ b/tools/perf/core/shard_maps/win-arm64-snapdragon-elite-perf_map.json
@@ -59,26 +59,22 @@ "display_name": "motionmark1.3.crossbench", "arguments": [] }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] } } }, "extra_infos": { - "num_stories": 181, - "predicted_min_shard_time": 2782.0, + "num_stories": 180, + "predicted_min_shard_time": 2722.0, "predicted_min_shard_index": 0, - "predicted_max_shard_time": 2782.0, + "predicted_max_shard_time": 2722.0, "predicted_max_shard_index": 0, - "shard #0": 2782.0 + "shard #0": 2722.0 } }
diff --git a/tools/perf/core/shard_maps/win-arm64-snapdragon-plus-perf_map.json b/tools/perf/core/shard_maps/win-arm64-snapdragon-plus-perf_map.json index 41c3e42b..01f8b4d 100644 --- a/tools/perf/core/shard_maps/win-arm64-snapdragon-plus-perf_map.json +++ b/tools/perf/core/shard_maps/win-arm64-snapdragon-plus-perf_map.json
@@ -59,26 +59,22 @@ "display_name": "motionmark1.3.crossbench", "arguments": [] }, - "speedometer_2.1": { - "display_name": "speedometer2.1.crossbench", + "speedometer_2": { + "display_name": "speedometer2.crossbench", "arguments": [] }, - "speedometer_3.1": { - "display_name": "speedometer3.1.crossbench", - "arguments": [] - }, - "speedometer_3.0": { + "speedometer_3": { "display_name": "speedometer3.crossbench", "arguments": [] } } }, "extra_infos": { - "num_stories": 181, - "predicted_min_shard_time": 2782.0, + "num_stories": 180, + "predicted_min_shard_time": 2722.0, "predicted_min_shard_index": 0, - "predicted_max_shard_time": 2782.0, + "predicted_max_shard_time": 2722.0, "predicted_max_shard_index": 0, - "shard #0": 2782.0 + "shard #0": 2722.0 } }
diff --git a/tools/perf/process_perf_results.pydeps b/tools/perf/process_perf_results.pydeps index f38f8f5..21ce947 100644 --- a/tools/perf/process_perf_results.pydeps +++ b/tools/perf/process_perf_results.pydeps
@@ -112,6 +112,7 @@ ../../third_party/catapult/devil/devil/utils/__init__.py ../../third_party/catapult/devil/devil/utils/cmd_helper.py ../../third_party/catapult/devil/devil/utils/geometry.py +../../third_party/catapult/devil/devil/utils/host_utils.py ../../third_party/catapult/devil/devil/utils/lazy/__init__.py ../../third_party/catapult/devil/devil/utils/lazy/weak_constant.py ../../third_party/catapult/devil/devil/utils/logging_common.py
diff --git a/tools/rust/update_rust.py b/tools/rust/update_rust.py index 780c2ac..805a9c6e 100755 --- a/tools/rust/update_rust.py +++ b/tools/rust/update_rust.py
@@ -32,7 +32,7 @@ # These fields are written by //tools/clang/scripts/upload_revision.py, and # should not be changed manually. # They are also read by build/config/compiler/BUILD.gn. -RUST_REVISION = '3350c1eb3fd8fe1bee1ed4c76944d707bd256876' +RUST_REVISION = '4a0969e06dbeaaa43914d2d00b2e843d49aa3886' RUST_SUB_REVISION = 1 # The revision of Crubit to use from https://github.com/google/crubit
diff --git a/tools/update_pgo_profiles.py b/tools/update_pgo_profiles.py index 4e331b4..d7e68d0a 100755 --- a/tools/update_pgo_profiles.py +++ b/tools/update_pgo_profiles.py
@@ -76,7 +76,7 @@ Raises: RuntimeError: If failed to download profiles from gcs. """ - profile_name = _read_profile_name(args.target) + profile_name = args.override_filename or _read_profile_name(args.target) profile_path = os.path.join(_PGO_PROFILE_DIR, profile_name) if os.path.isfile(profile_path): os.utime(profile_path, None) @@ -101,7 +101,8 @@ Raises: RuntimeError: If the current profile is missing. """ - profile_path = os.path.join(_PGO_PROFILE_DIR, _read_profile_name(args.target)) + profile_name = args.override_filename or _read_profile_name(args.target) + profile_path = os.path.join(_PGO_PROFILE_DIR, profile_name) if not os.path.isfile(profile_path): raise RuntimeError( 'requested profile "%s" doesn\'t exist, please make sure ' @@ -144,6 +145,8 @@ 'android-desktop-x64', ], help='Identifier of a specific target platform + architecture.') + parser.add_argument('--override-filename', + help='The filename to prefer instead of the sha1 file.') subparsers = parser.add_subparsers() parser_update = subparsers.add_parser('update')
diff --git a/ui/accelerated_widget_mac/accelerated_widget_mac_export.h b/ui/accelerated_widget_mac/accelerated_widget_mac_export.h index 181e822..1899179 100644 --- a/ui/accelerated_widget_mac/accelerated_widget_mac_export.h +++ b/ui/accelerated_widget_mac/accelerated_widget_mac_export.h
@@ -11,11 +11,7 @@ #if defined(COMPONENT_BUILD) -#if defined(ACCELERATED_WIDGET_MAC_IMPLEMENTATION) #define ACCELERATED_WIDGET_MAC_EXPORT __attribute__((visibility("default"))) -#else -#define ACCELERATED_WIDGET_MAC_EXPORT -#endif #else // defined(COMPONENT_BUILD) #define ACCELERATED_WIDGET_MAC_EXPORT
diff --git a/ui/accessibility/ax_base_export.h b/ui/accessibility/ax_base_export.h index b25d5d4..2a44095 100644 --- a/ui/accessibility/ax_base_export.h +++ b/ui/accessibility/ax_base_export.h
@@ -13,8 +13,7 @@ #define AX_BASE_EXPORT __declspec(dllexport) #elif defined(COMPONENT_BUILD) && defined(WIN32) #define AX_BASE_EXPORT __declspec(dllimport) -#elif defined(COMPONENT_BUILD) && !defined(WIN32) && \ - defined(AX_BASE_IMPLEMENTATION) +#elif defined(COMPONENT_BUILD) #define AX_BASE_EXPORT __attribute__((visibility("default"))) #else #define AX_BASE_EXPORT
diff --git a/ui/accessibility/ax_export.h b/ui/accessibility/ax_export.h index ad444a4..bf998e8 100644 --- a/ui/accessibility/ax_export.h +++ b/ui/accessibility/ax_export.h
@@ -12,7 +12,7 @@ #define AX_EXPORT __declspec(dllexport) #elif defined(COMPONENT_BUILD) && defined(WIN32) #define AX_EXPORT __declspec(dllimport) -#elif defined(COMPONENT_BUILD) && !defined(WIN32) && defined(AX_IMPLEMENTATION) +#elif defined(COMPONENT_BUILD) #define AX_EXPORT __attribute__((visibility("default"))) #else #define AX_EXPORT
diff --git a/ui/accessibility/platform/ax_platform_node_cocoa.mm b/ui/accessibility/platform/ax_platform_node_cocoa.mm index dd76d93b..ec9d749 100644 --- a/ui/accessibility/platform/ax_platform_node_cocoa.mm +++ b/ui/accessibility/platform/ax_platform_node_cocoa.mm
@@ -2433,8 +2433,7 @@ // LINT.IfChange - (NSString*)AXSelectedText { - NSRange selectedTextRange; - [[self AXSelectedTextRange] getValue:&selectedTextRange]; + NSRange selectedTextRange = [[self AXSelectedTextRange] rangeValue]; return [[self getAXValueAsString] substringWithRange:selectedTextRange]; } // LINT.ThenChange(accessibilitySelectedText)
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index fb151fe..135551ed 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -486,6 +486,7 @@ "java/src/org/chromium/ui/text/SpanApplier.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", "java/src/org/chromium/ui/util/ColorBlendAnimationFactory.java", "java/src/org/chromium/ui/util/ColorUtils.java", "java/src/org/chromium/ui/util/KeyboardNavigationListener.java",
diff --git a/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java b/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java index be25bf5f..9df226d4 100644 --- a/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java +++ b/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java
@@ -11,10 +11,10 @@ import org.jni_zero.CalledByNative; -import org.chromium.build.BuildConfig; import org.chromium.base.ContextUtils; import org.chromium.base.ResettersForTesting; import org.chromium.base.ThreadUtils; +import org.chromium.build.BuildConfig; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.ui.R; @@ -27,25 +27,39 @@ /** * Desktop form factor. * - * <p>Identified by <code>isDesktop() == true</code>. + * <p>Based on gn build argument, as identified by <code>isDesktop() == true</code>. */ public static final String DESKTOP = "Desktop"; /** * Phone form factor. * - * <p>Identified by <code>isNonMultiDisplayContextOnTablet() == false</code>. + * <p>Based on screen size of the device, as identified by <code> + * isNonMultiDisplayContextOnTablet() == false</code>. */ public static final String PHONE = "Phone"; /** - * Tablet form factor, including {@code #LARGETABLET} below. + * Tablet or desktop form factor, including {@code #LARGETABLET} below. * - * <p>Identified by <code>isNonMultiDisplayContextOnTablet() == true</code>. + * <p>Based on screen size of the device, as identified by <code> + * isNonMultiDisplayContextOnTablet() == true</code>. + * + * <p>TODO(crbug.com/415126396): Change to mean <code> + * isNonMultiDisplayContextOnTablet() == true && + * isDesktop() == false</code>. */ public static final String TABLET = "Tablet"; /** + * Tablet or desktop form factor, including {@code #LARGETABLET} below. + * + * <p>Based on screen size of the device, as identified by <code> + * isNonMultiDisplayContextOnTablet() == true</code>. + */ + public static final String TABLET_OR_DESKTOP = "TabletOrDesktop"; + + /** * Minimum screen size in dp to be considered a tablet. Matches the value used by res/ * directories. E.g.: res/values-sw600dp/values.xml */
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DragDropMetricUtils.java b/ui/android/java/src/org/chromium/ui/dragdrop/DragDropMetricUtils.java index 5a1610a..30bb1a74 100644 --- a/ui/android/java/src/org/chromium/ui/dragdrop/DragDropMetricUtils.java +++ b/ui/android/java/src/org/chromium/ui/dragdrop/DragDropMetricUtils.java
@@ -21,9 +21,9 @@ private DragDropMetricUtils() {} /** - * Enum used by Android.DragDrop.Tab.Type, which records the drag source and drop target when a - * tab is dropped successfully. These values are persisted to logs. Entries should not be - * renumbered and numeric values should never be reused. + * Enum used by Android.DragDrop.Tab.Type and Android.DragDrop.TabGroup.Type, which records the + * drag source and drop target when a tab is dropped successfully. These values are persisted to + * logs. Entries should not be renumbered and numeric values should never be reused. */ @IntDef({ DragDropType.TAB_STRIP_TO_TAB_STRIP, @@ -51,6 +51,7 @@ UrlIntentSource.UNKNOWN, UrlIntentSource.LINK, UrlIntentSource.TAB_IN_STRIP, + UrlIntentSource.TAB_GROUP_IN_STRIP, }) @Retention(RetentionPolicy.SOURCE) public @interface UrlIntentSource { @@ -62,97 +63,122 @@ } /** - * Enum used by Android.DragDrop.Tab.FromStrip.Result.*, which records the tab drag and drop + * Enum used by Android.DragDrop.Tab*.FromStrip.Result.* which records the drag and drop * results, including successful drops and failed drops with varies reasons. These values are * persisted to logs. Entries should not be renumbered and numeric values should never be * reused. */ @IntDef({ - DragDropTabResult.SUCCESS, - DragDropTabResult.IGNORED_TOOLBAR, - DragDropTabResult.IGNORED_DIFF_MODEL_NOT_SUPPORTED, - DragDropTabResult.IGNORED_TAB_SWITCHER, - DragDropTabResult.IGNORED_SAME_INSTANCE, - DragDropTabResult.ERROR_TAB_NOT_FOUND, - DragDropTabResult.IGNORED_MAX_INSTANCES, + DragDropResult.SUCCESS, + DragDropResult.IGNORED_TOOLBAR, + DragDropResult.IGNORED_DIFF_MODEL_NOT_SUPPORTED, + DragDropResult.IGNORED_TAB_SWITCHER, + DragDropResult.IGNORED_SAME_INSTANCE, + DragDropResult.ERROR_CONTENT_NOT_FOUND, + DragDropResult.IGNORED_MAX_INSTANCES, + DragDropResult.IGNORED_MHTML_TAB, }) @Retention(RetentionPolicy.SOURCE) - public @interface DragDropTabResult { + public @interface DragDropResult { int SUCCESS = 0; int IGNORED_TOOLBAR = 1; int IGNORED_DIFF_MODEL_NOT_SUPPORTED = 2; int IGNORED_TAB_SWITCHER = 3; int IGNORED_SAME_INSTANCE = 4; - int ERROR_TAB_NOT_FOUND = 5; + int ERROR_CONTENT_NOT_FOUND = 5; int IGNORED_MAX_INSTANCES = 6; - int NUM_ENTRIES = 7; + int IGNORED_MHTML_TAB = 7; + int NUM_ENTRIES = 8; } /** - * Record enumerated histogram Android.DragDrop.Tab.Type for dragged tab data. + * Record enumerated histogram Android.DragDrop.Tab.Type and Android.DragDrop.TabGroup.Type for + * dragged tab or tab group data. * * @param dragDropType An enum indicating the drag source and drop target. * @param isInDesktopWindow Whether the app is running in a desktop window. + * @param isTabGroup True if the dragged item is a tab group; otherwise, it is assumed to be a + * single tab. */ - public static void recordTabDragDropType( - @DragDropType int dragDropType, boolean isInDesktopWindow) { + public static void recordDragDropType( + @DragDropType int dragDropType, boolean isInDesktopWindow, boolean isTabGroup) { + String histogram = + String.format("Android.DragDrop.%s.Type", isTabGroup ? "TabGroup" : "Tab"); RecordHistogram.recordEnumeratedHistogram( - HISTOGRAM_DRAG_DROP_TAB_TYPE, dragDropType, DragDropType.NUM_ENTRIES); + histogram, dragDropType, DragDropType.NUM_ENTRIES); if (isInDesktopWindow) { RecordHistogram.recordEnumeratedHistogram( - "Android.DragDrop.Tab.Type.DesktopWindow", - dragDropType, - DragDropType.NUM_ENTRIES); + histogram + ".DesktopWindow", dragDropType, DragDropType.NUM_ENTRIES); } } /** - * Record enumerated histograms Android.DragDrop.Tab.FromStrip.Result.*. + * Record enumerated histograms Android.DragDrop.Tab.FromStrip.Result and + * Android.DragDrop.TabGroup.FromStrip.Result. * - * @param result An enum indicating the tab drag and drop results, including successful drops - * and failed drops with varies reasons. + * @param result An enum indicating the tab or tab group drag and drop results, including + * successful drops and failed drops with varies reasons. * @param isInDesktopWindow Whether the app is running in a desktop window. + * @param isTabGroup True if the dragged item is a tab group; otherwise, it is assumed to be a + * single tab. */ - public static void recordTabDragDropResult( - @DragDropTabResult int result, boolean isInDesktopWindow) { - RecordHistogram.recordEnumeratedHistogram( - "Android.DragDrop.Tab.FromStrip.Result", result, DragDropTabResult.NUM_ENTRIES); + public static void recordDragDropResult( + @DragDropResult int result, boolean isInDesktopWindow, boolean isTabGroup) { + String histogram = + String.format( + "Android.DragDrop.%s.FromStrip.Result", isTabGroup ? "TabGroup" : "Tab"); + RecordHistogram.recordEnumeratedHistogram(histogram, result, DragDropResult.NUM_ENTRIES); if (isInDesktopWindow) { RecordHistogram.recordEnumeratedHistogram( - "Android.DragDrop.Tab.FromStrip.Result.DesktopWindow", - result, - DragDropTabResult.NUM_ENTRIES); + histogram + ".DesktopWindow", result, DragDropResult.NUM_ENTRIES); } } /** - * Record boolean histogram Android.DragDrop.Tab.ReorderStripWithDragDrop. + * Record boolean histogram Android.DragDrop.Tab.ReorderStripWithDragDrop and + * Android.DragDrop.TabGroup.ReorderStripWithDragDrop. * * @param leavingStrip Whether the tab drag has left the source strip. + * @param isTabGroup True if the dragged item is a tab group; otherwise, it is assumed to be a + * single tab. */ - public static void recordTabReorderStripWithDragDrop(boolean leavingStrip) { - RecordHistogram.recordBooleanHistogram( - "Android.DragDrop.Tab.ReorderStripWithDragDrop", leavingStrip); + public static void recordReorderStripWithDragDrop(boolean leavingStrip, boolean isTabGroup) { + String histogram = + String.format( + "Android.DragDrop.%s.ReorderStripWithDragDrop", + isTabGroup ? "TabGroup" : "Tab"); + RecordHistogram.recordBooleanHistogram(histogram, leavingStrip); } /** - * Record times histogram Android.DragDrop.Tab.Duration.WithinDestStrip. + * Record times histogram Android.DragDrop.Tab.Duration.WithinDestStrip and + * Android.DragDrop.TabGroup.Duration.WithinDestStrip. * * @param duration scrolling on a destination strip. + * @param isTabGroup True if the dragged item is a tab group; otherwise, it is assumed to be a + * single tab. */ - public static void recordTabDurationWithinDestStrip(long duration) { - RecordHistogram.deprecatedRecordMediumTimesHistogram( - "Android.DragDrop.Tab.Duration.WithinDestStrip", duration); + public static void recordDurationWithinDestStrip(long duration, boolean isTabGroup) { + String histogram = + String.format( + "Android.DragDrop.%s.Duration.WithinDestStrip", + isTabGroup ? "TabGroup" : "Tab"); + RecordHistogram.recordMediumTimesHistogram(histogram, duration); } /** - * Record boolean histogram Android.DragDrop.Tab.SourceWindowClosed. + * Record boolean histogram Android.DragDrop.Tab.SourceWindowClosed and + * Android.DragDrop.TabGroup.SourceWindowClosed. * * @param didCloseWindow Whether a successful tab drag/drop resulted in closing the source * Chrome window. + * @param isTabGroup True if the dragged item is a tab group; otherwise, it is assumed to be a + * single tab. */ - public static void recordTabDragDropClosedWindow(boolean didCloseWindow) { - RecordHistogram.recordBooleanHistogram( - "Android.DragDrop.Tab.SourceWindowClosed", didCloseWindow); + public static void recordDragDropClosedWindow(boolean didCloseWindow, boolean isTabGroup) { + String histogram = + String.format( + "Android.DragDrop.%s.SourceWindowClosed", isTabGroup ? "TabGroup" : "Tab"); + RecordHistogram.recordBooleanHistogram(histogram, didCloseWindow); } }
diff --git a/ui/android/java/src/org/chromium/ui/util/ClickWithMetaStateCallback.java b/ui/android/java/src/org/chromium/ui/util/ClickWithMetaStateCallback.java new file mode 100644 index 0000000..3004cbb --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/util/ClickWithMetaStateCallback.java
@@ -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. + +package org.chromium.ui.util; + +import org.chromium.build.annotations.NullMarked; + +/** A callback used to pass meta state information from the time of click. */ +@NullMarked +@FunctionalInterface +public interface ClickWithMetaStateCallback { + /** Called when a click occurs. {@param metaState} is the meta key state at the time. */ + void onClickWithMeta(int metaState); +}
diff --git a/ui/android/java/src/org/chromium/ui/widget/ChromeImageButton.java b/ui/android/java/src/org/chromium/ui/widget/ChromeImageButton.java index ddcd54f..a206d74 100644 --- a/ui/android/java/src/org/chromium/ui/widget/ChromeImageButton.java +++ b/ui/android/java/src/org/chromium/ui/widget/ChromeImageButton.java
@@ -13,9 +13,9 @@ import androidx.appcompat.widget.AppCompatImageButton; -import org.chromium.base.Callback; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; +import org.chromium.ui.util.ClickWithMetaStateCallback; // TODO(crbug.com/40883889): See if we still need this class. /** @@ -86,7 +86,8 @@ * * @param callback the callback to notify. */ - public void setClickCallback(@Nullable Callback<Integer> callback) { - setOnClickListener(callback != null ? (v) -> callback.onResult(mLastEventMetaState) : null); + public void setClickCallback(@Nullable ClickWithMetaStateCallback callback) { + setOnClickListener( + callback != null ? (v) -> callback.onClickWithMeta(mLastEventMetaState) : null); } }
diff --git a/ui/android/javatests/src/org/chromium/ui/test/util/UiDisableIfSkipCheck.java b/ui/android/javatests/src/org/chromium/ui/test/util/UiDisableIfSkipCheck.java index 677559d..35423a6 100644 --- a/ui/android/javatests/src/org/chromium/ui/test/util/UiDisableIfSkipCheck.java +++ b/ui/android/javatests/src/org/chromium/ui/test/util/UiDisableIfSkipCheck.java
@@ -32,16 +32,18 @@ } return ThreadUtils.runOnUiThreadBlocking( () -> { - boolean isDesktop = DeviceFormFactor.isDesktop(); + boolean isDesktopBuild = DeviceFormFactor.isDesktop(); boolean isTablet = DeviceFormFactor.isNonMultiDisplayContextOnTablet(mTargetContext); switch (type) { - case DeviceFormFactor.DESKTOP: - return DeviceFormFactor.isDesktop(); case DeviceFormFactor.PHONE: - return !DeviceFormFactor.isDesktop() && !isTablet; + return !isDesktopBuild && !isTablet; case DeviceFormFactor.TABLET: - return !DeviceFormFactor.isDesktop() && isTablet; + return !isDesktopBuild && isTablet; + case DeviceFormFactor.DESKTOP: + return isDesktopBuild; + case DeviceFormFactor.TABLET_OR_DESKTOP: + return isTablet; default: return false; }
diff --git a/ui/android/javatests/src/org/chromium/ui/test/util/UiRestriction.java b/ui/android/javatests/src/org/chromium/ui/test/util/UiRestriction.java index 6dd3f59..31d45e21 100644 --- a/ui/android/javatests/src/org/chromium/ui/test/util/UiRestriction.java +++ b/ui/android/javatests/src/org/chromium/ui/test/util/UiRestriction.java
@@ -44,7 +44,10 @@ check.addHandler(DeviceFormFactor.DESKTOP, () -> !isDesktop()); // isTablet() returns True if the display is large enough to be considered a tablet, so // it is always True on desktop devices as well. + // TODO(crbug.com/415126396): Change PHONE to "isDesktop() || isTablet()" check.addHandler(DeviceFormFactor.PHONE, () -> isTablet()); + // TODO(crbug.com/415126396): Change TABLET to "isDesktop() || !isTablet()" check.addHandler(DeviceFormFactor.TABLET, () -> !isTablet()); + check.addHandler(DeviceFormFactor.TABLET_OR_DESKTOP, () -> !isTablet()); } }
diff --git a/ui/android/ui_android_export.h b/ui/android/ui_android_export.h index 9f600e9..b5a3c5b 100644 --- a/ui/android/ui_android_export.h +++ b/ui/android/ui_android_export.h
@@ -13,19 +13,11 @@ #if defined(WIN32) #error Unsupported target architecture. #else // !defined(WIN32) - -#if defined(UI_ANDROID_IMPLEMENTATION) #define UI_ANDROID_EXPORT __attribute__((visibility("default"))) -#else -#define UI_ANDROID_EXPORT -#endif - #endif #else // !defined(COMPONENT_BUILD) - #define UI_ANDROID_EXPORT - #endif #endif // UI_ANDROID_UI_ANDROID_EXPORT_H_
diff --git a/ui/aura/aura_export.h b/ui/aura/aura_export.h index be6a08a..90ebdf82 100644 --- a/ui/aura/aura_export.h +++ b/ui/aura/aura_export.h
@@ -18,11 +18,7 @@ #endif // defined(AURA_IMPLEMENTATION) #else // defined(WIN32) -#if defined(AURA_IMPLEMENTATION) #define AURA_EXPORT __attribute__((visibility("default"))) -#else -#define AURA_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/aura_extra/aura_extra_export.h b/ui/aura_extra/aura_extra_export.h index 5d95d4d..1773417 100644 --- a/ui/aura_extra/aura_extra_export.h +++ b/ui/aura_extra/aura_extra_export.h
@@ -18,11 +18,7 @@ #endif // defined(AURA_EXTRA_IMPLEMENTATION) #else // defined(WIN32) -#if defined(AURA_EXTRA_IMPLEMENTATION) #define AURA_EXTRA_EXPORT __attribute__((visibility("default"))) -#else -#define AURA_EXTRA_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc index 8c45e76..2aeb8892 100644 --- a/ui/base/ui_base_switches.cc +++ b/ui/base/ui_base_switches.cc
@@ -33,6 +33,10 @@ #if BUILDFLAG(IS_LINUX) // Specify the toolkit used to construct the Linux GUI. const char kUiToolkitFlag[] = "ui-toolkit"; +// Specify the GTK version to be loaded. +const char kGtkVersionFlag[] = "gtk-version"; +// Specify the QT version to be loaded. +const char kQtVersionFlag[] = "qt-version"; // Disables GTK IME integration. const char kDisableGtkIme[] = "disable-gtk-ime"; #endif
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h index 3f4773f..581965d 100644 --- a/ui/base/ui_base_switches.h +++ b/ui/base/ui_base_switches.h
@@ -28,6 +28,8 @@ #if BUILDFLAG(IS_LINUX) COMPONENT_EXPORT(UI_BASE) extern const char kUiToolkitFlag[]; +COMPONENT_EXPORT(UI_BASE) extern const char kGtkVersionFlag[]; +COMPONENT_EXPORT(UI_BASE) extern const char kQtVersionFlag[]; COMPONENT_EXPORT(UI_BASE) extern const char kDisableGtkIme[]; #endif
diff --git a/ui/chromeos/ui_chromeos_export.h b/ui/chromeos/ui_chromeos_export.h index 429a9a88..4c140186 100644 --- a/ui/chromeos/ui_chromeos_export.h +++ b/ui/chromeos/ui_chromeos_export.h
@@ -6,11 +6,7 @@ #define UI_CHROMEOS_UI_CHROMEOS_EXPORT_H_ #if defined(COMPONENT_BUILD) -#if defined(UI_CHROMEOS_IMPLEMENTATION) #define UI_CHROMEOS_EXPORT __attribute__((visibility("default"))) -#else -#define UI_CHROMEOS_EXPORT -#endif #else // defined(COMPONENT_BUILD) #define UI_CHROMEOS_EXPORT
diff --git a/ui/compositor/compositor_export.h b/ui/compositor/compositor_export.h index 02e4784..183832754 100644 --- a/ui/compositor/compositor_export.h +++ b/ui/compositor/compositor_export.h
@@ -15,11 +15,7 @@ #endif // defined(COMPOSITOR_IMPLEMENTATION) #else // defined(WIN32) -#if defined(COMPOSITOR_IMPLEMENTATION) #define COMPOSITOR_EXPORT __attribute__((visibility("default"))) -#else -#define COMPOSITOR_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/display/BUILD.gn b/ui/display/BUILD.gn index 491b8006..e598004 100644 --- a/ui/display/BUILD.gn +++ b/ui/display/BUILD.gn
@@ -69,8 +69,6 @@ "mac/display_link_mac.h", "mac/display_link_mac.mm", "mac/screen_mac.mm", - "mac/screen_mac_headless.h", - "mac/screen_mac_headless.mm", ] } @@ -149,7 +147,6 @@ } if (is_mac) { - deps += [ "//components/headless/screen_info" ] frameworks = [ "AppKit.framework", "CoreGraphics.framework",
diff --git a/ui/display/display_export.h b/ui/display/display_export.h index 443e9f8..c3087e4 100644 --- a/ui/display/display_export.h +++ b/ui/display/display_export.h
@@ -20,11 +20,7 @@ #else // !defined(WIN32) -#if defined(DISPLAY_IMPLEMENTATION) #define DISPLAY_EXPORT __attribute__((visibility("default"))) -#else -#define DISPLAY_EXPORT -#endif #endif
diff --git a/ui/display/mac/DEPS b/ui/display/mac/DEPS deleted file mode 100644 index 4a3d7376..0000000 --- a/ui/display/mac/DEPS +++ /dev/null
@@ -1,5 +0,0 @@ -specific_include_rules = { - "screen_mac_headless\.mm": [ - "+components/headless/screen_info", - ], -}
diff --git a/ui/display/mac/screen_mac.mm b/ui/display/mac/screen_mac.mm index 033ebc00..874ac9d 100644 --- a/ui/display/mac/screen_mac.mm +++ b/ui/display/mac/screen_mac.mm
@@ -21,8 +21,6 @@ #include "base/apple/bridging.h" #include "base/apple/foundation_util.h" #include "base/apple/scoped_cftyperef.h" -#include "base/check_deref.h" -#include "base/command_line.h" #include "base/functional/bind.h" #include "base/i18n/rtl.h" #include "base/logging.h" @@ -34,13 +32,11 @@ #include "components/device_event_log/device_event_log.h" #include "ui/display/display.h" #include "ui/display/display_change_notifier.h" -#include "ui/display/mac/screen_mac_headless.h" #include "ui/display/util/display_util.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/icc_profile.h" #include "ui/gfx/mac/coordinate_conversion.h" #include "ui/gfx/native_widget_types.h" -#include "ui/gfx/switches.h" extern "C" { Boolean CGDisplayUsesForceToGray(void); @@ -615,13 +611,6 @@ } Screen* CreateNativeScreen() { - const base::CommandLine& command_line = - CHECK_DEREF(base::CommandLine::ForCurrentProcess()); - - if (command_line.HasSwitch(switches::kHeadless)) { - return new ScreenMacHeadless; - } - return new ScreenMac; }
diff --git a/ui/display/mac/screen_mac_headless.h b/ui/display/mac/screen_mac_headless.h deleted file mode 100644 index 708cd0b8..0000000 --- a/ui/display/mac/screen_mac_headless.h +++ /dev/null
@@ -1,40 +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 UI_DISPLAY_MAC_SCREEN_MAC_HEADLESS_H_ -#define UI_DISPLAY_MAC_SCREEN_MAC_HEADLESS_H_ - -#include "ui/display/display.h" -#include "ui/display/screen_base.h" -#include "ui/gfx/geometry/point.h" -#include "ui/gfx/native_widget_types.h" - -namespace display { - -class ScreenMacHeadless : public ScreenBase { - public: - ScreenMacHeadless(); - - ScreenMacHeadless(const ScreenMacHeadless&) = delete; - ScreenMacHeadless& operator=(const ScreenMacHeadless&) = delete; - - ~ScreenMacHeadless() override; - - // display::Screen overrides: - gfx::Point GetCursorScreenPoint() override; - bool IsWindowUnderCursor(gfx::NativeWindow window) override; - gfx::NativeWindow GetWindowAtScreenPoint(const gfx::Point& point) override; - gfx::NativeWindow GetLocalProcessWindowAtPoint( - const gfx::Point& point, - const std::set<gfx::NativeWindow>& ignore) override; - Display GetDisplayNearestWindow(gfx::NativeWindow window) const override; - bool IsHeadless() const override; - - private: - void CreateDisplayList(); -}; - -} // namespace display - -#endif // UI_DISPLAY_MAC_SCREEN_MAC_HEADLESS_H_
diff --git a/ui/display/mac/screen_mac_headless.mm b/ui/display/mac/screen_mac_headless.mm deleted file mode 100644 index 2ae6774..0000000 --- a/ui/display/mac/screen_mac_headless.mm +++ /dev/null
@@ -1,125 +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 "ui/display/mac/screen_mac_headless.h" - -#import <AppKit/AppKit.h> - -#include <vector> - -#include "base/check_deref.h" -#include "base/command_line.h" -#include "base/containers/flat_set.h" -#include "base/types/expected.h" -#include "components/headless/screen_info/headless_screen_info.h" -#include "ui/display/util/display_util.h" -#include "ui/gfx/geometry/rect.h" -#include "ui/gfx/mac/coordinate_conversion.h" -#include "ui/gfx/switches.h" - -namespace display { - -namespace { - -// Headless display ids are synthesized sequential numbers. -constexpr int64_t kHeadlessDisplayIdBase = 1; - -std::vector<headless::HeadlessScreenInfo> GetHeadlessScreenInfos() { - std::vector<headless::HeadlessScreenInfo> screen_infos; - - const base::CommandLine& command_line = - CHECK_DEREF(base::CommandLine::ForCurrentProcess()); - - if (command_line.HasSwitch(switches::kScreenInfo)) { - const std::string switch_value = - command_line.GetSwitchValueASCII(switches::kScreenInfo); - base::expected<std::vector<headless::HeadlessScreenInfo>, std::string> - screen_infos_or_error = - headless::HeadlessScreenInfo::FromString(switch_value); - CHECK(screen_infos_or_error.has_value()) << screen_infos_or_error.error(); - screen_infos = screen_infos_or_error.value(); - } else { - screen_infos.push_back(headless::HeadlessScreenInfo()); - } - - return screen_infos; -} - -} // namespace - -ScreenMacHeadless::ScreenMacHeadless() { - CreateDisplayList(); -} - -ScreenMacHeadless::~ScreenMacHeadless() = default; - -void ScreenMacHeadless::CreateDisplayList() { - std::vector<headless::HeadlessScreenInfo> screen_infos = - GetHeadlessScreenInfos(); - CHECK(!screen_infos.empty()); - - bool is_primary = true; - base::flat_set<int64_t> internal_display_ids; - for (const headless::HeadlessScreenInfo& it : screen_infos) { - static int64_t synthesized_display_id = kHeadlessDisplayIdBase; - Display display(synthesized_display_id++); - display.set_label(it.label); - display.set_color_depth(it.color_depth); - display.SetScaleAndBounds(it.device_pixel_ratio, it.bounds); - - if (!it.work_area_insets.IsEmpty()) { - display.UpdateWorkAreaFromInsets(it.work_area_insets); - } - - if (it.rotation) { - CHECK(Display::IsValidRotation(it.rotation)); - display.SetRotationAsDegree(it.rotation); - } - - if (it.is_internal) { - internal_display_ids.insert(display.id()); - } - - ProcessDisplayChanged(display, is_primary); - is_primary = false; - } - - SetInternalDisplayIds(internal_display_ids); -} - -gfx::Point ScreenMacHeadless::GetCursorScreenPoint() { - return gfx::Point(); -} - -bool ScreenMacHeadless::IsWindowUnderCursor(gfx::NativeWindow window) { - return GetWindowAtScreenPoint(GetCursorScreenPoint()) == window; -} - -gfx::NativeWindow ScreenMacHeadless::GetWindowAtScreenPoint( - const gfx::Point& point) { - return gfx::NativeWindow(); -} - -gfx::NativeWindow ScreenMacHeadless::GetLocalProcessWindowAtPoint( - const gfx::Point& point, - const std::set<gfx::NativeWindow>& ignore) { - return gfx::NativeWindow(); -} - -Display ScreenMacHeadless::GetDisplayNearestWindow( - gfx::NativeWindow window) const { - if (window && GetNumDisplays() > 1) { - if (NSWindow* ns_window = window.GetNativeNSWindow()) { - const gfx::Rect bounds = gfx::ScreenRectFromNSRect([ns_window frame]); - return GetDisplayMatching(bounds); - } - } - return GetPrimaryDisplay(); -} - -bool ScreenMacHeadless::IsHeadless() const { - return true; -} - -} // namespace display
diff --git a/ui/display/manager/display_manager_export.h b/ui/display/manager/display_manager_export.h index de4272b..09af89e 100644 --- a/ui/display/manager/display_manager_export.h +++ b/ui/display/manager/display_manager_export.h
@@ -15,11 +15,7 @@ #endif #else // !defined(WIN32) -#if defined(DISPLAY_MANAGER_IMPLEMENTATION) #define DISPLAY_MANAGER_EXPORT __attribute__((visibility("default"))) -#else -#define DISPLAY_MANAGER_EXPORT -#endif #endif #else // !defined(COMPONENT_BUILD)
diff --git a/ui/display/types/display_types_export.h b/ui/display/types/display_types_export.h index 3637ea4..9680a24 100644 --- a/ui/display/types/display_types_export.h +++ b/ui/display/types/display_types_export.h
@@ -20,11 +20,7 @@ #else // !defined(WIN32) -#if defined(DISPLAY_TYPES_IMPLEMENTATION) #define DISPLAY_TYPES_EXPORT __attribute__((visibility("default"))) -#else -#define DISPLAY_TYPES_EXPORT -#endif #endif
diff --git a/ui/display/util/display_util_export.h b/ui/display/util/display_util_export.h index 27248eb..51f58f4 100644 --- a/ui/display/util/display_util_export.h +++ b/ui/display/util/display_util_export.h
@@ -20,11 +20,7 @@ #else // !defined(WIN32) -#if defined(DISPLAY_UTIL_IMPLEMENTATION) #define DISPLAY_UTIL_EXPORT __attribute__((visibility("default"))) -#else -#define DISPLAY_UTIL_EXPORT -#endif #endif
diff --git a/ui/events/devices/events_devices_export.h b/ui/events/devices/events_devices_export.h index 3f210d33..f4990ce 100644 --- a/ui/events/devices/events_devices_export.h +++ b/ui/events/devices/events_devices_export.h
@@ -15,11 +15,7 @@ #endif // defined(EVENTS_DEVICES_IMPLEMENTATION) #else // defined(WIN32) -#if defined(EVENTS_DEVICES_IMPLEMENTATION) #define EVENTS_DEVICES_EXPORT __attribute__((visibility("default"))) -#else -#define EVENTS_DEVICES_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/events/devices/x11/events_devices_x11_export.h b/ui/events/devices/x11/events_devices_x11_export.h index 04087e0..0ccae8a 100644 --- a/ui/events/devices/x11/events_devices_x11_export.h +++ b/ui/events/devices/x11/events_devices_x11_export.h
@@ -15,11 +15,7 @@ #endif // defined(EVENTS_DEVICES_X11_IMPLEMENTATION) #else // defined(WIN32) -#if defined(EVENTS_DEVICES_X11_IMPLEMENTATION) #define EVENTS_DEVICES_X11_EXPORT __attribute__((visibility("default"))) -#else -#define EVENTS_DEVICES_X11_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/events/events_base_export.h b/ui/events/events_base_export.h index 800a4e8d..830af7971 100644 --- a/ui/events/events_base_export.h +++ b/ui/events/events_base_export.h
@@ -15,11 +15,7 @@ #endif // defined(EVENTS_BASE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(EVENTS_BASE_IMPLEMENTATION) #define EVENTS_BASE_EXPORT __attribute__((visibility("default"))) -#else -#define EVENTS_BASE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/events/events_export.h b/ui/events/events_export.h index a926b0f5..c791796 100644 --- a/ui/events/events_export.h +++ b/ui/events/events_export.h
@@ -15,11 +15,7 @@ #endif // defined(EVENTS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(EVENTS_IMPLEMENTATION) #define EVENTS_EXPORT __attribute__((visibility("default"))) -#else -#define EVENTS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/events/gesture_detection/gesture_detection_export.h b/ui/events/gesture_detection/gesture_detection_export.h index 278bbc07..5e80720 100644 --- a/ui/events/gesture_detection/gesture_detection_export.h +++ b/ui/events/gesture_detection/gesture_detection_export.h
@@ -15,11 +15,7 @@ #endif // defined(GESTURES_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GESTURE_DETECTION_IMPLEMENTATION) #define GESTURE_DETECTION_EXPORT __attribute__((visibility("default"))) -#else -#define GESTURE_DETECTION_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/events/keycodes/keycodes_x_export.h b/ui/events/keycodes/keycodes_x_export.h index d0a21591..567015ed 100644 --- a/ui/events/keycodes/keycodes_x_export.h +++ b/ui/events/keycodes/keycodes_x_export.h
@@ -15,11 +15,7 @@ #endif // defined(KEYCODES_X_IMPLEMENTATION) #else // defined(WIN32) -#if defined(KEYCODES_X_IMPLEMENTATION) #define KEYCODES_X_EXPORT __attribute__((visibility("default"))) -#else -#define KEYCODES_X_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/events/x/events_x_export.h b/ui/events/x/events_x_export.h index c0ccb06..fb900ad9 100644 --- a/ui/events/x/events_x_export.h +++ b/ui/events/x/events_x_export.h
@@ -15,11 +15,7 @@ #endif // defined(EVENTS_X_IMPLEMENTATION) #else // defined(WIN32) -#if defined(EVENTS_X_IMPLEMENTATION) #define EVENTS_X_EXPORT __attribute__((visibility("default"))) -#else -#define EVENTS_X_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/file_manager/file_manager_export.h b/ui/file_manager/file_manager_export.h index 41d6708..f46a1b5 100644 --- a/ui/file_manager/file_manager_export.h +++ b/ui/file_manager/file_manager_export.h
@@ -18,11 +18,7 @@ #endif // defined(FILE_MANAGER_IMPLEMENTATION) #else // defined(WIN32) -#if defined(FILE_MANAGER_IMPLEMENTATION) #define FILE_MANAGER_EXPORT __attribute__((visibility("default"))) -#else -#define FILE_MANAGER_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/animation/animation_export.h b/ui/gfx/animation/animation_export.h index 586d5d8..0a53336 100644 --- a/ui/gfx/animation/animation_export.h +++ b/ui/gfx/animation/animation_export.h
@@ -15,11 +15,7 @@ #endif // defined(ANIMATION_IMPLEMENTATION) #else // defined(WIN32) -#if defined(ANIMATION_IMPLEMENTATION) #define ANIMATION_EXPORT __attribute__((visibility("default"))) -#else -#define ANIMATION_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/animation/keyframe/keyframe_animation_export.h b/ui/gfx/animation/keyframe/keyframe_animation_export.h index 518c84a..571b9f2 100644 --- a/ui/gfx/animation/keyframe/keyframe_animation_export.h +++ b/ui/gfx/animation/keyframe/keyframe_animation_export.h
@@ -15,11 +15,7 @@ #endif // defined(CC_ANIMATION_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_KEYFRAME_ANIMATION_IMPLEMENTATION) #define GFX_KEYFRAME_ANIMATION_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_KEYFRAME_ANIMATION_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/codec/codec_export.h b/ui/gfx/codec/codec_export.h index 76b31443..083dfb6 100644 --- a/ui/gfx/codec/codec_export.h +++ b/ui/gfx/codec/codec_export.h
@@ -15,11 +15,7 @@ #endif // defined(CODEC_IMPLEMENTATION) #else // defined(WIN32) -#if defined(CODEC_IMPLEMENTATION) #define CODEC_EXPORT __attribute__((visibility("default"))) -#else -#define CODEC_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/color_space_export.h b/ui/gfx/color_space_export.h index 2474ed93..b253d38 100644 --- a/ui/gfx/color_space_export.h +++ b/ui/gfx/color_space_export.h
@@ -15,11 +15,7 @@ #endif // defined(COLOR_SPACE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(COLOR_SPACE_IMPLEMENTATION) #define COLOR_SPACE_EXPORT __attribute__((visibility("default"))) -#else -#define COLOR_SPACE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/gfx_skia_export.h b/ui/gfx/gfx_skia_export.h index 7287f48..6e9e827 100644 --- a/ui/gfx/gfx_skia_export.h +++ b/ui/gfx/gfx_skia_export.h
@@ -15,11 +15,7 @@ #endif // defined(GEOMETRY_SKIA_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_SKIA_IMPLEMENTATION) #define GFX_SKIA_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_SKIA_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/ipc/buffer_types/gfx_ipc_export.h b/ui/gfx/ipc/buffer_types/gfx_ipc_export.h index ba99e9fd..4fad60a 100644 --- a/ui/gfx/ipc/buffer_types/gfx_ipc_export.h +++ b/ui/gfx/ipc/buffer_types/gfx_ipc_export.h
@@ -15,11 +15,7 @@ #endif // defined(GFX_IPC_BUFFER_TYPES_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_IPC_BUFFER_TYPES_IMPLEMENTATION) #define GFX_IPC_BUFFER_TYPES_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_IPC_BUFFER_TYPES_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/ipc/color/gfx_ipc_color_export.h b/ui/gfx/ipc/color/gfx_ipc_color_export.h index 4ba0e11d..0c0526ee 100644 --- a/ui/gfx/ipc/color/gfx_ipc_color_export.h +++ b/ui/gfx/ipc/color/gfx_ipc_color_export.h
@@ -15,11 +15,7 @@ #endif // defined(GFX_IPC_COLOR_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_IPC_COLOR_IMPLEMENTATION) #define GFX_IPC_COLOR_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_IPC_COLOR_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/ipc/geometry/gfx_ipc_geometry_export.h b/ui/gfx/ipc/geometry/gfx_ipc_geometry_export.h index 912a3b1..49d69087b 100644 --- a/ui/gfx/ipc/geometry/gfx_ipc_geometry_export.h +++ b/ui/gfx/ipc/geometry/gfx_ipc_geometry_export.h
@@ -15,11 +15,7 @@ #endif // defined(GFX_IPC_GEOMETRY_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_IPC_GEOMETRY_IMPLEMENTATION) #define GFX_IPC_GEOMETRY_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_IPC_GEOMETRY_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/ipc/gfx_ipc_export.h b/ui/gfx/ipc/gfx_ipc_export.h index 6cd3002e..c8aa394 100644 --- a/ui/gfx/ipc/gfx_ipc_export.h +++ b/ui/gfx/ipc/gfx_ipc_export.h
@@ -15,11 +15,7 @@ #endif // defined(GFX_IPC_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_IPC_IMPLEMENTATION) #define GFX_IPC_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_IPC_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/ipc/skia/gfx_skia_ipc_export.h b/ui/gfx/ipc/skia/gfx_skia_ipc_export.h index 0872eef..bdfc9e0 100644 --- a/ui/gfx/ipc/skia/gfx_skia_ipc_export.h +++ b/ui/gfx/ipc/skia/gfx_skia_ipc_export.h
@@ -15,11 +15,7 @@ #endif // defined(GFX_SKIA_IPC_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_SKIA_IPC_IMPLEMENTATION) #define GFX_SKIA_IPC_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_SKIA_IPC_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/range/gfx_range_export.h b/ui/gfx/range/gfx_range_export.h index db3491e..fcf717fd6 100644 --- a/ui/gfx/range/gfx_range_export.h +++ b/ui/gfx/range/gfx_range_export.h
@@ -15,11 +15,7 @@ #endif // defined(GFX_RANGE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_RANGE_IMPLEMENTATION) #define GFX_RANGE_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_RANGE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gfx/switches_export.h b/ui/gfx/switches_export.h index ba153f2b5..da608aad 100644 --- a/ui/gfx/switches_export.h +++ b/ui/gfx/switches_export.h
@@ -15,11 +15,7 @@ #endif // defined(GFX_SWITCHES_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GFX_SWITCHES_IMPLEMENTATION) #define GFX_SWITCHES_EXPORT __attribute__((visibility("default"))) -#else -#define GFX_SWITCHES_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gl/gl_export.h b/ui/gl/gl_export.h index e7e7cd3..9d1f1c8c 100644 --- a/ui/gl/gl_export.h +++ b/ui/gl/gl_export.h
@@ -15,11 +15,7 @@ #endif // defined(GL_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GL_IMPLEMENTATION) #define GL_EXPORT __attribute__((visibility("default"))) -#else -#define GL_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gl/init/gl_init_export.h b/ui/gl/init/gl_init_export.h index 1a6fe98c..e14db38a 100644 --- a/ui/gl/init/gl_init_export.h +++ b/ui/gl/init/gl_init_export.h
@@ -15,11 +15,7 @@ #endif // defined(GL_INIT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(GL_INIT_IMPLEMENTATION) #define GL_INIT_EXPORT __attribute__((visibility("default"))) -#else -#define GL_INIT_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/gtk/gtk_compat.cc b/ui/gtk/gtk_compat.cc index 946eb3e..37bb482 100644 --- a/ui/gtk/gtk_compat.cc +++ b/ui/gtk/gtk_compat.cc
@@ -15,6 +15,7 @@ #include "base/nix/xdg_util.h" #include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" +#include "ui/base/ui_base_switches.h" #include "ui/gfx/color_palette.h" #include "ui/gtk/gtk_stubs.h" #include "ui/gtk/ime_compat_check.h" @@ -26,8 +27,6 @@ namespace { -const char kGtkVersionFlag[] = "gtk-version"; - struct Gdk3Rgba { gdouble r; gdouble g; @@ -136,7 +135,7 @@ auto* cmd = base::CommandLine::ForCurrentProcess(); unsigned int gtk_version; - if (!base::StringToUint(cmd->GetSwitchValueASCII(kGtkVersionFlag), + if (!base::StringToUint(cmd->GetSwitchValueASCII(switches::kGtkVersionFlag), >k_version)) { gtk_version = 0; }
diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc index 95bdbe6..79cdad0 100644 --- a/ui/gtk/gtk_ui.cc +++ b/ui/gtk/gtk_ui.cc
@@ -30,6 +30,7 @@ #include "base/nix/xdg_util.h" #include "base/numerics/safe_conversions.h" #include "base/observer_list.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "chrome/browser/themes/theme_properties.h" // nogncheck #include "third_party/skia/include/core/SkBitmap.h" @@ -552,6 +553,15 @@ return dark; } +std::vector<std::string> GtkUi::GetCmdLineFlagsForCopy() const { + const auto& gtk_version = GtkVersion(); + uint32_t major_version = + gtk_version.IsValid() ? gtk_version.components()[0] : 0; + return {std::string(switches::kUiToolkitFlag) + "=gtk", + std::string(switches::kGtkVersionFlag) + "=" + + base::NumberToString(major_version)}; +} + void GtkUi::SetDarkTheme(bool dark) { auto* settings = gtk_settings_get_default(); g_object_set(settings, "gtk-application-prefer-dark-theme", dark, nullptr);
diff --git a/ui/gtk/gtk_ui.h b/ui/gtk/gtk_ui.h index 421b03a..b1245f2 100644 --- a/ui/gtk/gtk_ui.h +++ b/ui/gtk/gtk_ui.h
@@ -94,6 +94,7 @@ ui::WindowButtonOrderObserver* observer) override; WindowFrameAction GetWindowFrameAction( WindowFrameActionSource source) override; + std::vector<std::string> GetCmdLineFlagsForCopy() const override; // ui::LinuxUiTheme: ui::NativeTheme* GetNativeTheme() const override;
diff --git a/ui/linux/fake_linux_ui.cc b/ui/linux/fake_linux_ui.cc index 00e2e3a..c12919e 100644 --- a/ui/linux/fake_linux_ui.cc +++ b/ui/linux/fake_linux_ui.cc
@@ -89,6 +89,10 @@ return WindowFrameAction::kNone; } +std::vector<std::string> FakeLinuxUi::GetCmdLineFlagsForCopy() const { + return {}; +} + bool FakeLinuxUi::PreferDarkTheme() const { return false; }
diff --git a/ui/linux/fake_linux_ui.h b/ui/linux/fake_linux_ui.h index 95922e9..0d9fd7e 100644 --- a/ui/linux/fake_linux_ui.h +++ b/ui/linux/fake_linux_ui.h
@@ -47,6 +47,7 @@ ui::WindowButtonOrderObserver* observer) override; WindowFrameAction GetWindowFrameAction( WindowFrameActionSource source) override; + std::vector<std::string> GetCmdLineFlagsForCopy() const override; // ui::LinuxUiTheme: ui::NativeTheme* GetNativeTheme() const override;
diff --git a/ui/linux/fallback_linux_ui.cc b/ui/linux/fallback_linux_ui.cc index fb511d4..91a1b1f6 100644 --- a/ui/linux/fallback_linux_ui.cc +++ b/ui/linux/fallback_linux_ui.cc
@@ -6,6 +6,7 @@ #include "base/time/time.h" #include "ui/base/ime/linux/linux_input_method_context.h" +#include "ui/base/ui_base_switches.h" #include "ui/events/keycodes/dom/dom_keyboard_layout_map.h" #include "ui/gfx/font_render_params.h" #include "ui/gfx/geometry/size.h" @@ -116,6 +117,10 @@ } } +std::vector<std::string> FallbackLinuxUi::GetCmdLineFlagsForCopy() const { + return {std::string(switches::kUiToolkitFlag) + "=fallback"}; +} + bool FallbackLinuxUi::PreferDarkTheme() const { return theme_is_dark_; }
diff --git a/ui/linux/fallback_linux_ui.h b/ui/linux/fallback_linux_ui.h index d6bf9d3..47ff01e 100644 --- a/ui/linux/fallback_linux_ui.h +++ b/ui/linux/fallback_linux_ui.h
@@ -50,6 +50,7 @@ ui::WindowButtonOrderObserver* observer) override; WindowFrameAction GetWindowFrameAction( WindowFrameActionSource source) override; + std::vector<std::string> GetCmdLineFlagsForCopy() const override; // ui::LinuxUiTheme: ui::NativeTheme* GetNativeTheme() const override;
diff --git a/ui/linux/linux_ui.h b/ui/linux/linux_ui.h index 4ce8218e..c4805571 100644 --- a/ui/linux/linux_ui.h +++ b/ui/linux/linux_ui.h
@@ -205,6 +205,10 @@ virtual WindowFrameAction GetWindowFrameAction( WindowFrameActionSource source) = 0; + // Returns the command line flags that should be copied to subprocesses + // to have the same toolkit and version as this process. + virtual std::vector<std::string> GetCmdLineFlagsForCopy() const = 0; + protected: struct CmdLineArgs { CmdLineArgs();
diff --git a/ui/message_center/message_center_export.h b/ui/message_center/message_center_export.h index 3893917c..a4aa3eb 100644 --- a/ui/message_center/message_center_export.h +++ b/ui/message_center/message_center_export.h
@@ -18,11 +18,7 @@ #endif // defined(MESSAGE_CENTER_IMPLEMENTATION) #else // defined(WIN32) -#if defined(MESSAGE_CENTER_IMPLEMENTATION) #define MESSAGE_CENTER_EXPORT __attribute__((visibility("default"))) -#else -#define MESSAGE_CENTER_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/message_center/public/cpp/message_center_public_export.h b/ui/message_center/public/cpp/message_center_public_export.h index 553574e..2dff2ac6 100644 --- a/ui/message_center/public/cpp/message_center_public_export.h +++ b/ui/message_center/public/cpp/message_center_public_export.h
@@ -18,11 +18,7 @@ #endif // defined(MESSAGE_CENTER_PUBLIC_IMPLEMENTATION) #else // defined(WIN32) -#if defined(MESSAGE_CENTER_PUBLIC_IMPLEMENTATION) #define MESSAGE_CENTER_PUBLIC_EXPORT __attribute__((visibility("default"))) -#else -#define MESSAGE_CENTER_PUBLIC_EXPORT -#endif // defined(MESSAGE_CENTER_PUBLIC_IMPLEMENTATION) #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc b/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc index f89eb2f..5548279b 100644 --- a/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc +++ b/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc
@@ -203,19 +203,26 @@ } XdgForeignWrapper::XdgForeignWrapper(WaylandConnection* connection, - wl::Object<zxdg_exporter_v1> exporter_v1) { + wl::Object<zxdg_exporter_v1> exporter_v1) + : XdgForeignWrapper(connection) { impl_ = std::make_unique< XdgForeignWrapperImpl<zxdg_exporter_v1, zxdg_exported_v1>>( connection, std::move(exporter_v1)); } XdgForeignWrapper::XdgForeignWrapper(WaylandConnection* connection, - wl::Object<zxdg_exporter_v2> exporter_v2) { + wl::Object<zxdg_exporter_v2> exporter_v2) + : XdgForeignWrapper(connection) { impl_ = std::make_unique< XdgForeignWrapperImpl<zxdg_exporter_v2, zxdg_exported_v2>>( connection, std::move(exporter_v2)); } +XdgForeignWrapper::XdgForeignWrapper(WaylandConnection* connection) { + CHECK(connection); + window_removal_observer_.Observe(connection->window_manager()); +} + XdgForeignWrapper::~XdgForeignWrapper() = default; void XdgForeignWrapper::ExportSurfaceToForeign(WaylandWindow* window,
diff --git a/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.h b/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.h index c9ee679..cd99693 100644 --- a/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.h +++ b/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.h
@@ -49,9 +49,13 @@ void ExportSurfaceToForeign(WaylandWindow* window, OnHandleExported cb); private: + explicit XdgForeignWrapper(WaylandConnection* connection); + // WaylandWindowObserver: void OnWindowRemoved(WaylandWindow* window) override; + base::ScopedObservation<WaylandWindowManager, WaylandWindowObserver> + window_removal_observer_{this}; std::unique_ptr<XdgForeignWrapperInternal> impl_; };
diff --git a/ui/ozone/platform/wayland/host/xdg_session_manager.cc b/ui/ozone/platform/wayland/host/xdg_session_manager.cc index 3a461a6b..3c62452 100644 --- a/ui/ozone/platform/wayland/host/xdg_session_manager.cc +++ b/ui/ozone/platform/wayland/host/xdg_session_manager.cc
@@ -116,6 +116,7 @@ const int32_t window_id) { if (auto* session = GetSession(session_id)) { session->RemoveToplevel(window_id); + return; } DLOG(WARNING) << "No session found for id=" << session_id; }
diff --git a/ui/platform_window/stub/stub_window_export.h b/ui/platform_window/stub/stub_window_export.h index cf3f3ad9..33bf2b98 100644 --- a/ui/platform_window/stub/stub_window_export.h +++ b/ui/platform_window/stub/stub_window_export.h
@@ -15,11 +15,7 @@ #endif // defined(STUB_WINDOW_IMPLEMENTATION) #else // defined(WIN32) -#if defined(STUB_WINDOW_IMPLEMENTATION) #define STUB_WINDOW_EXPORT __attribute__((visibility("default"))) -#else -#define STUB_WINDOW_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/platform_window/win/win_window_export.h b/ui/platform_window/win/win_window_export.h index 09c5839..9b5b28a 100644 --- a/ui/platform_window/win/win_window_export.h +++ b/ui/platform_window/win/win_window_export.h
@@ -15,11 +15,7 @@ #endif // defined(WIN_WINDOW_IMPLEMENTATION) #else // defined(WIN32) -#if defined(WIN_WINDOW_IMPLEMENTATION) #define WIN_WINDOW_EXPORT __attribute__((visibility("default"))) -#else -#define WIN_WINDOW_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/qt/qt_ui.cc b/ui/qt/qt_ui.cc index 18b10a9..30364f9 100644 --- a/ui/qt/qt_ui.cc +++ b/ui/qt/qt_ui.cc
@@ -33,6 +33,7 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/ime/linux/linux_input_method_context.h" #include "ui/base/ime/text_edit_commands.h" +#include "ui/base/ui_base_switches.h" #include "ui/color/color_mixer.h" #include "ui/color/color_provider.h" #include "ui/color/color_provider_manager.h" @@ -61,16 +62,15 @@ namespace { -const char kQtVersionFlag[] = "qt-version"; - void* LoadLibrary(const base::FilePath& path) { return dlopen(path.value().c_str(), RTLD_NOW | RTLD_GLOBAL); } bool PreferQt6() { auto* cmd = base::CommandLine::ForCurrentProcess(); - if (cmd->HasSwitch(kQtVersionFlag)) { - std::string qt_version_string = cmd->GetSwitchValueASCII(kQtVersionFlag); + if (cmd->HasSwitch(switches::kQtVersionFlag)) { + std::string qt_version_string = + cmd->GetSwitchValueASCII(switches::kQtVersionFlag); unsigned int qt_version = 0; if (base::StringToUint(qt_version_string, &qt_version)) { switch (qt_version) { @@ -395,6 +395,12 @@ } } +std::vector<std::string> QtUi::GetCmdLineFlagsForCopy() const { + return {std::string(switches::kUiToolkitFlag) + "=qt", + std::string(switches::kQtVersionFlag) + "=" + + base::NumberToString(qt_version_)}; +} + DISABLE_CFI_VCALL bool QtUi::PreferDarkTheme() const { return color_utils::IsDark(
diff --git a/ui/qt/qt_ui.h b/ui/qt/qt_ui.h index c0cfead..a73906e 100644 --- a/ui/qt/qt_ui.h +++ b/ui/qt/qt_ui.h
@@ -65,6 +65,7 @@ ui::WindowButtonOrderObserver* observer) override; WindowFrameAction GetWindowFrameAction( WindowFrameActionSource source) override; + std::vector<std::string> GetCmdLineFlagsForCopy() const override; // ui::LinuxUiTheme: ui::NativeTheme* GetNativeTheme() const override;
diff --git a/ui/shell_dialogs/shell_dialogs_export.h b/ui/shell_dialogs/shell_dialogs_export.h index 2555a8f5..03a5e9d 100644 --- a/ui/shell_dialogs/shell_dialogs_export.h +++ b/ui/shell_dialogs/shell_dialogs_export.h
@@ -18,11 +18,7 @@ #endif // defined(SHELL_DIALOGS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(SHELL_DIALOGS_IMPLEMENTATION) #define SHELL_DIALOGS_EXPORT __attribute__((visibility("default"))) -#else -#define SHELL_DIALOGS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/snapshot/snapshot_export.h b/ui/snapshot/snapshot_export.h index 07df776..d3ad90a 100644 --- a/ui/snapshot/snapshot_export.h +++ b/ui/snapshot/snapshot_export.h
@@ -18,11 +18,7 @@ #endif // defined(SNAPSHOT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(SNAPSHOT_IMPLEMENTATION) #define SNAPSHOT_EXPORT __attribute__((visibility("default"))) -#else -#define SNAPSHOT_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/surface/surface_export.h b/ui/surface/surface_export.h index c1d62f86..662af5e 100644 --- a/ui/surface/surface_export.h +++ b/ui/surface/surface_export.h
@@ -15,11 +15,7 @@ #endif // defined(SURFACE_IMPLEMENTATION) #else // defined(WIN32) -#if defined(SURFACE_IMPLEMENTATION) #define SURFACE_EXPORT __attribute__((visibility("default"))) -#else -#define SURFACE_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/touch_selection/ui_touch_selection_export.h b/ui/touch_selection/ui_touch_selection_export.h index 160bc37d..b80d887 100644 --- a/ui/touch_selection/ui_touch_selection_export.h +++ b/ui/touch_selection/ui_touch_selection_export.h
@@ -22,11 +22,7 @@ #else // !defined(WIN32) -#if defined(UI_TOUCH_SELECTION_IMPLEMENTATION) #define UI_TOUCH_SELECTION_EXPORT __attribute__((visibility("default"))) -#else -#define UI_TOUCH_SELECTION_EXPORT -#endif #endif
diff --git a/ui/views/controls/webview/webview_export.h b/ui/views/controls/webview/webview_export.h index 5673b3b..919ec10 100644 --- a/ui/views/controls/webview/webview_export.h +++ b/ui/views/controls/webview/webview_export.h
@@ -18,11 +18,7 @@ #endif // defined(WEBVIEW_IMPLEMENTATION) #else // defined(WIN32) -#if defined(WEBVIEW_IMPLEMENTATION) #define WEBVIEW_EXPORT __attribute__((visibility("default"))) -#else -#define WEBVIEW_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/views/examples/views_examples_export.h b/ui/views/examples/views_examples_export.h index 4d3ea7c4..8471cb9 100644 --- a/ui/views/examples/views_examples_export.h +++ b/ui/views/examples/views_examples_export.h
@@ -18,11 +18,7 @@ #endif // defined(VIEWS_EXAMPLES_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VIEWS_EXAMPLES_IMPLEMENTATION) #define VIEWS_EXAMPLES_EXPORT __attribute__((visibility("default"))) -#else -#define VIEWS_EXAMPLES_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/views/views_export.h b/ui/views/views_export.h index 218900b..2bc88a45 100644 --- a/ui/views/views_export.h +++ b/ui/views/views_export.h
@@ -18,11 +18,7 @@ #endif // defined(VIEWS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VIEWS_IMPLEMENTATION) #define VIEWS_EXPORT __attribute__((visibility("default"))) -#else -#define VIEWS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/views_content_client/views_content_client_export.h b/ui/views_content_client/views_content_client_export.h index 8e05789..43ac0772 100644 --- a/ui/views_content_client/views_content_client_export.h +++ b/ui/views_content_client/views_content_client_export.h
@@ -18,11 +18,7 @@ #endif // defined(VIEWS_CONTENT_CLIENT_IMPLEMENTATION) #else // defined(WIN32) -#if defined(VIEWS_CONTENT_CLIENT_IMPLEMENTATION) #define VIEWS_CONTENT_CLIENT_EXPORT __attribute__((visibility("default"))) -#else -#define VIEWS_CONTENT_CLIENT_EXPORT -#endif #endif // defined(VIEWS_CONTENT_CLIENT_IMPLEMENTATION) #else // defined(COMPONENT_BUILD)
diff --git a/ui/web_dialogs/web_dialogs_export.h b/ui/web_dialogs/web_dialogs_export.h index a8d990e..7f616cf 100644 --- a/ui/web_dialogs/web_dialogs_export.h +++ b/ui/web_dialogs/web_dialogs_export.h
@@ -18,11 +18,7 @@ #endif // defined(WEB_DIALOGS_IMPLEMENTATION) #else // defined(WIN32) -#if defined(WEB_DIALOGS_IMPLEMENTATION) #define WEB_DIALOGS_EXPORT __attribute__((visibility("default"))) -#else -#define WEB_DIALOGS_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/ui/wm/public/wm_public_export.h b/ui/wm/public/wm_public_export.h index b376333..582ee09 100644 --- a/ui/wm/public/wm_public_export.h +++ b/ui/wm/public/wm_public_export.h
@@ -18,11 +18,7 @@ #endif // defined(WM_PUBLIC_IMPLEMENTATION) #else // defined(WIN32) -#if defined(WM_PUBLIC_IMPLEMENTATION) #define WM_PUBLIC_EXPORT __attribute__((visibility("default"))) -#else -#define WM_PUBLIC_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/url/ipc/url_ipc_export.h b/url/ipc/url_ipc_export.h index ca500ab..3780fc9 100644 --- a/url/ipc/url_ipc_export.h +++ b/url/ipc/url_ipc_export.h
@@ -15,11 +15,7 @@ #endif // defined(URL_IPC_IMPLEMENTATION) #else // defined(WIN32) -#if defined(URL_IPC_IMPLEMENTATION) #define URL_IPC_EXPORT __attribute__((visibility("default"))) -#else -#define URL_IPC_EXPORT -#endif #endif #else // defined(COMPONENT_BUILD)
diff --git a/v8 b/v8 index 8b2e5e5..3005b00 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 8b2e5e57af618aadee7b3b9f967348c87da61591 +Subproject commit 3005b00df2a95266a853252e20e78f637adc5c2f